pydioc 0.1

Creator: railscoderz

Last updated:

Add to Cart

Description:

pydioc 0.1

Python DI / IoC container

Dependency injection means giving an object its instance variables.
-- James Shore, Dependency Injection Demystified

Initially it was created for AWS Lambda Functions to simplify development
with loose coupling component and improved testing capabilities.
Inspiration comes from python:design_patterns:inversion_of_control summary article.
This modules is an optimized version of a container used in p3.4.advanced-di-ioc section of my lambda-modular-python MOB session @cloudreach.
Usage
Orchestrate container in ioc.py file:
# ioc.py
import pydioc
import boto3
import some_sdk
from . import services

def build_container(ssm_param_api_key: str, ddb_status_table: str, format_type: str) -> pydioc.Container:
return pydioc.Container(
("_boto3_session", boto3.Session),
("lambda_context", pydioc.ContextProxy),

("_api_key_loader", services.api_key_loader, ["_boto3_session", lambda: ssm_param_api_key]),
("_status_updater", services.status_updater, ["_boto3_session", "lambda_context", lambda: ddb_status_table]),

("_sdk_data_formatter", some_sdk.FormatterFactory, [lambda: format_type]),
("_sdk_client_factory", services.sdk_client_factory, ["_api_key_loader"]),

("_sdk_data_transfer", services.sdk_data_transfer, ["_sdk_client_factory", "_sdk_data_formatter", "lambda_context"]),

("event_handler", services.event_handler, ["_sdk_data_transfer", "_status_updater"]),
)

Define services in services.py file:
# services.py
import boto3
import some_sdk

# ...

def api_key_loader(session: boto3.Session, ssm_param_api_key: str):
assert ssm_param_api_key, 'expecting non empty api_key param'

def _api_key_loader():
# very simplified code
return session.client('ssm').get_parameter(Name=ssm_param_api_key)["Parameter"]["Value"]

return _api_key_loader

def sdk_client_factory(load_api_key: api_key_loader):
def _sdk_client_factory(client_type):
# very simplified code
api_key = load_api_key()
if client_type == 'User':
return some_sdk.user.Client(api_key)
raise ValueError(f"unknown client type: {client_type}")
return sdk_client_factory

def sdk_data_transfer(client_factory: sdk_client_factory, formatter: some_sdk.Formatter, context: object):
def _sdk_data_transfer(payload: dict)
# very simplified code
client = client_factory(payload['type'])
client.publish(formatter.format(payload['body']), handler=context.invoked_function_arn)
return _sdk_data_transfer

# ...

Configure and run in main.py file:
# main.py
import os
from . import ioc

init_error = None

try:
container = ioc.build_container(
ssm_param_api_key=os.environ.get("SSM_PARAM_API_KEY"),
ddb_status_table=os.environ.get("DDB_STATUS_TABLE"),
format_type=os.environ.get("FORMAT_TYPE", "YAML"),
)
except Exception as ex:
init_error = ex


def lambda_handler(event: dict, context: object):
if init_error:
raise init_error

container.lambda_context(context)

return container.event_handler(event)

In this example container would be compiled once per Lambda Function life cycle,
while lambda_handler processes incoming requests sequentially, until it dies after idle timeout.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.