Quickstart¶
Install the latest stable version into your virtual environment:
pip install sosw
sosw requires Python 3.12 – 3.14 and depends only on boto3 (which the AWS Lambda runtimes
already provide).
A minimal Processor Lambda¶
Create app.py with the following structure. Your business logic lives in a subclass of
Processor; the module-level lambda_handler is generated by
sosw.app.get_lambda_handler().
Note
AWS STS is used here just as an example of automatic initialization of boto3 clients.
from sosw.app import LambdaGlobals, get_lambda_handler, Processor as SoswProcessor
from sosw.components.benchmark import benchmark
class Processor(SoswProcessor):
DEFAULT_CONFIG = {
'init_clients': ['sts'], # Automatically initialize `self.sts_client`.
}
sts_client = None
def __call__(self, event, **kwargs):
super().__call__(event)
data = self.get_self_identity()
self.result['accounts_identified'] += 1
return {'account': data['Account'], **self.get_stats()}
@benchmark # Collect execution time in `self.stats`.
def get_self_identity(self):
return self.sts_client.get_caller_identity()
global_vars = LambdaGlobals()
lambda_handler = get_lambda_handler(Processor, global_vars)
What happens here:
On the first (cold) invocation the handler constructs the
Processor: it assembles the configuration (DEFAULT_CONFIG, then optional overrides from DynamoDB / SSM, thencustom_config— see Configuration) and initializes the clients listed ininit_clients.On warm invocations the very same Processor instance is reused from
global_vars— no re-initialization, no extra latency. Read more in Warm start.self.resultis your per-invocation accumulator,self.statscollects per-container counters that the handler logs after every call.
If you do not want the Processor to look for external configuration in DynamoDB at all, disable the lookup explicitly:
class Processor(SoswProcessor):
DEFAULT_CONFIG = {
'disable_ddb_config': True, # Skip the DynamoDB / SSM config lookup.
'init_clients': ['sts'],
}
Deploy with AWS SAM¶
The fastest way to ship this function is AWS SAM.
A minimal template.yaml:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: My first sosw-based Lambda.
Resources:
MyFirstSoswFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: my-first-sosw-function
CodeUri: src/
Handler: app.lambda_handler
Runtime: python3.14
Timeout: 30
MemorySize: 256
Put app.py into src/ together with a requirements.txt containing the single line
sosw, then:
sam build && sam deploy --guided
aws lambda invoke --function-name my-first-sosw-function --payload '{}' /dev/stdout
For a complete walkthrough (project layout, configuration table, unit tests, cleanup) follow the Your first sosw Lambda tutorial.
Test it¶
sosw Processors are designed to be unit-tested without any network access. Mock the config
lookup and boto3, then call the Processor directly:
import os
import unittest
from unittest.mock import MagicMock, patch
os.environ['STAGE'] = 'test'
os.environ['autotest'] = 'True'
from app import Processor
class ProcessorTestCase(unittest.TestCase):
@patch('boto3.client')
def setUp(self, mock_boto_client):
with patch.object(Processor, 'get_config', return_value={}):
self.processor = Processor()
self.processor.sts_client = MagicMock()
self.processor.sts_client.get_caller_identity.return_value = {'Account': '000000000000'}
def test_call(self):
result = self.processor({})
self.assertEqual(result['account'], '000000000000')
Setting STAGE=test before importing makes the Processor derive test=True
(see sosw.app._derive_test_flag()); patching get_config keeps the test free of
DynamoDB calls.
Next steps¶
Understand the core class: Processor.
Building an HTTP API? Use LambdaApi.
Long-running workflows? See durable functions.
Create a shared Lambda Layer with
soswfor faster deployments: Lambda Layer.