feat(core): support context manager dependency factories - #13
Merged
Conversation
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.
Deploying wireme with
|
| Latest commit: |
41de71c
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://3dfc90a8.wireme.pages.dev |
| Branch Preview URL: | https://feat-context-manager-depende.wireme.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@contextmanagerand@asynccontextmanagerfactories can now be used asWireme 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 twocontextlibdecorators 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)override_web_dependency()so declaration and override sites agree on one identity per dependency.
Normalizing only in
wired()would register the dependency under thewrapped 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 unrelatedfunctools.wrapsdecorators, including
functools.lru_cache, and silently changes theirbehavior. Regression tests cover both cases.
wired()gainsAbstractContextManager[R]andAbstractAsyncContextManager[R]overloads, so a decorated factory infersRrather than the context manager type.Behavior is unchanged for every existing dependency form. Recorded in
ADR 0020.
Coverage
endpoint exception, override by another context manager and by a plain
factory,
functools.wrapsdecorator preserved,lru_cachepreservedmanager nested inside a generator closing in reverse order, and
override_web_dependencyon a bridged context manager factoryassert_type(wired(cm), str)fixtures for both decoratorsa context manager dependency
context_managers.pyandfastapi_context_managers.py, bothself-checking, on stdlib
sqlite3onlyChecklist
default-branch commit and generated release-note entry.
skip-changelogisapplied for changes users do not need to see.
just checkpasses locally.