From dcc1e1bcf823927817d8c133962bdb7a29e3d797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 27 Jun 2019 20:51:17 +0200 Subject: [PATCH] :recycle: Refine internal type declarations and logic around them (#338) --- fastapi/applications.py | 44 +++++++++++------------ fastapi/dependencies/utils.py | 6 ++-- fastapi/openapi/models.py | 10 +++--- fastapi/openapi/utils.py | 5 +-- fastapi/routing.py | 66 +++++++++++++++++++---------------- fastapi/security/api_key.py | 2 +- fastapi/security/http.py | 4 ++- fastapi/security/oauth2.py | 2 +- fastapi/utils.py | 4 +-- scripts/lint.sh | 2 +- 10 files changed, 76 insertions(+), 69 deletions(-) diff --git a/fastapi/applications.py b/fastapi/applications.py index a1a2a5605..e5dce88d9 100644 --- a/fastapi/applications.py +++ b/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, diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 61dd01142..28c57c296 100644 --- a/fastapi/dependencies/utils.py +++ b/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 diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py index 82134d856..ddc5c6847 100644 --- a/fastapi/openapi/models.py +++ b/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 diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 6f741c6bc..8d02a4751 100644 --- a/fastapi/openapi/utils.py +++ b/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 diff --git a/fastapi/routing.py b/fastapi/routing.py index 8d013dd01..e349787d7 100644 --- a/fastapi/routing.py +++ b/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, diff --git a/fastapi/security/api_key.py b/fastapi/security/api_key.py index 356681eee..30fd3358f 100644 --- a/fastapi/security/api_key.py +++ b/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( diff --git a/fastapi/security/http.py b/fastapi/security/http.py index 362390b7a..9625951ae 100644 --- a/fastapi/security/http.py +++ b/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: diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 8c3cb819c..c7451cfaf 100644 --- a/fastapi/security/oauth2.py +++ b/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 diff --git a/fastapi/utils.py b/fastapi/utils.py index c3adda7f1..21bca1d3f 100644 --- a/fastapi/utils.py +++ b/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: diff --git a/scripts/lint.sh b/scripts/lint.sh index a00bf655f..11b59f2b9 100755 --- a/scripts/lint.sh +++ b/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