.. title:: Quickstart — your first Lambda with ``sosw`` .. _Quickstart: ========== Quickstart ========== Install the latest stable version into your virtual environment: .. code-block:: bash 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 :ref:`Processor`; the module-level ``lambda_handler`` is generated by :py:func:`sosw.app.get_lambda_handler`. .. note:: AWS STS is used here just as an example of automatic initialization of boto3 clients. .. code-block:: python 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, then ``custom_config`` — see :ref:`Configuration `) and initializes the clients listed in ``init_clients``. * On warm invocations the very same Processor instance is reused from ``global_vars`` — no re-initialization, no extra latency. Read more in :ref:`Warm start `. * ``self.result`` is your per-invocation accumulator, ``self.stats`` collects 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: .. code-block:: python 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``: .. code-block:: 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: .. code-block:: bash 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 :doc:`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: .. code-block:: python 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 :py:func:`sosw.app._derive_test_flag`); patching ``get_config`` keeps the test free of DynamoDB calls. Next steps ---------- * Understand the core class: :doc:`concepts/processor`. * Building an HTTP API? Use :doc:`LambdaApi `. * Long-running workflows? See :doc:`durable functions `. * Create a shared Lambda Layer with ``sosw`` for faster deployments: :ref:`SOSW Layer`.