Fix issue with double model parsing

This commit is contained in:
Yurii Karabas 2021-10-23 22:21:04 +03:00
parent 864643ef76
commit 1c84c7b96a
2 changed files with 46 additions and 12 deletions

View File

@ -467,7 +467,8 @@ async def solve_dependencies(
media_type=None, # type: ignore # in Starlette
background=None, # type: ignore # in Starlette
)
dependency_cache = dependency_cache or {}
if dependency_cache is None:
dependency_cache = {}
sub_dependant: Dependant
for sub_dependant in dependant.dependencies:
sub_dependant.call = cast(Callable[..., Any], sub_dependant.call)
@ -493,7 +494,21 @@ async def solve_dependencies(
)
use_sub_dependant.security_scopes = sub_dependant.security_scopes
solved_result = await solve_dependencies(
if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache:
solved = dependency_cache[sub_dependant.cache_key]
if sub_dependant.name is not None:
values[sub_dependant.name] = solved
continue
(
sub_values,
sub_errors,
background_tasks,
_, # the subdependency returns the same response we have
sub_dependency_cache,
) = await solve_dependencies(
request=request,
dependant=use_sub_dependant,
body=body,
@ -502,19 +517,10 @@ async def solve_dependencies(
dependency_overrides_provider=dependency_overrides_provider,
dependency_cache=dependency_cache,
)
(
sub_values,
sub_errors,
background_tasks,
_, # the subdependency returns the same response we have
sub_dependency_cache,
) = solved_result
dependency_cache.update(sub_dependency_cache)
if sub_errors:
errors.extend(sub_errors)
continue
if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache:
solved = dependency_cache[sub_dependant.cache_key]
elif is_gen_callable(call) or is_async_gen_callable(call):
stack = request.scope.get("fastapi_astack")
assert isinstance(stack, AsyncExitStack)

View File

@ -1,9 +1,21 @@
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, root_validator
app = FastAPI()
counter_holder = {"counter": 0}
counter_holder = {"counter": 0, "parsing_counter": 0}
class Model(BaseModel):
@root_validator
def __validate__(cls, _):
counter_holder["parsing_counter"] += 1
return {}
async def model_dep(model: Model) -> Model:
return model
async def dep_counter():
@ -35,6 +47,15 @@ async def get_sub_counter_no_cache(
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"]}
client = TestClient(app)
@ -66,3 +87,10 @@ def test_sub_counter_no_cache():
response = client.get("/sub-counter-no-cache/")
assert response.status_code == 200, response.text
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}