Browse Source

♻️ Refine internal type declarations and logic around them (#338)

pull/339/head
Sebastián Ramírez 6 years ago
committed by GitHub
parent
commit
dcc1e1bcf8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      fastapi/applications.py
  2. 6
      fastapi/dependencies/utils.py
  3. 10
      fastapi/openapi/models.py
  4. 5
      fastapi/openapi/utils.py
  5. 66
      fastapi/routing.py
  6. 2
      fastapi/security/api_key.py
  7. 4
      fastapi/security/http.py
  8. 2
      fastapi/security/oauth2.py
  9. 4
      fastapi/utils.py
  10. 2
      scripts/lint.sh

44
fastapi/applications.py

@ -1,4 +1,4 @@
from typing import Any, Callable, Dict, List, Optional, Set, Type, Union
from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Type, Union
from fastapi import routing
from fastapi.exception_handlers import (
@ -130,7 +130,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -152,7 +152,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -176,7 +176,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -199,7 +199,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -237,7 +237,7 @@ class FastAPI(Starlette):
*,
prefix: str = "",
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
responses: Dict[Union[int, str], Dict[str, Any]] = None,
) -> None:
self.router.include_router(
@ -255,7 +255,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -275,7 +275,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -298,7 +298,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -318,7 +318,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -341,7 +341,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -361,7 +361,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -384,7 +384,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -404,7 +404,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -427,7 +427,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -447,7 +447,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -470,7 +470,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -490,7 +490,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -513,7 +513,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -533,7 +533,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -556,7 +556,7 @@ class FastAPI(Starlette):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[Depends] = None,
dependencies: Sequence[Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -576,7 +576,7 @@ class FastAPI(Starlette):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,

6
fastapi/dependencies/utils.py

@ -242,7 +242,7 @@ def get_param_field(
if isinstance(schema, params.Param) and getattr(schema, "in_", None) is None:
schema.in_ = default_schema.in_
if force_type:
schema.in_ = force_type
schema.in_ = force_type # type: ignore
else:
schema = default_schema(default_value)
required = default_value == Required
@ -422,7 +422,7 @@ def request_params_to_args(
value = received_params.getlist(field.alias) or field.default
else:
value = received_params.get(field.alias)
schema: params.Param = field.schema
schema = field.schema
assert isinstance(schema, params.Param), "Params must be subclasses of Param"
if value is None:
if field.required:
@ -458,7 +458,7 @@ async def request_body_to_args(
if len(required_params) == 1 and not embed:
received_body = {field.alias: received_body}
for field in required_params:
value = None
value: Any = None
if received_body is not None:
if field.shape in sequence_shapes and isinstance(
received_body, FormData

10
fastapi/openapi/models.py

@ -122,7 +122,7 @@ class Schema(SchemaBase):
not_: Optional[List[SchemaBase]] = PSchema(None, alias="not") # type: ignore
items: Optional[SchemaBase] = None
properties: Optional[Dict[str, SchemaBase]] = None
additionalProperties: Optional[Union[SchemaBase, bool]] = None
additionalProperties: Optional[Union[SchemaBase, bool]] = None # type: ignore
class Example(BaseModel):
@ -149,9 +149,9 @@ class Encoding(BaseModel):
class MediaType(BaseModel):
schema_: Optional[Union[Schema, Reference]] = PSchema(
schema_: Optional[Union[Schema, Reference]] = PSchema( # type: ignore
None, alias="schema"
) # type: ignore
)
example: Optional[Any] = None
examples: Optional[Dict[str, Union[Example, Reference]]] = None
encoding: Optional[Dict[str, Encoding]] = None
@ -165,9 +165,9 @@ class ParameterBase(BaseModel):
style: Optional[str] = None
explode: Optional[bool] = None
allowReserved: Optional[bool] = None
schema_: Optional[Union[Schema, Reference]] = PSchema(
schema_: Optional[Union[Schema, Reference]] = PSchema( # type: ignore
None, alias="schema"
) # type: ignore
)
example: Optional[Any] = None
examples: Optional[Dict[str, Union[Example, Reference]]] = None
# Serialization rules for more complex scenarios

5
fastapi/openapi/utils.py

@ -71,7 +71,8 @@ def get_openapi_operation_parameters(
definitions: Dict[str, Dict] = {}
parameters = []
for param in all_route_params:
schema: Param = param.schema
schema = param.schema
schema = cast(Param, schema)
if "ValidationError" not in definitions:
definitions["ValidationError"] = validation_error_definition
definitions["HTTPValidationError"] = validation_error_response_definition
@ -90,7 +91,7 @@ def get_openapi_operation_parameters(
def get_openapi_operation_request_body(
*, body_field: Field, model_name_map: Dict[Type, str]
*, body_field: Optional[Field], model_name_map: Dict[Type, str]
) -> Optional[Dict]:
if not body_field:
return None

66
fastapi/routing.py

@ -1,7 +1,7 @@
import asyncio
import inspect
import logging
from typing import Any, Callable, Dict, List, Optional, Set, Type, Union
from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Type, Union
from fastapi import params
from fastapi.dependencies.models import Dependant
@ -184,14 +184,14 @@ class APIRoute(routing.Route):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
responses: Dict[Union[int, str], Dict[str, Any]] = None,
deprecated: bool = None,
name: str = None,
methods: List[str] = None,
methods: Optional[Union[Set[str], List[str]]] = None,
operation_id: str = None,
response_model_include: Set[str] = None,
response_model_exclude: Set[str] = set(),
@ -227,13 +227,18 @@ class APIRoute(routing.Route):
# would pass the validation and be returned as is.
# By being a new field, no inheritance will be passed as is. A new model
# will be always created.
self.secure_cloned_response_field = create_cloned_field(self.response_field)
self.secure_cloned_response_field: Optional[Field] = create_cloned_field(
self.response_field
)
else:
self.response_field = None
self.secure_cloned_response_field = None
self.status_code = status_code
self.tags = tags or []
self.dependencies = dependencies or []
if dependencies:
self.dependencies = list(dependencies)
else:
self.dependencies = []
self.summary = summary
self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "")
self.response_description = response_description
@ -264,7 +269,7 @@ class APIRoute(routing.Route):
self.deprecated = deprecated
if methods is None:
methods = ["GET"]
self.methods = methods
self.methods = set([method.upper() for method in methods])
self.operation_id = operation_id
self.response_model_include = response_model_include
self.response_model_exclude = response_model_exclude
@ -322,13 +327,13 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
responses: Dict[Union[int, str], Dict[str, Any]] = None,
deprecated: bool = None,
methods: List[str] = None,
methods: Optional[Union[Set[str], List[str]]] = None,
operation_id: str = None,
response_model_include: Set[str] = None,
response_model_exclude: Set[str] = set(),
@ -344,7 +349,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -370,7 +375,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -393,7 +398,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -432,7 +437,7 @@ class APIRouter(routing.Router):
*,
prefix: str = "",
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
responses: Dict[Union[int, str], Dict[str, Any]] = None,
) -> None:
if prefix:
@ -451,7 +456,8 @@ class APIRouter(routing.Router):
response_model=route.response_model,
status_code=route.status_code,
tags=(route.tags or []) + (tags or []),
dependencies=(dependencies or []) + (route.dependencies or []),
dependencies=list(dependencies or [])
+ list(route.dependencies or []),
summary=route.summary,
description=route.description,
response_description=route.response_description,
@ -471,7 +477,7 @@ class APIRouter(routing.Router):
self.add_route(
prefix + route.path,
route.endpoint,
methods=route.methods,
methods=list(route.methods or []),
include_in_schema=route.include_in_schema,
name=route.name,
)
@ -491,7 +497,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -512,7 +518,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -536,7 +542,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -556,7 +562,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -580,7 +586,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -600,7 +606,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -624,7 +630,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -644,7 +650,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -668,7 +674,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -688,7 +694,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -712,7 +718,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -732,7 +738,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -756,7 +762,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -776,7 +782,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
@ -800,7 +806,7 @@ class APIRouter(routing.Router):
response_model: Type[Any] = None,
status_code: int = 200,
tags: List[str] = None,
dependencies: List[params.Depends] = None,
dependencies: Sequence[params.Depends] = None,
summary: str = None,
description: str = None,
response_description: str = "Successful Response",
@ -820,7 +826,7 @@ class APIRouter(routing.Router):
response_model=response_model,
status_code=status_code,
tags=tags or [],
dependencies=dependencies or [],
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,

2
fastapi/security/api_key.py

@ -54,7 +54,7 @@ class APIKeyCookie(APIKeyBase):
self.auto_error = auto_error
async def __call__(self, request: Request) -> Optional[str]:
api_key: str = request.cookies.get(self.model.name)
api_key = request.cookies.get(self.model.name)
if not api_key:
if self.auto_error:
raise HTTPException(

4
fastapi/security/http.py

@ -56,7 +56,9 @@ class HTTPBasic(HTTPBase):
self.realm = realm
self.auto_error = auto_error
async def __call__(self, request: Request) -> Optional[HTTPBasicCredentials]:
async def __call__( # type: ignore
self, request: Request
) -> Optional[HTTPBasicCredentials]:
authorization: str = request.headers.get("Authorization")
scheme, param = get_authorization_scheme_param(authorization)
if self.realm:

2
fastapi/security/oauth2.py

@ -2,7 +2,7 @@ from typing import List, Optional
from fastapi.exceptions import HTTPException
from fastapi.openapi.models import OAuth2 as OAuth2Model, OAuthFlows as OAuthFlowsModel
from fastapi.params import Form
from fastapi.param_functions import Form
from fastapi.security.base import SecurityBase
from fastapi.security.utils import get_authorization_scheme_param
from starlette.requests import Request

4
fastapi/utils.py

@ -10,9 +10,7 @@ from pydantic.utils import lenient_issubclass
from starlette.routing import BaseRoute
def get_flat_models_from_routes(
routes: Sequence[Type[BaseRoute]]
) -> Set[Type[BaseModel]]:
def get_flat_models_from_routes(routes: Sequence[BaseRoute]) -> Set[Type[BaseModel]]:
body_fields_from_routes: List[Field] = []
responses_from_routes: List[Field] = []
for route in routes:

2
scripts/lint.sh

@ -3,6 +3,6 @@
set -e
set -x
mypy fastapi --disallow-untyped-defs --follow-imports=skip
mypy fastapi --disallow-untyped-defs
black fastapi tests --check
isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --check-only --thirdparty fastapi fastapi tests

Loading…
Cancel
Save