Browse Source

🐛 Fix constrained bytes, from defaults in Pydantic

#2
pull/11/head
Sebastián Ramírez 6 years ago
parent
commit
577c5a84db
  1. 16
      fastapi/dependencies/utils.py
  2. 5
      fastapi/routing.py
  3. 7
      fastapi/utils.py
  4. 12
      tests/test_tutorial/test_request_files/test_tutorial001.py

16
fastapi/dependencies/utils.py

@ -9,8 +9,8 @@ from uuid import UUID
from fastapi import params from fastapi import params
from fastapi.dependencies.models import Dependant, SecurityRequirement from fastapi.dependencies.models import Dependant, SecurityRequirement
from fastapi.security.base import SecurityBase from fastapi.security.base import SecurityBase
from fastapi.utils import get_path_param_names from fastapi.utils import UnconstrainedConfig, get_path_param_names
from pydantic import BaseConfig, Schema, create_model from pydantic import Schema, create_model
from pydantic.error_wrappers import ErrorWrapper from pydantic.error_wrappers import ErrorWrapper
from pydantic.errors import MissingError from pydantic.errors import MissingError
from pydantic.fields import Field, Required, Shape from pydantic.fields import Field, Required, Shape
@ -163,7 +163,7 @@ def add_param_to_fields(
default=None if required else default_value, default=None if required else default_value,
alias=alias, alias=alias,
required=required, required=required,
model_config=BaseConfig(), model_config=UnconstrainedConfig,
class_validators=[], class_validators=[],
schema=schema, schema=schema,
) )
@ -197,7 +197,7 @@ def add_param_to_body_fields(*, param: inspect.Parameter, dependant: Dependant)
default=None if required else default_value, default=None if required else default_value,
alias=schema.alias or param.name, alias=schema.alias or param.name,
required=required, required=required,
model_config=BaseConfig, model_config=UnconstrainedConfig,
class_validators=[], class_validators=[],
schema=schema, schema=schema,
) )
@ -281,7 +281,7 @@ def request_params_to_args(
ErrorWrapper( ErrorWrapper(
MissingError(), MissingError(),
loc=(schema.in_.value, field.alias), loc=(schema.in_.value, field.alias),
config=BaseConfig, config=UnconstrainedConfig,
) )
) )
else: else:
@ -315,7 +315,9 @@ async def request_body_to_args(
if field.required: if field.required:
errors.append( errors.append(
ErrorWrapper( ErrorWrapper(
MissingError(), loc=("body", field.alias), config=BaseConfig MissingError(),
loc=("body", field.alias),
config=UnconstrainedConfig,
) )
) )
else: else:
@ -356,7 +358,7 @@ def get_body_field(*, dependant: Dependant, name: str) -> Field:
type_=BodyModel, type_=BodyModel,
default=None, default=None,
required=required, required=required,
model_config=BaseConfig, model_config=UnconstrainedConfig,
class_validators=[], class_validators=[],
alias="body", alias="body",
schema=BodySchema(None), schema=BodySchema(None),

5
fastapi/routing.py

@ -7,7 +7,8 @@ from fastapi import params
from fastapi.dependencies.models import Dependant from fastapi.dependencies.models import Dependant
from fastapi.dependencies.utils import get_body_field, get_dependant, solve_dependencies from fastapi.dependencies.utils import get_body_field, get_dependant, solve_dependencies
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from pydantic import BaseConfig, BaseModel, Schema from fastapi.utils import UnconstrainedConfig
from pydantic import BaseModel, Schema
from pydantic.error_wrappers import ErrorWrapper, ValidationError from pydantic.error_wrappers import ErrorWrapper, ValidationError
from pydantic.fields import Field from pydantic.fields import Field
from pydantic.utils import lenient_issubclass from pydantic.utils import lenient_issubclass
@ -130,7 +131,7 @@ class APIRoute(routing.Route):
class_validators=[], class_validators=[],
default=None, default=None,
required=False, required=False,
model_config=BaseConfig(), model_config=UnconstrainedConfig,
schema=Schema(None), schema=Schema(None),
) )
else: else:

7
fastapi/utils.py

@ -3,12 +3,17 @@ from typing import Any, Dict, List, Sequence, Set, Type
from fastapi import routing from fastapi import routing
from fastapi.openapi.constants import REF_PREFIX from fastapi.openapi.constants import REF_PREFIX
from pydantic import BaseModel from pydantic import BaseConfig, BaseModel
from pydantic.fields import Field from pydantic.fields import Field
from pydantic.schema import get_flat_models_from_fields, model_process_schema from pydantic.schema import get_flat_models_from_fields, model_process_schema
from starlette.routing import BaseRoute from starlette.routing import BaseRoute
class UnconstrainedConfig(BaseConfig):
min_anystr_length = None
max_anystr_length = None
def get_flat_models_from_routes( def get_flat_models_from_routes(
routes: Sequence[Type[BaseRoute]] routes: Sequence[Type[BaseRoute]]
) -> Set[Type[BaseModel]]: ) -> Set[Type[BaseModel]]:

12
tests/test_tutorial/test_request_files/test_tutorial001.py

@ -119,3 +119,15 @@ def test_post_file(tmpdir):
response = client.post("/files/", files={"file": open(path, "rb")}) response = client.post("/files/", files={"file": open(path, "rb")})
assert response.status_code == 200 assert response.status_code == 200
assert response.json() == {"file_size": 14} assert response.json() == {"file_size": 14}
def test_post_large_file(tmpdir):
default_pydantic_max_size = 2 ** 16
path = os.path.join(tmpdir, "test.txt")
with open(path, "wb") as file:
file.write(b"x" * (default_pydantic_max_size + 1))
client = TestClient(app)
response = client.post("/files/", files={"file": open(path, "rb")})
assert response.status_code == 200
assert response.json() == {"file_size": default_pydantic_max_size + 1}

Loading…
Cancel
Save