Skip to content

feat(core): support context manager dependency factories - #13

Merged
mghalix merged 2 commits into
mainfrom
feat/context-manager-dependencies
Jul 31, 2026
Merged

feat(core): support context manager dependency factories#13
mghalix merged 2 commits into
mainfrom
feat/context-manager-dependencies

Conversation

@mghalix

@mghalix mghalix commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

@contextmanager and @asynccontextmanager factories can now be used as
Wireme dependencies. Previously they resolved to an unentered context
manager object instead of the dependency, so an existing resource had to be
rewritten as a bare generator function to be injectable.

One private _normalize_factory() recognizes the two contextlib
decorators by the code object their helper closures share, and returns the
generator function they wrap. It runs wherever a factory enters Wireme:

  • wired()
  • override_dependency() (original and replacement)
  • the bridged-adapter lookup behind override_web_dependency()

so declaration and override sites agree on one identity per dependency.
Normalizing only in wired() would register the dependency under the
wrapped generator while both override entry points still keyed on the
decorator helper, and overrides would silently do nothing.

Detection is narrow on purpose. inspect.unwrap() follows every
__wrapped__ chain, so it also strips unrelated functools.wraps
decorators, including functools.lru_cache, and silently changes their
behavior. Regression tests cover both cases.

wired() gains AbstractContextManager[R] and
AbstractAsyncContextManager[R] overloads, so a decorated factory infers
R rather than the context manager type.

Behavior is unchanged for every existing dependency form. Recorded in
ADR 0020.

Coverage

  • unit: sync and async context manager dependencies, cleanup after an
    endpoint exception, override by another context manager and by a plain
    factory, functools.wraps decorator preserved, lru_cache preserved
  • integration: FastAPI request lifecycle for both decorators, a context
    manager nested inside a generator closing in reverse order, and
    override_web_dependency on a bridged context manager factory
  • typing: assert_type(wired(cm), str) fixtures for both decorators
  • smoke: the built wheel and sdist exercise a real FastAPI request through
    a context manager dependency
  • examples: context_managers.py and fastapi_context_managers.py, both
    self-checking, on stdlib sqlite3 only

Checklist

  • The pull request title follows Conventional Commits; it becomes the
    default-branch commit and generated release-note entry.
  • Tests cover the changed behavior.
  • Documentation and examples reflect public changes.
  • The appropriate release-note label is applied, or skip-changelog is
    applied for changes users do not need to see.
  • just check passes locally.

Factories decorated with @contextmanager or @asynccontextmanager returned
an unentered context manager object instead of the dependency, so they
could not be used with wired(...) without rewriting them as bare
generator functions.

One private _normalize_factory() recognizes the two contextlib decorators
by the code object their helper closures share and returns the generator
function they wrap. It runs wherever a factory enters Wireme: wired(),
override_dependency(), and the bridged-adapter lookup behind
override_web_dependency(), so declaration and override sites agree on one
identity per dependency.

Detection is narrow on purpose. Unwrapping every __wrapped__ chain would
also strip unrelated functools.wraps decorators, including
functools.lru_cache, and silently change their behavior.

wired() gains AbstractContextManager and AbstractAsyncContextManager
overloads so a decorated factory infers the yielded type.

Recorded in ADR 0020.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 31, 2026

Copy link
Copy Markdown

Deploying wireme with  Cloudflare Pages  Cloudflare Pages

Latest commit: 41de71c
Status: ✅  Deploy successful!
Preview URL: https://3dfc90a8.wireme.pages.dev
Branch Preview URL: https://feat-context-manager-depende.wireme.pages.dev

View logs

@mghalix
mghalix merged commit c2ad161 into main Jul 31, 2026
12 checks passed
@mghalix
mghalix deleted the feat/context-manager-dependencies branch July 31, 2026 22:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant