Local development

Prerequisites

  • uv (it installs Python 3.12 itself, pinned by .python-version).

  • Git access to the private github.com/Payability repos — uv fetches pyb-flask-utils, eventlogger and messaging from git tags ([tool.uv.sources] in pyproject.toml).

  • AWS SAM CLI, only for make build / make deploy.

  • AWS SSO profiles dev (account 605668041275) and prod (account 625663093496).

Everyday commands

make install    # uv sync: .venv with runtime + dev dependencies
make test       # offline unit tests
make lint       # ruff (pyflakes rules)
make help       # everything else

Dependencies are declared in pyproject.toml and locked in uv.lock. Add one with uv add <pkg>==<version> (or uv add --dev …), commit both files. requirements.txt is generated for sam build by make requirements and is not committed.

Tests

make test runs python -m unittest discover -s tests -t .. The suite needs no AWS access:

  • tests/init.py sets AWS_SECRETS_MANAGER=False and dummy values for every required setting before the app is imported (-t . makes tests a package so this runs first);

  • DynamoDB is mocked with moto (mock_aws, tables created from dynamo_tables);

  • WORKER_FUNCTION_NAME is unset, so @async_task functions run inline;

  • HTTP calls to other services are mocked with requests-mock / mock.

Running the API locally

cp .env.example .env    # fill in the values (see the comments in the file)
make run                # uv run --env-file .env: Flask under gevent on http://localhost:5555

PyCharm users: the committed run configuration .idea/runConfigurations/Run.xml loads .env through the EnvFile plugin and runs run_locally.py.

Two ways to provide secrets locally:

Mode Set

Explicit values (default in .env.example)

AWS_SECRETS_MANAGER=False and every secret as a plain variable. pyb_flask_utils then also skips common/crm, so instance-token auth is off; JWT auth still works, since tokens are validated by the stage internal API (PAYABILITY_INTERNAL_API_URL).

From the stage secret

AWS_SECRETS_MANAGER=True, APP_SECRET_ID=actionstools/stage, AWS_PROFILE=dev after aws sso login --profile dev. Behaves like the deployed stage.

The local app uses the _staging tables of whichever account your credentials point at.

The Lambda entry points in lambda_handlers.py are not run locally; tests/test_lambda_handlers.py covers the API Gateway translation and every Worker event shape (async/worker.adoc#events). To exercise the real Worker, invoke the stage one by hand (Running things by hand).