I have a small fastapi example here
# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends
app = FastAPI()
class Dep:
    def __init__(self, inp):
        self.inp = inp
    @cache
    def __call__(self):
        print(self.inp * 100)
        return self.inp
@app.get("/a")
def a(v: str = Depends(Dep("a"))):
    return v
@app.get("/a/a")
def aa(v: str = Depends(Dep("a"))):
    return v
@app.get("/b")
def b(v: str = Depends(Dep("b"))):
    return v
@app.get("/b/b")
def bb(v: str = Depends(Dep("b"))):
    return v
def main():
    uvicorn.run(
        "run:app",
        host="0.0.0.0",
        reload=True,
        port=8000,
        workers=1
    )
if __name__ == "__main__":
    main()
I run python run.py and the application spins up.
What I expect is that:
the first time I hit /a or /a/a endpoints it shows logs to me and print 100 "a" for me. the next times no logging happens because of the @cache decorator
and
the first time I hit /b or /b/b endpoints it shows logs to me and print 100 "b"s for me. the next times no logging happens because of the @cache decorator
What happens
The first time I hit /b, it shows logs. the next times no log
The first time I hit /b/b, it shows logs. the next times no log
The first time I hit /a, it shows logs. the next times no log
The first time I hit /a/a, it shows logs. the next times no log
the reason is that each time I am passing a value to the Dep class it is creating a new object and the call method is that of a new object each time. that is why the caching is not working properly.
and the caching is being done by fastapi dependency . That is why when I call an endpoint for the next times, I do not see new logs
But the question is how do I
- pass arguments to the callable dependency (a class)
- and also cache the value the function returns
Extra information
I tried to achieve the same using the approach below:
# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends, Request
app = FastAPI()
@cache
def dep(inp):
    @cache
    def sub_dep():
        print(inp*100)
        return inp
    return sub_dep
@app.get("/a")
def a(v: str = Depends(dep("a"))):
    return v
@app.get("/a/a")
def aa(v: str = Depends(dep("a"))):
    return v
@app.get("/b")
def b(v: str = Depends(dep("b"))):
    return v
@app.get("/b/b")
def bb(v: str = Depends(dep("b"))):
    return v
def main():
    uvicorn.run(
        "run:app",
        host="0.0.0.0",
        reload=True,
        port=8000,
        workers=1
    )
if __name__ == "__main__":
    main()
and it working as expected above
 
    