Code Monkey home page Code Monkey logo

Comments (10)

dmontagu avatar dmontagu commented on April 28, 2024 4

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.

from fastapi.

haizaar avatar haizaar commented on April 28, 2024 1

Implemented in version 0.42.0 #595
Docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/

Thank you guys. It looks awesome!

from fastapi.

alexiri avatar alexiri commented on April 28, 2024

Sounds like a good idea. I don't particularly like having such a long list of arguments for the path functions, though. It will be easy to end up with something like this:

@app.get("/groups/{group_id}/user/{user_id}")
def read_user(group_id: int, user_id: int, request: Request, current_user: User = Depends(get_current_active_user), db_session: Session = Depends(db)):
    ...

from fastapi.

tiangolo avatar tiangolo commented on April 28, 2024

Great ideas!

Actually, I was thinking on adding it or something similar :)

I was thinking on vanilla context managers, classes with "dunder" methods, without @contextmanager, as it is only available in 3.7 and FastAPI is compatible with 3.6.

I agree using request.state.db is not ideal, as the typing is lost, etc. For that, I just updated the tutorial to have a dependency that extracts the DB from the request: https://fastapi.tiangolo.com/tutorial/sql-databases/

This doesn't solve having a session in requests that didn't need them, but at least is cleaner for bigger applications.

I also created a project generator with this style, for FastAPI with PostgreSQL, you might wanna check it out: https://github.com/tiangolo/full-stack-fastapi-postgresql


Coming back to the context managers, I would like to have them. I would prefer them both handled by Depends, but I think there are a couple of things that need to be taken care of/analyzed.

For example, right now, the dependency management handles a tree of dependencies, but if two dependencies require a DB connection, having a single dependency that provides it, would create 2 DB sessions, as the solved dependencies are not re-used (yet). If we solve it, by having a cache of already solved dependencies, the dependency injection system would be able to handle DAGs (directed acyclic graphs), a lot more powerful than only trees. That would allow us having a DB dependency that can be required by several points in the dependency chain/graph/tree but that re-uses the same connection for the same request.

from fastapi.

haizaar avatar haizaar commented on April 28, 2024

Glad you liked the idea.

Yeah, adding Depends() to extract session from request.state is a great idea - at least if one forgets to add a middleware it will fail early.

Back to the discussion...
I'm not sure that going with DAG it justified at this stage (at least most of my microservices have very simple requirements with regards to DI). The current DI is very light both API and implementation wise,
and if one uses his own "full-fledged" DI, he/she can easily integrate it with FastAPI.

To utilize caching I think you need to start distinguishing between Services and Factories (to cache the former but not the latter). And then it may start to look like "full-fledged" DI, which can deserve a project of its own. On the other hand, DI design pattern is not very popular in Python world AFAIK so may be FastAPI shouldn't go there as well.

My bottom line - lets follow agile philosophy. Stay with trees and see when the DAG user story comes in. If an injectable is essentially implemented as Service, there is no real performance penalty to resolve it twice, so I think trees are good enough, at least for me :)

Regarding using Depends for both - can you share your ideas on how to do it? When Depends resolves whatever was passed to it, it needs to deduce whether it should treat it as context manager or callable - and whatever you pass can be both. I can think of:

  • Requiring Depends argument to be either callable or context manager
  • Providing Depends with a hint that passed arg should be treated as a context manager: Depends(get_db, ctx_mgr=True)

Option one sounds a bit limiting to me.

P.S. Is there any particular reason you are holding on to Python 3.6? - This project is young, and it's a great advantage to be able to use the latest tech from upstream Python.
P.P.S At worst case, AsyncExitStack can be borrowed from upstream. It's just 130 LOC :)

from fastapi.

tiangolo avatar tiangolo commented on April 28, 2024

Sorry for the delay.


I agree, good idea to keep it agile and see what we are actually needing.


It needs to deduce whether it should treat it as context manager or callable [...]

What I would do, is check first if the object has __enter__ and __exit__, and then treat is a context manager, as that would be the "strange" case, it wouldn't be easy for a normal dependency to have those attributes, so then, default to standard dependency injection.

This is is somewhat similar to how the default parameter inference is done:

First, check if it's part of the path, it's just path. Then if it's a scalar value, it's a query param. Then if it's the Request or BackgroundTasks object, it's those two things, and then, otherwise, it is a body. All that overridden by explicit declarations of Query, Body, File, etc.


I'm holding to Python 3.6 to be compatible with libraries like TensorFlow and Celery, that currently don't have versions for Python 3.7 :)


I think the current state of the system works well enough for us all, with the middleware and dependency trick. Let's see if we find a strong need for context managers later, as it would probably require quite some work.

from fastapi.

haizaar avatar haizaar commented on April 28, 2024

What I would do, is check first if the object has enter and exit

Or __aenter__ and __aexit__.

I'm holding to Python 3.6 to be compatible with libraries like TensorFlow and Celery, that currently
don't have versions for Python 3.7 :)

Got it, thank you.

Let's see if we find a strong need for context managers later, as it would probably require quite some work.

I'll take it as "PR's welcome" in case I'll get to it :)

from fastapi.

tiangolo avatar tiangolo commented on April 28, 2024

Or aenter and aexit.

Yep, good point.

I'll take it as "PR's welcome" in case I'll get to it :)

Hehe, yep 😉 I still can do it, but as you said, let's keep it agile and see if we (or someone) actually need it.

from fastapi.

ademoverflow avatar ademoverflow commented on April 28, 2024

HI all ! I am looking for this feature, exactly for the same example given by @haizaar.
Is there something planned to implement this feature ?

from fastapi.

haizaar avatar haizaar commented on April 28, 2024

from fastapi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.