Canary Framework
Dependency injection and lifecycle for plain Python classes — standard library only, zero dependencies.
中文 · 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.configis aConfig,async with serviceyields your type, anddep(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)
| File | Size | Uploaded | |
|---|---|---|---|
| canary_framework-0.10.0.tar.gz | 62.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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