Skip to main content

Canary Framework

Dependency injection and lifecycle for plain Python classes — standard library only, zero dependencies.

CI PyPI Python License

中文 · Documentation · Changelog

Install

pip install canary-framework

Requires Python 3.12 or newer. Installing pulls in no third-party packages.

The model

Subclass Canary and you have a unit: it declares what it depends on with dep(), and what it does in each phase with @init / @start / @stop. Start one unit and its dependencies come up in dependency order; leaving reclaims them in reverse.

import asyncio

from canary_framework import Canary, dep, init, start, stop


class Config(Canary):
    @init
    def load(self) -> None:
        self.dsn = "postgresql://localhost/dev"


class Database(Canary):
    config = dep(Config)

    @start
    async def connect(self) -> None:
        print(f"connecting to {self.config.dsn}")

    @stop
    async def close(self) -> None:
        print("disconnected")


class UserService(Canary):
    database = dep(Database)


async def main() -> None:
    async with UserService() as service:
        print(service.database.config.dsn)


asyncio.run(main())
connecting to postgresql://localhost/dev
postgresql://localhost/dev
disconnected

Two rules

Advancing recurses along dependencies: a unit enters a phase only after its dependencies have completed it. One unit runs one phase exactly once no matter how many units depend on it, and independent dependencies advance concurrently.

Unwinding is linear: a dependency graph is not a tree, so reclamation runs over a ledger in reverse entry order.

init / start / stop are three names for these two rules. Adding a fourth phase is one line: Phase("migrate", after=init).

Highlights

  • Typed end to end. self.config is a Config, async with service yields your type, and dep(SomethingElse) is a type error. No plugin required.
  • Plain classes. Decorators only mark methods; units stay subclassable, mixable, nestable, and lifecycle methods can be overridden with super().
  • Failure paths are part of the design. A failing start() reclaims what started; stop() is the single reclamation path, shared by success and failure, and is idempotent.
  • Concurrent by default. Independent units advance together, scheduled by dependency.
  • Zero dependencies. A test asserts that a full lifecycle imports nothing from site-packages.

Hosting

The framework knows nothing about shells — HTTP, CLI, schedulers and consumers are all yours:

@asynccontextmanager
async def lifespan(_app: FastAPI):
    async with service:
        yield


app = FastAPI(lifespan=lifespan)

Documentation

Full documentation, including migration from 0.9.x, is at hotcocoacanary.github.io/Canary-Framework.

A complete five-layer example lives in examples/library/.

License

Apache-2.0. See LICENSE.

Release files for canary-framework 0.10.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for canary-framework 0.10.0
File Size Uploaded
canary_framework-0.10.0.tar.gz 62.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for canary-framework 0.10.0
File Interpreter ABI Platform
canary_framework-0.10.0-py3-none-any.whl Python 3 none any Details

Total release size: 87.2 kB

Release files / canary_framework-0.10.0.tar.gz

Download URL canary_framework-0.10.0.tar.gz
Size 62.9 kB
Tags Source
SHA-256 checksum
How to use checksums
ddf0028529dd15220dad2ec8310c67fc24926b5ec1760c1cca04de07e07cf142
BLAKE2b-256 checksum
How to use checksums
8c0f90bac6de832d787855630b188695d5fcd4dcb222e2a10d5f05e15ab649df
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release files / canary_framework-0.10.0-py3-none-any.whl

Download URL canary_framework-0.10.0-py3-none-any.whl
Size 24.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
df4b9e839d5293d5e09974a3bdc760f79b7c7cd997338f9a175998ffdf6a28d7
BLAKE2b-256 checksum
How to use checksums
66fe1c11721042e8fba2ae691a9570dfeb8e3f529f3d241a225fafee0a077415
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release history Release notifications | RSS feed

1.1.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

This release

0.10.0 This release

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.6.1

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.13

2 release files

0.4.9

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page