Contributing Guide
This guide is for contributors to the ActingWeb Python library. For user and API docs, see the pages under docs/.
Local Setup
Python 3.11+ and Poetry required.
Install (with all optional extras):
poetry install -E all
Useful commands:
Tests + coverage:
poetry run pytest(fails <80%; HTML inhtmlcov/)Parallel tests:
make test-parallel(3-4x faster using all CPU cores)Lint:
poetry run ruff check .Format:
poetry run black .Types:
poetry run mypy actingwebDocs:
make html(output in_build/html)
Development Workflow
Create a feature branch; keep changes focused.
Run ruff, black, mypy, and pytest locally; ensure coverage ≥ 80%.
Update docs under docs/ for user‑visible behavior; put contributor‑only notes here in CONTRIBUTING.rst.
Add CHANGELOG.rst entries (top section for unreleased) when behavior changes.
Open a PR with a clear description, motivation, and test coverage.
Coding Standards
Style: Black (line length 88), Ruff for lint, type hints required on public APIs; keep
py.typedintact.Naming: modules/functions
snake_case, classesPascalCase, constantsUPPER_SNAKE_CASE.Avoid one‑letter names; prefer explicit, minimal changes aligned with existing patterns.
Devtest Endpoints (Library Testing Aids)
Devtest endpoints are for validating ActingWeb behavior during development. Never enable in production.
Enable:
ActingWebApp(...).with_devtest(True)orConfig(devtest=True).Paths (all under
/<actor_id>/devtest):GET/POST/PUT/DELETE /devtest/ping→ 204 (auth/route sanity)./devtest/proxy/...: exercise peer calls via the loopback trust (shorttype="myself"): -GET /devtest/proxy/properties→ fetch peer properties. -PUT /devtest/proxy/properties/<name>with JSON → set a property via proxy. -DELETE /devtest/proxy/properties→ delete all peer properties./devtest/attribute/...: inspect/mutate internal Attributes storage: -GET /devtest/attribute→ list buckets;GET /devtest/attribute/<bucket>→ list entries. -POST /devtest/attribute/<bucket>with JSON → create bucket entries. -PUT /devtest/attribute/<bucket>/<key>with JSON → set value. -DELETE /devtest/attribute/<bucket>/<key>orDELETE /devtest/attribute→ remove key/buckets.
Running Tests
Sequential Execution
Run tests one at a time (traditional approach):
# All integration tests
make test-integration
# Unit tests only
poetry run pytest tests/ --ignore=tests/integration
# Specific test file
poetry run pytest tests/integration/test_factory.py -v
Parallel Execution (Recommended)
Run tests in parallel across multiple CPU cores for 3-4x speedup:
# All integration tests (auto-detects CPU cores)
make test-parallel
# Fast tests only (skips slow tests)
make test-parallel-fast
# All tests (unit + integration)
make test-all-parallel
# Manual control (4 workers with loadgroup distribution)
poetry run pytest tests/integration/ -n 4 -v --dist loadgroup
How Parallel Testing Works:
Each worker gets isolated database tables (
test_w0_,test_w1_, etc.)Test servers run on unique ports per worker (5555, 5565, 5575, etc.)
Actor emails are automatically made unique (
user_gw0_1_abc@example.com)Tests marked with
@pytest.mark.xdist_groupstay on the same worker (--dist loadgroup)No test code changes needed - isolation is automatic
Writing Parallel-Safe Tests:
Always use
actor_factoryfixture for creating actorsAvoid hardcoded emails - let the factory generate unique ones
Don’t share state between tests
Each test should be independent
# Good - automatically unique per worker
def test_something(actor_factory):
actor = actor_factory.create("test@example.com")
# Bad - may conflict across workers
def test_something(actor_factory):
actor = actor_factory.create("fixed_email_123@example.com")
Debugging Parallel Tests:
# Run with single worker for easier debugging
poetry run pytest tests/integration/ -n 1 -v
# Run sequentially (no parallelization)
poetry run pytest tests/integration/ -v
DynamoDB for Development
Local (DynamoDB Local):
docker run -p 8000:8000 amazon/dynamodb-local export AWS_ACCESS_KEY_ID=local AWS_SECRET_ACCESS_KEY=local AWS_DEFAULT_REGION=us-east-1
Production: use proper IAM; tables are accessed by modules under
actingweb.db_dynamodb.
Docs and Examples
User docs live under docs/; add or update examples in
docs/getting-started.rst,docs/developers.rst, and related pages.Build docs with
make htmland verify the updated pages in_build/html.Reference demo application (for patterns and testing): https://github.com/actingweb/actingwebdemo
Commits and PRs
Commits: imperative mood, concise (e.g., “Fix trust permission mapping”).
PRs: include motivation, scope, linked issues (e.g.,
Closes #123), test updates, and any doc changes.CI must pass: pytest (with coverage), mypy, Ruff, Black, and package build.
CI/CD Testing
GitHub Actions runs tests in parallel using
pytest-xdistfor 3-4× speedupTests run with 4 workers on public repos, 2 workers on private repos
Coverage reporting works seamlessly with parallel execution
Same test suite runs locally (
make test-parallel) and in CI
Release Process
Releases are decoupled from PRs. PRs merge to master without version bumps; releases are triggered by git tags.
For contributors: Add CHANGELOG.rst entries to the “Unreleased” section. No version bumps needed in PRs.
For maintainers (stable release):
Update version in
pyproject.tomlandactingweb/__init__.pyRename “Unreleased” to
vX.Y.Z: DateinCHANGELOG.rstAdd new empty “Unreleased” section at top
Commit:
git commit -am "Release vX.Y.Z"Tag:
git tag vX.Y.ZPush:
git push && git push --tags
GitHub Actions validates the tag is on master, runs tests, publishes to PyPI, and creates a GitHub Release.
Pre-Release Versions
Pre-release versions are automatically published to TestPyPI (not production PyPI).
Supported patterns:
Alpha:
X.Y.ZaN(e.g.,3.10.0a1)Beta:
X.Y.ZbN(e.g.,3.10.0b1)Release Candidate:
X.Y.ZrcN(e.g.,3.10.0rc1)Development:
X.Y.Z.devN(e.g.,3.10.0.dev1)
To create a pre-release:
Update version to pre-release version (e.g.,
3.10.0a1)Commit and tag:
git tag v3.10.0a1Push:
git push && git push --tags
Installing pre-releases from TestPyPI:
pip install --index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
actingweb==3.10.0a1
Branch restriction: Tags can only be released from commits on the master branch. Tags on feature branches will fail the release workflow.
Required repository secrets:
POETRY_PYPI_TOKEN_PYPI- Production PyPI API token (stable releases)POETRY_TESTPYPI_TOKEN- TestPyPI API token (pre-releases)