question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[FEATURE] Contextmanager as dependency

See original GitHub issue

Depends() works great, but does not support post-response cleanup. How about injecting from context managers? Taking the SQL Db example, it would not need middleware anymore:

from contextlib import contextmanager

@contextmanager
def db() -> Session:
    db_session = Session()
    try:
        yield db_session
    finally:
        db_session.close()

@app.get("/users/{user_id}")
def read_user(user_id: int, db_session: Session = Depends(db)):
    user = get_user(db_session, user_id=user_id)
    return user

Middlewares do the job and they have been there forever, but from the FastAPI idiomatic approach request.scope looks a bit of a “dumpster” - it’s not known in advance what to expect there without examining middlware docs/code. Middlewares also need to take care not to step on each other. And finally, not all paths may need that request.scope.db. By supporting contextmanager injection, I believe code can be more idiomatic, and more efficient (e.g. because we’ll only initialize Session() for requests that need it).

What do you think?

Implementation wise, I guess dependencies.utils.solve_dependencies needs to return ctxmgrs in addition to values and errors. Then during execution we can use either contextlib.ExitStack or contextlib.AsyncExitStack (the latter is Python 3.7 only though) to wrap the execution with. Also, since a “thing” passed to Depends() can be both callable and context manager, may be it worth having new DependsContextMgr() class. And finally, I think there should be some type checking to make sure that only async context managers are injected into async request handlers and vise-versa.

I can work on a PR for this if the initiative is going to be accepted.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:10 (9 by maintainers)

github_iconTop GitHub Comments

4reactions
dmontagucommented, Sep 26, 2019

I created a pull request that gets at this from a slightly different angle (#570). It supports functions similar to contextmanager-decorated functions or pytest yield fixtures. These can be easily used with enter and exit (and the async equivalents) by yielding inside the with statement.

I’m still working on docs for the pull request but I’ll include examples along the lines described above.

1reaction
haizaarcommented, Oct 9, 2019
Read more comments on GitHub >

github_iconTop Results From Across the Web

contextlib — Utilities for with-statement contexts ... - Python Docs
Similar to contextmanager() , but creates an asynchronous context manager. This function is a decorator that can be used to define a factory...
Read more >
Dependencies with yield - FastAPI
Any function that is valid to use with: @contextlib.contextmanager or; @contextlib.asynccontextmanager. would be valid to use as a FastAPI dependency.
Read more >
Using a context manager as a global dependency in Fast API
I have a FastAPI app that mostly calls external apis. In some instances, a path operation will make several calls to the same...
Read more >
Argument 1 passed to Drupal\context\ContextManager
I updated from 4.0-beta2 to beta4 with drush and I get an error which crashes my site. I had to downgrade back to...
Read more >
Advanced Python Concepts - GitHub Pages
One way to create a context manager is to have a function that has a yield . What is ``yield``?: It's like a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found