mirror of https://github.com/tiangolo/fastapi.git
Merge 0264bcbe80 into 272204c0c7
This commit is contained in:
commit
d1adfea6b2
|
|
@ -623,6 +623,17 @@ async def solve_dependencies(
|
||||||
dependency_cache = {}
|
dependency_cache = {}
|
||||||
for sub_dependant in dependant.dependencies:
|
for sub_dependant in dependant.dependencies:
|
||||||
sub_dependant.call = cast(Callable[..., Any], sub_dependant.call)
|
sub_dependant.call = cast(Callable[..., Any], sub_dependant.call)
|
||||||
|
|
||||||
|
if sub_dependant.use_cache:
|
||||||
|
# Use a unique object to compare against in case the cached value is None
|
||||||
|
cache_miss = object()
|
||||||
|
cached_value = dependency_cache.get(sub_dependant.cache_key, cache_miss)
|
||||||
|
# If the sub dependant is already cached, skip doing any more work
|
||||||
|
if cached_value is not cache_miss:
|
||||||
|
if sub_dependant.name is not None:
|
||||||
|
values[sub_dependant.name] = cached_value
|
||||||
|
continue
|
||||||
|
|
||||||
call = sub_dependant.call
|
call = sub_dependant.call
|
||||||
use_sub_dependant = sub_dependant
|
use_sub_dependant = sub_dependant
|
||||||
if (
|
if (
|
||||||
|
|
@ -657,11 +668,7 @@ async def solve_dependencies(
|
||||||
if solved_result.errors:
|
if solved_result.errors:
|
||||||
errors.extend(solved_result.errors)
|
errors.extend(solved_result.errors)
|
||||||
continue
|
continue
|
||||||
if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache:
|
if use_sub_dependant.is_gen_callable or use_sub_dependant.is_async_gen_callable:
|
||||||
solved = dependency_cache[sub_dependant.cache_key]
|
|
||||||
elif (
|
|
||||||
use_sub_dependant.is_gen_callable or use_sub_dependant.is_async_gen_callable
|
|
||||||
):
|
|
||||||
use_astack = request_astack
|
use_astack = request_astack
|
||||||
if sub_dependant.scope == "function":
|
if sub_dependant.scope == "function":
|
||||||
use_astack = function_astack
|
use_astack = function_astack
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,27 @@
|
||||||
from fastapi import Depends, FastAPI, Security
|
from fastapi import Depends, FastAPI, Security
|
||||||
|
from fastapi._compat import PYDANTIC_V2
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
counter_holder = {"counter": 0}
|
counter_holder = {"counter": 0, "parsing_counter": 0}
|
||||||
|
|
||||||
|
if PYDANTIC_V2:
|
||||||
|
from pydantic import model_validator
|
||||||
|
|
||||||
|
decorator = model_validator(mode="before")
|
||||||
|
else:
|
||||||
|
from pydantic import root_validator
|
||||||
|
|
||||||
|
decorator = root_validator
|
||||||
|
|
||||||
|
|
||||||
|
class Model(BaseModel):
|
||||||
|
@decorator
|
||||||
|
def __validate__(cls, _):
|
||||||
|
counter_holder["parsing_counter"] += 1
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
async def dep_counter():
|
async def dep_counter():
|
||||||
|
|
@ -15,6 +33,10 @@ async def super_dep(count: int = Depends(dep_counter)):
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
async def model_dep(model: Model) -> Model:
|
||||||
|
return model
|
||||||
|
|
||||||
|
|
||||||
@app.get("/counter/")
|
@app.get("/counter/")
|
||||||
async def get_counter(count: int = Depends(dep_counter)):
|
async def get_counter(count: int = Depends(dep_counter)):
|
||||||
return {"counter": count}
|
return {"counter": count}
|
||||||
|
|
@ -35,6 +57,15 @@ async def get_sub_counter_no_cache(
|
||||||
return {"counter": count, "subcounter": subcount}
|
return {"counter": count, "subcounter": subcount}
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/sub-model-parsing/")
|
||||||
|
async def get_double_model_parsing(
|
||||||
|
a: Model = Depends(model_dep),
|
||||||
|
b: Model = Depends(model_dep),
|
||||||
|
):
|
||||||
|
assert a is b
|
||||||
|
return {"parsing_counter": counter_holder["parsing_counter"]}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/scope-counter")
|
@app.get("/scope-counter")
|
||||||
async def get_scope_counter(
|
async def get_scope_counter(
|
||||||
count: int = Security(dep_counter),
|
count: int = Security(dep_counter),
|
||||||
|
|
@ -81,6 +112,13 @@ def test_sub_counter_no_cache():
|
||||||
assert response.json() == {"counter": 4, "subcounter": 3}
|
assert response.json() == {"counter": 4, "subcounter": 3}
|
||||||
|
|
||||||
|
|
||||||
|
def test_sub_model_parsing_no_repeatable_parsing():
|
||||||
|
counter_holder["parsing_counter"] = 0
|
||||||
|
response = client.post("/sub-model-parsing/", json={})
|
||||||
|
assert response.status_code == 200, response.text
|
||||||
|
assert response.json() == {"parsing_counter": 1}
|
||||||
|
|
||||||
|
|
||||||
def test_security_cache():
|
def test_security_cache():
|
||||||
counter_holder["counter"] = 0
|
counter_holder["counter"] = 0
|
||||||
response = client.get("/scope-counter/")
|
response = client.get("/scope-counter/")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue