Skip to main content

uncalled-for

Async dependency injection for Python functions.

Declare what your function needs as parameter defaults. They show up resolved when the function runs. No ceremony, no container, no configuration.

from uncalled_for import Depends

async def get_db():
    db = await connect()
    try:
        yield db
    finally:
        await db.close()

async def handle_request(db: Connection = Depends(get_db)):
    await db.execute("SELECT 1")

Features

  • Zero dependencies — standard library only
  • Async-native — built on AsyncExitStack and ContextVar
  • Context manager lifecycle — sync and async generators get proper cleanup
  • Nested dependencies — dependencies can depend on other dependencies
  • Caching — each dependency resolves once per call, even if referenced multiple times
  • Call arguments — a factory can reference the arguments of the call it serves

Annotated dependencies

Depends, Shared and CallArgument also work as Annotated metadata, so you can name a dependency once and reuse it:

DB = Annotated[Connection, Depends(get_db)]

async def handle_request(db: DB):
    await db.execute("SELECT 1")

This resolves like db: Connection = Depends(get_db), but to Python db is still a required parameter. A custom dependency supplies a value from metadata only if it subclasses Provider; other dependencies there wrap the call.

When something else calls the function with type-checked arguments, such as a task queue that schedules it, default the parameter to Provided so those callers can leave it out:

async def handle_request(db: DB = Provided): ...

A type alias works the same way: type DB = Annotated[Connection, Depends(get_db)].

Call arguments

A factory sometimes needs a value from the call itself, not from another dependency. CallArgument declares that reference:

from uncalled_for import CallArgument, Depends

def load_user(user_id: str = CallArgument()) -> User:
    return users[user_id]

async def handle_request(
    user_id: str,
    user: User = Depends(load_user),
):
    ...

The bare form takes the name of the parameter it is declared on. CallArgument("name") names a different parameter of the outer function. The reference sees the same value the outer function receives, whether the caller passed it or another dependency on the outer signature produced it. CallArgument(optional=True) yields None when the outer function has no such argument. References that form a cycle raise CycleError.

When the outer function doesn't declare the parameter, without_dependencies adds it to the wrapper's signature as keyword-only, required unless the reference has a default. Optional references are never added.

Bindings

Depends accepts keyword bindings, so you can wire up an ordinary function without changing it:

async def handle_request(
    user_id: str,
    user: User = Depends(load_user, user_id=CallArgument("user_id")),
):
    ...

A binding that is a Dependency, such as CallArgument(...) or another Depends(...), resolves first and the factory receives its value. Any other value passes through as it is. A binding replaces the factory parameter's own default, which is then never resolved. Two dependencies on the same factory share one cached result only when their bindings match.

Install

pip install uncalled-for

Metadata

Release files for uncalled-for 0.6.1

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

Source distribution (sdist)

Source distribution for uncalled-for 0.6.1
File Size Uploaded Provenance Actions
uncalled_for-0.6.1.tar.gz 71.8 kB With provenance Details for uncalled_for-0.6.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for uncalled-for 0.6.1
File Interpreter ABI Platform Actions
uncalled_for-0.6.1-py3-none-any.whl Python 3 none any Details for uncalled_for-0.6.1-py3-none-any.whl

Total release size: 90.8 kB

Release files / uncalled_for-0.6.1.tar.gz

Download URL uncalled_for-0.6.1.tar.gz
Size 71.8 kB
Tags Source
SHA-256 checksum
How to use checksums
49d9a55a806529dbb844f64a2e3adc8f44ad0b0802f5d91381a09c088c44e144
BLAKE2b-256 checksum
How to use checksums
9ce9056b74ca4559f93cd38080c110696ae9a8f6d1976b162eb3638895f829e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 10, 2026.

Transparency log

Release files / uncalled_for-0.6.1-py3-none-any.whl

Download URL uncalled_for-0.6.1-py3-none-any.whl
Size 19.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1e8f86f972684db50f2888f07caa87d81a431584fa77856660e0c5e89f1cc778
BLAKE2b-256 checksum
How to use checksums
0cd02db6b2299a07ddc6c6f49a39351a6faab1eb04f1c1b248a8270f1380276a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 10, 2026.

Transparency log

Security for uncalled-for 0.6.1

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for uncalled_for-0.6.1.tar.gz

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 Nov 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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