diff options
Diffstat (limited to 'venv/lib/python3.11/site-packages/litestar/handlers')
22 files changed, 0 insertions, 3305 deletions
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/__init__.py b/venv/lib/python3.11/site-packages/litestar/handlers/__init__.py deleted file mode 100644 index 822fe7e..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -from .asgi_handlers import ASGIRouteHandler, asgi -from .base import BaseRouteHandler -from .http_handlers import HTTPRouteHandler, delete, get, head, patch, post, put, route -from .websocket_handlers import ( - WebsocketListener, - WebsocketListenerRouteHandler, - WebsocketRouteHandler, - websocket, - websocket_listener, -) - -__all__ = ( - "ASGIRouteHandler", - "BaseRouteHandler", - "HTTPRouteHandler", - "WebsocketListener", - "WebsocketRouteHandler", - "WebsocketListenerRouteHandler", - "asgi", - "delete", - "get", - "head", - "patch", - "post", - "put", - "route", - "websocket", - "websocket_listener", -) diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/__init__.cpython-311.pyc Binary files differdeleted file mode 100644 index 6976d76..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/asgi_handlers.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/asgi_handlers.cpython-311.pyc Binary files differdeleted file mode 100644 index 85de8f8..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/asgi_handlers.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/base.cpython-311.pyc Binary files differdeleted file mode 100644 index 2331fc7..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/base.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/asgi_handlers.py b/venv/lib/python3.11/site-packages/litestar/handlers/asgi_handlers.py deleted file mode 100644 index 91f3517..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/asgi_handlers.py +++ /dev/null @@ -1,90 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Any, Mapping, Sequence - -from litestar.exceptions import ImproperlyConfiguredException -from litestar.handlers.base import BaseRouteHandler -from litestar.types.builtin_types import NoneType -from litestar.utils.predicates import is_async_callable - -__all__ = ("ASGIRouteHandler", "asgi") - - -if TYPE_CHECKING: - from litestar.types import ( - ExceptionHandlersMap, - Guard, - MaybePartial, # noqa: F401 - ) - - -class ASGIRouteHandler(BaseRouteHandler): - """ASGI Route Handler decorator. - - Use this decorator to decorate ASGI applications. - """ - - __slots__ = ("is_mount", "is_static") - - def __init__( - self, - path: str | Sequence[str] | None = None, - *, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - is_mount: bool = False, - is_static: bool = False, - signature_namespace: Mapping[str, Any] | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``ASGIRouteHandler``. - - Args: - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - name: A string identifying the route handler. - opt: A string key mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or - :class:`ASGI Scope <.types.Scope>`. - path: A path fragment for the route handler function or a list of path fragments. If not given defaults to - ``/`` - is_mount: A boolean dictating whether the handler's paths should be regarded as mount paths. Mount path - accept any arbitrary paths that begin with the defined prefixed path. For example, a mount with the path - ``/some-path/`` will accept requests for ``/some-path/`` and any sub path under this, e.g. - ``/some-path/sub-path/`` etc. - is_static: A boolean dictating whether the handler's paths should be regarded as static paths. Static paths - are used to deliver static files. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - self.is_mount = is_mount or is_static - self.is_static = is_static - super().__init__( - path, - exception_handlers=exception_handlers, - guards=guards, - name=name, - opt=opt, - signature_namespace=signature_namespace, - **kwargs, - ) - - def _validate_handler_function(self) -> None: - """Validate the route handler function once it's set by inspecting its return annotations.""" - super()._validate_handler_function() - - if not self.parsed_fn_signature.return_type.is_subclass_of(NoneType): - raise ImproperlyConfiguredException("ASGI handler functions should return 'None'") - - if any(key not in self.parsed_fn_signature.parameters for key in ("scope", "send", "receive")): - raise ImproperlyConfiguredException( - "ASGI handler functions should define 'scope', 'send' and 'receive' arguments" - ) - if not is_async_callable(self.fn): - raise ImproperlyConfiguredException("Functions decorated with 'asgi' must be async functions") - - -asgi = ASGIRouteHandler diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/base.py b/venv/lib/python3.11/site-packages/litestar/handlers/base.py deleted file mode 100644 index 9dbb70e..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/base.py +++ /dev/null @@ -1,577 +0,0 @@ -from __future__ import annotations - -from copy import copy -from functools import partial -from typing import TYPE_CHECKING, Any, Callable, Mapping, Sequence, cast - -from litestar._signature import SignatureModel -from litestar.config.app import ExperimentalFeatures -from litestar.di import Provide -from litestar.dto import DTOData -from litestar.exceptions import ImproperlyConfiguredException -from litestar.plugins import DIPlugin, PluginRegistry -from litestar.serialization import default_deserializer, default_serializer -from litestar.types import ( - Dependencies, - Empty, - ExceptionHandlersMap, - Guard, - Middleware, - TypeDecodersSequence, - TypeEncodersMap, -) -from litestar.typing import FieldDefinition -from litestar.utils import ensure_async_callable, get_name, normalize_path -from litestar.utils.helpers import unwrap_partial -from litestar.utils.signature import ParsedSignature, add_types_to_signature_namespace - -if TYPE_CHECKING: - from typing_extensions import Self - - from litestar.app import Litestar - from litestar.connection import ASGIConnection - from litestar.controller import Controller - from litestar.dto import AbstractDTO - from litestar.dto._backend import DTOBackend - from litestar.params import ParameterKwarg - from litestar.router import Router - from litestar.types import AnyCallable, AsyncAnyCallable, ExceptionHandler - from litestar.types.empty import EmptyType - -__all__ = ("BaseRouteHandler",) - - -class BaseRouteHandler: - """Base route handler. - - Serves as a subclass for all route handlers - """ - - __slots__ = ( - "_fn", - "_parsed_data_field", - "_parsed_fn_signature", - "_parsed_return_field", - "_resolved_data_dto", - "_resolved_dependencies", - "_resolved_guards", - "_resolved_layered_parameters", - "_resolved_return_dto", - "_resolved_signature_namespace", - "_resolved_type_decoders", - "_resolved_type_encoders", - "_signature_model", - "dependencies", - "dto", - "exception_handlers", - "guards", - "middleware", - "name", - "opt", - "owner", - "paths", - "return_dto", - "signature_namespace", - "type_decoders", - "type_encoders", - ) - - def __init__( - self, - path: str | Sequence[str] | None = None, - *, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - middleware: Sequence[Middleware] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - signature_types: Sequence[Any] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``HTTPRouteHandler``. - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. If not given defaults - to ``/`` - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or - :class:`ASGI Scope <.types.Scope>`. - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature - modelling. - signature_types: A sequence of types for use in forward reference resolution during signature modeling. - These types will be added to the signature namespace using their ``__name__`` attribute. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - self._parsed_fn_signature: ParsedSignature | EmptyType = Empty - self._parsed_return_field: FieldDefinition | EmptyType = Empty - self._parsed_data_field: FieldDefinition | None | EmptyType = Empty - self._resolved_data_dto: type[AbstractDTO] | None | EmptyType = Empty - self._resolved_dependencies: dict[str, Provide] | EmptyType = Empty - self._resolved_guards: list[Guard] | EmptyType = Empty - self._resolved_layered_parameters: dict[str, FieldDefinition] | EmptyType = Empty - self._resolved_return_dto: type[AbstractDTO] | None | EmptyType = Empty - self._resolved_signature_namespace: dict[str, Any] | EmptyType = Empty - self._resolved_type_decoders: TypeDecodersSequence | EmptyType = Empty - self._resolved_type_encoders: TypeEncodersMap | EmptyType = Empty - self._signature_model: type[SignatureModel] | EmptyType = Empty - - self.dependencies = dependencies - self.dto = dto - self.exception_handlers = exception_handlers - self.guards = guards - self.middleware = middleware - self.name = name - self.opt = dict(opt or {}) - self.opt.update(**kwargs) - self.owner: Controller | Router | None = None - self.return_dto = return_dto - self.signature_namespace = add_types_to_signature_namespace( - signature_types or [], dict(signature_namespace or {}) - ) - self.type_decoders = type_decoders - self.type_encoders = type_encoders - - self.paths = ( - {normalize_path(p) for p in path} if path and isinstance(path, list) else {normalize_path(path or "/")} # type: ignore[arg-type] - ) - - def __call__(self, fn: AsyncAnyCallable) -> Self: - """Replace a function with itself.""" - self._fn = fn - return self - - @property - def handler_id(self) -> str: - """A unique identifier used for generation of DTOs.""" - return f"{self!s}::{sum(id(layer) for layer in self.ownership_layers)}" - - @property - def default_deserializer(self) -> Callable[[Any, Any], Any]: - """Get a default deserializer for the route handler. - - Returns: - A default deserializer for the route handler. - - """ - return partial(default_deserializer, type_decoders=self.resolve_type_decoders()) - - @property - def default_serializer(self) -> Callable[[Any], Any]: - """Get a default serializer for the route handler. - - Returns: - A default serializer for the route handler. - - """ - return partial(default_serializer, type_encoders=self.resolve_type_encoders()) - - @property - def signature_model(self) -> type[SignatureModel]: - """Get the signature model for the route handler. - - Returns: - A signature model for the route handler. - - """ - if self._signature_model is Empty: - self._signature_model = SignatureModel.create( - dependency_name_set=self.dependency_name_set, - fn=cast("AnyCallable", self.fn), - parsed_signature=self.parsed_fn_signature, - data_dto=self.resolve_data_dto(), - type_decoders=self.resolve_type_decoders(), - ) - return self._signature_model - - @property - def fn(self) -> AsyncAnyCallable: - """Get the handler function. - - Raises: - ImproperlyConfiguredException: if handler fn is not set. - - Returns: - Handler function - """ - if not hasattr(self, "_fn"): - raise ImproperlyConfiguredException("No callable has been registered for this handler") - return self._fn - - @property - def parsed_fn_signature(self) -> ParsedSignature: - """Return the parsed signature of the handler function. - - This method is memoized so the computation occurs only once. - - Returns: - A ParsedSignature instance - """ - if self._parsed_fn_signature is Empty: - self._parsed_fn_signature = ParsedSignature.from_fn( - unwrap_partial(self.fn), self.resolve_signature_namespace() - ) - - return self._parsed_fn_signature - - @property - def parsed_return_field(self) -> FieldDefinition: - if self._parsed_return_field is Empty: - self._parsed_return_field = self.parsed_fn_signature.return_type - return self._parsed_return_field - - @property - def parsed_data_field(self) -> FieldDefinition | None: - if self._parsed_data_field is Empty: - self._parsed_data_field = self.parsed_fn_signature.parameters.get("data") - return self._parsed_data_field - - @property - def handler_name(self) -> str: - """Get the name of the handler function. - - Raises: - ImproperlyConfiguredException: if handler fn is not set. - - Returns: - Name of the handler function - """ - return get_name(unwrap_partial(self.fn)) - - @property - def dependency_name_set(self) -> set[str]: - """Set of all dependency names provided in the handler's ownership layers.""" - layered_dependencies = (layer.dependencies or {} for layer in self.ownership_layers) - return {name for layer in layered_dependencies for name in layer} # pyright: ignore - - @property - def ownership_layers(self) -> list[Self | Controller | Router]: - """Return the handler layers from the app down to the route handler. - - ``app -> ... -> route handler`` - """ - layers = [] - - cur: Any = self - while cur: - layers.append(cur) - cur = cur.owner - - return list(reversed(layers)) - - @property - def app(self) -> Litestar: - return cast("Litestar", self.ownership_layers[0]) - - def resolve_type_encoders(self) -> TypeEncodersMap: - """Return a merged type_encoders mapping. - - This method is memoized so the computation occurs only once. - - Returns: - A dict of type encoders - """ - if self._resolved_type_encoders is Empty: - self._resolved_type_encoders = {} - - for layer in self.ownership_layers: - if type_encoders := getattr(layer, "type_encoders", None): - self._resolved_type_encoders.update(type_encoders) - return cast("TypeEncodersMap", self._resolved_type_encoders) - - def resolve_type_decoders(self) -> TypeDecodersSequence: - """Return a merged type_encoders mapping. - - This method is memoized so the computation occurs only once. - - Returns: - A dict of type encoders - """ - if self._resolved_type_decoders is Empty: - self._resolved_type_decoders = [] - - for layer in self.ownership_layers: - if type_decoders := getattr(layer, "type_decoders", None): - self._resolved_type_decoders.extend(list(type_decoders)) - return cast("TypeDecodersSequence", self._resolved_type_decoders) - - def resolve_layered_parameters(self) -> dict[str, FieldDefinition]: - """Return all parameters declared above the handler.""" - if self._resolved_layered_parameters is Empty: - parameter_kwargs: dict[str, ParameterKwarg] = {} - - for layer in self.ownership_layers: - parameter_kwargs.update(getattr(layer, "parameters", {}) or {}) - - self._resolved_layered_parameters = { - key: FieldDefinition.from_kwarg(name=key, annotation=parameter.annotation, kwarg_definition=parameter) - for key, parameter in parameter_kwargs.items() - } - - return self._resolved_layered_parameters - - def resolve_guards(self) -> list[Guard]: - """Return all guards in the handlers scope, starting from highest to current layer.""" - if self._resolved_guards is Empty: - self._resolved_guards = [] - - for layer in self.ownership_layers: - self._resolved_guards.extend(layer.guards or []) # pyright: ignore - - self._resolved_guards = cast( - "list[Guard]", [ensure_async_callable(guard) for guard in self._resolved_guards] - ) - - return self._resolved_guards - - def _get_plugin_registry(self) -> PluginRegistry | None: - from litestar.app import Litestar - - root_owner = self.ownership_layers[0] - if isinstance(root_owner, Litestar): - return root_owner.plugins - return None - - def resolve_dependencies(self) -> dict[str, Provide]: - """Return all dependencies correlating to handler function's kwargs that exist in the handler's scope.""" - plugin_registry = self._get_plugin_registry() - if self._resolved_dependencies is Empty: - self._resolved_dependencies = {} - for layer in self.ownership_layers: - for key, provider in (layer.dependencies or {}).items(): - self._resolved_dependencies[key] = self._resolve_dependency( - key=key, provider=provider, plugin_registry=plugin_registry - ) - - return self._resolved_dependencies - - def _resolve_dependency( - self, key: str, provider: Provide | AnyCallable, plugin_registry: PluginRegistry | None - ) -> Provide: - if not isinstance(provider, Provide): - provider = Provide(provider) - - if self._resolved_dependencies is not Empty: # pragma: no cover - self._validate_dependency_is_unique(dependencies=self._resolved_dependencies, key=key, provider=provider) - - if not getattr(provider, "parsed_fn_signature", None): - dependency = unwrap_partial(provider.dependency) - plugin: DIPlugin | None = None - if plugin_registry: - plugin = next( - (p for p in plugin_registry.di if isinstance(p, DIPlugin) and p.has_typed_init(dependency)), - None, - ) - if plugin: - signature, init_type_hints = plugin.get_typed_init(dependency) - provider.parsed_fn_signature = ParsedSignature.from_signature(signature, init_type_hints) - else: - provider.parsed_fn_signature = ParsedSignature.from_fn(dependency, self.resolve_signature_namespace()) - - if not getattr(provider, "signature_model", None): - provider.signature_model = SignatureModel.create( - dependency_name_set=self.dependency_name_set, - fn=provider.dependency, - parsed_signature=provider.parsed_fn_signature, - data_dto=self.resolve_data_dto(), - type_decoders=self.resolve_type_decoders(), - ) - return provider - - def resolve_middleware(self) -> list[Middleware]: - """Build the middleware stack for the RouteHandler and return it. - - The middlewares are added from top to bottom (``app -> router -> controller -> route handler``) and then - reversed. - """ - resolved_middleware: list[Middleware] = [] - for layer in self.ownership_layers: - resolved_middleware.extend(layer.middleware or []) # pyright: ignore - return list(reversed(resolved_middleware)) - - def resolve_exception_handlers(self) -> ExceptionHandlersMap: - """Resolve the exception_handlers by starting from the route handler and moving up. - - This method is memoized so the computation occurs only once. - """ - resolved_exception_handlers: dict[int | type[Exception], ExceptionHandler] = {} - for layer in self.ownership_layers: - resolved_exception_handlers.update(layer.exception_handlers or {}) # pyright: ignore - return resolved_exception_handlers - - def resolve_opts(self) -> None: - """Build the route handler opt dictionary by going from top to bottom. - - When merging keys from multiple layers, if the same key is defined by multiple layers, the value from the - layer closest to the response handler will take precedence. - """ - - opt: dict[str, Any] = {} - for layer in self.ownership_layers: - opt.update(layer.opt or {}) # pyright: ignore - - self.opt = opt - - def resolve_signature_namespace(self) -> dict[str, Any]: - """Build the route handler signature namespace dictionary by going from top to bottom. - - When merging keys from multiple layers, if the same key is defined by multiple layers, the value from the - layer closest to the response handler will take precedence. - """ - if self._resolved_layered_parameters is Empty: - ns: dict[str, Any] = {} - for layer in self.ownership_layers: - ns.update(layer.signature_namespace) - - self._resolved_signature_namespace = ns - return cast("dict[str, Any]", self._resolved_signature_namespace) - - def _get_dto_backend_cls(self) -> type[DTOBackend] | None: - if ExperimentalFeatures.DTO_CODEGEN in self.app.experimental_features: - from litestar.dto._codegen_backend import DTOCodegenBackend - - return DTOCodegenBackend - return None - - def resolve_data_dto(self) -> type[AbstractDTO] | None: - """Resolve the data_dto by starting from the route handler and moving up. - If a handler is found it is returned, otherwise None is set. - This method is memoized so the computation occurs only once. - - Returns: - An optional :class:`DTO type <.dto.base_dto.AbstractDTO>` - """ - if self._resolved_data_dto is Empty: - if data_dtos := cast( - "list[type[AbstractDTO] | None]", - [layer.dto for layer in self.ownership_layers if layer.dto is not Empty], - ): - data_dto: type[AbstractDTO] | None = data_dtos[-1] - elif self.parsed_data_field and ( - plugins_for_data_type := [ - plugin - for plugin in self.app.plugins.serialization - if self.parsed_data_field.match_predicate_recursively(plugin.supports_type) - ] - ): - data_dto = plugins_for_data_type[0].create_dto_for_type(self.parsed_data_field) - else: - data_dto = None - - if self.parsed_data_field and data_dto: - data_dto.create_for_field_definition( - field_definition=self.parsed_data_field, - handler_id=self.handler_id, - backend_cls=self._get_dto_backend_cls(), - ) - - self._resolved_data_dto = data_dto - - return self._resolved_data_dto - - def resolve_return_dto(self) -> type[AbstractDTO] | None: - """Resolve the return_dto by starting from the route handler and moving up. - If a handler is found it is returned, otherwise None is set. - This method is memoized so the computation occurs only once. - - Returns: - An optional :class:`DTO type <.dto.base_dto.AbstractDTO>` - """ - if self._resolved_return_dto is Empty: - if return_dtos := cast( - "list[type[AbstractDTO] | None]", - [layer.return_dto for layer in self.ownership_layers if layer.return_dto is not Empty], - ): - return_dto: type[AbstractDTO] | None = return_dtos[-1] - elif plugins_for_return_type := [ - plugin - for plugin in self.app.plugins.serialization - if self.parsed_return_field.match_predicate_recursively(plugin.supports_type) - ]: - return_dto = plugins_for_return_type[0].create_dto_for_type(self.parsed_return_field) - else: - return_dto = self.resolve_data_dto() - - if return_dto and return_dto.is_supported_model_type_field(self.parsed_return_field): - return_dto.create_for_field_definition( - field_definition=self.parsed_return_field, - handler_id=self.handler_id, - backend_cls=self._get_dto_backend_cls(), - ) - self._resolved_return_dto = return_dto - else: - self._resolved_return_dto = None - - return self._resolved_return_dto - - async def authorize_connection(self, connection: ASGIConnection) -> None: - """Ensure the connection is authorized by running all the route guards in scope.""" - for guard in self.resolve_guards(): - await guard(connection, copy(self)) # type: ignore[misc] - - @staticmethod - def _validate_dependency_is_unique(dependencies: dict[str, Provide], key: str, provider: Provide) -> None: - """Validate that a given provider has not been already defined under a different key.""" - for dependency_key, value in dependencies.items(): - if provider == value: - raise ImproperlyConfiguredException( - f"Provider for key {key} is already defined under the different key {dependency_key}. " - f"If you wish to override a provider, it must have the same key." - ) - - def on_registration(self, app: Litestar) -> None: - """Called once per handler when the app object is instantiated. - - Args: - app: The :class:`Litestar<.app.Litestar>` app object. - - Returns: - None - """ - self._validate_handler_function() - self.resolve_dependencies() - self.resolve_guards() - self.resolve_middleware() - self.resolve_opts() - self.resolve_data_dto() - self.resolve_return_dto() - - def _validate_handler_function(self) -> None: - """Validate the route handler function once set by inspecting its return annotations.""" - if ( - self.parsed_data_field is not None - and self.parsed_data_field.is_subclass_of(DTOData) - and not self.resolve_data_dto() - ): - raise ImproperlyConfiguredException( - f"Handler function {self.handler_name} has a data parameter that is a subclass of DTOData but no " - "DTO has been registered for it." - ) - - def __str__(self) -> str: - """Return a unique identifier for the route handler. - - Returns: - A string - """ - target: type[AsyncAnyCallable] | AsyncAnyCallable # pyright: ignore - target = unwrap_partial(self.fn) - if not hasattr(target, "__qualname__"): - target = type(target) - return f"{target.__module__}.{target.__qualname__}" diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__init__.py b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__init__.py deleted file mode 100644 index 844f046..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import annotations - -from .base import HTTPRouteHandler, route -from .decorators import delete, get, head, patch, post, put - -__all__ = ( - "HTTPRouteHandler", - "delete", - "get", - "head", - "patch", - "post", - "put", - "route", -) diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/__init__.cpython-311.pyc Binary files differdeleted file mode 100644 index 848ac8f..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/_utils.cpython-311.pyc Binary files differdeleted file mode 100644 index 22a7f67..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/_utils.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/base.cpython-311.pyc Binary files differdeleted file mode 100644 index eb39166..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/base.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/decorators.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/decorators.cpython-311.pyc Binary files differdeleted file mode 100644 index 0acd7c8..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/decorators.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/_utils.py b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/_utils.py deleted file mode 100644 index ec95145..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/_utils.py +++ /dev/null @@ -1,221 +0,0 @@ -from __future__ import annotations - -from functools import lru_cache -from inspect import isawaitable -from typing import TYPE_CHECKING, Any, Sequence, cast - -from litestar.enums import HttpMethod -from litestar.exceptions import ValidationException -from litestar.response import Response -from litestar.status_codes import HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT -from litestar.types.builtin_types import NoneType - -if TYPE_CHECKING: - from litestar.app import Litestar - from litestar.background_tasks import BackgroundTask, BackgroundTasks - from litestar.connection import Request - from litestar.datastructures import Cookie, ResponseHeader - from litestar.types import AfterRequestHookHandler, ASGIApp, AsyncAnyCallable, Method, TypeEncodersMap - from litestar.typing import FieldDefinition - -__all__ = ( - "create_data_handler", - "create_generic_asgi_response_handler", - "create_response_handler", - "get_default_status_code", - "is_empty_response_annotation", - "normalize_headers", - "normalize_http_method", -) - - -def create_data_handler( - after_request: AfterRequestHookHandler | None, - background: BackgroundTask | BackgroundTasks | None, - cookies: frozenset[Cookie], - headers: frozenset[ResponseHeader], - media_type: str, - response_class: type[Response], - status_code: int, - type_encoders: TypeEncodersMap | None, -) -> AsyncAnyCallable: - """Create a handler function for arbitrary data. - - Args: - after_request: An after request handler. - background: A background task or background tasks. - cookies: A set of pre-defined cookies. - headers: A set of response headers. - media_type: The response media type. - response_class: The response class to use. - status_code: The response status code. - type_encoders: A mapping of types to encoder functions. - - Returns: - A handler function. - - """ - - async def handler( - data: Any, - request: Request[Any, Any, Any], - app: Litestar, - **kwargs: Any, - ) -> ASGIApp: - if isawaitable(data): - data = await data - - response = response_class( - background=background, - content=data, - media_type=media_type, - status_code=status_code, - type_encoders=type_encoders, - ) - - if after_request: - response = await after_request(response) # type: ignore[arg-type,misc] - - return response.to_asgi_response(app=None, request=request, headers=normalize_headers(headers), cookies=cookies) # pyright: ignore - - return handler - - -def create_generic_asgi_response_handler(after_request: AfterRequestHookHandler | None) -> AsyncAnyCallable: - """Create a handler function for Responses. - - Args: - after_request: An after request handler. - - Returns: - A handler function. - """ - - async def handler(data: ASGIApp, **kwargs: Any) -> ASGIApp: - return await after_request(data) if after_request else data # type: ignore[arg-type, misc, no-any-return] - - return handler - - -@lru_cache(1024) -def normalize_headers(headers: frozenset[ResponseHeader]) -> dict[str, str]: - """Given a dictionary of ResponseHeader, filter them and return a dictionary of values. - - Args: - headers: A dictionary of :class:`ResponseHeader <litestar.datastructures.ResponseHeader>` values - - Returns: - A string keyed dictionary of normalized values - """ - return { - header.name: cast("str", header.value) # we know value to be a string at this point because we validate it - # that it's not None when initializing a header with documentation_only=True - for header in headers - if not header.documentation_only - } - - -def create_response_handler( - after_request: AfterRequestHookHandler | None, - background: BackgroundTask | BackgroundTasks | None, - cookies: frozenset[Cookie], - headers: frozenset[ResponseHeader], - media_type: str, - status_code: int, - type_encoders: TypeEncodersMap | None, -) -> AsyncAnyCallable: - """Create a handler function for Litestar Responses. - - Args: - after_request: An after request handler. - background: A background task or background tasks. - cookies: A set of pre-defined cookies. - headers: A set of response headers. - media_type: The response media type. - status_code: The response status code. - type_encoders: A mapping of types to encoder functions. - - Returns: - A handler function. - """ - - normalized_headers = normalize_headers(headers) - cookie_list = list(cookies) - - async def handler( - data: Response, - app: Litestar, - request: Request, - **kwargs: Any, # kwargs is for return dto - ) -> ASGIApp: - response = await after_request(data) if after_request else data # type:ignore[arg-type,misc] - return response.to_asgi_response( # type: ignore[no-any-return] - app=None, - background=background, - cookies=cookie_list, - headers=normalized_headers, - media_type=media_type, - request=request, - status_code=status_code, - type_encoders=type_encoders, - ) - - return handler - - -def normalize_http_method(http_methods: HttpMethod | Method | Sequence[HttpMethod | Method]) -> set[Method]: - """Normalize HTTP method(s) into a set of upper-case method names. - - Args: - http_methods: A value for http method. - - Returns: - A normalized set of http methods. - """ - output: set[str] = set() - - if isinstance(http_methods, str): - http_methods = [http_methods] # pyright: ignore - - for method in http_methods: - method_name = method.value.upper() if isinstance(method, HttpMethod) else method.upper() - if method_name not in HTTP_METHOD_NAMES: - raise ValidationException(f"Invalid HTTP method: {method_name}") - output.add(method_name) - - return cast("set[Method]", output) - - -def get_default_status_code(http_methods: set[Method]) -> int: - """Return the default status code for a given set of HTTP methods. - - Args: - http_methods: A set of method strings - - Returns: - A status code - """ - if HttpMethod.POST in http_methods: - return HTTP_201_CREATED - if HttpMethod.DELETE in http_methods: - return HTTP_204_NO_CONTENT - return HTTP_200_OK - - -def is_empty_response_annotation(return_annotation: FieldDefinition) -> bool: - """Return whether the return annotation is an empty response. - - Args: - return_annotation: A return annotation. - - Returns: - Whether the return annotation is an empty response. - """ - return ( - return_annotation.is_subclass_of(NoneType) - or return_annotation.is_subclass_of(Response) - and return_annotation.has_inner_subclass_of(NoneType) - ) - - -HTTP_METHOD_NAMES = {m.value for m in HttpMethod} diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/base.py b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/base.py deleted file mode 100644 index 757253e..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/base.py +++ /dev/null @@ -1,591 +0,0 @@ -from __future__ import annotations - -from enum import Enum -from typing import TYPE_CHECKING, AnyStr, Mapping, Sequence, TypedDict, cast - -from litestar._layers.utils import narrow_response_cookies, narrow_response_headers -from litestar.connection import Request -from litestar.datastructures.cookie import Cookie -from litestar.datastructures.response_header import ResponseHeader -from litestar.enums import HttpMethod, MediaType -from litestar.exceptions import ( - HTTPException, - ImproperlyConfiguredException, -) -from litestar.handlers.base import BaseRouteHandler -from litestar.handlers.http_handlers._utils import ( - create_data_handler, - create_generic_asgi_response_handler, - create_response_handler, - get_default_status_code, - is_empty_response_annotation, - normalize_http_method, -) -from litestar.openapi.spec import Operation -from litestar.response import Response -from litestar.status_codes import HTTP_204_NO_CONTENT, HTTP_304_NOT_MODIFIED -from litestar.types import ( - AfterRequestHookHandler, - AfterResponseHookHandler, - AnyCallable, - ASGIApp, - BeforeRequestHookHandler, - CacheKeyBuilder, - Dependencies, - Empty, - EmptyType, - ExceptionHandlersMap, - Guard, - Method, - Middleware, - ResponseCookies, - ResponseHeaders, - TypeEncodersMap, -) -from litestar.utils import ensure_async_callable -from litestar.utils.predicates import is_async_callable -from litestar.utils.warnings import warn_implicit_sync_to_thread, warn_sync_to_thread_with_async_callable - -if TYPE_CHECKING: - from typing import Any, Awaitable, Callable - - from litestar.app import Litestar - from litestar.background_tasks import BackgroundTask, BackgroundTasks - from litestar.config.response_cache import CACHE_FOREVER - from litestar.datastructures import CacheControlHeader, ETag - from litestar.dto import AbstractDTO - from litestar.openapi.datastructures import ResponseSpec - from litestar.openapi.spec import SecurityRequirement - from litestar.types.callable_types import AsyncAnyCallable, OperationIDCreator - from litestar.types.composite_types import TypeDecodersSequence - -__all__ = ("HTTPRouteHandler", "route") - - -class ResponseHandlerMap(TypedDict): - default_handler: Callable[[Any], Awaitable[ASGIApp]] | EmptyType - response_type_handler: Callable[[Any], Awaitable[ASGIApp]] | EmptyType - - -class HTTPRouteHandler(BaseRouteHandler): - """HTTP Route Decorator. - - Use this decorator to decorate an HTTP handler with multiple methods. - """ - - __slots__ = ( - "_resolved_after_response", - "_resolved_before_request", - "_response_handler_mapping", - "_resolved_include_in_schema", - "_resolved_tags", - "_resolved_security", - "after_request", - "after_response", - "background", - "before_request", - "cache", - "cache_control", - "cache_key_builder", - "content_encoding", - "content_media_type", - "deprecated", - "description", - "etag", - "has_sync_callable", - "http_methods", - "include_in_schema", - "media_type", - "operation_class", - "operation_id", - "raises", - "request_class", - "response_class", - "response_cookies", - "response_description", - "response_headers", - "responses", - "security", - "status_code", - "summary", - "sync_to_thread", - "tags", - "template_name", - ) - - has_sync_callable: bool - - def __init__( - self, - path: str | Sequence[str] | None = None, - *, - after_request: AfterRequestHookHandler | None = None, - after_response: AfterResponseHookHandler | None = None, - background: BackgroundTask | BackgroundTasks | None = None, - before_request: BeforeRequestHookHandler | None = None, - cache: bool | int | type[CACHE_FOREVER] = False, - cache_control: CacheControlHeader | None = None, - cache_key_builder: CacheKeyBuilder | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - etag: ETag | None = None, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - http_method: HttpMethod | Method | Sequence[HttpMethod | Method], - media_type: MediaType | str | None = None, - middleware: Sequence[Middleware] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - request_class: type[Request] | None = None, - response_class: type[Response] | None = None, - response_cookies: ResponseCookies | None = None, - response_headers: ResponseHeaders | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - status_code: int | None = None, - sync_to_thread: bool | None = None, - # OpenAPI related attributes - content_encoding: str | None = None, - content_media_type: str | None = None, - deprecated: bool = False, - description: str | None = None, - include_in_schema: bool | EmptyType = Empty, - operation_class: type[Operation] = Operation, - operation_id: str | OperationIDCreator | None = None, - raises: Sequence[type[HTTPException]] | None = None, - response_description: str | None = None, - responses: Mapping[int, ResponseSpec] | None = None, - signature_namespace: Mapping[str, Any] | None = None, - security: Sequence[SecurityRequirement] | None = None, - summary: str | None = None, - tags: Sequence[str] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``HTTPRouteHandler``. - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. - If not given defaults to ``/`` - after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed - to any route handler. If this function returns a value, the request will not reach the route handler, - and instead this value will be used. - after_response: A sync or async function called after the response has been awaited. It receives the - :class:`Request <.connection.Request>` object and should not return any values. - background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or - :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished. - Defaults to ``None``. - before_request: A sync or async function called immediately before calling the route handler. Receives - the :class:`Request <.connection.Request>` instance and any non-``None`` return value is used for the - response, bypassing the route handler. - cache: Enables response caching if configured on the application level. Valid values are ``True`` or a - number of seconds (e.g. ``120``) to cache the response. - cache_control: A ``cache-control`` header of type - :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response. - cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization - of the cache key if caching is configured on the application level. - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - http_method: An :class:`http method string <.types.Method>`, a member of the enum - :class:`HttpMethod <.enums.HttpMethod>` or a list of these that correlates to the methods the route - handler function should handle. - media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a valid IANA - Media-Type. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or - :class:`ASGI Scope <.types.Scope>`. - request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's - default request. - response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's - default response. - response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances. - response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>` - instances. - responses: A mapping of additional status codes and a description of their expected content. - This information will be included in the OpenAPI schema - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and - ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``. - sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the - main event loop. This has an effect only for sync handler functions. See using sync handler functions. - content_encoding: A string describing the encoding of the content, e.g. ``"base64"``. - content_media_type: A string designating the media-type of the content, e.g. ``"image/png"``. - deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema. - description: Text used for the route's schema description section. - include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema. - operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema. - operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId. - raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation. - This list should describe all exceptions raised within the route handler's function/method. The Litestar - ValidationException will be added automatically for the schema if any validation is involved. - response_description: Text used for the route's response schema description section. - security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint. - summary: Text used for the route's schema summary section. - tags: A sequence of string tags that will be appended to the OpenAPI schema. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - if not http_method: - raise ImproperlyConfiguredException("An http_method kwarg is required") - - self.http_methods = normalize_http_method(http_methods=http_method) - self.status_code = status_code or get_default_status_code(http_methods=self.http_methods) - - super().__init__( - path=path, - dependencies=dependencies, - dto=dto, - exception_handlers=exception_handlers, - guards=guards, - middleware=middleware, - name=name, - opt=opt, - return_dto=return_dto, - signature_namespace=signature_namespace, - type_decoders=type_decoders, - type_encoders=type_encoders, - **kwargs, - ) - - self.after_request = ensure_async_callable(after_request) if after_request else None # pyright: ignore - self.after_response = ensure_async_callable(after_response) if after_response else None - self.background = background - self.before_request = ensure_async_callable(before_request) if before_request else None - self.cache = cache - self.cache_control = cache_control - self.cache_key_builder = cache_key_builder - self.etag = etag - self.media_type: MediaType | str = media_type or "" - self.request_class = request_class - self.response_class = response_class - self.response_cookies: Sequence[Cookie] | None = narrow_response_cookies(response_cookies) - self.response_headers: Sequence[ResponseHeader] | None = narrow_response_headers(response_headers) - - self.sync_to_thread = sync_to_thread - # OpenAPI related attributes - self.content_encoding = content_encoding - self.content_media_type = content_media_type - self.deprecated = deprecated - self.description = description - self.include_in_schema = include_in_schema - self.operation_class = operation_class - self.operation_id = operation_id - self.raises = raises - self.response_description = response_description - self.summary = summary - self.tags = tags - self.security = security - self.responses = responses - # memoized attributes, defaulted to Empty - self._resolved_after_response: AsyncAnyCallable | None | EmptyType = Empty - self._resolved_before_request: AsyncAnyCallable | None | EmptyType = Empty - self._response_handler_mapping: ResponseHandlerMap = {"default_handler": Empty, "response_type_handler": Empty} - self._resolved_include_in_schema: bool | EmptyType = Empty - self._resolved_security: list[SecurityRequirement] | EmptyType = Empty - self._resolved_tags: list[str] | EmptyType = Empty - - def __call__(self, fn: AnyCallable) -> HTTPRouteHandler: - """Replace a function with itself.""" - if not is_async_callable(fn): - if self.sync_to_thread is None: - warn_implicit_sync_to_thread(fn, stacklevel=3) - elif self.sync_to_thread is not None: - warn_sync_to_thread_with_async_callable(fn, stacklevel=3) - - super().__call__(fn) - return self - - def resolve_request_class(self) -> type[Request]: - """Return the closest custom Request class in the owner graph or the default Request class. - - This method is memoized so the computation occurs only once. - - Returns: - The default :class:`Request <.connection.Request>` class for the route handler. - """ - return next( - (layer.request_class for layer in reversed(self.ownership_layers) if layer.request_class is not None), - Request, - ) - - def resolve_response_class(self) -> type[Response]: - """Return the closest custom Response class in the owner graph or the default Response class. - - This method is memoized so the computation occurs only once. - - Returns: - The default :class:`Response <.response.Response>` class for the route handler. - """ - return next( - (layer.response_class for layer in reversed(self.ownership_layers) if layer.response_class is not None), - Response, - ) - - def resolve_response_headers(self) -> frozenset[ResponseHeader]: - """Return all header parameters in the scope of the handler function. - - Returns: - A dictionary mapping keys to :class:`ResponseHeader <.datastructures.ResponseHeader>` instances. - """ - resolved_response_headers: dict[str, ResponseHeader] = {} - - for layer in self.ownership_layers: - if layer_response_headers := layer.response_headers: - if isinstance(layer_response_headers, Mapping): - # this can't happen unless you manually set response_headers on an instance, which would result in a - # type-checking error on everything but the controller. We cover this case nevertheless - resolved_response_headers.update( - {name: ResponseHeader(name=name, value=value) for name, value in layer_response_headers.items()} - ) - else: - resolved_response_headers.update({h.name: h for h in layer_response_headers}) - for extra_header in ("cache_control", "etag"): - if header_model := getattr(layer, extra_header, None): - resolved_response_headers[header_model.HEADER_NAME] = ResponseHeader( - name=header_model.HEADER_NAME, - value=header_model.to_header(), - documentation_only=header_model.documentation_only, - ) - - return frozenset(resolved_response_headers.values()) - - def resolve_response_cookies(self) -> frozenset[Cookie]: - """Return a list of Cookie instances. Filters the list to ensure each cookie key is unique. - - Returns: - A list of :class:`Cookie <.datastructures.Cookie>` instances. - """ - response_cookies: set[Cookie] = set() - for layer in reversed(self.ownership_layers): - if layer_response_cookies := layer.response_cookies: - if isinstance(layer_response_cookies, Mapping): - # this can't happen unless you manually set response_cookies on an instance, which would result in a - # type-checking error on everything but the controller. We cover this case nevertheless - response_cookies.update( - {Cookie(key=key, value=value) for key, value in layer_response_cookies.items()} - ) - else: - response_cookies.update(cast("set[Cookie]", layer_response_cookies)) - return frozenset(response_cookies) - - def resolve_before_request(self) -> AsyncAnyCallable | None: - """Resolve the before_handler handler by starting from the route handler and moving up. - - If a handler is found it is returned, otherwise None is set. - This method is memoized so the computation occurs only once. - - Returns: - An optional :class:`before request lifecycle hook handler <.types.BeforeRequestHookHandler>` - """ - if self._resolved_before_request is Empty: - before_request_handlers = [layer.before_request for layer in self.ownership_layers if layer.before_request] - self._resolved_before_request = before_request_handlers[-1] if before_request_handlers else None - return cast("AsyncAnyCallable | None", self._resolved_before_request) - - def resolve_after_response(self) -> AsyncAnyCallable | None: - """Resolve the after_response handler by starting from the route handler and moving up. - - If a handler is found it is returned, otherwise None is set. - This method is memoized so the computation occurs only once. - - Returns: - An optional :class:`after response lifecycle hook handler <.types.AfterResponseHookHandler>` - """ - if self._resolved_after_response is Empty: - after_response_handlers: list[AsyncAnyCallable] = [ - layer.after_response # type: ignore[misc] - for layer in self.ownership_layers - if layer.after_response - ] - self._resolved_after_response = after_response_handlers[-1] if after_response_handlers else None - - return cast("AsyncAnyCallable | None", self._resolved_after_response) - - def resolve_include_in_schema(self) -> bool: - """Resolve the 'include_in_schema' property by starting from the route handler and moving up. - - If 'include_in_schema' is found in any of the ownership layers, the last value found is returned. - If not found in any layer, the default value ``True`` is returned. - - Returns: - bool: The resolved 'include_in_schema' property. - """ - if self._resolved_include_in_schema is Empty: - include_in_schemas = [ - i.include_in_schema for i in self.ownership_layers if isinstance(i.include_in_schema, bool) - ] - self._resolved_include_in_schema = include_in_schemas[-1] if include_in_schemas else True - - return self._resolved_include_in_schema - - def resolve_security(self) -> list[SecurityRequirement]: - """Resolve the security property by starting from the route handler and moving up. - - Security requirements are additive, so the security requirements of the route handler are the sum of all - security requirements of the ownership layers. - - Returns: - list[SecurityRequirement]: The resolved security property. - """ - if self._resolved_security is Empty: - self._resolved_security = [] - for layer in self.ownership_layers: - if isinstance(layer.security, Sequence): - self._resolved_security.extend(layer.security) - - return self._resolved_security - - def resolve_tags(self) -> list[str]: - """Resolve the tags property by starting from the route handler and moving up. - - Tags are additive, so the tags of the route handler are the sum of all tags of the ownership layers. - - Returns: - list[str]: A sorted list of unique tags. - """ - if self._resolved_tags is Empty: - tag_set = set() - for layer in self.ownership_layers: - for tag in layer.tags or []: - tag_set.add(tag) - self._resolved_tags = sorted(tag_set) - - return self._resolved_tags - - def get_response_handler(self, is_response_type_data: bool = False) -> Callable[[Any], Awaitable[ASGIApp]]: - """Resolve the response_handler function for the route handler. - - This method is memoized so the computation occurs only once. - - Args: - is_response_type_data: Whether to return a handler for 'Response' instances. - - Returns: - Async Callable to handle an HTTP Request - """ - if self._response_handler_mapping["default_handler"] is Empty: - after_request_handlers: list[AsyncAnyCallable] = [ - layer.after_request # type: ignore[misc] - for layer in self.ownership_layers - if layer.after_request - ] - after_request = cast( - "AfterRequestHookHandler | None", - after_request_handlers[-1] if after_request_handlers else None, - ) - - media_type = self.media_type.value if isinstance(self.media_type, Enum) else self.media_type - response_class = self.resolve_response_class() - headers = self.resolve_response_headers() - cookies = self.resolve_response_cookies() - type_encoders = self.resolve_type_encoders() - - return_type = self.parsed_fn_signature.return_type - return_annotation = return_type.annotation - - self._response_handler_mapping["response_type_handler"] = response_type_handler = create_response_handler( - after_request=after_request, - background=self.background, - cookies=cookies, - headers=headers, - media_type=media_type, - status_code=self.status_code, - type_encoders=type_encoders, - ) - - if return_type.is_subclass_of(Response): - self._response_handler_mapping["default_handler"] = response_type_handler - elif is_async_callable(return_annotation) or return_annotation is ASGIApp: - self._response_handler_mapping["default_handler"] = create_generic_asgi_response_handler( - after_request=after_request - ) - else: - self._response_handler_mapping["default_handler"] = create_data_handler( - after_request=after_request, - background=self.background, - cookies=cookies, - headers=headers, - media_type=media_type, - response_class=response_class, - status_code=self.status_code, - type_encoders=type_encoders, - ) - - return cast( - "Callable[[Any], Awaitable[ASGIApp]]", - self._response_handler_mapping["response_type_handler"] - if is_response_type_data - else self._response_handler_mapping["default_handler"], - ) - - async def to_response(self, app: Litestar, data: Any, request: Request) -> ASGIApp: - """Return a :class:`Response <.response.Response>` from the handler by resolving and calling it. - - Args: - app: The :class:`Litestar <litestar.app.Litestar>` app instance - data: Either an instance of a :class:`Response <.response.Response>`, - a Response instance or an arbitrary value. - request: A :class:`Request <.connection.Request>` instance - - Returns: - A Response instance - """ - if return_dto_type := self.resolve_return_dto(): - data = return_dto_type(request).data_to_encodable_type(data) - - response_handler = self.get_response_handler(is_response_type_data=isinstance(data, Response)) - return await response_handler(app=app, data=data, request=request) # type: ignore[call-arg] - - def on_registration(self, app: Litestar) -> None: - super().on_registration(app) - self.resolve_after_response() - self.resolve_include_in_schema() - self.has_sync_callable = not is_async_callable(self.fn) - - if self.has_sync_callable and self.sync_to_thread: - self._fn = ensure_async_callable(self.fn) - self.has_sync_callable = False - - def _validate_handler_function(self) -> None: - """Validate the route handler function once it is set by inspecting its return annotations.""" - super()._validate_handler_function() - - return_type = self.parsed_fn_signature.return_type - - if return_type.annotation is Empty: - raise ImproperlyConfiguredException( - "A return value of a route handler function should be type annotated. " - "If your function doesn't return a value, annotate it as returning 'None'." - ) - - if ( - self.status_code < 200 or self.status_code in {HTTP_204_NO_CONTENT, HTTP_304_NOT_MODIFIED} - ) and not is_empty_response_annotation(return_type): - raise ImproperlyConfiguredException( - "A status code 204, 304 or in the range below 200 does not support a response body. " - "If the function should return a value, change the route handler status code to an appropriate value.", - ) - - if not self.media_type: - if return_type.is_subclass_of((str, bytes)) or return_type.annotation is AnyStr: - self.media_type = MediaType.TEXT - elif not return_type.is_subclass_of(Response): - self.media_type = MediaType.JSON - - if "socket" in self.parsed_fn_signature.parameters: - raise ImproperlyConfiguredException("The 'socket' kwarg is not supported with http handlers") - - if "data" in self.parsed_fn_signature.parameters and "GET" in self.http_methods: - raise ImproperlyConfiguredException("'data' kwarg is unsupported for 'GET' request handlers") - - -route = HTTPRouteHandler diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/decorators.py b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/decorators.py deleted file mode 100644 index 1ae72e5..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/decorators.py +++ /dev/null @@ -1,1096 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -from litestar.enums import HttpMethod, MediaType -from litestar.exceptions import HTTPException, ImproperlyConfiguredException -from litestar.openapi.spec import Operation -from litestar.response.file import ASGIFileResponse, File -from litestar.types import Empty, TypeDecodersSequence -from litestar.types.builtin_types import NoneType -from litestar.utils import is_class_and_subclass - -from .base import HTTPRouteHandler - -if TYPE_CHECKING: - from typing import Any, Mapping, Sequence - - from litestar.background_tasks import BackgroundTask, BackgroundTasks - from litestar.config.response_cache import CACHE_FOREVER - from litestar.connection import Request - from litestar.datastructures import CacheControlHeader, ETag - from litestar.dto import AbstractDTO - from litestar.openapi.datastructures import ResponseSpec - from litestar.openapi.spec import SecurityRequirement - from litestar.response import Response - from litestar.types import ( - AfterRequestHookHandler, - AfterResponseHookHandler, - BeforeRequestHookHandler, - CacheKeyBuilder, - Dependencies, - EmptyType, - ExceptionHandlersMap, - Guard, - Middleware, - ResponseCookies, - ResponseHeaders, - TypeEncodersMap, - ) - from litestar.types.callable_types import OperationIDCreator - - -__all__ = ("get", "head", "post", "put", "patch", "delete") - -MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP = "semantic route handlers cannot define http_method" - - -class delete(HTTPRouteHandler): - """DELETE Route Decorator. - - Use this decorator to decorate an HTTP handler for DELETE requests. - """ - - def __init__( - self, - path: str | None | Sequence[str] = None, - *, - after_request: AfterRequestHookHandler | None = None, - after_response: AfterResponseHookHandler | None = None, - background: BackgroundTask | BackgroundTasks | None = None, - before_request: BeforeRequestHookHandler | None = None, - cache: bool | int | type[CACHE_FOREVER] = False, - cache_control: CacheControlHeader | None = None, - cache_key_builder: CacheKeyBuilder | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - etag: ETag | None = None, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - media_type: MediaType | str | None = None, - middleware: Sequence[Middleware] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - request_class: type[Request] | None = None, - response_class: type[Response] | None = None, - response_cookies: ResponseCookies | None = None, - response_headers: ResponseHeaders | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - status_code: int | None = None, - sync_to_thread: bool | None = None, - # OpenAPI related attributes - content_encoding: str | None = None, - content_media_type: str | None = None, - deprecated: bool = False, - description: str | None = None, - include_in_schema: bool | EmptyType = Empty, - operation_class: type[Operation] = Operation, - operation_id: str | OperationIDCreator | None = None, - raises: Sequence[type[HTTPException]] | None = None, - response_description: str | None = None, - responses: Mapping[int, ResponseSpec] | None = None, - security: Sequence[SecurityRequirement] | None = None, - summary: str | None = None, - tags: Sequence[str] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``delete`` - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. - If not given defaults to ``/`` - after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed - to any route handler. If this function returns a value, the request will not reach the route handler, - and instead this value will be used. - after_response: A sync or async function called after the response has been awaited. It receives the - :class:`Request <.connection.Request>` object and should not return any values. - background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or - :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished. - Defaults to ``None``. - before_request: A sync or async function called immediately before calling the route handler. Receives - the :class:`.connection.Request` instance and any non-``None`` return value is used for the response, - bypassing the route handler. - cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number - of seconds (e.g. ``120``) to cache the response. - cache_control: A ``cache-control`` header of type - :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response. - cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization - of the cache key if caching is configured on the application level. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - http_method: An :class:`http method string <.types.Method>`, a member of the enum - :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the - route handler function should handle. - media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a - valid IANA Media-Type. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`. - request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's - default request. - response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's - default response. - response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances. - response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>` - instances. - responses: A mapping of additional status codes and a description of their expected content. - This information will be included in the OpenAPI schema - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` - and ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``. - sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the - main event loop. This has an effect only for sync handler functions. See using sync handler functions. - content_encoding: A string describing the encoding of the content, e.g. ``base64``. - content_media_type: A string designating the media-type of the content, e.g. ``image/png``. - deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema. - description: Text used for the route's schema description section. - include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema. - operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema. - operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId. - raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation. - This list should describe all exceptions raised within the route handler's function/method. The Litestar - ValidationException will be added automatically for the schema if any validation is involved. - response_description: Text used for the route's response schema description section. - security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint. - summary: Text used for the route's schema summary section. - tags: A sequence of string tags that will be appended to the OpenAPI schema. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec - hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - if "http_method" in kwargs: - raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP) - super().__init__( - after_request=after_request, - after_response=after_response, - background=background, - before_request=before_request, - cache=cache, - cache_control=cache_control, - cache_key_builder=cache_key_builder, - content_encoding=content_encoding, - content_media_type=content_media_type, - dependencies=dependencies, - deprecated=deprecated, - description=description, - dto=dto, - etag=etag, - exception_handlers=exception_handlers, - guards=guards, - http_method=HttpMethod.DELETE, - include_in_schema=include_in_schema, - media_type=media_type, - middleware=middleware, - name=name, - operation_class=operation_class, - operation_id=operation_id, - opt=opt, - path=path, - raises=raises, - request_class=request_class, - response_class=response_class, - response_cookies=response_cookies, - response_description=response_description, - response_headers=response_headers, - responses=responses, - return_dto=return_dto, - security=security, - signature_namespace=signature_namespace, - status_code=status_code, - summary=summary, - sync_to_thread=sync_to_thread, - tags=tags, - type_decoders=type_decoders, - type_encoders=type_encoders, - **kwargs, - ) - - -class get(HTTPRouteHandler): - """GET Route Decorator. - - Use this decorator to decorate an HTTP handler for GET requests. - """ - - def __init__( - self, - path: str | None | Sequence[str] = None, - *, - after_request: AfterRequestHookHandler | None = None, - after_response: AfterResponseHookHandler | None = None, - background: BackgroundTask | BackgroundTasks | None = None, - before_request: BeforeRequestHookHandler | None = None, - cache: bool | int | type[CACHE_FOREVER] = False, - cache_control: CacheControlHeader | None = None, - cache_key_builder: CacheKeyBuilder | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - etag: ETag | None = None, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - media_type: MediaType | str | None = None, - middleware: Sequence[Middleware] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - request_class: type[Request] | None = None, - response_class: type[Response] | None = None, - response_cookies: ResponseCookies | None = None, - response_headers: ResponseHeaders | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - status_code: int | None = None, - sync_to_thread: bool | None = None, - # OpenAPI related attributes - content_encoding: str | None = None, - content_media_type: str | None = None, - deprecated: bool = False, - description: str | None = None, - include_in_schema: bool | EmptyType = Empty, - operation_class: type[Operation] = Operation, - operation_id: str | OperationIDCreator | None = None, - raises: Sequence[type[HTTPException]] | None = None, - response_description: str | None = None, - responses: Mapping[int, ResponseSpec] | None = None, - security: Sequence[SecurityRequirement] | None = None, - summary: str | None = None, - tags: Sequence[str] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``get``. - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. - If not given defaults to ``/`` - after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed - to any route handler. If this function returns a value, the request will not reach the route handler, - and instead this value will be used. - after_response: A sync or async function called after the response has been awaited. It receives the - :class:`Request <.connection.Request>` object and should not return any values. - background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or - :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished. - Defaults to ``None``. - before_request: A sync or async function called immediately before calling the route handler. Receives - the :class:`.connection.Request` instance and any non-``None`` return value is used for the response, - bypassing the route handler. - cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number - of seconds (e.g. ``120``) to cache the response. - cache_control: A ``cache-control`` header of type - :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response. - cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization - of the cache key if caching is configured on the application level. - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - http_method: An :class:`http method string <.types.Method>`, a member of the enum - :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the - route handler function should handle. - media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a - valid IANA Media-Type. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`. - request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's - default request. - response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's - default response. - response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances. - response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>` - instances. - responses: A mapping of additional status codes and a description of their expected content. - This information will be included in the OpenAPI schema - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and - ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``. - sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the - main event loop. This has an effect only for sync handler functions. See using sync handler functions. - content_encoding: A string describing the encoding of the content, e.g. ``base64``. - content_media_type: A string designating the media-type of the content, e.g. ``image/png``. - deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema. - description: Text used for the route's schema description section. - include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema. - operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema. - operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId. - raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation. - This list should describe all exceptions raised within the route handler's function/method. The Litestar - ValidationException will be added automatically for the schema if any validation is involved. - response_description: Text used for the route's response schema description section. - security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint. - summary: Text used for the route's schema summary section. - tags: A sequence of string tags that will be appended to the OpenAPI schema. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec - hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - if "http_method" in kwargs: - raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP) - - super().__init__( - after_request=after_request, - after_response=after_response, - background=background, - before_request=before_request, - cache=cache, - cache_control=cache_control, - cache_key_builder=cache_key_builder, - content_encoding=content_encoding, - content_media_type=content_media_type, - dependencies=dependencies, - deprecated=deprecated, - description=description, - dto=dto, - etag=etag, - exception_handlers=exception_handlers, - guards=guards, - http_method=HttpMethod.GET, - include_in_schema=include_in_schema, - media_type=media_type, - middleware=middleware, - name=name, - operation_class=operation_class, - operation_id=operation_id, - opt=opt, - path=path, - raises=raises, - request_class=request_class, - response_class=response_class, - response_cookies=response_cookies, - response_description=response_description, - response_headers=response_headers, - responses=responses, - return_dto=return_dto, - security=security, - signature_namespace=signature_namespace, - status_code=status_code, - summary=summary, - sync_to_thread=sync_to_thread, - tags=tags, - type_decoders=type_decoders, - type_encoders=type_encoders, - **kwargs, - ) - - -class head(HTTPRouteHandler): - """HEAD Route Decorator. - - Use this decorator to decorate an HTTP handler for HEAD requests. - """ - - def __init__( - self, - path: str | None | Sequence[str] = None, - *, - after_request: AfterRequestHookHandler | None = None, - after_response: AfterResponseHookHandler | None = None, - background: BackgroundTask | BackgroundTasks | None = None, - before_request: BeforeRequestHookHandler | None = None, - cache: bool | int | type[CACHE_FOREVER] = False, - cache_control: CacheControlHeader | None = None, - cache_key_builder: CacheKeyBuilder | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - etag: ETag | None = None, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - media_type: MediaType | str | None = None, - middleware: Sequence[Middleware] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - request_class: type[Request] | None = None, - response_class: type[Response] | None = None, - response_cookies: ResponseCookies | None = None, - response_headers: ResponseHeaders | None = None, - signature_namespace: Mapping[str, Any] | None = None, - status_code: int | None = None, - sync_to_thread: bool | None = None, - # OpenAPI related attributes - content_encoding: str | None = None, - content_media_type: str | None = None, - deprecated: bool = False, - description: str | None = None, - include_in_schema: bool | EmptyType = Empty, - operation_class: type[Operation] = Operation, - operation_id: str | OperationIDCreator | None = None, - raises: Sequence[type[HTTPException]] | None = None, - response_description: str | None = None, - responses: Mapping[int, ResponseSpec] | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - security: Sequence[SecurityRequirement] | None = None, - summary: str | None = None, - tags: Sequence[str] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``head``. - - Notes: - - A response to a head request cannot include a body. - See: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD). - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. - If not given defaults to ``/`` - after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed - to any route handler. If this function returns a value, the request will not reach the route handler, - and instead this value will be used. - after_response: A sync or async function called after the response has been awaited. It receives the - :class:`Request <.connection.Request>` object and should not return any values. - background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or - :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished. - Defaults to ``None``. - before_request: A sync or async function called immediately before calling the route handler. Receives - the :class:`.connection.Request` instance and any non-``None`` return value is used for the response, - bypassing the route handler. - cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number - of seconds (e.g. ``120``) to cache the response. - cache_control: A ``cache-control`` header of type - :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response. - cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization - of the cache key if caching is configured on the application level. - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - http_method: An :class:`http method string <.types.Method>`, a member of the enum - :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the - route handler function should handle. - media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a - valid IANA Media-Type. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`. - request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's - default request. - response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's - default response. - response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances. - response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>` - instances. - responses: A mapping of additional status codes and a description of their expected content. - This information will be included in the OpenAPI schema - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and - ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``. - sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the - main event loop. This has an effect only for sync handler functions. See using sync handler functions. - content_encoding: A string describing the encoding of the content, e.g. ``base64``. - content_media_type: A string designating the media-type of the content, e.g. ``image/png``. - deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema. - description: Text used for the route's schema description section. - include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema. - operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema. - operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId. - raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation. - This list should describe all exceptions raised within the route handler's function/method. The Litestar - ValidationException will be added automatically for the schema if any validation is involved. - response_description: Text used for the route's response schema description section. - security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint. - summary: Text used for the route's schema summary section. - tags: A sequence of string tags that will be appended to the OpenAPI schema. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec - hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - if "http_method" in kwargs: - raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP) - - super().__init__( - after_request=after_request, - after_response=after_response, - background=background, - before_request=before_request, - cache=cache, - cache_control=cache_control, - cache_key_builder=cache_key_builder, - content_encoding=content_encoding, - content_media_type=content_media_type, - dependencies=dependencies, - deprecated=deprecated, - description=description, - dto=dto, - etag=etag, - exception_handlers=exception_handlers, - guards=guards, - http_method=HttpMethod.HEAD, - include_in_schema=include_in_schema, - media_type=media_type, - middleware=middleware, - name=name, - operation_class=operation_class, - operation_id=operation_id, - opt=opt, - path=path, - raises=raises, - request_class=request_class, - response_class=response_class, - response_cookies=response_cookies, - response_description=response_description, - response_headers=response_headers, - responses=responses, - return_dto=return_dto, - security=security, - signature_namespace=signature_namespace, - status_code=status_code, - summary=summary, - sync_to_thread=sync_to_thread, - tags=tags, - type_decoders=type_decoders, - type_encoders=type_encoders, - **kwargs, - ) - - def _validate_handler_function(self) -> None: - """Validate the route handler function once it is set by inspecting its return annotations.""" - super()._validate_handler_function() - - # we allow here File and File because these have special setting for head responses - return_annotation = self.parsed_fn_signature.return_type.annotation - if not ( - return_annotation in {NoneType, None} - or is_class_and_subclass(return_annotation, File) - or is_class_and_subclass(return_annotation, ASGIFileResponse) - ): - raise ImproperlyConfiguredException("A response to a head request should not have a body") - - -class patch(HTTPRouteHandler): - """PATCH Route Decorator. - - Use this decorator to decorate an HTTP handler for PATCH requests. - """ - - def __init__( - self, - path: str | None | Sequence[str] = None, - *, - after_request: AfterRequestHookHandler | None = None, - after_response: AfterResponseHookHandler | None = None, - background: BackgroundTask | BackgroundTasks | None = None, - before_request: BeforeRequestHookHandler | None = None, - cache: bool | int | type[CACHE_FOREVER] = False, - cache_control: CacheControlHeader | None = None, - cache_key_builder: CacheKeyBuilder | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - etag: ETag | None = None, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - media_type: MediaType | str | None = None, - middleware: Sequence[Middleware] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - request_class: type[Request] | None = None, - response_class: type[Response] | None = None, - response_cookies: ResponseCookies | None = None, - response_headers: ResponseHeaders | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - status_code: int | None = None, - sync_to_thread: bool | None = None, - # OpenAPI related attributes - content_encoding: str | None = None, - content_media_type: str | None = None, - deprecated: bool = False, - description: str | None = None, - include_in_schema: bool | EmptyType = Empty, - operation_class: type[Operation] = Operation, - operation_id: str | OperationIDCreator | None = None, - raises: Sequence[type[HTTPException]] | None = None, - response_description: str | None = None, - responses: Mapping[int, ResponseSpec] | None = None, - security: Sequence[SecurityRequirement] | None = None, - summary: str | None = None, - tags: Sequence[str] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``patch``. - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. - If not given defaults to ``/`` - after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed - to any route handler. If this function returns a value, the request will not reach the route handler, - and instead this value will be used. - after_response: A sync or async function called after the response has been awaited. It receives the - :class:`Request <.connection.Request>` object and should not return any values. - background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or - :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished. - Defaults to ``None``. - before_request: A sync or async function called immediately before calling the route handler. Receives - the :class:`.connection.Request` instance and any non-``None`` return value is used for the response, - bypassing the route handler. - cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number - of seconds (e.g. ``120``) to cache the response. - cache_control: A ``cache-control`` header of type - :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response. - cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization - of the cache key if caching is configured on the application level. - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - http_method: An :class:`http method string <.types.Method>`, a member of the enum - :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the - route handler function should handle. - media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a - valid IANA Media-Type. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`. - request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's - default request. - response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's - default response. - response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances. - response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>` - instances. - responses: A mapping of additional status codes and a description of their expected content. - This information will be included in the OpenAPI schema - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and - ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``. - sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the - main event loop. This has an effect only for sync handler functions. See using sync handler functions. - content_encoding: A string describing the encoding of the content, e.g. ``base64``. - content_media_type: A string designating the media-type of the content, e.g. ``image/png``. - deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema. - description: Text used for the route's schema description section. - include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema. - operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema. - operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId. - raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation. - This list should describe all exceptions raised within the route handler's function/method. The Litestar - ValidationException will be added automatically for the schema if any validation is involved. - response_description: Text used for the route's response schema description section. - security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint. - summary: Text used for the route's schema summary section. - tags: A sequence of string tags that will be appended to the OpenAPI schema. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec - hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - if "http_method" in kwargs: - raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP) - super().__init__( - after_request=after_request, - after_response=after_response, - background=background, - before_request=before_request, - cache=cache, - cache_control=cache_control, - cache_key_builder=cache_key_builder, - content_encoding=content_encoding, - content_media_type=content_media_type, - dependencies=dependencies, - deprecated=deprecated, - description=description, - dto=dto, - etag=etag, - exception_handlers=exception_handlers, - guards=guards, - http_method=HttpMethod.PATCH, - include_in_schema=include_in_schema, - media_type=media_type, - middleware=middleware, - name=name, - operation_class=operation_class, - operation_id=operation_id, - opt=opt, - path=path, - raises=raises, - request_class=request_class, - response_class=response_class, - response_cookies=response_cookies, - response_description=response_description, - response_headers=response_headers, - responses=responses, - return_dto=return_dto, - security=security, - signature_namespace=signature_namespace, - status_code=status_code, - summary=summary, - sync_to_thread=sync_to_thread, - tags=tags, - type_decoders=type_decoders, - type_encoders=type_encoders, - **kwargs, - ) - - -class post(HTTPRouteHandler): - """POST Route Decorator. - - Use this decorator to decorate an HTTP handler for POST requests. - """ - - def __init__( - self, - path: str | None | Sequence[str] = None, - *, - after_request: AfterRequestHookHandler | None = None, - after_response: AfterResponseHookHandler | None = None, - background: BackgroundTask | BackgroundTasks | None = None, - before_request: BeforeRequestHookHandler | None = None, - cache: bool | int | type[CACHE_FOREVER] = False, - cache_control: CacheControlHeader | None = None, - cache_key_builder: CacheKeyBuilder | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - etag: ETag | None = None, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - media_type: MediaType | str | None = None, - middleware: Sequence[Middleware] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - request_class: type[Request] | None = None, - response_class: type[Response] | None = None, - response_cookies: ResponseCookies | None = None, - response_headers: ResponseHeaders | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - status_code: int | None = None, - sync_to_thread: bool | None = None, - # OpenAPI related attributes - content_encoding: str | None = None, - content_media_type: str | None = None, - deprecated: bool = False, - description: str | None = None, - include_in_schema: bool | EmptyType = Empty, - operation_class: type[Operation] = Operation, - operation_id: str | OperationIDCreator | None = None, - raises: Sequence[type[HTTPException]] | None = None, - response_description: str | None = None, - responses: Mapping[int, ResponseSpec] | None = None, - security: Sequence[SecurityRequirement] | None = None, - summary: str | None = None, - tags: Sequence[str] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``post`` - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. - If not given defaults to ``/`` - after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed - to any route handler. If this function returns a value, the request will not reach the route handler, - and instead this value will be used. - after_response: A sync or async function called after the response has been awaited. It receives the - :class:`Request <.connection.Request>` object and should not return any values. - background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or - :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished. - Defaults to ``None``. - before_request: A sync or async function called immediately before calling the route handler. Receives - the :class:`.connection.Request` instance and any non-``None`` return value is used for the response, - bypassing the route handler. - cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number - of seconds (e.g. ``120``) to cache the response. - cache_control: A ``cache-control`` header of type - :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response. - cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization - of the cache key if caching is configured on the application level. - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - http_method: An :class:`http method string <.types.Method>`, a member of the enum - :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the - route handler function should handle. - media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a - valid IANA Media-Type. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`. - request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's - default request. - response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's - default response. - response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances. - response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>` - instances. - responses: A mapping of additional status codes and a description of their expected content. - This information will be included in the OpenAPI schema - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and - ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``. - sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the - main event loop. This has an effect only for sync handler functions. See using sync handler functions. - content_encoding: A string describing the encoding of the content, e.g. ``base64``. - content_media_type: A string designating the media-type of the content, e.g. ``image/png``. - deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema. - description: Text used for the route's schema description section. - include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema. - operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema. - operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId. - raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation. - This list should describe all exceptions raised within the route handler's function/method. The Litestar - ValidationException will be added automatically for the schema if any validation is involved. - response_description: Text used for the route's response schema description section. - security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint. - summary: Text used for the route's schema summary section. - tags: A sequence of string tags that will be appended to the OpenAPI schema. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec - hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - if "http_method" in kwargs: - raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP) - super().__init__( - after_request=after_request, - after_response=after_response, - background=background, - before_request=before_request, - cache=cache, - cache_control=cache_control, - cache_key_builder=cache_key_builder, - content_encoding=content_encoding, - content_media_type=content_media_type, - dependencies=dependencies, - deprecated=deprecated, - description=description, - dto=dto, - exception_handlers=exception_handlers, - etag=etag, - guards=guards, - http_method=HttpMethod.POST, - include_in_schema=include_in_schema, - media_type=media_type, - middleware=middleware, - name=name, - operation_class=operation_class, - operation_id=operation_id, - opt=opt, - path=path, - raises=raises, - request_class=request_class, - response_class=response_class, - response_cookies=response_cookies, - response_description=response_description, - response_headers=response_headers, - responses=responses, - return_dto=return_dto, - signature_namespace=signature_namespace, - security=security, - status_code=status_code, - summary=summary, - sync_to_thread=sync_to_thread, - tags=tags, - type_decoders=type_decoders, - type_encoders=type_encoders, - **kwargs, - ) - - -class put(HTTPRouteHandler): - """PUT Route Decorator. - - Use this decorator to decorate an HTTP handler for PUT requests. - """ - - def __init__( - self, - path: str | None | Sequence[str] = None, - *, - after_request: AfterRequestHookHandler | None = None, - after_response: AfterResponseHookHandler | None = None, - background: BackgroundTask | BackgroundTasks | None = None, - before_request: BeforeRequestHookHandler | None = None, - cache: bool | int | type[CACHE_FOREVER] = False, - cache_control: CacheControlHeader | None = None, - cache_key_builder: CacheKeyBuilder | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - etag: ETag | None = None, - exception_handlers: ExceptionHandlersMap | None = None, - guards: Sequence[Guard] | None = None, - media_type: MediaType | str | None = None, - middleware: Sequence[Middleware] | None = None, - name: str | None = None, - opt: Mapping[str, Any] | None = None, - request_class: type[Request] | None = None, - response_class: type[Response] | None = None, - response_cookies: ResponseCookies | None = None, - response_headers: ResponseHeaders | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - status_code: int | None = None, - sync_to_thread: bool | None = None, - # OpenAPI related attributes - content_encoding: str | None = None, - content_media_type: str | None = None, - deprecated: bool = False, - description: str | None = None, - include_in_schema: bool | EmptyType = Empty, - operation_class: type[Operation] = Operation, - operation_id: str | OperationIDCreator | None = None, - raises: Sequence[type[HTTPException]] | None = None, - response_description: str | None = None, - responses: Mapping[int, ResponseSpec] | None = None, - security: Sequence[SecurityRequirement] | None = None, - summary: str | None = None, - tags: Sequence[str] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``put`` - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. - If not given defaults to ``/`` - after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed - to any route handler. If this function returns a value, the request will not reach the route handler, - and instead this value will be used. - after_response: A sync or async function called after the response has been awaited. It receives the - :class:`Request <.connection.Request>` object and should not return any values. - background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or - :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished. - Defaults to ``None``. - before_request: A sync or async function called immediately before calling the route handler. Receives - the :class:`.connection.Request` instance and any non-``None`` return value is used for the response, - bypassing the route handler. - cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number - of seconds (e.g. ``120``) to cache the response. - cache_control: A ``cache-control`` header of type - :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response. - cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization - of the cache key if caching is configured on the application level. - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - http_method: An :class:`http method string <.types.Method>`, a member of the enum - :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the - route handler function should handle. - media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a - valid IANA Media-Type. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`. - request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's - default request. - response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's - default response. - response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances. - response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>` - instances. - responses: A mapping of additional status codes and a description of their expected content. - This information will be included in the OpenAPI schema - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and - ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``. - sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the - main event loop. This has an effect only for sync handler functions. See using sync handler functions. - content_encoding: A string describing the encoding of the content, e.g. ``base64``. - content_media_type: A string designating the media-type of the content, e.g. ``image/png``. - deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema. - description: Text used for the route's schema description section. - include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema. - operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema. - operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId. - raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation. - This list should describe all exceptions raised within the route handler's function/method. The Litestar - ValidationException will be added automatically for the schema if any validation is involved. - response_description: Text used for the route's response schema description section. - security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint. - summary: Text used for the route's schema summary section. - tags: A sequence of string tags that will be appended to the OpenAPI schema. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec - hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - """ - if "http_method" in kwargs: - raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP) - super().__init__( - after_request=after_request, - after_response=after_response, - background=background, - before_request=before_request, - cache=cache, - cache_control=cache_control, - cache_key_builder=cache_key_builder, - content_encoding=content_encoding, - content_media_type=content_media_type, - dependencies=dependencies, - deprecated=deprecated, - description=description, - dto=dto, - exception_handlers=exception_handlers, - etag=etag, - guards=guards, - http_method=HttpMethod.PUT, - include_in_schema=include_in_schema, - media_type=media_type, - middleware=middleware, - name=name, - operation_class=operation_class, - operation_id=operation_id, - opt=opt, - path=path, - raises=raises, - request_class=request_class, - response_class=response_class, - response_cookies=response_cookies, - response_description=response_description, - response_headers=response_headers, - responses=responses, - return_dto=return_dto, - security=security, - signature_namespace=signature_namespace, - status_code=status_code, - summary=summary, - sync_to_thread=sync_to_thread, - tags=tags, - type_decoders=type_decoders, - type_encoders=type_encoders, - **kwargs, - ) diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__init__.py b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__init__.py deleted file mode 100644 index 5b24734..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import annotations - -from litestar.handlers.websocket_handlers.listener import ( - WebsocketListener, - WebsocketListenerRouteHandler, - websocket_listener, -) -from litestar.handlers.websocket_handlers.route_handler import WebsocketRouteHandler, websocket - -__all__ = ( - "WebsocketListener", - "WebsocketListenerRouteHandler", - "WebsocketRouteHandler", - "websocket", - "websocket_listener", -) diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/__init__.cpython-311.pyc Binary files differdeleted file mode 100644 index f6d1115..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/_utils.cpython-311.pyc Binary files differdeleted file mode 100644 index c5ae4c8..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/_utils.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/listener.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/listener.cpython-311.pyc Binary files differdeleted file mode 100644 index 38b8219..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/listener.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/route_handler.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/route_handler.cpython-311.pyc Binary files differdeleted file mode 100644 index 0e92ccd..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/route_handler.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/_utils.py b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/_utils.py deleted file mode 100644 index bcd90ac..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/_utils.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import annotations - -from functools import wraps -from inspect import Parameter, Signature -from typing import TYPE_CHECKING, Any, Callable, Coroutine, Dict - -from msgspec.json import Encoder as JsonEncoder - -from litestar.di import Provide -from litestar.serialization import decode_json -from litestar.types.builtin_types import NoneType -from litestar.utils import ensure_async_callable -from litestar.utils.helpers import unwrap_partial - -if TYPE_CHECKING: - from litestar import WebSocket - from litestar.handlers.websocket_handlers.listener import WebsocketListenerRouteHandler - from litestar.types import AnyCallable - from litestar.utils.signature import ParsedSignature - - -def create_handle_receive(listener: WebsocketListenerRouteHandler) -> Callable[[WebSocket], Coroutine[Any, None, None]]: - if data_dto := listener.resolve_data_dto(): - - async def handle_receive(socket: WebSocket) -> Any: - received_data = await socket.receive_data(mode=listener._receive_mode) - return data_dto(socket).decode_bytes( - received_data.encode("utf-8") if isinstance(received_data, str) else received_data - ) - - elif listener.parsed_data_field and listener.parsed_data_field.annotation is str: - - async def handle_receive(socket: WebSocket) -> Any: - received_data = await socket.receive_data(mode=listener._receive_mode) - return received_data.decode("utf-8") if isinstance(received_data, bytes) else received_data - - elif listener.parsed_data_field and listener.parsed_data_field.annotation is bytes: - - async def handle_receive(socket: WebSocket) -> Any: - received_data = await socket.receive_data(mode=listener._receive_mode) - return received_data.encode("utf-8") if isinstance(received_data, str) else received_data - - else: - - async def handle_receive(socket: WebSocket) -> Any: - received_data = await socket.receive_data(mode=listener._receive_mode) - return decode_json(value=received_data, type_decoders=socket.route_handler.resolve_type_decoders()) - - return handle_receive - - -def create_handle_send( - listener: WebsocketListenerRouteHandler, -) -> Callable[[WebSocket, Any], Coroutine[None, None, None]]: - json_encoder = JsonEncoder(enc_hook=listener.default_serializer) - - if return_dto := listener.resolve_return_dto(): - - async def handle_send(socket: WebSocket, data: Any) -> None: - encoded_data = return_dto(socket).data_to_encodable_type(data) - data = json_encoder.encode(encoded_data) - await socket.send_data(data=data, mode=listener._send_mode) - - elif listener.parsed_return_field.is_subclass_of((str, bytes)) or ( - listener.parsed_return_field.is_optional and listener.parsed_return_field.has_inner_subclass_of((str, bytes)) - ): - - async def handle_send(socket: WebSocket, data: Any) -> None: - await socket.send_data(data=data, mode=listener._send_mode) - - else: - - async def handle_send(socket: WebSocket, data: Any) -> None: - data = json_encoder.encode(data) - await socket.send_data(data=data, mode=listener._send_mode) - - return handle_send - - -class ListenerHandler: - __slots__ = ("_can_send_data", "_fn", "_listener", "_pass_socket") - - def __init__( - self, - listener: WebsocketListenerRouteHandler, - fn: AnyCallable, - parsed_signature: ParsedSignature, - namespace: dict[str, Any], - ) -> None: - self._can_send_data = not parsed_signature.return_type.is_subclass_of(NoneType) - self._fn = ensure_async_callable(fn) - self._listener = listener - self._pass_socket = "socket" in parsed_signature.parameters - - async def __call__( - self, - *args: Any, - socket: WebSocket, - connection_lifespan_dependencies: Dict[str, Any], # noqa: UP006 - **kwargs: Any, - ) -> None: - lifespan_mananger = self._listener._connection_lifespan or self._listener.default_connection_lifespan - handle_send = self._listener.resolve_send_handler() if self._can_send_data else None - handle_receive = self._listener.resolve_receive_handler() - - if self._pass_socket: - kwargs["socket"] = socket - - async with lifespan_mananger(**connection_lifespan_dependencies): - while True: - received_data = await handle_receive(socket) - data = await self._fn(*args, data=received_data, **kwargs) - if handle_send: - await handle_send(socket, data) - - -def create_handler_signature(callback_signature: Signature) -> Signature: - """Creates a :class:`Signature` for the handler function for signature modelling. - - This is required for two reasons: - - 1. the :class:`.handlers.WebsocketHandler` signature model cannot contain the ``data`` parameter, which is - required for :class:`.handlers.websocket_listener` handlers. - 2. the :class;`.handlers.WebsocketHandler` signature model must include the ``socket`` parameter, which is - optional for :class:`.handlers.websocket_listener` handlers. - - Args: - callback_signature: The :class:`Signature` of the listener callback. - - Returns: - The :class:`Signature` for the listener callback as required for signature modelling. - """ - new_params = [p for p in callback_signature.parameters.values() if p.name != "data"] - if "socket" not in callback_signature.parameters: - new_params.append(Parameter(name="socket", kind=Parameter.KEYWORD_ONLY, annotation="WebSocket")) - - new_params.append( - Parameter(name="connection_lifespan_dependencies", kind=Parameter.KEYWORD_ONLY, annotation="Dict[str, Any]") - ) - - return callback_signature.replace(parameters=new_params) - - -def create_stub_dependency(src: AnyCallable) -> Provide: - """Create a stub dependency, accepting any kwargs defined in ``src``, and - wrap it in ``Provide`` - """ - src = unwrap_partial(src) - - @wraps(src) - async def stub(**kwargs: Any) -> Dict[str, Any]: # noqa: UP006 - return kwargs - - return Provide(stub) diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/listener.py b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/listener.py deleted file mode 100644 index 86fefc9..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/listener.py +++ /dev/null @@ -1,417 +0,0 @@ -from __future__ import annotations - -from abc import ABC, abstractmethod -from contextlib import AbstractAsyncContextManager, asynccontextmanager -from typing import ( - TYPE_CHECKING, - Any, - AsyncGenerator, - Callable, - Dict, - Mapping, - Optional, - cast, - overload, -) - -from litestar._signature import SignatureModel -from litestar.connection import WebSocket -from litestar.exceptions import ImproperlyConfiguredException, WebSocketDisconnect -from litestar.types import ( - AnyCallable, - Dependencies, - Empty, - EmptyType, - ExceptionHandler, - Guard, - Middleware, - TypeEncodersMap, -) -from litestar.utils import ensure_async_callable -from litestar.utils.signature import ParsedSignature, get_fn_type_hints - -from ._utils import ( - ListenerHandler, - create_handle_receive, - create_handle_send, - create_handler_signature, - create_stub_dependency, -) -from .route_handler import WebsocketRouteHandler - -if TYPE_CHECKING: - from typing import Coroutine - - from typing_extensions import Self - - from litestar import Router - from litestar.dto import AbstractDTO - from litestar.types.asgi_types import WebSocketMode - from litestar.types.composite_types import TypeDecodersSequence - -__all__ = ("WebsocketListener", "WebsocketListenerRouteHandler", "websocket_listener") - - -class WebsocketListenerRouteHandler(WebsocketRouteHandler): - """A websocket listener that automatically accepts a connection, handles disconnects, - invokes a callback function every time new data is received and sends any data - returned - """ - - __slots__ = { - "connection_accept_handler": "Callback to accept a WebSocket connection. By default, calls WebSocket.accept", - "on_accept": "Callback invoked after a WebSocket connection has been accepted", - "on_disconnect": "Callback invoked after a WebSocket connection has been closed", - "weboscket_class": "WebSocket class", - "_connection_lifespan": None, - "_handle_receive": None, - "_handle_send": None, - "_receive_mode": None, - "_send_mode": None, - } - - @overload - def __init__( - self, - path: str | list[str] | None = None, - *, - connection_lifespan: Callable[..., AbstractAsyncContextManager[Any]] | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None, - guards: list[Guard] | None = None, - middleware: list[Middleware] | None = None, - receive_mode: WebSocketMode = "text", - send_mode: WebSocketMode = "text", - name: str | None = None, - opt: dict[str, Any] | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - websocket_class: type[WebSocket] | None = None, - **kwargs: Any, - ) -> None: ... - - @overload - def __init__( - self, - path: str | list[str] | None = None, - *, - connection_accept_handler: Callable[[WebSocket], Coroutine[Any, Any, None]] = WebSocket.accept, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None, - guards: list[Guard] | None = None, - middleware: list[Middleware] | None = None, - receive_mode: WebSocketMode = "text", - send_mode: WebSocketMode = "text", - name: str | None = None, - on_accept: AnyCallable | None = None, - on_disconnect: AnyCallable | None = None, - opt: dict[str, Any] | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - websocket_class: type[WebSocket] | None = None, - **kwargs: Any, - ) -> None: ... - - def __init__( - self, - path: str | list[str] | None = None, - *, - connection_accept_handler: Callable[[WebSocket], Coroutine[Any, Any, None]] = WebSocket.accept, - connection_lifespan: Callable[..., AbstractAsyncContextManager[Any]] | None = None, - dependencies: Dependencies | None = None, - dto: type[AbstractDTO] | None | EmptyType = Empty, - exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None, - guards: list[Guard] | None = None, - middleware: list[Middleware] | None = None, - receive_mode: WebSocketMode = "text", - send_mode: WebSocketMode = "text", - name: str | None = None, - on_accept: AnyCallable | None = None, - on_disconnect: AnyCallable | None = None, - opt: dict[str, Any] | None = None, - return_dto: type[AbstractDTO] | None | EmptyType = Empty, - signature_namespace: Mapping[str, Any] | None = None, - type_decoders: TypeDecodersSequence | None = None, - type_encoders: TypeEncodersMap | None = None, - websocket_class: type[WebSocket] | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``WebsocketRouteHandler`` - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. If not given defaults - to ``/`` - connection_accept_handler: A callable that accepts a :class:`WebSocket <.connection.WebSocket>` instance - and returns a coroutine that when awaited, will accept the connection. Defaults to ``WebSocket.accept``. - connection_lifespan: An asynchronous context manager, handling the lifespan of the connection. By default, - it calls the ``connection_accept_handler``, ``on_connect`` and ``on_disconnect``. Can request any - dependencies, for example the :class:`WebSocket <.connection.WebSocket>` connection - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and - validation of request data. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - receive_mode: Websocket mode to receive data in, either `text` or `binary`. - send_mode: Websocket mode to receive data in, either `text` or `binary`. - name: A string identifying the route handler. - on_accept: Callback invoked after a connection has been accepted. Can request any dependencies, for example - the :class:`WebSocket <.connection.WebSocket>` connection - on_disconnect: Callback invoked after a connection has been closed. Can request any dependencies, for - example the :class:`WebSocket <.connection.WebSocket>` connection - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or - :class:`ASGI Scope <.types.Scope>`. - return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing - outbound response data. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature - modelling. - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec - hook for deserialization. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - websocket_class: A custom subclass of :class:`WebSocket <.connection.WebSocket>` to be used as route handler's - default websocket class. - """ - if connection_lifespan and any([on_accept, on_disconnect, connection_accept_handler is not WebSocket.accept]): - raise ImproperlyConfiguredException( - "connection_lifespan can not be used with connection hooks " - "(on_accept, on_disconnect, connection_accept_handler)", - ) - - self._receive_mode: WebSocketMode = receive_mode - self._send_mode: WebSocketMode = send_mode - self._connection_lifespan = connection_lifespan - self._send_handler: Callable[[WebSocket, Any], Coroutine[None, None, None]] | EmptyType = Empty - self._receive_handler: Callable[[WebSocket], Any] | EmptyType = Empty - - self.connection_accept_handler = connection_accept_handler - self.on_accept = ensure_async_callable(on_accept) if on_accept else None - self.on_disconnect = ensure_async_callable(on_disconnect) if on_disconnect else None - self.type_decoders = type_decoders - self.type_encoders = type_encoders - self.websocket_class = websocket_class - - listener_dependencies = dict(dependencies or {}) - - listener_dependencies["connection_lifespan_dependencies"] = create_stub_dependency( - connection_lifespan or self.default_connection_lifespan - ) - - if self.on_accept: - listener_dependencies["on_accept_dependencies"] = create_stub_dependency(self.on_accept) - - if self.on_disconnect: - listener_dependencies["on_disconnect_dependencies"] = create_stub_dependency(self.on_disconnect) - - super().__init__( - path=path, - dependencies=listener_dependencies, - exception_handlers=exception_handlers, - guards=guards, - middleware=middleware, - name=name, - opt=opt, - signature_namespace=signature_namespace, - dto=dto, - return_dto=return_dto, - type_decoders=type_decoders, - type_encoders=type_encoders, - websocket_class=websocket_class, - **kwargs, - ) - - def __call__(self, fn: AnyCallable) -> Self: - parsed_signature = ParsedSignature.from_fn(fn, self.resolve_signature_namespace()) - - if "data" not in parsed_signature.parameters: - raise ImproperlyConfiguredException("Websocket listeners must accept a 'data' parameter") - - for param in ("request", "body"): - if param in parsed_signature.parameters: - raise ImproperlyConfiguredException(f"The {param} kwarg is not supported with websocket listeners") - - # we are manipulating the signature of the decorated function below, so we must store the original values for - # use elsewhere. - self._parsed_return_field = parsed_signature.return_type - self._parsed_data_field = parsed_signature.parameters.get("data") - self._parsed_fn_signature = ParsedSignature.from_signature( - create_handler_signature(parsed_signature.original_signature), - fn_type_hints={ - **get_fn_type_hints(fn, namespace=self.resolve_signature_namespace()), - **get_fn_type_hints(ListenerHandler.__call__, namespace=self.resolve_signature_namespace()), - }, - ) - - return super().__call__( - ListenerHandler( - listener=self, fn=fn, parsed_signature=parsed_signature, namespace=self.resolve_signature_namespace() - ) - ) - - def _validate_handler_function(self) -> None: - """Validate the route handler function once it's set by inspecting its return annotations.""" - # validation occurs in the call method - - @property - def signature_model(self) -> type[SignatureModel]: - """Get the signature model for the route handler. - - Returns: - A signature model for the route handler. - - """ - if self._signature_model is Empty: - self._signature_model = SignatureModel.create( - dependency_name_set=self.dependency_name_set, - fn=cast("AnyCallable", self.fn), - parsed_signature=self.parsed_fn_signature, - type_decoders=self.resolve_type_decoders(), - ) - return self._signature_model - - @asynccontextmanager - async def default_connection_lifespan( - self, - socket: WebSocket, - on_accept_dependencies: Optional[Dict[str, Any]] = None, # noqa: UP006, UP007 - on_disconnect_dependencies: Optional[Dict[str, Any]] = None, # noqa: UP006, UP007 - ) -> AsyncGenerator[None, None]: - """Handle the connection lifespan of a :class:`WebSocket <.connection.WebSocket>`. - - Args: - socket: The :class:`WebSocket <.connection.WebSocket>` connection - on_accept_dependencies: Dependencies requested by the :attr:`on_accept` hook - on_disconnect_dependencies: Dependencies requested by the :attr:`on_disconnect` hook - - By, default this will - - - Call :attr:`connection_accept_handler` to accept a connection - - Call :attr:`on_accept` if defined after a connection has been accepted - - Call :attr:`on_disconnect` upon leaving the context - """ - await self.connection_accept_handler(socket) - - if self.on_accept: - await self.on_accept(**(on_accept_dependencies or {})) - - try: - yield - except WebSocketDisconnect: - pass - finally: - if self.on_disconnect: - await self.on_disconnect(**(on_disconnect_dependencies or {})) - - def resolve_receive_handler(self) -> Callable[[WebSocket], Any]: - if self._receive_handler is Empty: - self._receive_handler = create_handle_receive(self) - return self._receive_handler - - def resolve_send_handler(self) -> Callable[[WebSocket, Any], Coroutine[None, None, None]]: - if self._send_handler is Empty: - self._send_handler = create_handle_send(self) - return self._send_handler - - -websocket_listener = WebsocketListenerRouteHandler - - -class WebsocketListener(ABC): - path: str | list[str] | None = None - """A path fragment for the route handler function or a sequence of path fragments. If not given defaults to ``/``""" - dependencies: Dependencies | None = None - """A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.""" - dto: type[AbstractDTO] | None | EmptyType = Empty - """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and validation of request data""" - exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None - """A mapping of status codes and/or exception types to handler functions.""" - guards: list[Guard] | None = None - """A sequence of :class:`Guard <.types.Guard>` callables.""" - middleware: list[Middleware] | None = None - """A sequence of :class:`Middleware <.types.Middleware>`.""" - on_accept: AnyCallable | None = None - """Called after a :class:`WebSocket <.connection.WebSocket>` connection has been accepted. Can receive any dependencies""" - on_disconnect: AnyCallable | None = None - """Called after a :class:`WebSocket <.connection.WebSocket>` connection has been disconnected. Can receive any dependencies""" - receive_mode: WebSocketMode = "text" - """:class:`WebSocket <.connection.WebSocket>` mode to receive data in, either ``text`` or ``binary``.""" - send_mode: WebSocketMode = "text" - """Websocket mode to send data in, either `text` or `binary`.""" - name: str | None = None - """A string identifying the route handler.""" - opt: dict[str, Any] | None = None - """ - A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or wherever you - have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`. - """ - return_dto: type[AbstractDTO] | None | EmptyType = Empty - """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing outbound response data.""" - signature_namespace: Mapping[str, Any] | None = None - """ - A mapping of names to types for use in forward reference resolution during signature modelling. - """ - type_decoders: TypeDecodersSequence | None = None - """ - type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec - hook for deserialization. - """ - type_encoders: TypeEncodersMap | None = None - """ - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - """ - websocket_class: type[WebSocket] | None = None - """ - websocket_class: A custom subclass of :class:`WebSocket <.connection.WebSocket>` to be used as route handler's - default websocket class. - """ - - def __init__(self, owner: Router) -> None: - """Initialize a WebsocketListener instance. - - Args: - owner: The :class:`Router <.router.Router>` instance that owns this listener. - """ - self._owner = owner - - def to_handler(self) -> WebsocketListenerRouteHandler: - handler = WebsocketListenerRouteHandler( - dependencies=self.dependencies, - dto=self.dto, - exception_handlers=self.exception_handlers, - guards=self.guards, - middleware=self.middleware, - send_mode=self.send_mode, - receive_mode=self.receive_mode, - name=self.name, - on_accept=self.on_accept, - on_disconnect=self.on_disconnect, - opt=self.opt, - path=self.path, - return_dto=self.return_dto, - signature_namespace=self.signature_namespace, - type_decoders=self.type_decoders, - type_encoders=self.type_encoders, - websocket_class=self.websocket_class, - )(self.on_receive) - handler.owner = self._owner - return handler - - @abstractmethod - def on_receive(self, *args: Any, **kwargs: Any) -> Any: - """Called after data has been received from the WebSocket. - - This should take a ``data`` argument, receiving the processed WebSocket data, - and can additionally include handler dependencies such as ``state``, or other - regular dependencies. - - Data returned from this function will be serialized and sent via the socket - according to handler configuration. - """ - raise NotImplementedError diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/route_handler.py b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/route_handler.py deleted file mode 100644 index edb49c3..0000000 --- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/route_handler.py +++ /dev/null @@ -1,99 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Any, Mapping - -from litestar.connection import WebSocket -from litestar.exceptions import ImproperlyConfiguredException -from litestar.handlers import BaseRouteHandler -from litestar.types.builtin_types import NoneType -from litestar.utils.predicates import is_async_callable - -if TYPE_CHECKING: - from litestar.types import Dependencies, ExceptionHandler, Guard, Middleware - - -class WebsocketRouteHandler(BaseRouteHandler): - """Websocket route handler decorator. - - Use this decorator to decorate websocket handler functions. - """ - - def __init__( - self, - path: str | list[str] | None = None, - *, - dependencies: Dependencies | None = None, - exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None, - guards: list[Guard] | None = None, - middleware: list[Middleware] | None = None, - name: str | None = None, - opt: dict[str, Any] | None = None, - signature_namespace: Mapping[str, Any] | None = None, - websocket_class: type[WebSocket] | None = None, - **kwargs: Any, - ) -> None: - """Initialize ``WebsocketRouteHandler`` - - Args: - path: A path fragment for the route handler function or a sequence of path fragments. If not given defaults - to ``/`` - dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances. - exception_handlers: A mapping of status codes and/or exception types to handler functions. - guards: A sequence of :class:`Guard <.types.Guard>` callables. - middleware: A sequence of :class:`Middleware <.types.Middleware>`. - name: A string identifying the route handler. - opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or - wherever you have access to :class:`Request <.connection.Request>` or - :class:`ASGI Scope <.types.Scope>`. - signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling. - type_encoders: A mapping of types to callables that transform them into types supported for serialization. - **kwargs: Any additional kwarg - will be set in the opt dictionary. - websocket_class: A custom subclass of :class:`WebSocket <.connection.WebSocket>` to be used as route handler's - default websocket class. - """ - self.websocket_class = websocket_class - - super().__init__( - path=path, - dependencies=dependencies, - exception_handlers=exception_handlers, - guards=guards, - middleware=middleware, - name=name, - opt=opt, - signature_namespace=signature_namespace, - **kwargs, - ) - - def resolve_websocket_class(self) -> type[WebSocket]: - """Return the closest custom WebSocket class in the owner graph or the default Websocket class. - - This method is memoized so the computation occurs only once. - - Returns: - The default :class:`WebSocket <.connection.WebSocket>` class for the route handler. - """ - return next( - (layer.websocket_class for layer in reversed(self.ownership_layers) if layer.websocket_class is not None), - WebSocket, - ) - - def _validate_handler_function(self) -> None: - """Validate the route handler function once it's set by inspecting its return annotations.""" - super()._validate_handler_function() - - if not self.parsed_fn_signature.return_type.is_subclass_of(NoneType): - raise ImproperlyConfiguredException("Websocket handler functions should return 'None'") - - if "socket" not in self.parsed_fn_signature.parameters: - raise ImproperlyConfiguredException("Websocket handlers must set a 'socket' kwarg") - - for param in ("request", "body", "data"): - if param in self.parsed_fn_signature.parameters: - raise ImproperlyConfiguredException(f"The {param} kwarg is not supported with websocket handlers") - - if not is_async_callable(self.fn): - raise ImproperlyConfiguredException("Functions decorated with 'websocket' must be async functions") - - -websocket = WebsocketRouteHandler |