def __init__(self, path: str, endpoint: Callable, *, name: str = None) -> None: self.path = path self.endpoint = endpoint self.name = get_name(endpoint) if name is None else name self.dependant = get_dependant(path=path, call=self.endpoint) self.app = websocket_session(get_websocket_app(dependant=self.dependant)) regex = "^" + path + "$" regex = re.sub("{([a-zA-Z_][a-zA-Z0-9_]*)}", r"(?P<\1>[^/]+)", regex) self.path_regex, self.path_format, self.param_convertors = compile_path(path)
def __init__(self, path: str, endpoint: Callable, *, name: str = None, dependency_overrides_provider: Any = None) -> None: super().__init__(path, endpoint, name=name) self.path = path self.endpoint = endpoint self.name = get_name(endpoint) if name is None else name self.dependant = get_dependant(path=path, call=self.endpoint) self.app = websocket_session( get_websocket_app( dependant=self.dependant, dependency_overrides_provider=dependency_overrides_provider, )) self.path_regex, self.path_format, self.param_convertors = compile_path( path)
def __init__( self, path: str, endpoint: Callable, *, response_model: Type[Any] = None, status_code: int = 200, tags: List[str] = 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: Optional[Union[Set[str], List[str]]] = None, operation_id: str = None, response_model_include: Union[SetIntStr, DictIntStrAny] = None, response_model_exclude: Union[SetIntStr, DictIntStrAny] = set(), response_model_by_alias: bool = True, response_model_exclude_unset: bool = False, include_in_schema: bool = True, response_class: Optional[Type[Response]] = None, dependency_overrides_provider: Any = None, callbacks: Optional[List["APIRoute"]] = None, ) -> None: self.path = path self.endpoint = endpoint self.name = get_name(endpoint) if name is None else name self.path_regex, self.path_format, self.param_convertors = compile_path(path) if methods is None: methods = ["GET"] self.methods = set([method.upper() for method in methods]) self.unique_id = generate_operation_id_for_path( name=self.name, path=self.path_format, method=list(methods)[0] ) self.response_model = response_model if self.response_model: assert ( status_code not in STATUS_CODES_WITH_NO_BODY ), f"Status code {status_code} must not have a response body" response_name = "Response_" + self.unique_id self.response_field = create_response_field( name=response_name, type_=self.response_model ) # Create a clone of the field, so that a Pydantic submodel is not returned # as is just because it's an instance of a subclass of a more limited class # e.g. UserInDB (containing hashed_password) could be a subclass of User # that doesn't have the hashed_password. But because it's a subclass, it # 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: Optional[ ModelField ] = create_cloned_field(self.response_field) else: self.response_field = None # type: ignore self.secure_cloned_response_field = None self.status_code = status_code self.tags = tags or [] if dependencies: self.dependencies = list(dependencies) else: self.dependencies = [] self.summary = summary self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "") # if a "form feed" character (page break) is found in the description text, # truncate description text to the content preceding the first "form feed" self.description = self.description.split("\f")[0] self.response_description = response_description self.responses = responses or {} response_fields = {} for additional_status_code, response in self.responses.items(): assert isinstance(response, dict), "An additional response must be a dict" model = response.get("model") if model: assert ( additional_status_code not in STATUS_CODES_WITH_NO_BODY ), f"Status code {additional_status_code} must not have a response body" response_name = f"Response_{additional_status_code}_{self.unique_id}" response_field = create_response_field(name=response_name, type_=model) response_fields[additional_status_code] = response_field if response_fields: self.response_fields: Dict[Union[int, str], ModelField] = response_fields else: self.response_fields = {} self.deprecated = deprecated self.operation_id = operation_id self.response_model_include = response_model_include self.response_model_exclude = response_model_exclude self.response_model_by_alias = response_model_by_alias self.response_model_exclude_unset = response_model_exclude_unset self.include_in_schema = include_in_schema self.response_class = response_class assert callable(endpoint), f"An endpoint must be a callable" self.dependant = get_dependant(path=self.path_format, call=self.endpoint) for depends in self.dependencies[::-1]: self.dependant.dependencies.insert( 0, get_parameterless_sub_dependant(depends=depends, path=self.path_format), ) self.body_field = get_body_field(dependant=self.dependant, name=self.unique_id) self.dependency_overrides_provider = dependency_overrides_provider self.callbacks = callbacks self.app = request_response(self.get_route_handler())
def __init__( self, path: str, endpoint: Callable, *, response_model: Type[BaseModel] = None, status_code: int = 200, tags: List[str] = 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, operation_id: str = None, include_in_schema: bool = True, response_class: Type[Response] = JSONResponse, ) -> None: assert path.startswith("/"), "Routed paths must always start with '/'" self.path = path self.endpoint = endpoint self.name = get_name(endpoint) if name is None else name self.response_model = response_model if self.response_model: assert lenient_issubclass( response_class, JSONResponse ), "To declare a type the response must be a JSON response" response_name = "Response_" + self.name self.response_field: Optional[Field] = Field( name=response_name, type_=self.response_model, class_validators={}, default=None, required=False, model_config=BaseConfig, schema=Schema(None), ) else: self.response_field = None self.status_code = status_code self.tags = tags or [] self.summary = summary self.description = description or inspect.cleandoc( self.endpoint.__doc__ or "") self.response_description = response_description self.responses = responses or {} response_fields = {} for additional_status_code, response in self.responses.items(): assert isinstance(response, dict), "An additional response must be a dict" model = response.get("model") if model: assert lenient_issubclass( model, BaseModel), "A response model must be a Pydantic model" response_name = f"Response_{additional_status_code}_{self.name}" response_field = Field( name=response_name, type_=model, class_validators=None, default=None, required=False, model_config=BaseConfig, schema=Schema(None), ) response_fields[additional_status_code] = response_field if response_fields: self.response_fields: Dict[Union[int, str], Field] = response_fields else: self.response_fields = {} self.deprecated = deprecated if methods is None: methods = ["GET"] self.methods = methods self.operation_id = operation_id self.include_in_schema = include_in_schema self.response_class = response_class self.path_regex, self.path_format, self.param_convertors = compile_path( path) assert inspect.isfunction(endpoint) or inspect.ismethod( endpoint), f"An endpoint must be a function or method" self.dependant = get_dependant(path=path, call=self.endpoint) self.body_field = get_body_field(dependant=self.dependant, name=self.name) self.app = request_response( get_app( dependant=self.dependant, body_field=self.body_field, status_code=self.status_code, response_class=self.response_class, response_field=self.response_field, ))
def __init__( self, path: str, endpoint: Callable, *, response_model: Type[Any] = None, status_code: int = 200, tags: List[str] = 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: Optional[Union[Set[str], List[str]]] = None, operation_id: str = None, response_model_include: Set[str] = None, response_model_exclude: Set[str] = set(), response_model_by_alias: bool = True, response_model_skip_defaults: bool = False, include_in_schema: bool = True, response_class: Type[Response] = JSONResponse, dependency_overrides_provider: Any = None, ) -> None: assert path.startswith("/"), "Routed paths must always start with '/'" self.path = path self.endpoint = endpoint self.name = get_name(endpoint) if name is None else name self.path_regex, self.path_format, self.param_convertors = compile_path( path) if methods is None: methods = ["GET"] self.methods = set([method.upper() for method in methods]) self.unique_id = generate_operation_id_for_path( name=self.name, path=self.path_format, method=list(methods)[0]) self.response_model = response_model if self.response_model: assert lenient_issubclass( response_class, JSONResponse ), "To declare a type the response must be a JSON response" response_name = "Response_" + self.unique_id self.response_field: Optional[Field] = Field( name=response_name, type_=self.response_model, class_validators={}, default=None, required=False, model_config=BaseConfig, schema=Schema(None), ) # Create a clone of the field, so that a Pydantic submodel is not returned # as is just because it's an instance of a subclass of a more limited class # e.g. UserInDB (containing hashed_password) could be a subclass of User # that doesn't have the hashed_password. But because it's a subclass, it # 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: 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 [] 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 self.responses = responses or {} response_fields = {} for additional_status_code, response in self.responses.items(): assert isinstance(response, dict), "An additional response must be a dict" model = response.get("model") if model: assert lenient_issubclass( model, BaseModel), "A response model must be a Pydantic model" response_name = f"Response_{additional_status_code}_{self.unique_id}" response_field = Field( name=response_name, type_=model, class_validators=None, default=None, required=False, model_config=BaseConfig, schema=Schema(None), ) response_fields[additional_status_code] = response_field if response_fields: self.response_fields: Dict[Union[int, str], Field] = response_fields else: self.response_fields = {} self.deprecated = deprecated self.operation_id = operation_id self.response_model_include = response_model_include self.response_model_exclude = response_model_exclude self.response_model_by_alias = response_model_by_alias self.response_model_skip_defaults = response_model_skip_defaults self.include_in_schema = include_in_schema self.response_class = response_class assert inspect.isfunction(endpoint) or inspect.ismethod( endpoint), f"An endpoint must be a function or method" self.dependant = get_dependant(path=self.path_format, call=self.endpoint) for depends in self.dependencies[::-1]: self.dependant.dependencies.insert( 0, get_parameterless_sub_dependant(depends=depends, path=self.path_format), ) self.body_field = get_body_field(dependant=self.dependant, name=self.unique_id) self.dependency_overrides_provider = dependency_overrides_provider self.app = request_response( get_app( dependant=self.dependant, body_field=self.body_field, status_code=self.status_code, response_class=self.response_class, response_field=self.secure_cloned_response_field, response_model_include=self.response_model_include, response_model_exclude=self.response_model_exclude, response_model_by_alias=self.response_model_by_alias, response_model_skip_defaults=self.response_model_skip_defaults, dependency_overrides_provider=self. dependency_overrides_provider, ))
def __init__( self, path: str, endpoint: Callable, *, response_model: Type[BaseModel] = None, status_code: int = 200, tags: List[str] = None, summary: str = None, description: str = None, response_description: str = "Successful Response", deprecated: bool = None, name: str = None, methods: List[str] = None, operation_id: str = None, include_in_schema: bool = True, content_type: Type[Response] = JSONResponse, ) -> None: assert path.startswith("/"), "Routed paths must always start with '/'" self.path = path self.endpoint = endpoint self.name = get_name(endpoint) if name is None else name self.response_model = response_model if self.response_model: assert lenient_issubclass( content_type, JSONResponse ), "To declare a type the response must be a JSON response" response_name = "Response_" + self.name self.response_field: Optional[Field] = Field( name=response_name, type_=self.response_model, class_validators=[], default=None, required=False, model_config=UnconstrainedConfig, schema=Schema(None), ) else: self.response_field = None self.status_code = status_code self.tags = tags or [] self.summary = summary self.description = description or self.endpoint.__doc__ self.response_description = response_description self.deprecated = deprecated if methods is None: methods = ["GET"] self.methods = methods self.operation_id = operation_id self.include_in_schema = include_in_schema self.content_type = content_type self.path_regex, self.path_format, self.param_convertors = self.compile_path( path) assert inspect.isfunction(endpoint) or inspect.ismethod( endpoint), f"An endpoint must be a function or method" self.dependant = get_dependant(path=path, call=self.endpoint) self.body_field = get_body_field(dependant=self.dependant, name=self.name) self.app = request_response( get_app( dependant=self.dependant, body_field=self.body_field, status_code=self.status_code, content_type=self.content_type, response_field=self.response_field, ))
def __init__( self, entrypoint: 'Entrypoint', path: str, func: Union[FunctionType, CoroutineType], *, result_model: Type[Any] = None, name: str = None, errors: Sequence[Type[BaseError]] = None, dependencies: Sequence[Depends] = None, response_class: Type[Response] = JSONResponse, **kwargs, ): name = name or func.__name__ result_model = result_model or func.__annotations__.get('return') _, path_format, _ = compile_path(path) func_dependant = get_dependant(path=path_format, call=func) insert_dependencies(func_dependant, dependencies) insert_dependencies(func_dependant, entrypoint.common_dependencies) fix_query_dependencies(func_dependant) flat_dependant = get_flat_dependant(func_dependant, skip_repeats=True) _Request = make_request_model(name, func.__module__, flat_dependant.body_params) @component_name(f'_Response[{name}]', func.__module__) class _Response(BaseModel): jsonrpc: StrictStr = Field('2.0', const=True, example='2.0') id: Union[StrictStr, int] = Field(None, example=0) result: result_model class Config: extra = 'forbid' # Only needed to generate OpenAPI async def endpoint(__request__: _Request): del __request__ endpoint.__name__ = func.__name__ endpoint.__doc__ = func.__doc__ responses = errors_responses(errors) super().__init__( path, endpoint, methods=['POST'], name=name, response_class=response_class, response_model=_Response, response_model_exclude_unset=True, responses=responses, **kwargs, ) # Add dependencies and other parameters from func_dependant for correct OpenAPI generation self.dependant.path_params = func_dependant.path_params self.dependant.header_params = func_dependant.header_params self.dependant.cookie_params = func_dependant.cookie_params self.dependant.dependencies = func_dependant.dependencies self.dependant.security_requirements = func_dependant.security_requirements self.func = func self.func_dependant = func_dependant self.entrypoint = entrypoint self.app = request_response(self.handle_http_request)
from pprint import pprint from fastapi.routing import Request from fastapi.dependencies.utils import get_dependant from fastapi.dependencies.utils import get_typed_signature def f(n: int, req: Request): pass print(get_dependant(path="/f", call=f)) pprint(vars(get_dependant(path="/f", call=f))) print(get_typed_signature(f)) # <fastapi.dependencies.models.Dependant object at 0x7f3e3f1ec410> # {'background_tasks_param_name': None, # 'body_params': [], # 'cache_key': (<function f at 0x7f3e3f1c58c0>, ()), # 'call': <function f at 0x7f3e3f1c58c0>, # 'cookie_params': [], # 'dependencies': [], # 'header_params': [], # 'name': None, # 'path': '/f', # 'path_params': [], # 'query_params': [], # 'request_param_name': None, # 'response_param_name': None, # 'security_requirements': [], # 'security_scopes': None, # 'security_scopes_param_name': None,