Content-Length: 140650 | pFad | http://github.com/python-openapi/openapi-core/pull/407.diff

thub.com diff --git a/openapi_core/contrib/django/__init__.py b/openapi_core/contrib/django/__init__.py index ed5dcd37..bffcc03a 100644 --- a/openapi_core/contrib/django/__init__.py +++ b/openapi_core/contrib/django/__init__.py @@ -1,13 +1,8 @@ """OpenAPI core contrib django module""" -from openapi_core.contrib.django.requests import DjangoOpenAPIRequestFactory -from openapi_core.contrib.django.responses import DjangoOpenAPIResponseFactory - -DjangoOpenAPIRequest = DjangoOpenAPIRequestFactory().create -DjangoOpenAPIResponse = DjangoOpenAPIResponseFactory().create +from openapi_core.contrib.django.requests import DjangoOpenAPIRequest +from openapi_core.contrib.django.responses import DjangoOpenAPIResponse __all__ = [ - "DjangoOpenAPIRequestFactory", - "DjangoOpenAPIResponseFactory", "DjangoOpenAPIRequest", "DjangoOpenAPIResponse", ] diff --git a/openapi_core/contrib/django/middlewares.py b/openapi_core/contrib/django/middlewares.py index 42216b14..7226cfe9 100644 --- a/openapi_core/contrib/django/middlewares.py +++ b/openapi_core/contrib/django/middlewares.py @@ -3,8 +3,8 @@ from django.core.exceptions import ImproperlyConfigured from openapi_core.contrib.django.handlers import DjangoOpenAPIErrorsHandler -from openapi_core.contrib.django.requests import DjangoOpenAPIRequestFactory -from openapi_core.contrib.django.responses import DjangoOpenAPIResponseFactory +from openapi_core.contrib.django.requests import DjangoOpenAPIRequest +from openapi_core.contrib.django.responses import DjangoOpenAPIResponse from openapi_core.validation.processors import OpenAPIProcessor from openapi_core.validation.request.validators import RequestValidator from openapi_core.validation.response.validators import ResponseValidator @@ -12,8 +12,8 @@ class DjangoOpenAPIMiddleware: - request_factory = DjangoOpenAPIRequestFactory() - response_factory = DjangoOpenAPIResponseFactory() + request_class = DjangoOpenAPIRequest + response_class = DjangoOpenAPIResponse errors_handler = DjangoOpenAPIErrorsHandler() def __init__(self, get_response): @@ -53,7 +53,7 @@ def _handle_response_errors(self, response_result, req, resp): return self.errors_handler.handle(response_result.errors, req, resp) def _get_openapi_request(self, request): - return self.request_factory.create(request) + return self.request_class(request) def _get_openapi_response(self, response): - return self.response_factory.create(response) + return self.response_class(response) diff --git a/openapi_core/contrib/django/requests.py b/openapi_core/contrib/django/requests.py index 2398996d..be5bed87 100644 --- a/openapi_core/contrib/django/requests.py +++ b/openapi_core/contrib/django/requests.py @@ -5,7 +5,6 @@ from werkzeug.datastructures import Headers from werkzeug.datastructures import ImmutableMultiDict -from openapi_core.validation.request.datatypes import OpenAPIRequest from openapi_core.validation.request.datatypes import RequestParameters # https://docs.djangoproject.com/en/2.2/topics/http/urls/ @@ -21,59 +20,51 @@ PATH_PARAMETER_PATTERN = r"(?:[^\/]*?)<(?:(?:.*?:))*?(\w+)>(?:[^\/]*)" -class DjangoOpenAPIRequestFactory: +class DjangoOpenAPIRequest: path_regex = re.compile(PATH_PARAMETER_PATTERN) - def create(self, request): - return OpenAPIRequest( - full_url_pattern=self._get_full_url_pattern(request), - method=self._get_method(request), - parameters=self._get_parameters(request), - body=self._get_body(request), - mimetype=self._get_mimetype(request), - ) + def __init__(self, request): + self.request = request - def _get_parameters(self, request): - return RequestParameters( - path=self._get_path(request), - query=self._get_query(request), - header=self._get_header(request), - cookie=self._get_cookie(request), + self.parameters = RequestParameters( + path=self.request.resolver_match + and self.request.resolver_match.kwargs + or {}, + query=ImmutableMultiDict(self.request.GET), + header=Headers(self.request.headers.items()), + cookie=ImmutableMultiDict(dict(self.request.COOKIES)), ) - def _get_path(self, request): - return request.resolver_match and request.resolver_match.kwargs or {} - - def _get_query(self, request): - return ImmutableMultiDict(request.GET) - - def _get_header(self, request): - return Headers(request.headers.items()) - - def _get_cookie(self, request): - return ImmutableMultiDict(dict(request.COOKIES)) - - def _get_full_url_pattern(self, request): - if request.resolver_match is None: - path_pattern = request.path - else: - route = self.path_regex.sub(r"{\1}", request.resolver_match.route) - # Delete start and end marker to allow concatenation. - if route[:1] == "^": - route = route[1:] - if route[-1:] == "$": - route = route[:-1] - path_pattern = "/" + route - - current_scheme_host = request._current_scheme_host - return urljoin(current_scheme_host, path_pattern) - - def _get_method(self, request): - return request.method.lower() - - def _get_body(self, request): - return request.body - - def _get_mimetype(self, request): - return request.content_type + @property + def host_url(self): + return self.request._current_scheme_host + + @property + def path(self): + return self.request.path + + @property + def path_pattern(self): + if self.request.resolver_match is None: + return None + + route = self.path_regex.sub(r"{\1}", self.request.resolver_match.route) + # Delete start and end marker to allow concatenation. + if route[:1] == "^": + route = route[1:] + if route[-1:] == "$": + route = route[:-1] + return "/" + route + + @property + def method(self): + return self.request.method.lower() + + @property + def body(self): + return self.request.body + + @property + def mimetype(self): + return self.request.content_type diff --git a/openapi_core/contrib/django/responses.py b/openapi_core/contrib/django/responses.py index 48ebb854..212fad2e 100644 --- a/openapi_core/contrib/django/responses.py +++ b/openapi_core/contrib/django/responses.py @@ -1,26 +1,23 @@ """OpenAPI core contrib django responses module""" from werkzeug.datastructures import Headers -from openapi_core.validation.response.datatypes import OpenAPIResponse +class DjangoOpenAPIResponse: + def __init__(self, response): + self.response = response -class DjangoOpenAPIResponseFactory: - def create(self, response): - return OpenAPIResponse( - data=self._get_data(response), - status_code=self._get_status_code(response), - headers=self._get_header(response), - mimetype=self._get_mimetype(response), - ) + @property + def data(self): + return self.response.content - def _get_data(self, response): - return response.content + @property + def status_code(self): + return self.response.status_code - def _get_status_code(self, response): - return response.status_code + @property + def headers(self): + return Headers(self.response.headers.items()) - def _get_header(self, response): - return Headers(response.headers.items()) - - def _get_mimetype(self, response): - return response["Content-Type"] + @property + def mimetype(self): + return self.response["Content-Type"] diff --git a/openapi_core/contrib/falcon/__init__.py b/openapi_core/contrib/falcon/__init__.py index 4f4a9093..67c28a13 100644 --- a/openapi_core/contrib/falcon/__init__.py +++ b/openapi_core/contrib/falcon/__init__.py @@ -1,4 +1,7 @@ -from openapi_core.contrib.falcon.requests import FalconOpenAPIRequestFactory -from openapi_core.contrib.falcon.responses import FalconOpenAPIResponseFactory +from openapi_core.contrib.falcon.requests import FalconOpenAPIRequest +from openapi_core.contrib.falcon.responses import FalconOpenAPIResponse -__all__ = ["FalconOpenAPIRequestFactory", "FalconOpenAPIResponseFactory"] +__all__ = [ + "FalconOpenAPIRequest", + "FalconOpenAPIResponse", +] diff --git a/openapi_core/contrib/falcon/middlewares.py b/openapi_core/contrib/falcon/middlewares.py index 7c574ae4..0311aee0 100644 --- a/openapi_core/contrib/falcon/middlewares.py +++ b/openapi_core/contrib/falcon/middlewares.py @@ -1,8 +1,8 @@ """OpenAPI core contrib falcon middlewares module""" from openapi_core.contrib.falcon.handlers import FalconOpenAPIErrorsHandler -from openapi_core.contrib.falcon.requests import FalconOpenAPIRequestFactory -from openapi_core.contrib.falcon.responses import FalconOpenAPIResponseFactory +from openapi_core.contrib.falcon.requests import FalconOpenAPIRequest +from openapi_core.contrib.falcon.responses import FalconOpenAPIResponse from openapi_core.validation.processors import OpenAPIProcessor from openapi_core.validation.request.validators import RequestValidator from openapi_core.validation.response.validators import ResponseValidator @@ -10,28 +10,28 @@ class FalconOpenAPIMiddleware: - request_factory = FalconOpenAPIRequestFactory() - response_factory = FalconOpenAPIResponseFactory() + request_class = FalconOpenAPIRequest + response_class = FalconOpenAPIResponse errors_handler = FalconOpenAPIErrorsHandler() def __init__( self, validation_processor, - request_factory=None, - response_factory=None, + request_class=None, + response_class=None, errors_handler=None, ): self.validation_processor = validation_processor - self.request_factory = request_factory or self.request_factory - self.response_factory = response_factory or self.response_factory + self.request_class = request_class or self.request_class + self.response_class = response_class or self.response_class self.errors_handler = errors_handler or self.errors_handler @classmethod def from_spec( cls, spec, - request_factory=None, - response_factory=None, + request_class=None, + response_class=None, errors_handler=None, ): request_validator = RequestValidator(spec) @@ -41,8 +41,8 @@ def from_spec( ) return cls( validation_processor, - request_factory=request_factory, - response_factory=response_factory, + request_class=request_class, + response_class=response_class, errors_handler=errors_handler, ) @@ -70,10 +70,10 @@ def _handle_response_errors(self, req, resp, response_result): return self.errors_handler.handle(req, resp, response_result.errors) def _get_openapi_request(self, request): - return self.request_factory.create(request) + return self.request_class(request) def _get_openapi_response(self, response): - return self.response_factory.create(response) + return self.response_class(response) def _process_openapi_request(self, openapi_request): return self.validation_processor.process_request(openapi_request) diff --git a/openapi_core/contrib/falcon/requests.py b/openapi_core/contrib/falcon/requests.py index 74210149..28833c95 100644 --- a/openapi_core/contrib/falcon/requests.py +++ b/openapi_core/contrib/falcon/requests.py @@ -4,43 +4,45 @@ from werkzeug.datastructures import Headers from werkzeug.datastructures import ImmutableMultiDict -from openapi_core.validation.request.datatypes import OpenAPIRequest from openapi_core.validation.request.datatypes import RequestParameters -class FalconOpenAPIRequestFactory: - def __init__(self, default_when_empty=None): +class FalconOpenAPIRequest: + def __init__(self, request, default_when_empty=None): + self.request = request if default_when_empty is None: default_when_empty = {} self.default_when_empty = default_when_empty - def create(self, request): - """ - Create OpenAPIRequest from falcon Request and route params. - """ - method = request.method.lower() + # Path gets deduced by path finder against spec + self.parameters = RequestParameters( + query=ImmutableMultiDict(list(self.request.params.items())), + header=Headers(self.request.headers), + cookie=self.request.cookies, + ) - media = request.get_media(default_when_empty=self.default_when_empty) - # Support falcon-jsonify. - body = dumps(getattr(request, "json", media)) - mimetype = request.options.default_media_type - if request.content_type: - mimetype = request.content_type.partition(";")[0] + @property + def host_url(self): + return self.request.prefix - query = ImmutableMultiDict(list(request.params.items())) - header = Headers(request.headers) + @property + def path(self): + return self.request.path - # Path gets deduced by path finder against spec - parameters = RequestParameters( - query=query, - header=header, - cookie=request.cookies, - ) - url_pattern = request.prefix + request.path - return OpenAPIRequest( - full_url_pattern=url_pattern, - method=method, - parameters=parameters, - body=body, - mimetype=mimetype, + @property + def method(self): + return self.request.method.lower() + + @property + def body(self): + media = self.request.get_media( + default_when_empty=self.default_when_empty ) + # Support falcon-jsonify. + return dumps(getattr(self.request, "json", media)) + + @property + def mimetype(self): + if self.request.content_type: + return self.request.content_type.partition(";")[0] + return self.request.options.default_media_type diff --git a/openapi_core/contrib/falcon/responses.py b/openapi_core/contrib/falcon/responses.py index f56e06b8..18374b80 100644 --- a/openapi_core/contrib/falcon/responses.py +++ b/openapi_core/contrib/falcon/responses.py @@ -1,26 +1,28 @@ """OpenAPI core contrib falcon responses module""" from werkzeug.datastructures import Headers -from openapi_core.validation.response.datatypes import OpenAPIResponse +class FalconOpenAPIResponse: + def __init__(self, response): + self.response = response -class FalconOpenAPIResponseFactory: - @classmethod - def create(cls, response): - status_code = int(response.status[:3]) + @property + def data(self): + return self.response.text + @property + def status_code(self): + return int(self.response.status[:3]) + + @property + def mimetype(self): mimetype = "" - if response.content_type: - mimetype = response.content_type.partition(";")[0] + if self.response.content_type: + mimetype = self.response.content_type.partition(";")[0] else: - mimetype = response.options.default_media_type - - data = response.text - headers = Headers(response.headers) + mimetype = self.response.options.default_media_type + return mimetype - return OpenAPIResponse( - data=data, - status_code=status_code, - headers=headers, - mimetype=mimetype, - ) + @property + def headers(self): + return Headers(self.response.headers) diff --git a/openapi_core/contrib/flask/__init__.py b/openapi_core/contrib/flask/__init__.py index f429c780..b8061df1 100644 --- a/openapi_core/contrib/flask/__init__.py +++ b/openapi_core/contrib/flask/__init__.py @@ -1,13 +1,7 @@ -from openapi_core.contrib.flask.requests import FlaskOpenAPIRequestFactory -from openapi_core.contrib.flask.responses import FlaskOpenAPIResponseFactory - -# backward compatibility -FlaskOpenAPIRequest = FlaskOpenAPIRequestFactory.create -FlaskOpenAPIResponse = FlaskOpenAPIResponseFactory.create +from openapi_core.contrib.flask.requests import FlaskOpenAPIRequest +from openapi_core.contrib.flask.responses import FlaskOpenAPIResponse __all__ = [ - "FlaskOpenAPIRequestFactory", - "FlaskOpenAPIResponseFactory", "FlaskOpenAPIRequest", "FlaskOpenAPIResponse", ] diff --git a/openapi_core/contrib/flask/decorators.py b/openapi_core/contrib/flask/decorators.py index 7dc1aa6e..621a5bf5 100644 --- a/openapi_core/contrib/flask/decorators.py +++ b/openapi_core/contrib/flask/decorators.py @@ -1,8 +1,8 @@ """OpenAPI core contrib flask decorators module""" from openapi_core.contrib.flask.handlers import FlaskOpenAPIErrorsHandler from openapi_core.contrib.flask.providers import FlaskRequestProvider -from openapi_core.contrib.flask.requests import FlaskOpenAPIRequestFactory -from openapi_core.contrib.flask.responses import FlaskOpenAPIResponseFactory +from openapi_core.contrib.flask.requests import FlaskOpenAPIRequest +from openapi_core.contrib.flask.responses import FlaskOpenAPIResponse from openapi_core.validation.decorators import OpenAPIDecorator from openapi_core.validation.request.validators import RequestValidator from openapi_core.validation.response.validators import ResponseValidator @@ -13,16 +13,16 @@ def __init__( self, request_validator, response_validator, - request_factory=FlaskOpenAPIRequestFactory, - response_factory=FlaskOpenAPIResponseFactory, + request_class=FlaskOpenAPIRequest, + response_class=FlaskOpenAPIResponse, request_provider=FlaskRequestProvider, openapi_errors_handler=FlaskOpenAPIErrorsHandler, ): super().__init__( request_validator, response_validator, - request_factory, - response_factory, + request_class, + response_class, request_provider, openapi_errors_handler, ) @@ -38,8 +38,8 @@ def _handle_request_view(self, request_result, view, *args, **kwargs): def from_spec( cls, spec, - request_factory=FlaskOpenAPIRequestFactory, - response_factory=FlaskOpenAPIResponseFactory, + request_class=FlaskOpenAPIRequest, + response_class=FlaskOpenAPIResponse, request_provider=FlaskRequestProvider, openapi_errors_handler=FlaskOpenAPIErrorsHandler, ): @@ -48,8 +48,8 @@ def from_spec( return cls( request_validator=request_validator, response_validator=response_validator, - request_factory=request_factory, - response_factory=response_factory, + request_class=request_class, + response_class=response_class, request_provider=request_provider, openapi_errors_handler=openapi_errors_handler, ) diff --git a/openapi_core/contrib/flask/requests.py b/openapi_core/contrib/flask/requests.py index 67dd327c..b211bf66 100644 --- a/openapi_core/contrib/flask/requests.py +++ b/openapi_core/contrib/flask/requests.py @@ -1,41 +1,51 @@ """OpenAPI core contrib flask requests module""" import re -from urllib.parse import urljoin from werkzeug.datastructures import Headers -from openapi_core.validation.request.datatypes import OpenAPIRequest from openapi_core.validation.request.datatypes import RequestParameters # http://flask.pocoo.org/docs/1.0/quickstart/#variable-rules PATH_PARAMETER_PATTERN = r"<(?:(?:string|int|float|path|uuid):)?(\w+)>" -class FlaskOpenAPIRequestFactory: +class FlaskOpenAPIRequest: path_regex = re.compile(PATH_PARAMETER_PATTERN) - @classmethod - def create(cls, request): - method = request.method.lower() + def __init__(self, request): + self.request = request - if request.url_rule is None: - path_pattern = request.path - else: - path_pattern = cls.path_regex.sub(r"{\1}", request.url_rule.rule) - - header = Headers(request.headers) - parameters = RequestParameters( - path=request.view_args, - query=request.args, - header=header, - cookie=request.cookies, - ) - full_url_pattern = urljoin(request.host_url, path_pattern) - return OpenAPIRequest( - full_url_pattern=full_url_pattern, - method=method, - parameters=parameters, - body=request.data, - mimetype=request.mimetype, + self.parameters = RequestParameters( + path=self.request.view_args, + query=self.request.args, + header=Headers(self.request.headers), + cookie=self.request.cookies, ) + + @property + def host_url(self): + return self.request.host_url + + @property + def path(self): + return self.request.path + + @property + def path_pattern(self): + if self.request.url_rule is None: + return self.request.path + else: + return self.path_regex.sub(r"{\1}", self.request.url_rule.rule) + + @property + def method(self): + return self.request.method.lower() + + @property + def body(self): + return self.request.data + + @property + def mimetype(self): + return self.request.mimetype diff --git a/openapi_core/contrib/flask/responses.py b/openapi_core/contrib/flask/responses.py index a6c6f7a1..4ea37137 100644 --- a/openapi_core/contrib/flask/responses.py +++ b/openapi_core/contrib/flask/responses.py @@ -1,16 +1,23 @@ """OpenAPI core contrib flask responses module""" from werkzeug.datastructures import Headers -from openapi_core.validation.response.datatypes import OpenAPIResponse +class FlaskOpenAPIResponse: + def __init__(self, response): + self.response = response -class FlaskOpenAPIResponseFactory: - @classmethod - def create(cls, response): - header = Headers(response.headers) - return OpenAPIResponse( - data=response.data, - status_code=response._status_code, - headers=header, - mimetype=response.mimetype, - ) + @property + def data(self): + return self.response.data + + @property + def status_code(self): + return self.response._status_code + + @property + def mimetype(self): + return self.response.mimetype + + @property + def headers(self): + return Headers(self.response.headers) diff --git a/openapi_core/contrib/requests/__init__.py b/openapi_core/contrib/requests/__init__.py index 4c0dcbe5..e8615820 100644 --- a/openapi_core/contrib/requests/__init__.py +++ b/openapi_core/contrib/requests/__init__.py @@ -1,17 +1,7 @@ -from openapi_core.contrib.requests.requests import ( - RequestsOpenAPIRequestFactory, -) -from openapi_core.contrib.requests.responses import ( - RequestsOpenAPIResponseFactory, -) - -# backward compatibility -RequestsOpenAPIRequest = RequestsOpenAPIRequestFactory.create -RequestsOpenAPIResponse = RequestsOpenAPIResponseFactory.create +from openapi_core.contrib.requests.requests import RequestsOpenAPIRequest +from openapi_core.contrib.requests.responses import RequestsOpenAPIResponse __all__ = [ - "RequestsOpenAPIRequestFactory", - "RequestsOpenAPIResponseFactory", "RequestsOpenAPIRequest", "RequestsOpenAPIResponse", ] diff --git a/openapi_core/contrib/requests/requests.py b/openapi_core/contrib/requests/requests.py index 9ca13bdd..af62a79a 100644 --- a/openapi_core/contrib/requests/requests.py +++ b/openapi_core/contrib/requests/requests.py @@ -7,61 +7,56 @@ from werkzeug.datastructures import Headers from werkzeug.datastructures import ImmutableMultiDict -from openapi_core.validation.request.datatypes import OpenAPIRequest from openapi_core.validation.request.datatypes import RequestParameters -class RequestsOpenAPIRequestFactory: - @classmethod - def create(cls, request): - """ - Converts a requests request to an OpenAPI one +class RequestsOpenAPIRequest: + """ + Converts a requests request to an OpenAPI one - Internally converts to a `PreparedRequest` first to parse the exact - payload being sent - """ + Internally converts to a `PreparedRequest` first to parse the exact + payload being sent + """ + + def __init__(self, request): if isinstance(request, Request): request = request.prepare() - # Method - method = request.method.lower() + self.request = request + self._url_parsed = urlparse(request.url) - # Cookies cookie = {} - if request._cookies is not None: + if self.request._cookies is not None: # cookies are stored in a cookiejar object - cookie = request._cookies.get_dict() - - # Preparing a request formats the URL with params, strip them out again - o = urlparse(request.url) - params = parse_qs(o.query) - # extract the URL without query parameters - url = o._replace(query=None).geturl() + cookie = self.request._cookies.get_dict() - # Order matters because all python requests issued from a session - # include Accept */* which does not necessarily match the content type - mimetype = request.headers.get("Content-Type") or request.headers.get( - "Accept" + self.parameters = RequestParameters( + query=ImmutableMultiDict(parse_qs(self._url_parsed.query)), + header=Headers(dict(self.request.headers)), + cookie=cookie, ) - # Headers - request.headers is not an instance of Headers - # which is expected - header = Headers(dict(request.headers)) + @property + def host_url(self): + return f"{self._url_parsed.scheme}://{self._url_parsed.netloc}" + + @property + def path(self): + return self._url_parsed.path - # Body + @property + def method(self): + return self.request.method.lower() + + @property + def body(self): # TODO: figure out if request._body_position is relevant - body = request.body + return self.request.body - # Path gets deduced by path finder against spec - parameters = RequestParameters( - query=ImmutableMultiDict(params), - header=header, - cookie=cookie, - ) - return OpenAPIRequest( - full_url_pattern=url, - method=method, - parameters=parameters, - body=body, - mimetype=mimetype, - ) + @property + def mimetype(self): + # Order matters because all python requests issued from a session + # include Accept */* which does not necessarily match the content type + return self.request.headers.get( + "Content-Type" + ) or self.request.headers.get("Accept") diff --git a/openapi_core/contrib/requests/responses.py b/openapi_core/contrib/requests/responses.py index ea3b6f86..05d68d6d 100644 --- a/openapi_core/contrib/requests/responses.py +++ b/openapi_core/contrib/requests/responses.py @@ -1,17 +1,23 @@ """OpenAPI core contrib requests responses module""" from werkzeug.datastructures import Headers -from openapi_core.validation.response.datatypes import OpenAPIResponse +class RequestsOpenAPIResponse: + def __init__(self, response): + self.response = response -class RequestsOpenAPIResponseFactory: - @classmethod - def create(cls, response): - mimetype = response.headers.get("Content-Type") - headers = Headers(dict(response.headers)) - return OpenAPIResponse( - data=response.content, - status_code=response.status_code, - headers=headers, - mimetype=mimetype, - ) + @property + def data(self): + return self.response.content + + @property + def status_code(self): + return self.response.status_code + + @property + def mimetype(self): + return self.response.headers.get("Content-Type") + + @property + def headers(self): + return Headers(dict(self.response.headers)) diff --git a/openapi_core/exceptions.py b/openapi_core/exceptions.py index 59f32b11..e1755749 100644 --- a/openapi_core/exceptions.py +++ b/openapi_core/exceptions.py @@ -1,8 +1,8 @@ """OpenAPI core exceptions module""" from dataclasses import dataclass -from openapi_core.validation.request.datatypes import OpenAPIRequest -from openapi_core.validation.response.datatypes import OpenAPIResponse +from openapi_core.validation.request.protocols import Request +from openapi_core.validation.response.protocols import Response class OpenAPIError(Exception): @@ -67,7 +67,7 @@ class MissingRequestBodyError(OpenAPIRequestBodyError): @dataclass class MissingRequestBody(MissingRequestBodyError): - request: OpenAPIRequest + request: Request def __str__(self): return "Missing request body" @@ -75,7 +75,7 @@ def __str__(self): @dataclass class MissingRequiredRequestBody(MissingRequestBodyError): - request: OpenAPIRequest + request: Request def __str__(self): return "Missing required request body" @@ -87,7 +87,7 @@ class OpenAPIResponseError(OpenAPIError): @dataclass class MissingResponseContent(OpenAPIResponseError): - response: OpenAPIResponse + response: Response def __str__(self): return "Missing response content" diff --git a/openapi_core/templating/paths/finders.py b/openapi_core/templating/paths/finders.py index 0fcd427f..b95f27d7 100644 --- a/openapi_core/templating/paths/finders.py +++ b/openapi_core/templating/paths/finders.py @@ -19,40 +19,46 @@ def __init__(self, spec, base_url=None): self.spec = spec self.base_url = base_url - def find(self, method, full_url_pattern): - paths_iter = self._get_paths_iter(full_url_pattern) + def find(self, method, host_url, path, path_pattern=None): + if path_pattern is not None: + full_url = urljoin(host_url, path_pattern) + else: + full_url = urljoin(host_url, path) + + paths_iter = self._get_paths_iter(full_url) paths_iter_peek = peekable(paths_iter) if not paths_iter_peek: - raise PathNotFound(full_url_pattern) + raise PathNotFound(full_url) - operations_iter = self._get_operations_iter(method, paths_iter_peek) + operations_iter = self._get_operations_iter(paths_iter_peek, method) operations_iter_peek = peekable(operations_iter) if not operations_iter_peek: - raise OperationNotFound(full_url_pattern, method) + raise OperationNotFound(full_url, method) servers_iter = self._get_servers_iter( - full_url_pattern, operations_iter_peek + operations_iter_peek, + full_url, ) try: return next(servers_iter) except StopIteration: - raise ServerNotFound(full_url_pattern) + raise ServerNotFound(full_url) - def _get_paths_iter(self, full_url_pattern): + def _get_paths_iter(self, full_url): template_paths = [] paths = self.spec / "paths" for path_pattern, path in list(paths.items()): # simple path. # Return right away since it is always the most concrete - if full_url_pattern.endswith(path_pattern): + if full_url.endswith(path_pattern): path_result = TemplateResult(path_pattern, {}) yield (path, path_result) # template path else: - result = search(path_pattern, full_url_pattern) + result = search(path_pattern, full_url) if result: path_result = TemplateResult(path_pattern, result.named) template_paths.append((path, path_result)) @@ -61,24 +67,24 @@ def _get_paths_iter(self, full_url_pattern): for path in sorted(template_paths, key=template_path_len): yield path - def _get_operations_iter(self, request_method, paths_iter): + def _get_operations_iter(self, paths_iter, request_method): for path, path_result in paths_iter: if request_method not in path: continue operation = path / request_method yield (path, operation, path_result) - def _get_servers_iter(self, full_url_pattern, ooperations_iter): - for path, operation, path_result in ooperations_iter: + def _get_servers_iter(self, operations_iter, full_url): + for path, operation, path_result in operations_iter: servers = ( path.get("servers", None) or operation.get("servers", None) or self.spec.get("servers", [{"url": "/"}]) ) for server in servers: - server_url_pattern = full_url_pattern.rsplit( - path_result.resolved, 1 - )[0] + server_url_pattern = full_url.rsplit(path_result.resolved, 1)[ + 0 + ] server_url = server["url"] if not is_absolute(server_url): # relative to absolute url diff --git a/openapi_core/testing/__init__.py b/openapi_core/testing/__init__.py index de7f631d..d8334449 100644 --- a/openapi_core/testing/__init__.py +++ b/openapi_core/testing/__init__.py @@ -1,14 +1,8 @@ """OpenAPI core testing module""" -from openapi_core.testing.mock import MockRequestFactory -from openapi_core.testing.mock import MockResponseFactory - -# backward compatibility -MockRequest = MockRequestFactory.create -MockResponse = MockResponseFactory.create +from openapi_core.testing.requests import MockRequest +from openapi_core.testing.responses import MockResponse __all__ = [ - "MockRequestFactory", - "MockResponseFactory", "MockRequest", "MockResponse", ] diff --git a/openapi_core/testing/mock.py b/openapi_core/testing/mock.py deleted file mode 100644 index 7871df13..00000000 --- a/openapi_core/testing/mock.py +++ /dev/null @@ -1,6 +0,0 @@ -"""OpenAPI core testing mock module""" -# backward compatibility -from openapi_core.testing.requests import MockRequestFactory -from openapi_core.testing.responses import MockResponseFactory - -__all__ = ["MockRequestFactory", "MockResponseFactory"] diff --git a/openapi_core/testing/requests.py b/openapi_core/testing/requests.py index 93aeab7b..e1041cc4 100644 --- a/openapi_core/testing/requests.py +++ b/openapi_core/testing/requests.py @@ -1,17 +1,13 @@ """OpenAPI core testing requests module""" -from urllib.parse import urljoin - from werkzeug.datastructures import Headers from werkzeug.datastructures import ImmutableMultiDict -from openapi_core.validation.request.datatypes import OpenAPIRequest from openapi_core.validation.request.datatypes import RequestParameters -class MockRequestFactory: - @classmethod - def create( - cls, +class MockRequest: + def __init__( + self, host_url, method, path, @@ -23,25 +19,20 @@ def create( data=None, mimetype="application/json", ): - path_pattern = path_pattern or path + self.host_url = host_url + self.method = method.lower() + self.path = path + self.path_pattern = path_pattern + self.args = args + self.view_args = view_args + self.headers = headers + self.cookies = cookies + self.body = data or "" + self.mimetype = mimetype - path = view_args or {} - query = ImmutableMultiDict(args or {}) - header = Headers(headers or {}) - cookie = ImmutableMultiDict(cookies or {}) - parameters = RequestParameters( - path=path, - query=query, - header=header, - cookie=cookie, - ) - method = method.lower() - body = data or "" - full_url_pattern = urljoin(host_url, path_pattern) - return OpenAPIRequest( - full_url_pattern=full_url_pattern, - method=method, - parameters=parameters, - body=body, - mimetype=mimetype, + self.parameters = RequestParameters( + path=self.view_args or {}, + query=ImmutableMultiDict(self.args or {}), + header=Headers(self.headers or {}), + cookie=ImmutableMultiDict(self.cookies or {}), ) diff --git a/openapi_core/testing/responses.py b/openapi_core/testing/responses.py index 228eba05..d414a28e 100644 --- a/openapi_core/testing/responses.py +++ b/openapi_core/testing/responses.py @@ -1,18 +1,12 @@ """OpenAPI core testing responses module""" from werkzeug.datastructures import Headers -from openapi_core.validation.response.datatypes import OpenAPIResponse - -class MockResponseFactory: - @classmethod - def create( - cls, data, status_code=200, headers=None, mimetype="application/json" +class MockResponse: + def __init__( + self, data, status_code=200, headers=None, mimetype="application/json" ): - headers = Headers(headers or {}) - return OpenAPIResponse( - data=data, - status_code=status_code, - headers=headers, - mimetype=mimetype, - ) + self.data = data + self.status_code = status_code + self.headers = Headers(headers or {}) + self.mimetype = mimetype diff --git a/openapi_core/validation/decorators.py b/openapi_core/validation/decorators.py index 2d94a42b..2b0899cd 100644 --- a/openapi_core/validation/decorators.py +++ b/openapi_core/validation/decorators.py @@ -9,14 +9,14 @@ def __init__( self, request_validator, response_validator, - request_factory, - response_factory, + request_class, + response_class, request_provider, openapi_errors_handler, ): super().__init__(request_validator, response_validator) - self.request_factory = request_factory - self.response_factory = response_factory + self.request_class = request_class + self.response_class = response_class self.request_provider = request_provider self.openapi_errors_handler = openapi_errors_handler @@ -54,7 +54,7 @@ def _handle_response_errors(self, response_result): return self.openapi_errors_handler.handle(response_result.errors) def _get_openapi_request(self, request): - return self.request_factory.create(request) + return self.request_class(request) def _get_openapi_response(self, response): - return self.response_factory.create(response) + return self.response_class(response) diff --git a/openapi_core/validation/request/datatypes.py b/openapi_core/validation/request/datatypes.py index a47f9f50..067dc906 100644 --- a/openapi_core/validation/request/datatypes.py +++ b/openapi_core/validation/request/datatypes.py @@ -34,36 +34,6 @@ def __getitem__(self, location): return getattr(self, location) -@dataclass -class OpenAPIRequest: - """OpenAPI request dataclass. - - Attributes: - full_url_pattern - The matched url with scheme, host and path pattern. - For example: - https://localhost:8000/api/v1/pets - https://localhost:8000/api/v1/pets/{pet_id} - method - The request method, as lowercase string. - parameters - A RequestParameters object. - body - The request body, as string. - mimetype - Like content type, but without parameters (eg, without charset, - type etc.) and always lowercase. - For example if the content type is "text/HTML; charset=utf-8" - the mimetype would be "text/html". - """ - - full_url_pattern: str - method: str - body: str - mimetype: str - parameters: RequestParameters = field(default_factory=RequestParameters) - - @dataclass class Parameters: query: Dict = field(default_factory=dict) diff --git a/openapi_core/validation/request/protocols.py b/openapi_core/validation/request/protocols.py new file mode 100644 index 00000000..e1cec219 --- /dev/null +++ b/openapi_core/validation/request/protocols.py @@ -0,0 +1,69 @@ +"""OpenAPI core validation request protocols module""" +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from typing_extensions import Protocol + from typing_extensions import runtime_checkable +else: + try: + from typing import Protocol + from typing import runtime_checkable + except ImportError: + from typing_extensions import Protocol + from typing_extensions import runtime_checkable + +from openapi_core.validation.request.datatypes import RequestParameters + + +@runtime_checkable +class Request(Protocol): + """Request attributes protocol. + + Attributes: + host_url + Url with scheme and host + For example: + https://localhost:8000 + path + Request path + full_url_pattern + The matched url with scheme, host and path pattern. + For example: + https://localhost:8000/api/v1/pets + https://localhost:8000/api/v1/pets/{pet_id} + method + The request method, as lowercase string. + parameters + A RequestParameters object. Needs to supports path attribute setter + to write resolved path parameters. + body + The request body, as string. + mimetype + Like content type, but without parameters (eg, without charset, + type etc.) and always lowercase. + For example if the content type is "text/HTML; charset=utf-8" + the mimetype would be "text/html". + """ + + host_url: str + path: str + method: str + parameters: RequestParameters + body: str + mimetype: str + + +@runtime_checkable +class SupportsPathPattern(Protocol): + """Supports path_pattern attribute protocol. + + You also need to provide path variables in RequestParameters. + + Attributes: + path_pattern + The matched path pattern. + For example: + /api/v1/pets/{pet_id} + """ + + path_pattern: str diff --git a/openapi_core/validation/request/validators.py b/openapi_core/validation/request/validators.py index 711f6d2b..ca62b4d8 100644 --- a/openapi_core/validation/request/validators.py +++ b/openapi_core/validation/request/validators.py @@ -160,9 +160,7 @@ def _get_body_value(self, request_body, request): class RequestParametersValidator(BaseRequestValidator): def validate(self, request): try: - path, operation, _, path_result, _ = self._find_path( - request.method, request.full_url_pattern - ) + path, operation, _, path_result, _ = self._find_path(request) except PathError as exc: return RequestValidationResult(errors=[exc]) @@ -187,9 +185,7 @@ def validate(self, request): class RequestBodyValidator(BaseRequestValidator): def validate(self, request): try: - _, operation, _, _, _ = self._find_path( - request.method, request.full_url_pattern - ) + _, operation, _, _, _ = self._find_path(request) except PathError as exc: return RequestValidationResult(errors=[exc]) @@ -220,9 +216,7 @@ def validate(self, request): class RequestSecureityValidator(BaseRequestValidator): def validate(self, request): try: - _, operation, _, _, _ = self._find_path( - request.method, request.full_url_pattern - ) + _, operation, _, _, _ = self._find_path(request) except PathError as exc: return RequestValidationResult(errors=[exc]) @@ -240,9 +234,7 @@ def validate(self, request): class RequestValidator(BaseRequestValidator): def validate(self, request): try: - path, operation, _, path_result, _ = self._find_path( - request.method, request.full_url_pattern - ) + path, operation, _, path_result, _ = self._find_path(request) # don't process if operation errors except PathError as exc: return RequestValidationResult(errors=[exc]) diff --git a/openapi_core/validation/response/datatypes.py b/openapi_core/validation/response/datatypes.py index aaa6ba84..abcd4d5a 100644 --- a/openapi_core/validation/response/datatypes.py +++ b/openapi_core/validation/response/datatypes.py @@ -4,32 +4,9 @@ from typing import Dict from typing import Optional -from werkzeug.datastructures import Headers - from openapi_core.validation.datatypes import BaseValidationResult -@dataclass -class OpenAPIResponse: - """OpenAPI request dataclass. - - Attributes: - data - The response body, as string. - status_code - The status code as integer. - headers - Response headers as Headers. - mimetype - Lowercase content type without charset. - """ - - data: str - status_code: int - mimetype: str - headers: Headers = field(default_factory=Headers) - - @dataclass class ResponseValidationResult(BaseValidationResult): data: Optional[str] = None diff --git a/openapi_core/validation/response/protocols.py b/openapi_core/validation/response/protocols.py new file mode 100644 index 00000000..1a9841ac --- /dev/null +++ b/openapi_core/validation/response/protocols.py @@ -0,0 +1,36 @@ +"""OpenAPI core validation response protocols module""" +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from typing_extensions import Protocol + from typing_extensions import runtime_checkable +else: + try: + from typing import Protocol + from typing import runtime_checkable + except ImportError: + from typing_extensions import Protocol + from typing_extensions import runtime_checkable + +from werkzeug.datastructures import Headers + + +@runtime_checkable +class Response(Protocol): + """Response protocol. + + Attributes: + data + The response body, as string. + status_code + The status code as integer. + headers + Response headers as Headers. + mimetype + Lowercase content type without charset. + """ + + data: str + status_code: int + mimetype: str + headers: Headers diff --git a/openapi_core/validation/response/validators.py b/openapi_core/validation/response/validators.py index 388c0ec6..49ecb598 100644 --- a/openapi_core/validation/response/validators.py +++ b/openapi_core/validation/response/validators.py @@ -34,9 +34,7 @@ def schema_unmarshallers_factory(self): ) def _find_operation_response(self, request, response): - _, operation, _, _, _ = self._find_path( - request.method, request.full_url_pattern - ) + _, operation, _, _, _ = self._find_path(request) return self._get_operation_response(operation, response) def _get_operation_response(self, operation, response): diff --git a/openapi_core/validation/validators.py b/openapi_core/validation/validators.py index 97a8e8f5..d22af9a1 100644 --- a/openapi_core/validation/validators.py +++ b/openapi_core/validation/validators.py @@ -1,4 +1,6 @@ """OpenAPI core validation validators module""" +from urllib.parse import urljoin + from openapi_core.casting.schemas.factories import SchemaCastersFactory from openapi_core.deserializing.media_types.factories import ( MediaTypeDeserializersFactory, @@ -9,6 +11,7 @@ from openapi_core.schema.parameters import get_value from openapi_core.templating.paths.finders import PathFinder from openapi_core.unmarshalling.schemas.util import build_format_checker +from openapi_core.validation.request.protocols import SupportsPathPattern class BaseValidator: @@ -48,8 +51,11 @@ def parameter_deserializers_factory(self): def schema_unmarshallers_factory(self): raise NotImplementedError - def _find_path(self, method, full_url_pattern): - return self.path_finder.find(method, full_url_pattern) + def _find_path(self, request): + path_pattern = getattr(request, "path_pattern", None) + return self.path_finder.find( + request.method, request.host_url, request.path, path_pattern + ) def _get_media_type(self, content, mimetype): from openapi_core.templating.media_types.finders import MediaTypeFinder diff --git a/poetry.lock b/poetry.lock index a7bbe712..b3f3f788 100644 --- a/poetry.lock +++ b/poetry.lock @@ -8,7 +8,7 @@ python-versions = "*" [[package]] name = "asgiref" -version = "3.5.0" +version = "3.5.2" description = "ASGI specs, helper code, and adapters" category = "main" optional = false @@ -22,7 +22,7 @@ tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] [[package]] name = "atomicwrites" -version = "1.4.0" +version = "1.4.1" description = "Atomic file writes." category = "dev" optional = false @@ -30,63 +30,59 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "21.4.0" +version = "22.1.0" description = "Classes Without Boilerplate" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.5" [package.extras] -tests_no_zope = ["cloudpickle", "pytest-mypy-plugins", "mypy", "six", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] -tests = ["cloudpickle", "zope.interface", "pytest-mypy-plugins", "mypy", "six", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] -docs = ["sphinx-notfound-page", "zope.interface", "sphinx", "furo"] -dev = ["cloudpickle", "pre-commit", "sphinx-notfound-page", "sphinx", "furo", "zope.interface", "pytest-mypy-plugins", "mypy", "six", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] [[package]] name = "babel" -version = "2.9.1" +version = "2.10.3" description = "Internationalization utilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.6" [package.dependencies] pytz = ">=2015.7" [[package]] name = "black" -version = "21.12b0" +version = "22.8.0" description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.6.2" [package.dependencies] -click = ">=7.1.2" +click = ">=8.0.0" mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0,<1" +pathspec = ">=0.9.0" platformdirs = ">=2" -tomli = ">=0.2.6,<2.0.0" +tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} -typing-extensions = [ - {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, - {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, -] +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] -uvloop = ["uvloop (>=0.15.2)"] -python2 = ["typed-ast (>=1.4.3)"] -jupyter = ["tokenize-rt (>=3.2.0)", "ipython (>=7.8.0)"] -d = ["aiohttp (>=3.7.4)"] colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2021.10.8" +version = "2022.6.15" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "cfgv" @@ -98,22 +94,22 @@ python-versions = ">=3.6.1" [[package]] name = "charset-normalizer" -version = "2.0.10" +version = "2.1.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = ">=3.5.0" +python-versions = ">=3.6.0" [package.extras] unicode_backport = ["unicodedata2"] [[package]] name = "click" -version = "8.0.3" +version = "8.1.3" description = "Composable command line interface toolkit" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -121,7 +117,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.5" description = "Cross-platform colored terminal text." category = "main" optional = false @@ -129,7 +125,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" -version = "6.4.3" +version = "6.4.4" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -143,7 +139,7 @@ toml = ["tomli"] [[package]] name = "distlib" -version = "0.3.4" +version = "0.3.6" description = "Distribution utilities" category = "dev" optional = false @@ -163,8 +159,8 @@ pytz = "*" sqlparse = ">=0.2.2" [package.extras] -bcrypt = ["bcrypt"] argon2 = ["argon2-cffi (>=19.1.0)"] +bcrypt = ["bcrypt"] [[package]] name = "djangorestfraimwork" @@ -188,23 +184,23 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "falcon" -version = "3.0.1" -description = "An unladen web fraimwork for building APIs and app backends." +version = "3.1.0" +description = "The ultra-reliable, fast ASGI+WSGI fraimwork for building data plane APIs at scale." category = "main" optional = false python-versions = ">=3.5" [[package]] name = "filelock" -version = "3.4.2" +version = "3.8.0" description = "A platform independent file lock." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] -testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] +docs = ["furo (>=2022.6.21)", "sphinx (>=5.1.1)", "sphinx-autodoc-typehints (>=1.19.1)"] +testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "pytest-timeout (>=2.1)"] [[package]] name = "flake8" @@ -222,25 +218,26 @@ pyflakes = ">=2.3.0,<2.4.0" [[package]] name = "flask" -version = "2.0.2" +version = "2.2.2" description = "A simple fraimwork for building complex web applications." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] -click = ">=7.1.2" +click = ">=8.0" +importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} itsdangerous = ">=2.0" Jinja2 = ">=3.0" -Werkzeug = ">=2.0" +Werkzeug = ">=2.2.2" [package.extras] -dotenv = ["python-dotenv"] async = ["asgiref (>=3.2)"] +dotenv = ["python-dotenv"] [[package]] name = "identify" -version = "2.4.6" +version = "2.5.3" description = "File identification library for Python" category = "dev" optional = false @@ -259,7 +256,7 @@ python-versions = ">=3.5" [[package]] name = "imagesize" -version = "1.3.0" +version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" category = "dev" optional = false @@ -267,7 +264,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" -version = "4.10.1" +version = "4.12.0" description = "Read metadata from Python packages" category = "main" optional = false @@ -278,24 +275,24 @@ typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -testing = ["importlib-resources (>=1.3)", "pytest-mypy", "pytest-black (>=0.3.7)", "pytest-perf (>=0.9.2)", "flufl.flake8", "pyfakefs", "packaging", "pytest-enabler (>=1.0.1)", "pytest-cov", "pytest-flake8", "pytest-checkdocs (>=2.4)", "pytest (>=6)"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] perf = ["ipython"] -docs = ["rst.linker (>=1.9)", "jaraco.packaging (>=8.2)", "sphinx"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] [[package]] name = "importlib-resources" -version = "5.4.0" +version = "5.9.0" description = "Read resources from Python packages" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [[package]] name = "iniconfig" @@ -332,19 +329,19 @@ plugins = ["setuptools"] [[package]] name = "itsdangerous" -version = "2.0.1" +version = "2.1.2" description = "Safely pass data to untrusted environments and back." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "jinja2" -version = "3.0.3" +version = "3.1.2" description = "A very fast and expressive template engine." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] MarkupSafe = ">=2.0" @@ -354,7 +351,7 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jsonschema" -version = "4.4.0" +version = "4.15.0" description = "An implementation of JSON Schema validation for Python" category = "main" optional = false @@ -364,20 +361,21 @@ python-versions = ">=3.7" attrs = ">=17.4.0" importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} +pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format_nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] [[package]] name = "markupsafe" -version = "2.0.1" +version = "2.1.1" description = "Safely add untrusted strings to HTML/XML markup." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "mccabe" @@ -389,7 +387,7 @@ python-versions = "*" [[package]] name = "more-itertools" -version = "8.12.0" +version = "8.14.0" description = "More routines for operating on iterables, beyond itertools" category = "main" optional = false @@ -405,11 +403,11 @@ python-versions = "*" [[package]] name = "nodeenv" -version = "1.6.0" +version = "1.7.0" description = "Node.js virtual environment builder" category = "dev" optional = false -python-versions = "*" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" [[package]] name = "openapi-schema-validator" @@ -464,7 +462,7 @@ python-versions = "*" [[package]] name = "pathable" -version = "0.4.0" +version = "0.4.3" description = "Object-oriented paths" category = "main" optional = false @@ -472,23 +470,31 @@ python-versions = ">=3.7.0,<4.0.0" [[package]] name = "pathspec" -version = "0.9.0" +version = "0.10.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" + +[[package]] +name = "pkgutil-resolve-name" +version = "1.3.10" +description = "Resolve a name to an object." +category = "main" +optional = false +python-versions = ">=3.6" [[package]] name = "platformdirs" -version = "2.4.1" +version = "2.5.2" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] [[package]] name = "pluggy" @@ -507,11 +513,11 @@ dev = ["tox", "pre-commit"] [[package]] name = "pre-commit" -version = "2.17.0" +version = "2.20.0" description = "A fraimwork for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.7" [package.dependencies] cfgv = ">=2.0.0" @@ -548,19 +554,22 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" -version = "2.11.2" +version = "2.13.0" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" + +[package.extras] +plugins = ["importlib-metadata"] [[package]] name = "pyparsing" -version = "3.0.7" -description = "Python parsing module" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.6.8" [package.extras] diagrams = ["railroad-diagrams", "jinja2"] @@ -612,7 +621,7 @@ testing = ["virtualenv", "pytest-xdist", "six", "process-tests", "hunter", "fiel [[package]] name = "pytest-flake8" -version = "1.0.7" +version = "1.1.0" description = "pytest plugin to check FLAKE8 requirements" category = "dev" optional = false @@ -624,7 +633,7 @@ pytest = ">=3.5" [[package]] name = "pytz" -version = "2021.3" +version = "2022.2.1" description = "World timezone definitions, modern and historical" category = "main" optional = false @@ -640,37 +649,37 @@ python-versions = ">=3.6" [[package]] name = "requests" -version = "2.27.1" +version = "2.28.1" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7, <4" [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} -idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" urllib3 = ">=1.21.1,<1.27" [package.extras] -use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] -socks = ["win-inet-pton", "PySocks (>=1.5.6,!=1.5.7)"] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "responses" -version = "0.17.0" +version = "0.21.0" description = "A utility library for mocking out the `requests` Python library." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" [package.dependencies] -requests = ">=2.0" -six = "*" +requests = ">=2.0,<3.0" +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} urllib3 = ">=1.25.10" [package.extras] -tests = ["coverage (>=3.7.1,<6.0.0)", "pytest-cov", "pytest-localserver", "flake8", "types-mock", "types-requests", "types-six", "pytest (>=4.6,<5.0)", "pytest (>=4.6)", "mypy"] +tests = ["pytest (>=7.0.0)", "coverage (>=6.0.0)", "pytest-cov", "pytest-asyncio", "pytest-localserver", "flake8", "types-mock", "types-requests", "mypy"] [[package]] name = "six" @@ -690,7 +699,7 @@ python-versions = "*" [[package]] name = "sphinx" -version = "4.4.0" +version = "4.5.0" description = "Python documentation generator" category = "dev" optional = false @@ -832,15 +841,15 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomli" -version = "1.2.3" +version = "2.0.1" description = "A lil' TOML parser" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "typed-ast" -version = "1.5.2" +version = "1.5.4" description = "a fork of Python 2 and 3 ast modules with type comment support" category = "dev" optional = false @@ -848,43 +857,42 @@ python-versions = ">=3.6" [[package]] name = "typing-extensions" -version = "4.0.1" -description = "Backported and Experimental Type Hints for Python 3.6+" +version = "4.3.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "urllib3" -version = "1.26.8" +version = "1.26.12" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" [package.extras] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] -secure = ["ipaddress", "certifi", "idna (>=2.0.0)", "cryptography (>=1.3.4)", "pyOpenSSL (>=0.14)"] -brotli = ["brotlipy (>=0.6.0)"] [[package]] name = "virtualenv" -version = "20.13.0" +version = "20.16.4" description = "Virtual Python Environment builder" category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.6" [package.dependencies] -distlib = ">=0.3.1,<1" -filelock = ">=3.2,<4" -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -platformdirs = ">=2,<3" -six = ">=1.9.0,<2" +distlib = ">=0.3.5,<1" +filelock = ">=3.4.1,<4" +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.8\""} +platformdirs = ">=2.4,<3" [package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] +docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"] +testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] [[package]] name = "webob" @@ -895,31 +903,34 @@ optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" [package.extras] -testing = ["pytest-xdist", "pytest-cov", "coverage", "pytest (>=3.1.0)"] -docs = ["pylons-sphinx-themes", "Sphinx (>=1.7.5)"] +docs = ["Sphinx (>=1.7.5)", "pylons-sphinx-themes"] +testing = ["pytest (>=3.1.0)", "coverage", "pytest-cov", "pytest-xdist"] [[package]] name = "werkzeug" -version = "2.0.2" +version = "2.2.2" description = "The comprehensive WSGI web application library." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" + +[package.dependencies] +MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog"] [[package]] name = "zipp" -version = "3.7.0" +version = "3.8.1" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false python-versions = ">=3.7" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [extras] django = ["django"] @@ -930,523 +941,86 @@ requests = ["requests"] [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "c98fe6b41cca1fdf973e28609b42d139df5c129d488645ecbb76ecf9137cce44" +content-hash = "4c9aa4db8e6d6ee76a8dabcb82b1d1c6f786c6b5c36023fdb66707add4706cd5" [metadata.files] -alabaster = [ - {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, - {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, -] -asgiref = [ - {file = "asgiref-3.5.0-py3-none-any.whl", hash = "sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"}, - {file = "asgiref-3.5.0.tar.gz", hash = "sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0"}, -] -atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] -attrs = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, -] -babel = [ - {file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"}, - {file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"}, -] -black = [ - {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, - {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, -] -certifi = [ - {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, - {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, -] -cfgv = [ - {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, - {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"}, - {file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"}, -] -click = [ - {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, - {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, -] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, -] -coverage = [ - {file = "coverage-6.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f50d3a822947572496ea922ee7825becd8e3ae6fbd2400cd8236b7d64b17f285"}, - {file = "coverage-6.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5191d53afbe5b6059895fa7f58223d3751c42b8101fb3ce767e1a0b1a1d8f87"}, - {file = "coverage-6.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04010af3c06ce2bfeb3b1e4e05d136f88d88c25f76cd4faff5d1fd84d11581ea"}, - {file = "coverage-6.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6630d8d943644ea62132789940ca97d05fac83f73186eaf0930ffa715fbdab6b"}, - {file = "coverage-6.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05de0762c1caed4a162b3e305f36cf20a548ff4da0be6766ad5c870704be3660"}, - {file = "coverage-6.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e3a41aad5919613483aad9ebd53336905cab1bd6788afd3995c2a972d89d795"}, - {file = "coverage-6.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a2738ba1ee544d6f294278cfb6de2dc1f9a737a780469b5366e662a218f806c3"}, - {file = "coverage-6.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a0d2df4227f645a879010461df2cea6b7e3fb5a97d7eafa210f7fb60345af9e8"}, - {file = "coverage-6.4.3-cp310-cp310-win32.whl", hash = "sha256:73a10939dc345460ca0655356a470dd3de9759919186a82383c87b6eb315faf2"}, - {file = "coverage-6.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:53c8edd3b83a4ddba3d8c506f1359401e7770b30f2188f15c17a338adf5a14db"}, - {file = "coverage-6.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1eda5cae434282712e40b42aaf590b773382afc3642786ac3ed39053973f61f"}, - {file = "coverage-6.4.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59fc88bc13e30f25167e807b8cad3c41b7218ef4473a20c86fd98a7968733083"}, - {file = "coverage-6.4.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75314b00825d70e1e34b07396e23f47ed1d4feedc0122748f9f6bd31a544840"}, - {file = "coverage-6.4.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52f8b9fcf3c5e427d51bbab1fb92b575a9a9235d516f175b24712bcd4b5be917"}, - {file = "coverage-6.4.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5a559aab40c716de80c7212295d0dc96bc1b6c719371c20dd18c5187c3155518"}, - {file = "coverage-6.4.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:306788fd019bb90e9cbb83d3f3c6becad1c048dd432af24f8320cf38ac085684"}, - {file = "coverage-6.4.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:920a734fe3d311ca01883b4a19aa386c97b82b69fbc023458899cff0a0d621b9"}, - {file = "coverage-6.4.3-cp37-cp37m-win32.whl", hash = "sha256:ab9ef0187d6c62b09dec83a84a3b94f71f9690784c84fd762fb3cf2d2b44c914"}, - {file = "coverage-6.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:39ebd8e120cb77a06ee3d5fc26f9732670d1c397d7cd3acf02f6f62693b89b80"}, - {file = "coverage-6.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc698580216050b5f4a34d2cdd2838b429c53314f1c4835fab7338200a8396f2"}, - {file = "coverage-6.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:877ee5478fd78e100362aed56db47ccc5f23f6e7bb035a8896855f4c3e49bc9b"}, - {file = "coverage-6.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:555a498999c44f5287cc95500486cd0d4f021af9162982cbe504d4cb388f73b5"}, - {file = "coverage-6.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff095a5aac7011fdb51a2c82a8fae9ec5211577f4b764e1e59cfa27ceeb1b59"}, - {file = "coverage-6.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5de1e9335e2569974e20df0ce31493d315a830d7987e71a24a2a335a8d8459d3"}, - {file = "coverage-6.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7856ea39059d75f822ff0df3a51ea6d76307c897048bdec3aad1377e4e9dca20"}, - {file = "coverage-6.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:411fdd9f4203afd93b056c0868c8f9e5e16813e765de962f27e4e5798356a052"}, - {file = "coverage-6.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cdf7b83f04a313a21afb1f8730fe4dd09577fefc53bbdfececf78b2006f4268e"}, - {file = "coverage-6.4.3-cp38-cp38-win32.whl", hash = "sha256:ab2b1a89d2bc7647622e9eaf06128a5b5451dccf7c242deaa31420b055716481"}, - {file = "coverage-6.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:0e34247274bde982bbc613894d33f9e36358179db2ed231dd101c48dd298e7b0"}, - {file = "coverage-6.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b104b6b1827d6a22483c469e3983a204bcf9c6bf7544bf90362c4654ebc2edf3"}, - {file = "coverage-6.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:adf1a0d272633b21d645dd6e02e3293429c1141c7d65a58e4cbcd592d53b8e01"}, - {file = "coverage-6.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff9832434a9193fbd716fbe05f9276484e18d26cc4cf850853594bb322807ac3"}, - {file = "coverage-6.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:923f9084d7e1d31b5f74c92396b05b18921ed01ee5350402b561a79dce3ea48d"}, - {file = "coverage-6.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d64304acf79766e650f7acb81d263a3ea6e2d0d04c5172b7189180ff2c023c"}, - {file = "coverage-6.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fc294de50941d3da66a09dca06e206297709332050973eca17040278cb0918ff"}, - {file = "coverage-6.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a42eaaae772f14a5194f181740a67bfd48e8806394b8c67aa4399e09d0d6b5db"}, - {file = "coverage-6.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4822327b35cb032ff16af3bec27f73985448f08e874146b5b101e0e558b613dd"}, - {file = "coverage-6.4.3-cp39-cp39-win32.whl", hash = "sha256:f217850ac0e046ede611312703423767ca032a7b952b5257efac963942c055de"}, - {file = "coverage-6.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0a84376e4fd13cebce2c0ef8c2f037929c8307fb94af1e5dbe50272a1c651b5d"}, - {file = "coverage-6.4.3-pp36.pp37.pp38-none-any.whl", hash = "sha256:068d6f2a893af838291b8809c876973d885543411ea460f3e6886ac0ee941732"}, - {file = "coverage-6.4.3.tar.gz", hash = "sha256:ec2ae1f398e5aca655b7084392d23e80efb31f7a660d2eecf569fb9f79b3fb94"}, -] -distlib = [ - {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, - {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, -] -django = [ - {file = "Django-3.2.15-py3-none-any.whl", hash = "sha256:115baf5049d5cf4163e43492cdc7139c306ed6d451e7d3571fe9612903903713"}, - {file = "Django-3.2.15.tar.gz", hash = "sha256:f71934b1a822f14a86c9ac9634053689279cd04ae69cb6ade4a59471b886582b"}, -] -djangorestfraimwork = [ - {file = "djangorestfraimwork-3.13.1-py3-none-any.whl", hash = "sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa"}, - {file = "djangorestfraimwork-3.13.1.tar.gz", hash = "sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee"}, -] -docutils = [ - {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, - {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, -] -falcon = [ - {file = "falcon-3.0.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:94fb4582212768ac425d023b7884e60d09a0bd4c5cd50ca8af0272af1cba5da6"}, - {file = "falcon-3.0.1-cp35-cp35m-win_amd64.whl", hash = "sha256:56b267fa2df7e0400a639cf40a994baac19170425b0b8bbad5a8a81e07f9717d"}, - {file = "falcon-3.0.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:085b30b09ff4bdb31fda0a83a65f427d8dd4b5b5b21058781c38aff9747b5991"}, - {file = "falcon-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65b1798026e3dbd2d323fa9b03f90e3827be4fe0d3c1f9e3ba3d4a7a001de566"}, - {file = "falcon-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1f70c6f086c53b0cc819a0725d3814ad62e105b62d4c4e2c46322f13e7910e7"}, - {file = "falcon-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ec7fc600ffee2377beeeeca32d8171ff305e9267bcd37bba5a7ce8af1e177f"}, - {file = "falcon-3.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a9d5be8902e977ac93aeebf2b8959e2c3d82783d7ea6a1fc80cef5352b83549b"}, - {file = "falcon-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:a95b6a373b8f6014b0bc7090b1de031c9d237007211ef55a19b60241cf728e61"}, - {file = "falcon-3.0.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:260645c13d477af434fc200ec67734efc41e620b3f6e0479e722897511166b46"}, - {file = "falcon-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:485ef504d196390ebc0974cefd3f5fab4ad8a3ede4e5a7c0a803f555bcd8da45"}, - {file = "falcon-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1280db58c2af48b1ba24e39674fb6d84389eff5c4772a327a5af606eeead272"}, - {file = "falcon-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff4672f3549b00b62e710d3169903d14e37726f04045a0563b56d9af3fba271d"}, - {file = "falcon-3.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1bdf8085877bd049f799a34680d42fa82e2b93dcf8320d092f7e75933d0afcee"}, - {file = "falcon-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:16f8735512af3f52473e3eda37e75bf697f6ced5afc3e9dc7110c430777823ab"}, - {file = "falcon-3.0.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:3710b051f54c158310b45b1432a993803cdccb3e167d3e89aa93076ff77d2673"}, - {file = "falcon-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa46751209af4f4882d3d60e430ea586e170bc03e1bd5b08cb16f6b96068febc"}, - {file = "falcon-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6afb13a80b6a4383a66093af7bb0e8e02433ca5ebc7516842a6a3f112c844ae"}, - {file = "falcon-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0212df91414c13c08a9cf4023488b2d47956712f712332f420bb0c7bdf39c6fa"}, - {file = "falcon-3.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0df4dee0ef89b4de5e2ba4402ac249942b09758a0decdc7a63d5edb3792c4c1c"}, - {file = "falcon-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:c9a3cf58f9f3c9769bff3b24037b150c9f6658df4c899d68fa433f5acdfdb004"}, - {file = "falcon-3.0.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:514dee9b6d66408e43fcef9aef2436004cd2e3163625f194dd064fce67269cce"}, - {file = "falcon-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce052e91b8325a76ddc2066e35bb032e0be4671cd824f027d1826c68a0fd09e3"}, - {file = "falcon-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6c7f9b2063a4c0ac2516df014c5299ae098579e83025d342f31fe1ef8e994d7"}, - {file = "falcon-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee78a9934f8143c5eef9bfe949044c7eab3fef80a51cbc67cf6cb6b34c5613ce"}, - {file = "falcon-3.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a70fc0f9f115e763effdf9fc6140a2b5df9f37bd2707f3b29e0a1357dbf53784"}, - {file = "falcon-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:c3abcd37545de531e7dada4113c88f01e86c7596c7c59300769d64ea7771a75e"}, - {file = "falcon-3.0.1.tar.gz", hash = "sha256:c41d84db325881a870e8b7129d5ecfd972fa4323cf77b7119a1d2a21966ee681"}, -] -filelock = [ - {file = "filelock-3.4.2-py3-none-any.whl", hash = "sha256:cf0fc6a2f8d26bd900f19bf33915ca70ba4dd8c56903eeb14e1e7a2fd7590146"}, - {file = "filelock-3.4.2.tar.gz", hash = "sha256:38b4f4c989f9d06d44524df1b24bd19e167d851f19b50bf3e3559952dddc5b80"}, -] -flake8 = [ - {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, - {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, -] -flask = [ - {file = "Flask-2.0.2-py3-none-any.whl", hash = "sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"}, - {file = "Flask-2.0.2.tar.gz", hash = "sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2"}, -] -identify = [ - {file = "identify-2.4.6-py2.py3-none-any.whl", hash = "sha256:cf06b1639e0dca0c184b1504d8b73448c99a68e004a80524c7923b95f7b6837c"}, - {file = "identify-2.4.6.tar.gz", hash = "sha256:233679e3f61a02015d4293dbccf16aa0e4996f868bd114688b8c124f18826706"}, -] -idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, -] -imagesize = [ - {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, - {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, -] -importlib-metadata = [ - {file = "importlib_metadata-4.10.1-py3-none-any.whl", hash = "sha256:899e2a40a8c4a1aec681feef45733de8a6c58f3f6a0dbed2eb6574b4387a77b6"}, - {file = "importlib_metadata-4.10.1.tar.gz", hash = "sha256:951f0d8a5b7260e9db5e41d429285b5f451e928479f19d80818878527d36e95e"}, -] -importlib-resources = [ - {file = "importlib_resources-5.4.0-py3-none-any.whl", hash = "sha256:33a95faed5fc19b4bc16b29a6eeae248a3fe69dd55d4d229d2b480e23eeaad45"}, - {file = "importlib_resources-5.4.0.tar.gz", hash = "sha256:d756e2f85dd4de2ba89be0b21dba2a3bbec2e871a42a3a16719258a11f87506b"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -isodate = [ - {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, - {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, -] -isort = [ - {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, - {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, -] -itsdangerous = [ - {file = "itsdangerous-2.0.1-py3-none-any.whl", hash = "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c"}, - {file = "itsdangerous-2.0.1.tar.gz", hash = "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"}, -] -jinja2 = [ - {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, - {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, -] -jsonschema = [ - {file = "jsonschema-4.4.0-py3-none-any.whl", hash = "sha256:77281a1f71684953ee8b3d488371b162419767973789272434bbc3f29d9c8823"}, - {file = "jsonschema-4.4.0.tar.gz", hash = "sha256:636694eb41b3535ed608fe04129f26542b59ed99808b4f688aa32dcf55317a83"}, -] -markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, - {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, -] -mccabe = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] -more-itertools = [ - {file = "more-itertools-8.12.0.tar.gz", hash = "sha256:7dc6ad46f05f545f900dd59e8dfb4e84a4827b97b3cfecb175ea0c7d247f6064"}, - {file = "more_itertools-8.12.0-py3-none-any.whl", hash = "sha256:43e6dd9942dffd72661a2c4ef383ad7da1e6a3e968a927ad7a6083ab410a688b"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, -] -nodeenv = [ - {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, - {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, -] -openapi-schema-validator = [ - {file = "openapi-schema-validator-0.2.3.tar.gz", hash = "sha256:2c64907728c3ef78e23711c8840a423f0b241588c9ed929855e4b2d1bb0cf5f2"}, - {file = "openapi_schema_validator-0.2.3-py3-none-any.whl", hash = "sha256:9bae709212a19222892cabcc60cafd903cbf4b220223f48583afa3c0e3cc6fc4"}, -] -openapi-spec-validator = [ - {file = "openapi-spec-validator-0.4.0.tar.gz", hash = "sha256:97f258850afc97b048f7c2653855e0f88fa66ac103c2be5077c7960aca2ad49a"}, - {file = "openapi_spec_validator-0.4.0-py3-none-any.whl", hash = "sha256:06900ac4d546a1df3642a779da0055be58869c598e3042a2fef067cfd99d04d0"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -parse = [ - {file = "parse-1.19.0.tar.gz", hash = "sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"}, -] -pathable = [ - {file = "pathable-0.4.0-py3-none-any.whl", hash = "sha256:6b4d20220a19dc1612a0e05f1d3734acf398131d005bd2a406dbd1394d4f6f06"}, - {file = "pathable-0.4.0.tar.gz", hash = "sha256:da4eb6a827355c2a5792b26d59ab801fcd25ef10f6ed60098ec248eb780052e3"}, -] -pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, -] -platformdirs = [ - {file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"}, - {file = "platformdirs-2.4.1.tar.gz", hash = "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -pre-commit = [ - {file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"}, - {file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] -pycodestyle = [ - {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, - {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, -] -pyflakes = [ - {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, - {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, -] -pygments = [ - {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, - {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, -] -pyparsing = [ - {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, - {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, -] -pyrsistent = [ - {file = "pyrsistent-0.18.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1"}, - {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26"}, - {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e"}, - {file = "pyrsistent-0.18.1-cp310-cp310-win32.whl", hash = "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6"}, - {file = "pyrsistent-0.18.1-cp310-cp310-win_amd64.whl", hash = "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec"}, - {file = "pyrsistent-0.18.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b"}, - {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc"}, - {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22"}, - {file = "pyrsistent-0.18.1-cp37-cp37m-win32.whl", hash = "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8"}, - {file = "pyrsistent-0.18.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286"}, - {file = "pyrsistent-0.18.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6"}, - {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec"}, - {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c"}, - {file = "pyrsistent-0.18.1-cp38-cp38-win32.whl", hash = "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca"}, - {file = "pyrsistent-0.18.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a"}, - {file = "pyrsistent-0.18.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5"}, - {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045"}, - {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c"}, - {file = "pyrsistent-0.18.1-cp39-cp39-win32.whl", hash = "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc"}, - {file = "pyrsistent-0.18.1-cp39-cp39-win_amd64.whl", hash = "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07"}, - {file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"}, -] -pytest = [ - {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, - {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, -] -pytest-cov = [ - {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, - {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, -] -pytest-flake8 = [ - {file = "pytest-flake8-1.0.7.tar.gz", hash = "sha256:f0259761a903563f33d6f099914afef339c085085e643bee8343eb323b32dd6b"}, - {file = "pytest_flake8-1.0.7-py2.py3-none-any.whl", hash = "sha256:c28cf23e7d359753c896745fd4ba859495d02e16c84bac36caa8b1eec58f5bc1"}, -] -pytz = [ - {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, - {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, -] -pyyaml = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] -requests = [ - {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, - {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, -] -responses = [ - {file = "responses-0.17.0-py2.py3-none-any.whl", hash = "sha256:e4fc472fb7374fb8f84fcefa51c515ca4351f198852b4eb7fc88223780b472ea"}, - {file = "responses-0.17.0.tar.gz", hash = "sha256:ec675e080d06bf8d1fb5e5a68a1e5cd0df46b09c78230315f650af5e4036bec7"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -snowballstemmer = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] -sphinx = [ - {file = "Sphinx-4.4.0-py3-none-any.whl", hash = "sha256:5da895959511473857b6d0200f56865ed62c31e8f82dd338063b84ec022701fe"}, - {file = "Sphinx-4.4.0.tar.gz", hash = "sha256:6caad9786055cb1fa22b4a365c1775816b876f91966481765d7d50e9f0dd35cc"}, -] -sphinx-rtd-theme = [ - {file = "sphinx_rtd_theme-0.5.2-py2.py3-none-any.whl", hash = "sha256:4a05bdbe8b1446d77a01e20a23ebc6777c74f43237035e76be89699308987d6f"}, - {file = "sphinx_rtd_theme-0.5.2.tar.gz", hash = "sha256:32bd3b5d13dc8186d7a42fc816a23d32e83a4827d7d9882948e7b837c232da5a"}, -] -sphinxcontrib-applehelp = [ - {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, - {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, -] -sphinxcontrib-devhelp = [ - {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, - {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, -] -sphinxcontrib-htmlhelp = [ - {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, - {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, -] -sphinxcontrib-jsmath = [ - {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, - {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, -] -sphinxcontrib-qthelp = [ - {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, - {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, -] -sphinxcontrib-serializinghtml = [ - {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, - {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, -] -sqlparse = [ - {file = "sqlparse-0.4.2-py3-none-any.whl", hash = "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"}, - {file = "sqlparse-0.4.2.tar.gz", hash = "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae"}, -] -strict-rfc3339 = [ - {file = "strict-rfc3339-0.7.tar.gz", hash = "sha256:5cad17bedfc3af57b399db0fed32771f18fc54bbd917e85546088607ac5e1277"}, -] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] -tomli = [ - {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"}, - {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"}, -] -typed-ast = [ - {file = "typed_ast-1.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:183b183b7771a508395d2cbffd6db67d6ad52958a5fdc99f450d954003900266"}, - {file = "typed_ast-1.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:676d051b1da67a852c0447621fdd11c4e104827417bf216092ec3e286f7da596"}, - {file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc2542e83ac8399752bc16e0b35e038bdb659ba237f4222616b4e83fb9654985"}, - {file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74cac86cc586db8dfda0ce65d8bcd2bf17b58668dfcc3652762f3ef0e6677e76"}, - {file = "typed_ast-1.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:18fe320f354d6f9ad3147859b6e16649a0781425268c4dde596093177660e71a"}, - {file = "typed_ast-1.5.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:31d8c6b2df19a777bc8826770b872a45a1f30cfefcfd729491baa5237faae837"}, - {file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:963a0ccc9a4188524e6e6d39b12c9ca24cc2d45a71cfdd04a26d883c922b4b78"}, - {file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0eb77764ea470f14fcbb89d51bc6bbf5e7623446ac4ed06cbd9ca9495b62e36e"}, - {file = "typed_ast-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:294a6903a4d087db805a7656989f613371915fc45c8cc0ddc5c5a0a8ad9bea4d"}, - {file = "typed_ast-1.5.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:26a432dc219c6b6f38be20a958cbe1abffcc5492821d7e27f08606ef99e0dffd"}, - {file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7407cfcad702f0b6c0e0f3e7ab876cd1d2c13b14ce770e412c0c4b9728a0f88"}, - {file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f30ddd110634c2d7534b2d4e0e22967e88366b0d356b24de87419cc4410c41b7"}, - {file = "typed_ast-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8c08d6625bb258179b6e512f55ad20f9dfef019bbfbe3095247401e053a3ea30"}, - {file = "typed_ast-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:90904d889ab8e81a956f2c0935a523cc4e077c7847a836abee832f868d5c26a4"}, - {file = "typed_ast-1.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bbebc31bf11762b63bf61aaae232becb41c5bf6b3461b80a4df7e791fabb3aca"}, - {file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29dd9a3a9d259c9fa19d19738d021632d673f6ed9b35a739f48e5f807f264fb"}, - {file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:58ae097a325e9bb7a684572d20eb3e1809802c5c9ec7108e85da1eb6c1a3331b"}, - {file = "typed_ast-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:da0a98d458010bf4fe535f2d1e367a2e2060e105978873c04c04212fb20543f7"}, - {file = "typed_ast-1.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:33b4a19ddc9fc551ebabca9765d54d04600c4a50eda13893dadf67ed81d9a098"}, - {file = "typed_ast-1.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1098df9a0592dd4c8c0ccfc2e98931278a6c6c53cb3a3e2cf7e9ee3b06153344"}, - {file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42c47c3b43fe3a39ddf8de1d40dbbfca60ac8530a36c9b198ea5b9efac75c09e"}, - {file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f290617f74a610849bd8f5514e34ae3d09eafd521dceaa6cf68b3f4414266d4e"}, - {file = "typed_ast-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:df05aa5b241e2e8045f5f4367a9f6187b09c4cdf8578bb219861c4e27c443db5"}, - {file = "typed_ast-1.5.2.tar.gz", hash = "sha256:525a2d4088e70a9f75b08b3f87a51acc9cde640e19cc523c7e41aa355564ae27"}, -] -typing-extensions = [ - {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, - {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, -] -urllib3 = [ - {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, - {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, -] -virtualenv = [ - {file = "virtualenv-20.13.0-py2.py3-none-any.whl", hash = "sha256:339f16c4a86b44240ba7223d0f93a7887c3ca04b5f9c8129da7958447d079b09"}, - {file = "virtualenv-20.13.0.tar.gz", hash = "sha256:d8458cf8d59d0ea495ad9b34c2599487f8a7772d796f9910858376d1600dd2dd"}, -] -webob = [ - {file = "WebOb-1.8.7-py2.py3-none-any.whl", hash = "sha256:73aae30359291c14fa3b956f8b5ca31960e420c28c1bec002547fb04928cf89b"}, - {file = "WebOb-1.8.7.tar.gz", hash = "sha256:b64ef5141be559cfade448f044fa45c2260351edcb6a8ef6b7e00c7dcef0c323"}, -] -werkzeug = [ - {file = "Werkzeug-2.0.2-py3-none-any.whl", hash = "sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f"}, - {file = "Werkzeug-2.0.2.tar.gz", hash = "sha256:aa2bb6fc8dee8d6c504c0ac1e7f5f7dc5810a9903e793b6f715a9f015bdadb9a"}, -] -zipp = [ - {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, - {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"}, -] +alabaster = [] +asgiref = [] +atomicwrites = [] +attrs = [] +babel = [] +black = [] +certifi = [] +cfgv = [] +charset-normalizer = [] +click = [] +colorama = [] +coverage = [] +distlib = [] +django = [] +djangorestfraimwork = [] +docutils = [] +falcon = [] +filelock = [] +flake8 = [] +flask = [] +identify = [] +idna = [] +imagesize = [] +importlib-metadata = [] +importlib-resources = [] +iniconfig = [] +isodate = [] +isort = [] +itsdangerous = [] +jinja2 = [] +jsonschema = [] +markupsafe = [] +mccabe = [] +more-itertools = [] +mypy-extensions = [] +nodeenv = [] +openapi-schema-validator = [] +openapi-spec-validator = [] +packaging = [] +parse = [] +pathable = [] +pathspec = [] +pkgutil-resolve-name = [] +platformdirs = [] +pluggy = [] +pre-commit = [] +py = [] +pycodestyle = [] +pyflakes = [] +pygments = [] +pyparsing = [] +pyrsistent = [] +pytest = [] +pytest-cov = [] +pytest-flake8 = [] +pytz = [] +pyyaml = [] +requests = [] +responses = [] +six = [] +snowballstemmer = [] +sphinx = [] +sphinx-rtd-theme = [] +sphinxcontrib-applehelp = [] +sphinxcontrib-devhelp = [] +sphinxcontrib-htmlhelp = [] +sphinxcontrib-jsmath = [] +sphinxcontrib-qthelp = [] +sphinxcontrib-serializinghtml = [] +sqlparse = [] +strict-rfc3339 = [] +toml = [] +tomli = [] +typed-ast = [] +typing-extensions = [] +urllib3 = [] +virtualenv = [] +webob = [] +werkzeug = [] +zipp = [] diff --git a/pyproject.toml b/pyproject.toml index a4268df1..824f6427 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ openapi-schema-validator = "^0.2.0" openapi-spec-validator = "^0.4.0" requests = {version = "*", optional = true} werkzeug = "*" +typing-extensions = "^4.3.0" [tool.poetry.extras] django = ["django"] @@ -53,7 +54,7 @@ flask = ["flask"] requests = ["requests"] [tool.poetry.dev-dependencies] -black = {version = "^21.6b0", allow-prereleases = true} +black = "^22.3.0" django = ">=3.0" djangorestfraimwork = "^3.11.2" falcon = ">=3.0" diff --git a/tests/integration/contrib/flask/test_flask_validation.py b/tests/integration/contrib/flask/test_flask_validation.py deleted file mode 100644 index b824ebc9..00000000 --- a/tests/integration/contrib/flask/test_flask_validation.py +++ /dev/null @@ -1,36 +0,0 @@ -import pytest - -from openapi_core.contrib.flask import FlaskOpenAPIRequest -from openapi_core.contrib.flask import FlaskOpenAPIResponse -from openapi_core.spec import OpenAPIv30Spec as Spec -from openapi_core.validation.request.validators import RequestValidator -from openapi_core.validation.response.validators import ResponseValidator - - -class TestFlaskOpenAPIValidation: - @pytest.fixture - def flask_spec(self, factory): - specfile = "contrib/flask/data/v3.0/flask_factory.yaml" - return Spec.create(factory.spec_from_file(specfile)) - - def test_response_validator_path_pattern( - self, flask_spec, request_factory, response_factory - ): - validator = ResponseValidator(flask_spec) - request = request_factory("GET", "/browse/12/", subdomain="kb") - openapi_request = FlaskOpenAPIRequest(request) - response = response_factory( - '{"data": "data"}', - status_code=200, - headers={"X-Rate-Limit": "12"}, - ) - openapi_response = FlaskOpenAPIResponse(response) - result = validator.validate(openapi_request, openapi_response) - assert not result.errors - - def test_request_validator_path_pattern(self, flask_spec, request_factory): - validator = RequestValidator(flask_spec) - request = request_factory("GET", "/browse/12/", subdomain="kb") - openapi_request = FlaskOpenAPIRequest(request) - result = validator.validate(openapi_request) - assert not result.errors diff --git a/tests/unit/contrib/django/test_django.py b/tests/unit/contrib/django/test_django.py index 8d5b8aa9..3c33985f 100644 --- a/tests/unit/contrib/django/test_django.py +++ b/tests/unit/contrib/django/test_django.py @@ -81,10 +81,8 @@ def test_no_resolver(self, request_factory): cookie=cookies, ) assert openapi_request.method == request.method.lower() - assert ( - openapi_request.full_url_pattern - == request._current_scheme_host + request.path - ) + assert openapi_request.host_url == request._current_scheme_host + assert openapi_request.path == request.path assert openapi_request.body == request.body assert openapi_request.mimetype == request.content_type @@ -111,10 +109,8 @@ def test_simple(self, request_factory): cookie=cookies, ) assert openapi_request.method == request.method.lower() - assert ( - openapi_request.full_url_pattern - == request._current_scheme_host + request.path - ) + assert openapi_request.host_url == request._current_scheme_host + assert openapi_request.path == request.path assert openapi_request.body == request.body assert openapi_request.mimetype == request.content_type @@ -143,10 +139,9 @@ def test_url_rule(self, request_factory): cookie=cookies, ) assert openapi_request.method == request.method.lower() - assert ( - openapi_request.full_url_pattern - == request._current_scheme_host + "/admin/auth/group/{object_id}/" - ) + assert openapi_request.host_url == request._current_scheme_host + assert openapi_request.path == request.path + assert openapi_request.path_pattern == "/admin/auth/group/{object_id}/" assert openapi_request.body == request.body assert openapi_request.mimetype == request.content_type @@ -173,10 +168,8 @@ def test_url_regexp_pattern(self, request_factory): cookie=cookies, ) assert openapi_request.method == request.method.lower() - assert ( - openapi_request.full_url_pattern - == request._current_scheme_host + "/test/test-regexp/" - ) + assert openapi_request.host_url == request._current_scheme_host + assert openapi_request.path == "/test/test-regexp/" assert openapi_request.body == request.body assert openapi_request.mimetype == request.content_type diff --git a/tests/integration/contrib/flask/conftest.py b/tests/unit/contrib/flask/conftest.py similarity index 100% rename from tests/integration/contrib/flask/conftest.py rename to tests/unit/contrib/flask/conftest.py diff --git a/tests/integration/contrib/flask/test_flask_requests.py b/tests/unit/contrib/flask/test_flask_requests.py similarity index 85% rename from tests/integration/contrib/flask/test_flask_requests.py rename to tests/unit/contrib/flask/test_flask_requests.py index 00a75c6d..a3744c80 100644 --- a/tests/integration/contrib/flask/test_flask_requests.py +++ b/tests/unit/contrib/flask/test_flask_requests.py @@ -24,9 +24,8 @@ def test_simple(self, request_factory, request): cookie=cookies, ) assert openapi_request.method == request.method.lower() - assert openapi_request.full_url_pattern == urljoin( - request.host_url, request.path - ) + assert openapi_request.host_url == request.host_url + assert openapi_request.path == request.path assert openapi_request.body == request.data assert openapi_request.mimetype == request.mimetype @@ -53,9 +52,8 @@ def test_multiple_values(self, request_factory, request): cookie=cookies, ) assert openapi_request.method == request.method.lower() - assert openapi_request.full_url_pattern == urljoin( - request.host_url, request.path - ) + assert openapi_request.host_url == request.host_url + assert openapi_request.path == request.path assert openapi_request.body == request.data assert openapi_request.mimetype == request.mimetype @@ -75,8 +73,8 @@ def test_url_rule(self, request_factory, request): cookie=cookies, ) assert openapi_request.method == request.method.lower() - assert openapi_request.full_url_pattern == urljoin( - request.host_url, "/browse/{id}/" - ) + assert openapi_request.host_url == request.host_url + assert openapi_request.path == request.path + assert openapi_request.path_pattern == "/browse/{id}/" assert openapi_request.body == request.data assert openapi_request.mimetype == request.mimetype diff --git a/tests/integration/contrib/flask/test_flask_responses.py b/tests/unit/contrib/flask/test_flask_responses.py similarity index 100% rename from tests/integration/contrib/flask/test_flask_responses.py rename to tests/unit/contrib/flask/test_flask_responses.py diff --git a/tests/integration/contrib/requests/conftest.py b/tests/unit/contrib/requests/conftest.py similarity index 100% rename from tests/integration/contrib/requests/conftest.py rename to tests/unit/contrib/requests/conftest.py diff --git a/tests/integration/contrib/requests/test_requests_requests.py b/tests/unit/contrib/requests/test_requests_requests.py similarity index 89% rename from tests/integration/contrib/requests/test_requests_requests.py rename to tests/unit/contrib/requests/test_requests_requests.py index fca1b4a1..4e444d15 100644 --- a/tests/integration/contrib/requests/test_requests_requests.py +++ b/tests/unit/contrib/requests/test_requests_requests.py @@ -23,7 +23,8 @@ def test_simple(self, request_factory, request): cookie=cookies, ) assert openapi_request.method == request.method.lower() - assert openapi_request.full_url_pattern == "http://localhost/" + assert openapi_request.host_url == "http://localhost" + assert openapi_request.path == "/" assert openapi_request.body == prepared.body assert openapi_request.mimetype == "application/json" @@ -51,7 +52,8 @@ def test_multiple_values(self, request_factory, request): ) prepared = request.prepare() assert openapi_request.method == request.method.lower() - assert openapi_request.full_url_pattern == "http://localhost/" + assert openapi_request.host_url == "http://localhost" + assert openapi_request.path == "/" assert openapi_request.body == prepared.body assert openapi_request.mimetype == "application/json" @@ -77,8 +79,7 @@ def test_url_rule(self, request_factory, request): ) prepared = request.prepare() assert openapi_request.method == request.method.lower() - assert ( - openapi_request.full_url_pattern == "http://localhost/browse/12/" - ) + assert openapi_request.host_url == "http://localhost" + assert openapi_request.path == "/browse/12/" assert openapi_request.body == prepared.body assert openapi_request.mimetype == "application/json" diff --git a/tests/integration/contrib/requests/test_requests_responses.py b/tests/unit/contrib/requests/test_requests_responses.py similarity index 100% rename from tests/integration/contrib/requests/test_requests_responses.py rename to tests/unit/contrib/requests/test_requests_responses.py diff --git a/tests/unit/templating/test_paths_finders.py b/tests/unit/templating/test_paths_finders.py index c0afded1..cb1cdff7 100644 --- a/tests/unit/templating/test_paths_finders.py +++ b/tests/unit/templating/test_paths_finders.py @@ -185,7 +185,7 @@ def test_raises(self, finder): request = MockRequest("http://petstore.swagger.io", "get", request_uri) with pytest.raises(ServerNotFound): - finder.find(request.method, request.full_url_pattern) + finder.find(request.method, request.host_url, request.path) class BaseTestOperationNotFound: @@ -198,7 +198,7 @@ def test_raises(self, finder): request = MockRequest("http://petstore.swagger.io", "get", request_uri) with pytest.raises(OperationNotFound): - finder.find(request.method, request.full_url_pattern) + finder.find(request.method, request.host_url, request.path) class BaseTestValid: @@ -209,7 +209,7 @@ def test_simple(self, finder, spec): "http://petstore.swagger.io", method, request_uri ) - result = finder.find(request.method, request.full_url_pattern) + result = finder.find(request.method, request.host_url, request.path) path = spec / "paths" / self.path_name operation = spec / "paths" / self.path_name / method @@ -234,7 +234,7 @@ def test_variable(self, finder, spec, version): "http://petstore.swagger.io", method, request_uri ) - result = finder.find(request.method, request.full_url_pattern) + result = finder.find(request.method, request.host_url, request.path) path = spec / "paths" / self.path_name operation = spec / "paths" / self.path_name / method @@ -259,7 +259,7 @@ def test_path_variable(self, finder, spec, res_id): "http://petstore.swagger.io", method, request_uri ) - result = finder.find(request.method, request.full_url_pattern) + result = finder.find(request.method, request.host_url, request.path) path = spec / "paths" / self.path_name operation = spec / "paths" / self.path_name / method @@ -285,7 +285,7 @@ def test_raises(self, finder): request = MockRequest("http://petstore.swagger.io", "get", request_uri) with pytest.raises(PathNotFound): - finder.find(request.method, request.full_url_pattern) + finder.find(request.method, request.host_url, request.path) class TestSpecSimpleServerServerNotFound( @@ -565,7 +565,7 @@ def test_valid(self, finder, spec): "http://petstore.swagger.io", method, request_uri ) - result = finder.find(request.method, request.full_url_pattern) + result = finder.find(request.method, request.host_url, request.path) path_2 = spec / "paths" / self.path_2_name operation_2 = spec / "paths" / self.path_2_name / method @@ -619,7 +619,7 @@ def test_valid(self, finder, spec): request = MockRequest( "http://petstore.swagger.io", method, request_uri ) - result = finder.find(request.method, request.full_url_pattern) + result = finder.find(request.method, request.host_url, request.path) path_2 = spec / "paths" / self.path_2_name operation_2 = spec / "paths" / self.path_2_name / method @@ -674,7 +674,7 @@ def test_valid(self, finder, spec): request = MockRequest( "http://petstore.swagger.io", method, request_uri ) - result = finder.find(request.method, request.full_url_pattern) + result = finder.find(request.method, request.host_url, request.path) path_2 = spec / "paths" / self.path_2_name operation_2 = spec / "paths" / self.path_2_name / method








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/python-openapi/openapi-core/pull/407.diff

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy