Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/connexion/apps/asynchronous.py: 56%
63 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:12 +0000
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:12 +0000
1"""
2This module defines a native connexion asynchronous application.
3"""
5import functools
6import logging
7import pathlib
8import typing as t
10from starlette.responses import Response as StarletteResponse
11from starlette.routing import Router
12from starlette.types import Receive, Scope, Send
14from connexion.apps.abstract import AbstractApp
15from connexion.decorators import StarletteDecorator
16from connexion.jsonifier import Jsonifier
17from connexion.middleware.abstract import RoutedAPI, RoutedMiddleware
18from connexion.middleware.lifespan import Lifespan
19from connexion.operations import AbstractOperation
20from connexion.resolver import Resolver
21from connexion.uri_parsing import AbstractURIParser
23logger = logging.getLogger(__name__)
26class AsyncOperation:
27 def __init__(
28 self,
29 fn: t.Callable,
30 jsonifier: Jsonifier,
31 operation_id: str,
32 pythonic_params: bool,
33 ) -> None:
34 self._fn = fn
35 self.jsonifier = jsonifier
36 self.operation_id = operation_id
37 self.pythonic_params = pythonic_params
38 functools.update_wrapper(self, fn)
40 @classmethod
41 def from_operation(
42 cls,
43 operation: AbstractOperation,
44 *,
45 pythonic_params: bool,
46 jsonifier: Jsonifier,
47 ) -> "AsyncOperation":
48 return cls(
49 operation.function,
50 jsonifier=jsonifier,
51 operation_id=operation.operation_id,
52 pythonic_params=pythonic_params,
53 )
55 @property
56 def fn(self) -> t.Callable:
57 decorator = StarletteDecorator(
58 pythonic_params=self.pythonic_params,
59 jsonifier=self.jsonifier,
60 )
61 return decorator(self._fn)
63 async def __call__(
64 self, scope: Scope, receive: Receive, send: Send
65 ) -> StarletteResponse:
66 response = await self.fn()
67 return await response(scope, receive, send)
70class AsyncApi(RoutedAPI[AsyncOperation]):
71 def __init__(
72 self,
73 *args,
74 pythonic_params: bool,
75 jsonifier: t.Optional[Jsonifier] = None,
76 **kwargs,
77 ) -> None:
78 super().__init__(*args, **kwargs)
79 self.pythonic_params = pythonic_params
80 self.jsonifier = jsonifier or Jsonifier()
81 self.router = Router()
82 self.add_paths()
84 def make_operation(self, operation: AbstractOperation) -> AsyncOperation:
85 return AsyncOperation.from_operation(
86 operation, pythonic_params=self.pythonic_params, jsonifier=self.jsonifier
87 )
90class AsyncMiddlewareApp(RoutedMiddleware[AsyncApi]):
92 api_cls = AsyncApi
94 def __init__(self) -> None:
95 self.apis: t.Dict[str, AsyncApi] = {}
96 self.operations: t.Dict[str, AsyncOperation] = {}
97 self.router = Router()
98 super().__init__(self.router)
100 def add_api(self, *args, **kwargs):
101 api = super().add_api(*args, **kwargs)
102 self.router.mount(api.base_path, api.router)
103 return api
105 def add_url_rule(
106 self,
107 rule,
108 endpoint: str = None,
109 view_func: t.Callable = None,
110 methods: t.List[str] = None,
111 **options,
112 ):
113 self.router.add_route(rule, endpoint=view_func, name=endpoint, methods=methods)
116class AsyncApp(AbstractApp):
117 """Connexion Application based on ConnexionMiddleware wrapping a async Connexion application
118 based on starlette tools."""
120 def __init__(
121 self,
122 import_name: str,
123 *,
124 lifespan: t.Optional[Lifespan] = None,
125 middlewares: t.Optional[list] = None,
126 specification_dir: t.Union[pathlib.Path, str] = "",
127 arguments: t.Optional[dict] = None,
128 auth_all_paths: t.Optional[bool] = None,
129 jsonifier: t.Optional[Jsonifier] = None,
130 pythonic_params: t.Optional[bool] = None,
131 resolver: t.Optional[t.Union[Resolver, t.Callable]] = None,
132 resolver_error: t.Optional[int] = None,
133 strict_validation: t.Optional[bool] = None,
134 swagger_ui_options: t.Optional[dict] = None,
135 uri_parser_class: t.Optional[AbstractURIParser] = None,
136 validate_responses: t.Optional[bool] = None,
137 validator_map: t.Optional[dict] = None,
138 ) -> None:
139 """
140 :param import_name: The name of the package or module that this object belongs to. If you
141 are using a single module, __name__ is always the correct value. If you however are
142 using a package, it’s usually recommended to hardcode the name of your package there.
143 :param middlewares: The list of middlewares to wrap around the application. Defaults to
144 :obj:`middleware.main.ConnexionmMiddleware.default_middlewares`
145 :param specification_dir: The directory holding the specification(s). The provided path
146 should either be absolute or relative to the root path of the application. Defaults to
147 the root path.
148 :param arguments: Arguments to substitute the specification using Jinja.
149 :param auth_all_paths: whether to authenticate not paths not defined in the specification.
150 Defaults to False.
151 :param jsonifier: Custom jsonifier to overwrite json encoding for json responses.
152 :param pythonic_params: When True, CamelCase parameters are converted to snake_case and an
153 underscore is appended to any shadowed built-ins. Defaults to False.
154 :param resolver: Callable that maps operationId to a function or instance of
155 :class:`resolver.Resolver`.
156 :param resolver_error: Error code to return for operations for which the operationId could
157 not be resolved. If no error code is provided, the application will fail when trying to
158 start.
159 :param strict_validation: When True, extra form or query parameters not defined in the
160 specification result in a validation error. Defaults to False.
161 :param swagger_ui_options: A :class:`options.ConnexionOptions` instance with configuration
162 options for the swagger ui.
163 :param uri_parser_class: Class to use for uri parsing. See :mod:`uri_parsing`.
164 :param validate_responses: Whether to validate responses against the specification. This has
165 an impact on performance. Defaults to False.
166 :param validator_map: A dictionary of validators to use. Defaults to
167 :obj:`validators.VALIDATOR_MAP`.
168 """
169 self.middleware_app: AsyncMiddlewareApp = AsyncMiddlewareApp()
171 super().__init__(
172 import_name,
173 lifespan=lifespan,
174 middlewares=middlewares,
175 specification_dir=specification_dir,
176 arguments=arguments,
177 auth_all_paths=auth_all_paths,
178 jsonifier=jsonifier,
179 pythonic_params=pythonic_params,
180 resolver=resolver,
181 resolver_error=resolver_error,
182 strict_validation=strict_validation,
183 swagger_ui_options=swagger_ui_options,
184 uri_parser_class=uri_parser_class,
185 validate_responses=validate_responses,
186 validator_map=validator_map,
187 )
189 def add_url_rule(
190 self, rule, endpoint: str = None, view_func: t.Callable = None, **options
191 ):
192 self.middleware_app.add_url_rule(
193 rule, endpoint=endpoint, view_func=view_func, **options
194 )
196 def add_error_handler(
197 self, code_or_exception: t.Union[int, t.Type[Exception]], function: t.Callable
198 ) -> None:
199 self.middleware.add_error_handler(code_or_exception, function)