From e1fa3daeb97e5214d607938bafe96b30a8f85295 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 29 Jun 2023 17:57:22 -0600 Subject: [PATCH 01/18] Prototype tighter httpx integration --- .../api/body/post_body_multipart.py | 20 +- .../api/parameters/post_parameters_header.py | 26 +- integration-tests/integration_tests/client.py | 251 +++++++++++++++--- integration-tests/poetry.lock | 107 ++------ integration-tests/pyproject.toml | 3 + integration-tests/tests/conftest.py | 2 +- .../test_body/test_post_body_multipart.py | 150 +++++++++++ .../templates/client.py.jinja | 3 + 8 files changed, 404 insertions(+), 158 deletions(-) diff --git a/integration-tests/integration_tests/api/body/post_body_multipart.py b/integration-tests/integration_tests/api/body/post_body_multipart.py index 9aaf6c388..491860007 100644 --- a/integration-tests/integration_tests/api/body/post_body_multipart.py +++ b/integration-tests/integration_tests/api/body/post_body_multipart.py @@ -13,23 +13,15 @@ def _get_kwargs( *, - client: Client, multipart_data: PostBodyMultipartMultipartData, ) -> Dict[str, Any]: - url = "{}/body/multipart".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + path = "/body/multipart" multipart_multipart_data = multipart_data.to_multipart() return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": path, "files": multipart_multipart_data, } @@ -80,12 +72,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, multipart_data=multipart_data, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -133,12 +123,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, multipart_data=multipart_data, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/integration-tests/integration_tests/api/parameters/post_parameters_header.py b/integration-tests/integration_tests/api/parameters/post_parameters_header.py index 4d881bd0f..1043226b0 100644 --- a/integration-tests/integration_tests/api/parameters/post_parameters_header.py +++ b/integration-tests/integration_tests/api/parameters/post_parameters_header.py @@ -12,32 +12,20 @@ def _get_kwargs( *, - client: Client, boolean_header: bool, string_header: str, number_header: float, integer_header: int, ) -> Dict[str, Any]: - url = "{}/parameters/header".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() - - headers["Boolean-Header"] = "true" if boolean_header else "false" - - headers["String-Header"] = string_header + url = "/parameters/header" - headers["Number-Header"] = str(number_header) - - headers["Integer-Header"] = str(integer_header) + headers: Dict[str, Any] = {"Boolean-Header": "true" if boolean_header else "false", "String-Header": string_header, + "Number-Header": str(number_header), "Integer-Header": str(integer_header)} return { "method": "post", "url": url, "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, } @@ -93,15 +81,13 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, boolean_header=boolean_header, string_header=string_header, number_header=number_header, integer_header=integer_header, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -164,15 +150,13 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, boolean_header=boolean_header, string_header=string_header, number_header=number_header, integer_header=integer_header, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/integration-tests/integration_tests/client.py b/integration-tests/integration_tests/client.py index 2f45c655b..8f8c11b75 100644 --- a/integration-tests/integration_tests/client.py +++ b/integration-tests/integration_tests/client.py @@ -1,66 +1,239 @@ import ssl -from typing import Dict, Union +from typing import Dict, Union, Optional, Tuple -import attr +from attrs import define, field, evolve +import httpx -@attr.s(auto_attribs=True) +@define class Client: """A class for keeping track of data related to the API + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + Attributes: - base_url: The base URL for the API, all requests are made to a relative path to this URL - cookies: A dictionary of cookies to be sent with every request - headers: A dictionary of headers to be sent with every request - timeout: The maximum amount of a time in seconds a request can take. API functions will raise - httpx.TimeoutException if this is exceeded. - verify_ssl: Whether or not to verify the SSL certificate of the API server. This should be True in production, - but can be set to False for testing purposes. raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a - status code that was not documented in the source OpenAPI document. - follow_redirects: Whether or not to follow redirects. Default value is False. + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. """ - base_url: str - cookies: Dict[str, str] = attr.ib(factory=dict, kw_only=True) - headers: Dict[str, str] = attr.ib(factory=dict, kw_only=True) - timeout: float = attr.ib(5.0, kw_only=True) - verify_ssl: Union[str, bool, ssl.SSLContext] = attr.ib(True, kw_only=True) - raise_on_unexpected_status: bool = attr.ib(False, kw_only=True) - follow_redirects: bool = attr.ib(False, kw_only=True) - - def get_headers(self) -> Dict[str, str]: - """Get headers to be used in all endpoints""" - return {**self.headers} + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str + _cookies: Dict[str, str] = field(factory=dict, kw_only=True) + _headers: Dict[str, str] = field(factory=dict, kw_only=True) + _timeout: float = field(default=5.0, kw_only=True) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) + _follow_redirects: bool = field(default=False, kw_only=True) + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) def with_headers(self, headers: Dict[str, str]) -> "Client": """Get a new client matching this one with additional headers""" - return attr.evolve(self, headers={**self.headers, **headers}) - - def get_cookies(self) -> Dict[str, str]: - return {**self.cookies} + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) def with_cookies(self, cookies: Dict[str, str]) -> "Client": """Get a new client matching this one with additional cookies""" - return attr.evolve(self, cookies={**self.cookies, **cookies}) - - def get_timeout(self) -> float: - return self.timeout + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) def with_timeout(self, timeout: float) -> "Client": """Get a new client matching this one with a new timeout (in seconds)""" - return attr.evolve(self, timeout=timeout) + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_client(self, client: httpx.Client) -> "Client": + """Manually the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._client + + def __enter__(self) -> "Client": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_client().__enter__() + return self + + def __exit__(self, *args, **kwargs) -> None: + """Exit a context manager for self.client (see httpx docs)""" + self.get_client().__exit__(*args, **kwargs) + + def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._async_client = httpx.AsyncClient(base_url=self._base_url, cookies=self._cookies, headers=self._headers, timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects) + return self._async_client + + async def __aenter__(self) -> "Client": + """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + await self.get_async_client().__aenter__() + return self + + async def __aexit__(self, *args, **kwargs) -> None: + """Exit a context manager for self.async_client (see httpx docs)""" + await self.get_async_client().__aexit__(*args, **kwargs) + + +@define +class AuthenticatedClient: + """A Client which has been authenticated for use on secured endpoints + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: -@attr.s(auto_attribs=True) -class AuthenticatedClient(Client): - """A Client which has been authenticated for use on secured endpoints""" + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str token: str prefix: str = "Bearer" auth_header_name: str = "Authorization" + _cookies: Dict[str, str] = field(factory=dict, kw_only=True) + _headers: Dict[str, str] = field(factory=dict, kw_only=True) + _timeout: float = field(default=5.0, kw_only=True) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) + _follow_redirects: bool = field(default=False, kw_only=True) + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: float) -> "AuthenticatedClient": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_client(self, client: httpx.Client) -> "AuthenticatedClient": + """Manually the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up + auth **manually** if using this method. + """ + self._client = client + return self + + def get_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._client + + def __enter__(self) -> "Client": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + with self.get_client(): + yield self + + def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up + auth **manually** if using this method. + """ + self._async_client = async_client + return self + + def get_async_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient""" + if self._async_client is None: + self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._async_client - def get_headers(self) -> Dict[str, str]: - """Get headers to be used in authenticated endpoints""" - auth_header_value = f"{self.prefix} {self.token}" if self.prefix else self.token - return {self.auth_header_name: auth_header_value, **self.headers} + async def __aenter__(self) -> "Client": + """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + async with self.get_async_client(): + yield self diff --git a/integration-tests/poetry.lock b/integration-tests/poetry.lock index 527e78222..dbb1bb29b 100644 --- a/integration-tests/poetry.lock +++ b/integration-tests/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "anyio" version = "3.5.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "main" optional = false python-versions = ">=3.6.2" files = [ @@ -15,7 +14,6 @@ files = [ [package.dependencies] idna = ">=2.8" sniffio = ">=1.1" -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] @@ -26,7 +24,6 @@ trio = ["trio (>=0.16)"] name = "atomicwrites" version = "1.4.0" description = "Atomic file writes." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -38,7 +35,6 @@ files = [ name = "attrs" version = "21.4.0" description = "Classes Without Boilerplate" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -56,7 +52,6 @@ tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy" name = "certifi" version = "2022.12.7" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -68,7 +63,6 @@ files = [ name = "colorama" version = "0.4.4" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -80,7 +74,6 @@ files = [ name = "h11" version = "0.12.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -92,7 +85,6 @@ files = [ name = "httpcore" version = "0.15.0" description = "A minimal low-level HTTP client." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -101,20 +93,19 @@ files = [ ] [package.dependencies] -anyio = ">=3.0.0,<4.0.0" +anyio = "==3.*" certifi = "*" h11 = ">=0.11,<0.13" -sniffio = ">=1.0.0,<2.0.0" +sniffio = "==1.*" [package.extras] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] +socks = ["socksio (==1.*)"] [[package]] name = "httpx" version = "0.24.0" description = "The next generation HTTP client." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -130,15 +121,14 @@ sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] -cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] +socks = ["socksio (==1.*)"] [[package]] name = "idna" version = "3.3" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -146,32 +136,10 @@ files = [ {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] -[[package]] -name = "importlib-metadata" -version = "4.8.3" -description = "Read metadata from Python packages" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "importlib_metadata-4.8.3-py3-none-any.whl", hash = "sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e"}, - {file = "importlib_metadata-4.8.3.tar.gz", hash = "sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668"}, -] - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" - -[package.extras] -docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy", "pytest-perf (>=0.9.2)"] - [[package]] name = "iniconfig" version = "1.1.1" description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = "*" files = [ @@ -183,7 +151,6 @@ files = [ name = "packaging" version = "21.3" description = "Core utilities for Python packages" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -198,7 +165,6 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -206,9 +172,6 @@ files = [ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] @@ -217,7 +180,6 @@ testing = ["pytest", "pytest-benchmark"] name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -229,7 +191,6 @@ files = [ name = "pyparsing" version = "3.0.6" description = "Python parsing module" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -244,7 +205,6 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "pytest" version = "7.0.0" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -256,7 +216,6 @@ files = [ atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" @@ -266,11 +225,28 @@ tomli = ">=1.0.0" [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +[[package]] +name = "pytest-asyncio" +version = "0.21.0" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-asyncio-0.21.0.tar.gz", hash = "sha256:2b38a496aef56f56b0e87557ec313e11e1ab9276fc3863f6a7be0f1d0e415e1b"}, + {file = "pytest_asyncio-0.21.0-py3-none-any.whl", hash = "sha256:f2b3366b7cd501a4056858bd39349d5af19742aed2d81660b7998b6341c7eb9c"}, +] + +[package.dependencies] +pytest = ">=7.0.0" + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] + [[package]] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -285,7 +261,6 @@ six = ">=1.5" name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -297,7 +272,6 @@ files = [ name = "sniffio" version = "1.2.0" description = "Sniff out which async library your code is running under" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -309,7 +283,6 @@ files = [ name = "tomli" version = "2.0.0" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -317,35 +290,7 @@ files = [ {file = "tomli-2.0.0.tar.gz", hash = "sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1"}, ] -[[package]] -name = "typing-extensions" -version = "4.0.1" -description = "Backported and Experimental Type Hints for Python 3.6+" -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, - {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, -] - -[[package]] -name = "zipp" -version = "3.6.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, - {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, -] - -[package.extras] -docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] -testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] - [metadata] lock-version = "2.0" -python-versions = "^3.7" -content-hash = "d2ba854b56858173a3cf70405d9d48bd6f7cfa43e7374f0bd52140b019a2b355" +python-versions = "^3.8" +content-hash = "0cb4dd94817307ed1ec4baf850cf41cdb1d5190463752b5c63836b006e06eb3d" diff --git a/integration-tests/pyproject.toml b/integration-tests/pyproject.toml index 23e3a8daf..0ac763d5c 100644 --- a/integration-tests/pyproject.toml +++ b/integration-tests/pyproject.toml @@ -18,6 +18,9 @@ python-dateutil = "^2.8.0" [tool.poetry.dev-dependencies] pytest = "^7.0.0" +[tool.poetry.group.dev.dependencies] +pytest-asyncio = "^0.21.0" + [build-system] requires = ["poetry>=1.0"] build-backend = "poetry.masonry.api" diff --git a/integration-tests/tests/conftest.py b/integration-tests/tests/conftest.py index 9cdd679fa..f5c500ba4 100644 --- a/integration-tests/tests/conftest.py +++ b/integration-tests/tests/conftest.py @@ -3,6 +3,6 @@ from integration_tests.client import Client -@pytest.fixture(scope="session") +@pytest.fixture def client() -> Client: return Client("http://localhost:3000") diff --git a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py index 5ff6cbcf6..0ab181407 100644 --- a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py +++ b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py @@ -1,5 +1,8 @@ from io import BytesIO +import httpx +import pytest + from integration_tests.api.body import post_body_multipart from integration_tests.client import Client from integration_tests.models.post_body_multipart_multipart_data import PostBodyMultipartMultipartData @@ -36,3 +39,150 @@ def test(client: Client) -> None: assert content.file_content_type == mime_type assert content.file_data.encode() == payload assert content.description == description + +def test_context_manager(client: Client) -> None: + a_string = "a test string" + payload = b"some file content" + file_name = "cool_stuff.txt" + mime_type = "application/openapi-python-client" + description = "super descriptive thing" + + with client as client: + post_body_multipart.sync_detailed( + client=client, + multipart_data=PostBodyMultipartMultipartData( + a_string=a_string, + file=File( + payload=BytesIO(payload), + file_name=file_name, + mime_type=mime_type, + ), + description=description, + ), + ) + response = post_body_multipart.sync_detailed( + client=client, + multipart_data=PostBodyMultipartMultipartData( + a_string=a_string, + file=File( + payload=BytesIO(payload), + file_name=file_name, + mime_type=mime_type, + ), + description=description, + ), + ) + + with pytest.raises(RuntimeError): + post_body_multipart.sync_detailed( + client=client, + multipart_data=PostBodyMultipartMultipartData( + a_string=a_string, + file=File( + payload=BytesIO(payload), + file_name=file_name, + mime_type=mime_type, + ), + description=description, + ), + ) + + content = response.parsed + if not isinstance(content, PostBodyMultipartResponse200): + raise AssertionError(f"Received status {response.status_code} from test server with payload: {content!r}") + + assert content.a_string == a_string + assert content.file_name == file_name + assert content.file_content_type == mime_type + assert content.file_data.encode() == payload + assert content.description == description + + +@pytest.mark.asyncio +async def test_async(client: Client) -> None: + a_string = "a test string" + payload = b"some file content" + file_name = "cool_stuff.txt" + mime_type = "application/openapi-python-client" + description = "super descriptive thing" + + response = await post_body_multipart.asyncio_detailed( + client=client, + multipart_data=PostBodyMultipartMultipartData( + a_string=a_string, + file=File( + payload=BytesIO(payload), + file_name=file_name, + mime_type=mime_type, + ), + description=description, + ), + ) + + content = response.parsed + if not isinstance(content, PostBodyMultipartResponse200): + raise AssertionError(f"Received status {response.status_code} from test server with payload: {content!r}") + + assert content.a_string == a_string + assert content.file_name == file_name + assert content.file_content_type == mime_type + assert content.file_data.encode() == payload + assert content.description == description + +@pytest.mark.asyncio +async def test_async_context_manager(client: Client) -> None: + a_string = "a test string" + payload = b"some file content" + file_name = "cool_stuff.txt" + mime_type = "application/openapi-python-client" + description = "super descriptive thing" + + async with client as client: + await post_body_multipart.asyncio_detailed( + client=client, + multipart_data=PostBodyMultipartMultipartData( + a_string=a_string, + file=File( + payload=BytesIO(payload), + file_name=file_name, + mime_type=mime_type, + ), + description=description, + ), + ) + response = await post_body_multipart.asyncio_detailed( + client=client, + multipart_data=PostBodyMultipartMultipartData( + a_string=a_string, + file=File( + payload=BytesIO(payload), + file_name=file_name, + mime_type=mime_type, + ), + description=description, + ), + ) + + with pytest.raises(RuntimeError): + await post_body_multipart.asyncio_detailed( + client=client, + multipart_data=PostBodyMultipartMultipartData( + a_string=a_string, + file=File( + payload=BytesIO(payload), + file_name=file_name, + mime_type=mime_type, + ), + description=description, + ), + ) + + content = response.parsed + if not isinstance(content, PostBodyMultipartResponse200): + raise AssertionError(f"Received status {response.status_code} from test server with payload: {content!r}") + + assert content.a_string == a_string + assert content.file_name == file_name + assert content.file_content_type == mime_type + assert content.file_data.encode() == payload + assert content.description == description diff --git a/openapi_python_client/templates/client.py.jinja b/openapi_python_client/templates/client.py.jinja index c6e6b2305..71e509bd7 100644 --- a/openapi_python_client/templates/client.py.jinja +++ b/openapi_python_client/templates/client.py.jinja @@ -1,6 +1,8 @@ import ssl from typing import Dict, Union + import attr +from httpx import Client @attr.s(auto_attribs=True) class Client: @@ -26,6 +28,7 @@ class Client: verify_ssl: Union[str, bool, ssl.SSLContext] = attr.ib(True, kw_only=True) raise_on_unexpected_status: bool = attr.ib(False, kw_only=True) follow_redirects: bool = attr.ib(False, kw_only=True) + httpx_client: Client = attr.ib(None, kw_only=True) def get_headers(self) -> Dict[str, str]: """ Get headers to be used in all endpoints """ From a9618bae8e62720a6c957ca9979afeeacb9bac96 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 29 Jun 2023 19:21:40 -0600 Subject: [PATCH 02/18] Blacken --- .../api/parameters/post_parameters_header.py | 8 ++++++-- integration-tests/integration_tests/client.py | 9 ++++++++- .../tests/test_api/test_body/test_post_body_multipart.py | 2 ++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/integration-tests/integration_tests/api/parameters/post_parameters_header.py b/integration-tests/integration_tests/api/parameters/post_parameters_header.py index 1043226b0..e9c7ddfc8 100644 --- a/integration-tests/integration_tests/api/parameters/post_parameters_header.py +++ b/integration-tests/integration_tests/api/parameters/post_parameters_header.py @@ -19,8 +19,12 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "/parameters/header" - headers: Dict[str, Any] = {"Boolean-Header": "true" if boolean_header else "false", "String-Header": string_header, - "Number-Header": str(number_header), "Integer-Header": str(integer_header)} + headers: Dict[str, Any] = { + "Boolean-Header": "true" if boolean_header else "false", + "String-Header": string_header, + "Number-Header": str(number_header), + "Integer-Header": str(integer_header), + } return { "method": "post", diff --git a/integration-tests/integration_tests/client.py b/integration-tests/integration_tests/client.py index 8f8c11b75..f0beb5c89 100644 --- a/integration-tests/integration_tests/client.py +++ b/integration-tests/integration_tests/client.py @@ -106,7 +106,14 @@ def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": def get_async_client(self) -> httpx.AsyncClient: """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" if self._async_client is None: - self._async_client = httpx.AsyncClient(base_url=self._base_url, cookies=self._cookies, headers=self._headers, timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects) + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) return self._async_client async def __aenter__(self) -> "Client": diff --git a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py index 0ab181407..1197fb532 100644 --- a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py +++ b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py @@ -40,6 +40,7 @@ def test(client: Client) -> None: assert content.file_data.encode() == payload assert content.description == description + def test_context_manager(client: Client) -> None: a_string = "a test string" payload = b"some file content" @@ -129,6 +130,7 @@ async def test_async(client: Client) -> None: assert content.file_data.encode() == payload assert content.description == description + @pytest.mark.asyncio async def test_async_context_manager(client: Client) -> None: a_string = "a test string" From 6bedc75591caca9196a40eeb8948393b86ff47a5 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 29 Jun 2023 19:24:32 -0600 Subject: [PATCH 03/18] New client template --- integration-tests/integration_tests/client.py | 2 +- .../templates/client.py.jinja | 270 +++++++++++++++--- 2 files changed, 226 insertions(+), 46 deletions(-) diff --git a/integration-tests/integration_tests/client.py b/integration-tests/integration_tests/client.py index f0beb5c89..c4b147b29 100644 --- a/integration-tests/integration_tests/client.py +++ b/integration-tests/integration_tests/client.py @@ -1,5 +1,5 @@ import ssl -from typing import Dict, Union, Optional, Tuple +from typing import Dict, Union, Optional from attrs import define, field, evolve import httpx diff --git a/openapi_python_client/templates/client.py.jinja b/openapi_python_client/templates/client.py.jinja index 71e509bd7..c4b147b29 100644 --- a/openapi_python_client/templates/client.py.jinja +++ b/openapi_python_client/templates/client.py.jinja @@ -1,66 +1,246 @@ import ssl -from typing import Dict, Union +from typing import Dict, Union, Optional -import attr -from httpx import Client +from attrs import define, field, evolve +import httpx -@attr.s(auto_attribs=True) + +@define class Client: - """ A class for keeping track of data related to the API + """A class for keeping track of data related to the API + + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. Attributes: - base_url: The base URL for the API, all requests are made to a relative path to this URL - cookies: A dictionary of cookies to be sent with every request - headers: A dictionary of headers to be sent with every request - timeout: The maximum amount of a time in seconds a request can take. API functions will raise - httpx.TimeoutException if this is exceeded. - verify_ssl: Whether or not to verify the SSL certificate of the API server. This should be True in production, - but can be set to False for testing purposes. raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a - status code that was not documented in the source OpenAPI document. - follow_redirects: Whether or not to follow redirects. Default value is False. + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. """ - base_url: str - cookies: Dict[str, str] = attr.ib(factory=dict, kw_only=True) - headers: Dict[str, str] = attr.ib(factory=dict, kw_only=True) - timeout: float = attr.ib(5.0, kw_only=True) - verify_ssl: Union[str, bool, ssl.SSLContext] = attr.ib(True, kw_only=True) - raise_on_unexpected_status: bool = attr.ib(False, kw_only=True) - follow_redirects: bool = attr.ib(False, kw_only=True) - httpx_client: Client = attr.ib(None, kw_only=True) - - def get_headers(self) -> Dict[str, str]: - """ Get headers to be used in all endpoints """ - return {**self.headers} + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str + _cookies: Dict[str, str] = field(factory=dict, kw_only=True) + _headers: Dict[str, str] = field(factory=dict, kw_only=True) + _timeout: float = field(default=5.0, kw_only=True) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) + _follow_redirects: bool = field(default=False, kw_only=True) + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) def with_headers(self, headers: Dict[str, str]) -> "Client": - """ Get a new client matching this one with additional headers """ - return attr.evolve(self, headers={**self.headers, **headers}) - - def get_cookies(self) -> Dict[str, str]: - return {**self.cookies} + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) def with_cookies(self, cookies: Dict[str, str]) -> "Client": - """ Get a new client matching this one with additional cookies """ - return attr.evolve(self, cookies={**self.cookies, **cookies}) - - def get_timeout(self) -> float: - return self.timeout + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) def with_timeout(self, timeout: float) -> "Client": - """ Get a new client matching this one with a new timeout (in seconds) """ - return attr.evolve(self, timeout=timeout) + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_client(self, client: httpx.Client) -> "Client": + """Manually the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._client + + def __enter__(self) -> "Client": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_client().__enter__() + return self + + def __exit__(self, *args, **kwargs) -> None: + """Exit a context manager for self.client (see httpx docs)""" + self.get_client().__exit__(*args, **kwargs) + + def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._async_client + + async def __aenter__(self) -> "Client": + """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + await self.get_async_client().__aenter__() + return self + + async def __aexit__(self, *args, **kwargs) -> None: + """Exit a context manager for self.async_client (see httpx docs)""" + await self.get_async_client().__aexit__(*args, **kwargs) + -@attr.s(auto_attribs=True) -class AuthenticatedClient(Client): - """ A Client which has been authenticated for use on secured endpoints """ +@define +class AuthenticatedClient: + """A Client which has been authenticated for use on secured endpoints + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str token: str prefix: str = "Bearer" auth_header_name: str = "Authorization" + _cookies: Dict[str, str] = field(factory=dict, kw_only=True) + _headers: Dict[str, str] = field(factory=dict, kw_only=True) + _timeout: float = field(default=5.0, kw_only=True) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) + _follow_redirects: bool = field(default=False, kw_only=True) + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: float) -> "AuthenticatedClient": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_client(self, client: httpx.Client) -> "AuthenticatedClient": + """Manually the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up + auth **manually** if using this method. + """ + self._client = client + return self + + def get_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._client + + def __enter__(self) -> "Client": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + with self.get_client(): + yield self + + def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up + auth **manually** if using this method. + """ + self._async_client = async_client + return self + + def get_async_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient""" + if self._async_client is None: + self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._async_client - def get_headers(self) -> Dict[str, str]: - """Get headers to be used in authenticated endpoints""" - auth_header_value = f"{self.prefix} {self.token}" if self.prefix else self.token - return {self.auth_header_name: auth_header_value, **self.headers} + async def __aenter__(self) -> "Client": + """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + async with self.get_async_client(): + yield self From 544ddcf4bd8a8b72cd498e64aac2dc0674ae5fdd Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Mon, 3 Jul 2023 11:43:28 -0600 Subject: [PATCH 04/18] Update templates & tests --- .../api/default/get_common_parameters.py | 20 +- .../api/default/post_common_parameters.py | 20 +- .../api/default/reserved_parameters.py | 20 +- .../api/location/get_location_header_types.py | 20 +- .../get_location_query_optionality.py | 20 +- .../get_parameter_references_path_param.py | 24 +- ...lete_common_parameters_overriding_param.py | 22 +- .../get_common_parameters_overriding_param.py | 22 +- .../get_same_name_multiple_locations_param.py | 24 +- .../parameters/multiple_path_parameters.py | 28 +- ..._responses_unions_simple_before_complex.py | 30 +- .../api/tag1/get_tag_with_number.py | 30 +- .../api/tests/callback_test.py | 20 +- .../api/tests/defaults_tests_defaults_post.py | 20 +- .../api/tests/description_with_backslash.py | 30 +- .../api/tests/get_basic_list_of_booleans.py | 30 +- .../api/tests/get_basic_list_of_floats.py | 30 +- .../api/tests/get_basic_list_of_integers.py | 30 +- .../api/tests/get_basic_list_of_strings.py | 30 +- .../api/tests/get_user_list.py | 20 +- .../api/tests/int_enum_tests_int_enum_post.py | 20 +- .../tests/json_body_tests_json_body_post.py | 20 +- .../no_response_tests_no_response_get.py | 30 +- .../octet_stream_tests_octet_stream_get.py | 30 +- .../api/tests/post_form_data.py | 21 +- .../api/tests/post_form_data_inline.py | 21 +- .../api/tests/post_tests_json_body_string.py | 20 +- .../api/tests/test_inline_objects.py | 20 +- ..._with_cookie_auth_token_with_cookie_get.py | 20 +- ...d_content_tests_unsupported_content_get.py | 30 +- .../tests/upload_file_tests_upload_post.py | 20 +- ...upload_multiple_files_tests_upload_post.py | 20 +- .../my_test_api_client/api/true_/false_.py | 20 +- .../my_test_api_client/client.py | 268 +++++++++++++++--- .../api/body/post_body_multipart.py | 4 +- .../api/parameters/post_parameters_header.py | 16 +- integration-tests/integration_tests/client.py | 38 ++- .../test_body/test_post_body_multipart.py | 1 - .../templates/client.py.jinja | 36 ++- .../templates/endpoint_macros.py.jinja | 18 +- .../templates/endpoint_module.py.jinja | 60 ++-- .../boolean_property.py.jinja | 4 +- .../property_templates/enum_property.py.jinja | 4 +- .../float_property.py.jinja | 4 +- .../property_templates/int_property.py.jinja | 4 +- 45 files changed, 512 insertions(+), 727 deletions(-) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py index a2478b80d..29a60581e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py @@ -10,13 +10,9 @@ def _get_kwargs( *, - client: Client, common: Union[Unset, None, str] = UNSET, ) -> Dict[str, Any]: - url = "{}/common_parameters".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} params["common"] = common @@ -25,11 +21,7 @@ def _get_kwargs( return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/common_parameters", "params": params, } @@ -70,12 +62,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, common=common, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -100,11 +90,9 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, common=common, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py index 99e7f21d7..223fbbfd5 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py @@ -10,13 +10,9 @@ def _get_kwargs( *, - client: Client, common: Union[Unset, None, str] = UNSET, ) -> Dict[str, Any]: - url = "{}/common_parameters".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} params["common"] = common @@ -25,11 +21,7 @@ def _get_kwargs( return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/common_parameters", "params": params, } @@ -70,12 +62,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, common=common, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -100,11 +90,9 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, common=common, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py index d7eceda17..7a9774a51 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py @@ -10,14 +10,10 @@ def _get_kwargs( *, - client: Client, client_query: str, url_query: str, ) -> Dict[str, Any]: - url = "{}/naming/reserved-parameters".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} params["client"] = client_query @@ -28,11 +24,7 @@ def _get_kwargs( return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/naming/reserved-parameters", "params": params, } @@ -75,13 +67,11 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, client_query=client_query, url_query=url_query, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -108,12 +98,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, client_query=client_query, url_query=url_query, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py index 9249eab31..071dd38dc 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py @@ -12,7 +12,6 @@ def _get_kwargs( *, - client: Client, boolean_header: Union[Unset, bool] = UNSET, string_header: Union[Unset, str] = UNSET, number_header: Union[Unset, float] = UNSET, @@ -20,11 +19,7 @@ def _get_kwargs( int_enum_header: Union[Unset, GetLocationHeaderTypesIntEnumHeader] = UNSET, string_enum_header: Union[Unset, GetLocationHeaderTypesStringEnumHeader] = UNSET, ) -> Dict[str, Any]: - url = "{}/location/header/types".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() - + headers = {} if not isinstance(boolean_header, Unset): headers["Boolean-Header"] = "true" if boolean_header else "false" @@ -45,11 +40,8 @@ def _get_kwargs( return { "method": "get", - "url": url, + "url": "/location/header/types", "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, } @@ -99,7 +91,6 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, boolean_header=boolean_header, string_header=string_header, number_header=number_header, @@ -108,8 +99,7 @@ def sync_detailed( string_enum_header=string_enum_header, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -144,7 +134,6 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, boolean_header=boolean_header, string_header=string_header, number_header=number_header, @@ -153,7 +142,6 @@ async def asyncio_detailed( string_enum_header=string_enum_header, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py index 0209c7319..95f5a155c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py @@ -11,16 +11,12 @@ def _get_kwargs( *, - client: Client, not_null_required: datetime.datetime, null_required: Union[Unset, None, datetime.datetime] = UNSET, null_not_required: Union[Unset, None, datetime.datetime] = UNSET, not_null_not_required: Union[Unset, None, datetime.datetime] = UNSET, ) -> Dict[str, Any]: - url = "{}/location/query/optionality".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} json_not_null_required = not_null_required.isoformat() @@ -49,11 +45,7 @@ def _get_kwargs( return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/location/query/optionality", "params": params, } @@ -100,15 +92,13 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, not_null_required=not_null_required, null_required=null_required, null_not_required=null_not_required, not_null_not_required=not_null_not_required, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -139,14 +129,12 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, not_null_required=not_null_required, null_required=null_required, null_not_required=null_not_required, not_null_not_required=not_null_not_required, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py index b8c33ec94..d859a0803 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py @@ -11,20 +11,16 @@ def _get_kwargs( path_param: str, *, - client: Client, string_param: Union[Unset, None, str] = UNSET, integer_param: Union[Unset, None, int] = 0, header_param: Union[Unset, str] = UNSET, cookie_param: Union[Unset, str] = UNSET, ) -> Dict[str, Any]: - url = "{}/parameter-references/{path_param}".format(client.base_url, path_param=path_param) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() - + headers = {} if not isinstance(header_param, Unset): headers["header param"] = header_param + cookies = {} if cookie_param is not UNSET: cookies["cookie param"] = cookie_param @@ -37,12 +33,12 @@ def _get_kwargs( return { "method": "get", - "url": url, + "url": "/parameter-references/{path_param}".format( + path_param=path_param, + ), + "params": params, "headers": headers, "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, - "params": params, } @@ -92,15 +88,13 @@ def sync_detailed( kwargs = _get_kwargs( path_param=path_param, - client=client, string_param=string_param, integer_param=integer_param, header_param=header_param, cookie_param=cookie_param, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -135,14 +129,12 @@ async def asyncio_detailed( kwargs = _get_kwargs( path_param=path_param, - client=client, string_param=string_param, integer_param=integer_param, header_param=header_param, cookie_param=cookie_param, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py index 2816ec304..1bd00664a 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py @@ -11,13 +11,9 @@ def _get_kwargs( param_path: str, *, - client: Client, param_query: Union[Unset, None, str] = UNSET, ) -> Dict[str, Any]: - url = "{}/common_parameters_overriding/{param}".format(client.base_url, param=param_path) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} params["param"] = param_query @@ -26,11 +22,9 @@ def _get_kwargs( return { "method": "delete", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/common_parameters_overriding/{param}".format( + param=param_path, + ), "params": params, } @@ -74,12 +68,10 @@ def sync_detailed( kwargs = _get_kwargs( param_path=param_path, - client=client, param_query=param_query, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -107,11 +99,9 @@ async def asyncio_detailed( kwargs = _get_kwargs( param_path=param_path, - client=client, param_query=param_query, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py index f1d97abc5..b6c0923f2 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py @@ -11,13 +11,9 @@ def _get_kwargs( param_path: str, *, - client: Client, param_query: str = "overridden_in_GET", ) -> Dict[str, Any]: - url = "{}/common_parameters_overriding/{param}".format(client.base_url, param=param_path) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} params["param"] = param_query @@ -26,11 +22,9 @@ def _get_kwargs( return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/common_parameters_overriding/{param}".format( + param=param_path, + ), "params": params, } @@ -76,12 +70,10 @@ def sync_detailed( kwargs = _get_kwargs( param_path=param_path, - client=client, param_query=param_query, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -111,11 +103,9 @@ async def asyncio_detailed( kwargs = _get_kwargs( param_path=param_path, - client=client, param_query=param_query, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py index ee9c35016..9e10fc237 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py @@ -11,19 +11,15 @@ def _get_kwargs( param_path: str, *, - client: Client, param_query: Union[Unset, None, str] = UNSET, param_header: Union[Unset, str] = UNSET, param_cookie: Union[Unset, str] = UNSET, ) -> Dict[str, Any]: - url = "{}/same-name-multiple-locations/{param}".format(client.base_url, param=param_path) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() - + headers = {} if not isinstance(param_header, Unset): headers["param"] = param_header + cookies = {} if param_cookie is not UNSET: cookies["param"] = param_cookie @@ -34,12 +30,12 @@ def _get_kwargs( return { "method": "get", - "url": url, + "url": "/same-name-multiple-locations/{param}".format( + param=param_path, + ), + "params": params, "headers": headers, "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, - "params": params, } @@ -86,14 +82,12 @@ def sync_detailed( kwargs = _get_kwargs( param_path=param_path, - client=client, param_query=param_query, param_header=param_header, param_cookie=param_cookie, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -125,13 +119,11 @@ async def asyncio_detailed( kwargs = _get_kwargs( param_path=param_path, - client=client, param_query=param_query, param_header=param_header, param_cookie=param_cookie, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py index 347aa36b4..4842da8b9 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py @@ -13,23 +13,17 @@ def _get_kwargs( param2: int, param1: str, param3: int, - *, - client: Client, ) -> Dict[str, Any]: - url = "{}/multiple-path-parameters/{param4}/something/{param2}/{param1}/{param3}".format( - client.base_url, param4=param4, param2=param2, param1=param1, param3=param3 - ) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/multiple-path-parameters/{param4}/something/{param2}/{param1}/{param3}".format( + param4=param4, + param2=param2, + param1=param1, + param3=param3, + ), } @@ -79,11 +73,9 @@ def sync_detailed( param2=param2, param1=param1, param3=param3, - client=client, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -118,10 +110,8 @@ async def asyncio_detailed( param2=param2, param1=param1, param3=param3, - client=client, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py b/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py index b092e529d..16765d331 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py @@ -11,22 +11,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/responses/unions/simple_before_complex".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/responses/unions/simple_before_complex", } @@ -68,12 +58,9 @@ def sync_detailed( Response[PostResponsesUnionsSimpleBeforeComplexResponse200] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -113,12 +100,9 @@ async def asyncio_detailed( Response[PostResponsesUnionsSimpleBeforeComplexResponse200] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py b/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py index 05f976082..ffb392058 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py @@ -8,22 +8,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tag_with_number".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tag_with_number", } @@ -58,12 +48,9 @@ def sync_detailed( Response[Any] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -83,11 +70,8 @@ async def asyncio_detailed( Response[Any] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py index 34a238b2d..f13f5824b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py @@ -12,23 +12,15 @@ def _get_kwargs( *, - client: Client, json_body: AModel, ) -> Dict[str, Any]: - url = "{}/tests/callback".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass json_json_body = json_body.to_dict() return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/callback", "json": json_json_body, } @@ -77,12 +69,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, json_body=json_body, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -136,12 +126,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, json_body=json_body, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index 414542116..941eb3462 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -15,7 +15,6 @@ def _get_kwargs( *, - client: Client, string_prop: str = "the default string", date_prop: datetime.date = isoparse("1010-10-10").date(), float_prop: float = 3.14, @@ -28,10 +27,7 @@ def _get_kwargs( model_prop: "ModelWithUnionProperty", required_model_prop: "ModelWithUnionProperty", ) -> Dict[str, Any]: - url = "{}/tests/defaults".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} params["string_prop"] = string_prop @@ -91,11 +87,7 @@ def _get_kwargs( return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/defaults", "params": params, } @@ -162,7 +154,6 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, string_prop=string_prop, date_prop=date_prop, float_prop=float_prop, @@ -176,8 +167,7 @@ def sync_detailed( required_model_prop=required_model_prop, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -277,7 +267,6 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, string_prop=string_prop, date_prop=date_prop, float_prop=float_prop, @@ -291,8 +280,7 @@ async def asyncio_detailed( required_model_prop=required_model_prop, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py index 31923ad11..6b415634b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py @@ -8,22 +8,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/description-with-backslash".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/description-with-backslash", } @@ -61,12 +51,9 @@ def sync_detailed( Response[Any] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -89,11 +76,8 @@ async def asyncio_detailed( Response[Any] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py index 266e5eb41..7ce8362b9 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py @@ -8,22 +8,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/basic_lists/booleans".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/basic_lists/booleans", } @@ -63,12 +53,9 @@ def sync_detailed( Response[List[bool]] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -112,12 +99,9 @@ async def asyncio_detailed( Response[List[bool]] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py index a1101a547..e36f90d93 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py @@ -8,22 +8,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/basic_lists/floats".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/basic_lists/floats", } @@ -63,12 +53,9 @@ def sync_detailed( Response[List[float]] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -112,12 +99,9 @@ async def asyncio_detailed( Response[List[float]] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py index 29627228c..6b3043fcc 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py @@ -8,22 +8,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/basic_lists/integers".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/basic_lists/integers", } @@ -63,12 +53,9 @@ def sync_detailed( Response[List[int]] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -112,12 +99,9 @@ async def asyncio_detailed( Response[List[int]] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py index 2c52de82b..749623101 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py @@ -8,22 +8,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/basic_lists/strings".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/basic_lists/strings", } @@ -63,12 +53,9 @@ def sync_detailed( Response[List[str]] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -112,12 +99,9 @@ async def asyncio_detailed( Response[List[str]] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py index cef38f2ff..be88e9b4d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py @@ -15,16 +15,12 @@ def _get_kwargs( *, - client: Client, an_enum_value: List[AnEnum], an_enum_value_with_null: List[Optional[AnEnumWithNull]], an_enum_value_with_only_null: List[None], some_date: Union[datetime.date, datetime.datetime], ) -> Dict[str, Any]: - url = "{}/tests/".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} json_an_enum_value = [] @@ -62,11 +58,7 @@ def _get_kwargs( return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/", "params": params, } @@ -135,15 +127,13 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, an_enum_value=an_enum_value, an_enum_value_with_null=an_enum_value_with_null, an_enum_value_with_only_null=an_enum_value_with_only_null, some_date=some_date, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -212,15 +202,13 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, an_enum_value=an_enum_value, an_enum_value_with_null=an_enum_value_with_null, an_enum_value_with_only_null=an_enum_value_with_only_null, some_date=some_date, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py index 5a3ee4c7b..bdbe17f16 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py @@ -12,13 +12,9 @@ def _get_kwargs( *, - client: Client, int_enum: AnIntEnum, ) -> Dict[str, Any]: - url = "{}/tests/int_enum".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} json_int_enum = int_enum.value @@ -29,11 +25,7 @@ def _get_kwargs( return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/int_enum", "params": params, } @@ -80,12 +72,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, int_enum=int_enum, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -135,12 +125,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, int_enum=int_enum, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py index d482d0e3c..7b0fd8e20 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py @@ -12,23 +12,15 @@ def _get_kwargs( *, - client: Client, json_body: AModel, ) -> Dict[str, Any]: - url = "{}/tests/json_body".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass json_json_body = json_body.to_dict() return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/json_body", "json": json_json_body, } @@ -77,12 +69,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, json_body=json_body, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -136,12 +126,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, json_body=json_body, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py index 075452512..231537ff8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py @@ -8,22 +8,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/no_response".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/no_response", } @@ -59,12 +49,9 @@ def sync_detailed( Response[Any] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -85,11 +72,8 @@ async def asyncio_detailed( Response[Any] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py index 68e0a7fd5..528202ffd 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py @@ -9,22 +9,12 @@ from ...types import File, Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/octet_stream".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/octet_stream", } @@ -62,12 +52,9 @@ def sync_detailed( Response[File] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -107,12 +94,9 @@ async def asyncio_detailed( Response[File] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py index 07c0b225e..344e4e88f 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py @@ -10,22 +10,13 @@ def _get_kwargs( - *, - client: Client, form_data: AFormData, ) -> Dict[str, Any]: - url = "{}/tests/post_form_data".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/post_form_data", "data": form_data.to_dict(), } @@ -66,12 +57,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, form_data=form_data, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -96,11 +85,9 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, form_data=form_data, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py index e93a22986..7b567d101 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py @@ -10,22 +10,13 @@ def _get_kwargs( - *, - client: Client, form_data: PostFormDataInlineData, ) -> Dict[str, Any]: - url = "{}/tests/post_form_data_inline".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/post_form_data_inline", "data": form_data.to_dict(), } @@ -66,12 +57,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, form_data=form_data, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -96,11 +85,9 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, form_data=form_data, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py index 289eac03c..6e040b35c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py @@ -11,23 +11,15 @@ def _get_kwargs( *, - client: Client, json_body: str, ) -> Dict[str, Any]: - url = "{}/tests/json_body/string".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass json_json_body = json_body return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/json_body/string", "json": json_json_body, } @@ -74,12 +66,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, json_body=json_body, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -129,12 +119,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, json_body=json_body, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py index f7ce0eda3..a17efbaae 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py @@ -12,23 +12,15 @@ def _get_kwargs( *, - client: Client, json_body: TestInlineObjectsJsonBody, ) -> Dict[str, Any]: - url = "{}/tests/inline_objects".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass json_json_body = json_body.to_dict() return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/inline_objects", "json": json_json_body, } @@ -72,12 +64,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, json_body=json_body, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -127,12 +117,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, json_body=json_body, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py index 994f1ee4e..6d71e23c2 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py @@ -10,23 +10,15 @@ def _get_kwargs( *, - client: Client, my_token: str, ) -> Dict[str, Any]: - url = "{}/auth/token_with_cookie".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() - + cookies = {} cookies["MyToken"] = my_token return { "method": "get", - "url": url, - "headers": headers, + "url": "/auth/token_with_cookie", "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, } @@ -71,12 +63,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, my_token=my_token, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -104,11 +94,9 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, my_token=my_token, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py index 6b719cb38..0fbea8c06 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py @@ -8,22 +8,12 @@ from ...types import Response -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/unsupported_content".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() +def _get_kwargs() -> Dict[str, Any]: + pass return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/unsupported_content", } @@ -59,12 +49,9 @@ def sync_detailed( Response[Any] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -85,11 +72,8 @@ async def asyncio_detailed( Response[Any] """ - kwargs = _get_kwargs( - client=client, - ) + kwargs = _get_kwargs() - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py index 61f28a42e..97f64baf7 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py @@ -12,23 +12,15 @@ def _get_kwargs( *, - client: Client, multipart_data: BodyUploadFileTestsUploadPost, ) -> Dict[str, Any]: - url = "{}/tests/upload".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass multipart_multipart_data = multipart_data.to_multipart() return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/upload", "files": multipart_multipart_data, } @@ -77,12 +69,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, multipart_data=multipart_data, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -136,12 +126,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, multipart_data=multipart_data, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py index 58c459a1d..9ea57fcb7 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py @@ -11,13 +11,9 @@ def _get_kwargs( *, - client: Client, multipart_data: List[File], ) -> Dict[str, Any]: - url = "{}/tests/upload/multiple".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass multipart_multipart_data = [] for multipart_data_item_data in multipart_data: @@ -27,11 +23,7 @@ def _get_kwargs( return { "method": "post", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/tests/upload/multiple", "files": multipart_multipart_data, } @@ -80,12 +72,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, multipart_data=multipart_data, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -139,12 +129,10 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, multipart_data=multipart_data, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py b/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py index 05967d439..283851625 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py @@ -10,13 +10,9 @@ def _get_kwargs( *, - client: Client, import_: str, ) -> Dict[str, Any]: - url = "{}/naming/keywords".format(client.base_url) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() + pass params: Dict[str, Any] = {} params["import"] = import_ @@ -25,11 +21,7 @@ def _get_kwargs( return { "method": "get", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, + "url": "/naming/keywords", "params": params, } @@ -70,12 +62,10 @@ def sync_detailed( """ kwargs = _get_kwargs( - client=client, import_=import_, ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -100,11 +90,9 @@ async def asyncio_detailed( """ kwargs = _get_kwargs( - client=client, import_=import_, ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request(**kwargs) + response = await client.get_async_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/client.py b/end_to_end_tests/golden-record/my_test_api_client/client.py index 2f45c655b..f09665339 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/client.py +++ b/end_to_end_tests/golden-record/my_test_api_client/client.py @@ -1,66 +1,254 @@ import ssl -from typing import Dict, Union +from typing import Any, Dict, Optional, Union -import attr +import httpx +from attrs import define, evolve, field -@attr.s(auto_attribs=True) +@define class Client: """A class for keeping track of data related to the API + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + Attributes: - base_url: The base URL for the API, all requests are made to a relative path to this URL - cookies: A dictionary of cookies to be sent with every request - headers: A dictionary of headers to be sent with every request - timeout: The maximum amount of a time in seconds a request can take. API functions will raise - httpx.TimeoutException if this is exceeded. - verify_ssl: Whether or not to verify the SSL certificate of the API server. This should be True in production, - but can be set to False for testing purposes. raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a - status code that was not documented in the source OpenAPI document. - follow_redirects: Whether or not to follow redirects. Default value is False. + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. """ - base_url: str - cookies: Dict[str, str] = attr.ib(factory=dict, kw_only=True) - headers: Dict[str, str] = attr.ib(factory=dict, kw_only=True) - timeout: float = attr.ib(5.0, kw_only=True) - verify_ssl: Union[str, bool, ssl.SSLContext] = attr.ib(True, kw_only=True) - raise_on_unexpected_status: bool = attr.ib(False, kw_only=True) - follow_redirects: bool = attr.ib(False, kw_only=True) - - def get_headers(self) -> Dict[str, str]: - """Get headers to be used in all endpoints""" - return {**self.headers} + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str + _cookies: Dict[str, str] = field(factory=dict, kw_only=True) + _headers: Dict[str, str] = field(factory=dict, kw_only=True) + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) + _follow_redirects: bool = field(default=False, kw_only=True) + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) def with_headers(self, headers: Dict[str, str]) -> "Client": """Get a new client matching this one with additional headers""" - return attr.evolve(self, headers={**self.headers, **headers}) - - def get_cookies(self) -> Dict[str, str]: - return {**self.cookies} + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) def with_cookies(self, cookies: Dict[str, str]) -> "Client": """Get a new client matching this one with additional cookies""" - return attr.evolve(self, cookies={**self.cookies, **cookies}) + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) - def get_timeout(self) -> float: - return self.timeout - - def with_timeout(self, timeout: float) -> "Client": + def with_timeout(self, timeout: httpx.Timeout) -> "Client": """Get a new client matching this one with a new timeout (in seconds)""" - return attr.evolve(self, timeout=timeout) + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_client(self, client: httpx.Client) -> "Client": + """Manually the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._client + + def __enter__(self) -> "Client": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for self.client (see httpx docs)""" + self.get_client().__exit__(*args, **kwargs) + + def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._async_client + + async def __aenter__(self) -> "Client": + """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + await self.get_async_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for self.async_client (see httpx docs)""" + await self.get_async_client().__aexit__(*args, **kwargs) + + +@define +class AuthenticatedClient: + """A Client which has been authenticated for use on secured endpoints + + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL -@attr.s(auto_attribs=True) -class AuthenticatedClient(Client): - """A Client which has been authenticated for use on secured endpoints""" + ``cookies``: A dictionary of cookies to be sent with every request + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str token: str prefix: str = "Bearer" auth_header_name: str = "Authorization" + _cookies: Dict[str, str] = field(factory=dict, kw_only=True) + _headers: Dict[str, str] = field(factory=dict, kw_only=True) + _timeout: httpx.Timeout = field(default=None, kw_only=True) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) + _follow_redirects: bool = field(default=False, kw_only=True) + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_client(self, client: httpx.Client) -> "AuthenticatedClient": + """Manually the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up + auth **manually** if using this method. + """ + self._client = client + return self + + def get_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._client + + def __enter__(self) -> "AuthenticatedClient": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for self.client (see httpx docs)""" + self.get_client().__exit__(*args, **kwargs) + + def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up + auth **manually** if using this method. + """ + self._async_client = async_client + return self + + def get_async_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient""" + if self._async_client is None: + self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + ) + return self._async_client + + async def __aenter__(self) -> "AuthenticatedClient": + """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + await self.get_async_client().__aenter__() + return self - def get_headers(self) -> Dict[str, str]: - """Get headers to be used in authenticated endpoints""" - auth_header_value = f"{self.prefix} {self.token}" if self.prefix else self.token - return {self.auth_header_name: auth_header_value, **self.headers} + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for self.async_client (see httpx docs)""" + await self.get_async_client().__aexit__(*args, **kwargs) diff --git a/integration-tests/integration_tests/api/body/post_body_multipart.py b/integration-tests/integration_tests/api/body/post_body_multipart.py index 491860007..54c236cae 100644 --- a/integration-tests/integration_tests/api/body/post_body_multipart.py +++ b/integration-tests/integration_tests/api/body/post_body_multipart.py @@ -15,13 +15,13 @@ def _get_kwargs( *, multipart_data: PostBodyMultipartMultipartData, ) -> Dict[str, Any]: - path = "/body/multipart" + pass multipart_multipart_data = multipart_data.to_multipart() return { "method": "post", - "url": path, + "url": "/body/multipart", "files": multipart_multipart_data, } diff --git a/integration-tests/integration_tests/api/parameters/post_parameters_header.py b/integration-tests/integration_tests/api/parameters/post_parameters_header.py index e9c7ddfc8..e60e7ccf2 100644 --- a/integration-tests/integration_tests/api/parameters/post_parameters_header.py +++ b/integration-tests/integration_tests/api/parameters/post_parameters_header.py @@ -17,18 +17,18 @@ def _get_kwargs( number_header: float, integer_header: int, ) -> Dict[str, Any]: - url = "/parameters/header" + headers = {} + headers["Boolean-Header"] = "true" if boolean_header else "false" - headers: Dict[str, Any] = { - "Boolean-Header": "true" if boolean_header else "false", - "String-Header": string_header, - "Number-Header": str(number_header), - "Integer-Header": str(integer_header), - } + headers["String-Header"] = string_header + + headers["Number-Header"] = str(number_header) + + headers["Integer-Header"] = str(integer_header) return { "method": "post", - "url": url, + "url": "/parameters/header", "headers": headers, } diff --git a/integration-tests/integration_tests/client.py b/integration-tests/integration_tests/client.py index c4b147b29..f09665339 100644 --- a/integration-tests/integration_tests/client.py +++ b/integration-tests/integration_tests/client.py @@ -1,8 +1,8 @@ import ssl -from typing import Dict, Union, Optional +from typing import Any, Dict, Optional, Union -from attrs import define, field, evolve import httpx +from attrs import define, evolve, field @define @@ -17,7 +17,7 @@ class Client: ``headers``: A dictionary of headers to be sent with every request - ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + ``timeout``: The maximum amount of a time a request can take. API functions will raise httpx.TimeoutException if this is exceeded. ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, @@ -35,7 +35,7 @@ class Client: _base_url: str _cookies: Dict[str, str] = field(factory=dict, kw_only=True) _headers: Dict[str, str] = field(factory=dict, kw_only=True) - _timeout: float = field(default=5.0, kw_only=True) + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) @@ -57,7 +57,7 @@ def with_cookies(self, cookies: Dict[str, str]) -> "Client": self._async_client.cookies.update(cookies) return evolve(self, cookies={**self._cookies, **cookies}) - def with_timeout(self, timeout: float) -> "Client": + def with_timeout(self, timeout: httpx.Timeout) -> "Client": """Get a new client matching this one with a new timeout (in seconds)""" if self._client is not None: self._client.timeout = timeout @@ -91,7 +91,7 @@ def __enter__(self) -> "Client": self.get_client().__enter__() return self - def __exit__(self, *args, **kwargs) -> None: + def __exit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.client (see httpx docs)""" self.get_client().__exit__(*args, **kwargs) @@ -121,7 +121,7 @@ async def __aenter__(self) -> "Client": await self.get_async_client().__aenter__() return self - async def __aexit__(self, *args, **kwargs) -> None: + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.async_client (see httpx docs)""" await self.get_async_client().__aexit__(*args, **kwargs) @@ -159,7 +159,7 @@ class AuthenticatedClient: auth_header_name: str = "Authorization" _cookies: Dict[str, str] = field(factory=dict, kw_only=True) _headers: Dict[str, str] = field(factory=dict, kw_only=True) - _timeout: float = field(default=5.0, kw_only=True) + _timeout: httpx.Timeout = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) @@ -181,7 +181,7 @@ def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient": self._async_client.cookies.update(cookies) return evolve(self, cookies={**self._cookies, **cookies}) - def with_timeout(self, timeout: float) -> "AuthenticatedClient": + def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": """Get a new client matching this one with a new timeout (in seconds)""" if self._client is not None: self._client.timeout = timeout @@ -212,10 +212,14 @@ def get_client(self) -> httpx.Client: ) return self._client - def __enter__(self) -> "Client": + def __enter__(self) -> "AuthenticatedClient": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - with self.get_client(): - yield self + self.get_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for self.client (see httpx docs)""" + self.get_client().__exit__(*args, **kwargs) def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": """Manually the underlying httpx.AsyncClient @@ -240,7 +244,11 @@ def get_async_client(self) -> httpx.AsyncClient: ) return self._async_client - async def __aenter__(self) -> "Client": + async def __aenter__(self) -> "AuthenticatedClient": """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - async with self.get_async_client(): - yield self + await self.get_async_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for self.async_client (see httpx docs)""" + await self.get_async_client().__aexit__(*args, **kwargs) diff --git a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py index 1197fb532..454de400b 100644 --- a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py +++ b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py @@ -1,6 +1,5 @@ from io import BytesIO -import httpx import pytest from integration_tests.api.body import post_body_multipart diff --git a/openapi_python_client/templates/client.py.jinja b/openapi_python_client/templates/client.py.jinja index c4b147b29..14f6430f4 100644 --- a/openapi_python_client/templates/client.py.jinja +++ b/openapi_python_client/templates/client.py.jinja @@ -1,5 +1,5 @@ import ssl -from typing import Dict, Union, Optional +from typing import Any, Dict, Union, Optional from attrs import define, field, evolve import httpx @@ -17,7 +17,7 @@ class Client: ``headers``: A dictionary of headers to be sent with every request - ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + ``timeout``: The maximum amount of a time a request can take. API functions will raise httpx.TimeoutException if this is exceeded. ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, @@ -35,7 +35,7 @@ class Client: _base_url: str _cookies: Dict[str, str] = field(factory=dict, kw_only=True) _headers: Dict[str, str] = field(factory=dict, kw_only=True) - _timeout: float = field(default=5.0, kw_only=True) + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) @@ -57,7 +57,7 @@ class Client: self._async_client.cookies.update(cookies) return evolve(self, cookies={**self._cookies, **cookies}) - def with_timeout(self, timeout: float) -> "Client": + def with_timeout(self, timeout: httpx.Timeout) -> "Client": """Get a new client matching this one with a new timeout (in seconds)""" if self._client is not None: self._client.timeout = timeout @@ -91,7 +91,7 @@ class Client: self.get_client().__enter__() return self - def __exit__(self, *args, **kwargs) -> None: + def __exit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.client (see httpx docs)""" self.get_client().__exit__(*args, **kwargs) @@ -121,7 +121,7 @@ class Client: await self.get_async_client().__aenter__() return self - async def __aexit__(self, *args, **kwargs) -> None: + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.async_client (see httpx docs)""" await self.get_async_client().__aexit__(*args, **kwargs) @@ -159,7 +159,7 @@ class AuthenticatedClient: auth_header_name: str = "Authorization" _cookies: Dict[str, str] = field(factory=dict, kw_only=True) _headers: Dict[str, str] = field(factory=dict, kw_only=True) - _timeout: float = field(default=5.0, kw_only=True) + _timeout: httpx.Timeout = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) @@ -181,7 +181,7 @@ class AuthenticatedClient: self._async_client.cookies.update(cookies) return evolve(self, cookies={**self._cookies, **cookies}) - def with_timeout(self, timeout: float) -> "AuthenticatedClient": + def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": """Get a new client matching this one with a new timeout (in seconds)""" if self._client is not None: self._client.timeout = timeout @@ -212,10 +212,14 @@ class AuthenticatedClient: ) return self._client - def __enter__(self) -> "Client": + def __enter__(self) -> "AuthenticatedClient": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - with self.get_client(): - yield self + self.get_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for self.client (see httpx docs)""" + self.get_client().__exit__(*args, **kwargs) def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": """Manually the underlying httpx.AsyncClient @@ -240,7 +244,11 @@ class AuthenticatedClient: ) return self._async_client - async def __aenter__(self) -> "Client": + async def __aenter__(self) -> "AuthenticatedClient": """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - async with self.get_async_client(): - yield self + await self.get_async_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for self.async_client (see httpx docs)""" + await self.get_async_client().__aexit__(*args, **kwargs) \ No newline at end of file diff --git a/openapi_python_client/templates/endpoint_macros.py.jinja b/openapi_python_client/templates/endpoint_macros.py.jinja index 090796537..391ab2e40 100644 --- a/openapi_python_client/templates/endpoint_macros.py.jinja +++ b/openapi_python_client/templates/endpoint_macros.py.jinja @@ -3,20 +3,22 @@ {% macro header_params(endpoint) %} {% if endpoint.header_parameters %} +headers = {} {% for parameter in endpoint.header_parameters.values() %} - {% set destination = 'headers["' + parameter.name + '"]' %} {% import "property_templates/" + parameter.template as param_template %} {% if param_template.transform_header %} - {% set statement = param_template.transform_header(parameter, parameter.python_name, destination) %} + {% set expression = param_template.transform_header(parameter.python_name) %} {% else %} - {% set statement = destination + " = " + parameter.python_name %} + {% set expression = parameter.python_name %} {% endif %} + {% set statement = 'headers["' + parameter.name + '"]' + " = " + expression %} {{ guarded_statement(parameter, parameter.python_name, statement) }} {% endfor %} {% endif %} {% endmacro %} {% macro cookie_params(endpoint) %} +cookies = {} {% if endpoint.cookie_parameters %} {% for parameter in endpoint.cookie_parameters.values() %} {% if parameter.required %} @@ -78,18 +80,22 @@ params = {k: v for k, v in params.items() if v is not UNSET and v is not None} {% endmacro %} {# The all the kwargs passed into an endpoint (and variants thereof)) #} -{% macro arguments(endpoint) %} +{% macro arguments(endpoint, include_client=True) %} {# path parameters #} {% for parameter in endpoint.path_parameters.values() %} {{ parameter.to_string() }}, {% endfor %} +{% if include_client or ((endpoint.list_all_parameters() | length) > (endpoint.path_parameters | length)) %} *, +{% endif %} {# Proper client based on whether or not the endpoint requires authentication #} +{% if include_client %} {% if endpoint.requires_security %} client: AuthenticatedClient, {% else %} client: Client, {% endif %} +{% endif %} {# Form data if any #} {% if endpoint.form_body %} form_data: {{ endpoint.form_body.get_type_string() }}, @@ -116,11 +122,13 @@ json_body: {{ endpoint.json_body.get_type_string() }}, {% endmacro %} {# Just lists all kwargs to endpoints as name=name for passing to other functions #} -{% macro kwargs(endpoint) %} +{% macro kwargs(endpoint, include_client=True) %} {% for parameter in endpoint.path_parameters.values() %} {{ parameter.python_name }}={{ parameter.python_name }}, {% endfor %} +{% if include_client %} client=client, +{% endif %} {% if endpoint.form_body %} form_data=form_data, {% endif %} diff --git a/openapi_python_client/templates/endpoint_module.py.jinja b/openapi_python_client/templates/endpoint_module.py.jinja index a94c6f025..6f2240871 100644 --- a/openapi_python_client/templates/endpoint_module.py.jinja +++ b/openapi_python_client/templates/endpoint_module.py.jinja @@ -18,18 +18,8 @@ from ... import errors {% set parsed_responses = (endpoint.responses | length > 0) and return_string != "Any" %} def _get_kwargs( - {{ arguments(endpoint) | indent(4) }} + {{ arguments(endpoint, include_client=False) | indent(4) }} ) -> Dict[str, Any]: - url = "{}{{ endpoint.path }}".format( - client.base_url - {%- for parameter in endpoint.path_parameters.values() -%} - ,{{parameter.name}}={{parameter.python_name}} - {%- endfor -%} - ) - - headers: Dict[str, str] = client.get_headers() - cookies: Dict[str, Any] = client.get_cookies() - {{ header_params(endpoint) | indent(4) }} {{ cookie_params(endpoint) | indent(4) }} @@ -41,22 +31,32 @@ def _get_kwargs( {{ multipart_body(endpoint) | indent(4) }} return { - "method": "{{ endpoint.method }}", - "url": url, - "headers": headers, - "cookies": cookies, - "timeout": client.get_timeout(), - "follow_redirects": client.follow_redirects, - {% if endpoint.form_body %} + "method": "{{ endpoint.method }}", + {% if endpoint.path_parameters %} + "url": "{{ endpoint.path }}".format( + {%- for parameter in endpoint.path_parameters.values() -%} + {{parameter.name}}={{parameter.python_name}}, + {%- endfor -%} + ), + {% else %} + "url": "{{ endpoint.path }}", + {% endif %} + {% if endpoint.form_body %} "data": form_data.to_dict(), - {% elif endpoint.multipart_body %} + {% elif endpoint.multipart_body %} "files": {{ "multipart_" + endpoint.multipart_body.python_name }}, - {% elif endpoint.json_body %} + {% elif endpoint.json_body %} "json": {{ "json_" + endpoint.json_body.python_name }}, - {% endif %} - {% if endpoint.query_parameters %} + {% endif %} + {% if endpoint.query_parameters %} "params": params, - {% endif %} + {% endif %} + {% if endpoint.header_parameters %} + "headers": headers, + {% endif %} + {% if endpoint.cookie_parameters %} + "cookies": cookies, + {% endif %} } @@ -95,11 +95,10 @@ def sync_detailed( {{ docstring(endpoint, return_string, is_detailed=true) | indent(4) }} kwargs = _get_kwargs( - {{ kwargs(endpoint) }} + {{ kwargs(endpoint, include_client=False) }} ) - response = httpx.request( - verify=client.verify_ssl, + response = client.get_client().request( **kwargs, ) @@ -122,13 +121,12 @@ async def asyncio_detailed( {{ docstring(endpoint, return_string, is_detailed=true) | indent(4) }} kwargs = _get_kwargs( - {{ kwargs(endpoint) }} + {{ kwargs(endpoint, include_client=False) }} ) - async with httpx.AsyncClient(verify=client.verify_ssl) as _client: - response = await _client.request( - **kwargs - ) + response = await client.get_async_client().request( + **kwargs + ) return _build_response(client=client, response=response) diff --git a/openapi_python_client/templates/property_templates/boolean_property.py.jinja b/openapi_python_client/templates/property_templates/boolean_property.py.jinja index a63639bc5..3b16b7d20 100644 --- a/openapi_python_client/templates/property_templates/boolean_property.py.jinja +++ b/openapi_python_client/templates/property_templates/boolean_property.py.jinja @@ -1,3 +1,3 @@ -{% macro transform_header(property, source, destination) %} -{{ destination }} = "true" if {{ source }} else "false" +{% macro transform_header(source) %} +"true" if {{ source }} else "false" {% endmacro %} diff --git a/openapi_python_client/templates/property_templates/enum_property.py.jinja b/openapi_python_client/templates/property_templates/enum_property.py.jinja index 52418a182..2e9a55520 100644 --- a/openapi_python_client/templates/property_templates/enum_property.py.jinja +++ b/openapi_python_client/templates/property_templates/enum_property.py.jinja @@ -34,6 +34,6 @@ if not isinstance({{ source }}, Unset): {% endif %} {% endmacro %} -{% macro transform_header(property, source, destination) %} -{{ destination }} = str({{ source }}) +{% macro transform_header(source) %} +str({{ source }}) {% endmacro %} diff --git a/openapi_python_client/templates/property_templates/float_property.py.jinja b/openapi_python_client/templates/property_templates/float_property.py.jinja index f66f991ee..0d433c22e 100644 --- a/openapi_python_client/templates/property_templates/float_property.py.jinja +++ b/openapi_python_client/templates/property_templates/float_property.py.jinja @@ -1,3 +1,3 @@ -{% macro transform_header(property, source, destination) %} -{{ destination }} = str({{ source }}) +{% macro transform_header(source) %} +str({{ source }}) {% endmacro %} diff --git a/openapi_python_client/templates/property_templates/int_property.py.jinja b/openapi_python_client/templates/property_templates/int_property.py.jinja index f66f991ee..0d433c22e 100644 --- a/openapi_python_client/templates/property_templates/int_property.py.jinja +++ b/openapi_python_client/templates/property_templates/int_property.py.jinja @@ -1,3 +1,3 @@ -{% macro transform_header(property, source, destination) %} -{{ destination }} = str({{ source }}) +{% macro transform_header(source) %} +str({{ source }}) {% endmacro %} From a43738f22dbab1722c10e24b04917261f5265ebc Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Mon, 3 Jul 2023 12:15:59 -0600 Subject: [PATCH 05/18] Update generated readmes --- ..._generated_readmes_when_not_appropriate.md | 5 ++ end_to_end_tests/golden-record/README.md | 58 ++++++++++++++---- .../test_body/test_post_body_multipart.py | 39 ++++++++++++ openapi_python_client/__init__.py | 2 +- .../templates/README.md.jinja | 60 +++++++++++++++---- tests/test___init__.py | 4 +- 6 files changed, 141 insertions(+), 27 deletions(-) create mode 100644 .changeset/stop_showing_poetry_instructions_in_generated_readmes_when_not_appropriate.md diff --git a/.changeset/stop_showing_poetry_instructions_in_generated_readmes_when_not_appropriate.md b/.changeset/stop_showing_poetry_instructions_in_generated_readmes_when_not_appropriate.md new file mode 100644 index 000000000..f06b4eb3e --- /dev/null +++ b/.changeset/stop_showing_poetry_instructions_in_generated_readmes_when_not_appropriate.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +#### Stop showing Poetry instructions in generated READMEs when not appropriate diff --git a/end_to_end_tests/golden-record/README.md b/end_to_end_tests/golden-record/README.md index 3def2172e..ffcf5003f 100644 --- a/end_to_end_tests/golden-record/README.md +++ b/end_to_end_tests/golden-record/README.md @@ -25,9 +25,10 @@ from my_test_api_client.models import MyDataModel from my_test_api_client.api.my_tag import get_my_data_model from my_test_api_client.types import Response -my_data: MyDataModel = get_my_data_model.sync(client=client) -# or if you need more info (e.g. status_code) -response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client) +with client as client: + my_data: MyDataModel = get_my_data_model.sync(client=client) + # or if you need more info (e.g. status_code) + response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client) ``` Or do the same thing with an async version: @@ -37,8 +38,9 @@ from my_test_api_client.models import MyDataModel from my_test_api_client.api.my_tag import get_my_data_model from my_test_api_client.types import Response -my_data: MyDataModel = await get_my_data_model.asyncio(client=client) -response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client) +async with client as client: + my_data: MyDataModel = await get_my_data_model.asyncio(client=client) + response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client) ``` By default, when you're calling an HTTPS API it will attempt to verify that SSL is working correctly. Using certificate verification is highly recommended most of the time, but sometimes you may need to authenticate to a server (especially an internal server) using a custom certificate bundle. @@ -61,20 +63,52 @@ client = AuthenticatedClient( ) ``` -There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. - Things to know: 1. Every path/method combo becomes a Python module with four functions: - 1. `sync`: Blocking request that returns parsed data (if successful) or `None` - 1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. - 1. `asyncio`: Like `sync` but async instead of blocking - 1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking +1. `sync`: Blocking request that returns parsed data (if successful) or `None` +1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. +1. `asyncio`: Like `sync` but async instead of blocking +1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking 1. All path/query params, and bodies become method arguments. 1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above) 1. Any endpoint which did not have a tag will be in `my_test_api_client.api.default` -## Building / publishing this Client +## Advanced customizations + +There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. You can also customize the underlying `httpx.Client` or `httpx.AsyncClient` (depending on your use-case): + +```python +from my_test_api_client import Client + +client = Client( + base_url="https://api.example.com", +) +httpx_client = client.get_client() +def log_request(request): + print(f"Request event hook: {request.method} {request.url} - Waiting for response") + +def log_response(response): + request = response.request + print(f"Response event hook: {request.method} {request.url} - Status {response.status_code}") + +httpx_client.event_hooks = {"request": [log_request], "response": [log_response]} +``` + +You can even set the httpx client directly, but beware that this will override any existing settings (e.g., base_url): + +```python +import httpx +from my_test_api_client import Client + +client = Client( + base_url="https://api.example.com", +) +# Note that base_url needs to be re-set, as would any shared cookies, headers, etc. +client.set_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030")) +``` + +## Building / publishing this package This project uses [Poetry](https://python-poetry.org/) to manage dependencies and packaging. Here are the basics: 1. Update the metadata in pyproject.toml (e.g. authors, version) 1. If you're using a private repository, configure it with Poetry diff --git a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py index 454de400b..e6fe535d9 100644 --- a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py +++ b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py @@ -1,4 +1,5 @@ from io import BytesIO +from typing import Any import pytest @@ -40,6 +41,44 @@ def test(client: Client) -> None: assert content.description == description +def test_custom_hooks(client: Client) -> None: + a_string = "a test string" + payload = b"some file content" + file_name = "cool_stuff.txt" + mime_type = "application/openapi-python-client" + description = "super descriptive thing" + + httpx_client = client.get_client() + request_hook_called = False + response_hook_called = False + + def log_request(*_: Any, **__: Any) -> None: + nonlocal request_hook_called + request_hook_called = True + + def log_response(*_: Any, **__: Any) -> None: + nonlocal response_hook_called + response_hook_called = True + + httpx_client.event_hooks = {"request": [log_request], "response": [log_response]} + + post_body_multipart.sync_detailed( + client=client, + multipart_data=PostBodyMultipartMultipartData( + a_string=a_string, + file=File( + payload=BytesIO(payload), + file_name=file_name, + mime_type=mime_type, + ), + description=description, + ), + ) + + assert request_hook_called + assert response_hook_called + + def test_context_manager(client: Client) -> None: a_string = "a test string" payload = b"some file content" diff --git a/openapi_python_client/__init__.py b/openapi_python_client/__init__.py index e7bd51475..975813bf4 100644 --- a/openapi_python_client/__init__.py +++ b/openapi_python_client/__init__.py @@ -197,7 +197,7 @@ def _build_metadata(self) -> None: readme = self.project_dir / "README.md" readme_template = self.env.get_template("README.md.jinja") readme.write_text( - readme_template.render(), + readme_template.render(poetry=self.meta == MetaType.POETRY), encoding=self.file_encoding, ) diff --git a/openapi_python_client/templates/README.md.jinja b/openapi_python_client/templates/README.md.jinja index 1d50c8d2a..c82d8a7b4 100644 --- a/openapi_python_client/templates/README.md.jinja +++ b/openapi_python_client/templates/README.md.jinja @@ -25,9 +25,10 @@ from {{ package_name }}.models import MyDataModel from {{ package_name }}.api.my_tag import get_my_data_model from {{ package_name }}.types import Response -my_data: MyDataModel = get_my_data_model.sync(client=client) -# or if you need more info (e.g. status_code) -response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client) +with client as client: + my_data: MyDataModel = get_my_data_model.sync(client=client) + # or if you need more info (e.g. status_code) + response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client) ``` Or do the same thing with an async version: @@ -37,8 +38,9 @@ from {{ package_name }}.models import MyDataModel from {{ package_name }}.api.my_tag import get_my_data_model from {{ package_name }}.types import Response -my_data: MyDataModel = await get_my_data_model.asyncio(client=client) -response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client) +async with client as client: + my_data: MyDataModel = await get_my_data_model.asyncio(client=client) + response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client) ``` By default, when you're calling an HTTPS API it will attempt to verify that SSL is working correctly. Using certificate verification is highly recommended most of the time, but sometimes you may need to authenticate to a server (especially an internal server) using a custom certificate bundle. @@ -61,20 +63,53 @@ client = AuthenticatedClient( ) ``` -There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. - Things to know: 1. Every path/method combo becomes a Python module with four functions: - 1. `sync`: Blocking request that returns parsed data (if successful) or `None` - 1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. - 1. `asyncio`: Like `sync` but async instead of blocking - 1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking +1. `sync`: Blocking request that returns parsed data (if successful) or `None` +1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. +1. `asyncio`: Like `sync` but async instead of blocking +1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking 1. All path/query params, and bodies become method arguments. 1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above) 1. Any endpoint which did not have a tag will be in `{{ package_name }}.api.default` -## Building / publishing this Client +## Advanced customizations + +There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. You can also customize the underlying `httpx.Client` or `httpx.AsyncClient` (depending on your use-case): + +```python +from {{ package_name }} import Client + +client = Client( + base_url="https://api.example.com", +) +httpx_client = client.get_client() +def log_request(request): + print(f"Request event hook: {request.method} {request.url} - Waiting for response") + +def log_response(response): + request = response.request + print(f"Response event hook: {request.method} {request.url} - Status {response.status_code}") + +httpx_client.event_hooks = {"request": [log_request], "response": [log_response]} +``` + +You can even set the httpx client directly, but beware that this will override any existing settings (e.g., base_url): + +```python +import httpx +from {{ package_name }} import Client + +client = Client( + base_url="https://api.example.com", +) +# Note that base_url needs to be re-set, as would any shared cookies, headers, etc. +client.set_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030")) +``` + +{% if poetry %} +## Building / publishing this package This project uses [Poetry](https://python-poetry.org/) to manage dependencies and packaging. Here are the basics: 1. Update the metadata in pyproject.toml (e.g. authors, version) 1. If you're using a private repository, configure it with Poetry @@ -87,3 +122,4 @@ If you want to install this client into another project without publishing it (e 1. If that project is not using Poetry: 1. Build a wheel with `poetry build -f wheel` 1. Install that wheel from the other project `pip install ` +{% endif %} \ No newline at end of file diff --git a/tests/test___init__.py b/tests/test___init__.py index fcf767cc9..5f50614f0 100644 --- a/tests/test___init__.py +++ b/tests/test___init__.py @@ -453,7 +453,7 @@ def test__build_metadata_poetry(self, mocker): project._build_metadata() project.env.get_template.assert_has_calls([mocker.call("README.md.jinja"), mocker.call(".gitignore.jinja")]) - readme_template.render.assert_called_once_with() + readme_template.render.assert_called_once_with(poetry=True) readme_path.write_text.assert_called_once_with(readme_template.render(), encoding="utf-8") git_ignore_template.render.assert_called_once() git_ignore_path.write_text.assert_called_once_with(git_ignore_template.render(), encoding="utf-8") @@ -486,7 +486,7 @@ def test__build_metadata_setup(self, mocker): project._build_metadata() project.env.get_template.assert_has_calls([mocker.call("README.md.jinja"), mocker.call(".gitignore.jinja")]) - readme_template.render.assert_called_once_with() + readme_template.render.assert_called_once_with(poetry=False) readme_path.write_text.assert_called_once_with(readme_template.render(), encoding="utf-8") git_ignore_template.render.assert_called_once() git_ignore_path.write_text.assert_called_once_with(git_ignore_template.render(), encoding="utf-8") From 5b3199c576523055a399285d131d18b478c49990 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Tue, 4 Jul 2023 12:41:04 -0600 Subject: [PATCH 06/18] Rename `*_client` functions to `*_httpx_client` --- end_to_end_tests/golden-record/README.md | 4 +-- .../api/default/get_common_parameters.py | 4 +-- .../api/default/post_common_parameters.py | 4 +-- .../api/default/reserved_parameters.py | 4 +-- .../api/location/get_location_header_types.py | 4 +-- .../get_location_query_optionality.py | 4 +-- .../get_parameter_references_path_param.py | 4 +-- ...lete_common_parameters_overriding_param.py | 4 +-- .../get_common_parameters_overriding_param.py | 4 +-- .../get_same_name_multiple_locations_param.py | 4 +-- .../parameters/multiple_path_parameters.py | 4 +-- ..._responses_unions_simple_before_complex.py | 4 +-- .../api/tag1/get_tag_with_number.py | 4 +-- .../api/tests/callback_test.py | 4 +-- .../api/tests/defaults_tests_defaults_post.py | 4 +-- .../api/tests/description_with_backslash.py | 4 +-- .../api/tests/get_basic_list_of_booleans.py | 4 +-- .../api/tests/get_basic_list_of_floats.py | 4 +-- .../api/tests/get_basic_list_of_integers.py | 4 +-- .../api/tests/get_basic_list_of_strings.py | 4 +-- .../api/tests/get_user_list.py | 4 +-- .../api/tests/int_enum_tests_int_enum_post.py | 4 +-- .../tests/json_body_tests_json_body_post.py | 4 +-- .../no_response_tests_no_response_get.py | 4 +-- .../octet_stream_tests_octet_stream_get.py | 4 +-- .../api/tests/post_form_data.py | 4 +-- .../api/tests/post_form_data_inline.py | 4 +-- .../api/tests/post_tests_json_body_string.py | 4 +-- .../api/tests/test_inline_objects.py | 4 +-- ..._with_cookie_auth_token_with_cookie_get.py | 4 +-- ...d_content_tests_unsupported_content_get.py | 4 +-- .../tests/upload_file_tests_upload_post.py | 4 +-- ...upload_multiple_files_tests_upload_post.py | 4 +-- .../my_test_api_client/api/true_/false_.py | 4 +-- .../my_test_api_client/client.py | 32 +++++++++---------- .../api/body/post_body_multipart.py | 4 +-- .../api/parameters/post_parameters_header.py | 4 +-- integration-tests/integration_tests/client.py | 32 +++++++++---------- .../test_body/test_post_body_multipart.py | 2 +- .../templates/README.md.jinja | 4 +-- .../templates/client.py.jinja | 32 +++++++++---------- .../templates/endpoint_module.py.jinja | 4 +-- 42 files changed, 125 insertions(+), 125 deletions(-) diff --git a/end_to_end_tests/golden-record/README.md b/end_to_end_tests/golden-record/README.md index ffcf5003f..324cd885e 100644 --- a/end_to_end_tests/golden-record/README.md +++ b/end_to_end_tests/golden-record/README.md @@ -84,7 +84,7 @@ from my_test_api_client import Client client = Client( base_url="https://api.example.com", ) -httpx_client = client.get_client() +httpx_client = client.get_httpx_client() def log_request(request): print(f"Request event hook: {request.method} {request.url} - Waiting for response") @@ -105,7 +105,7 @@ client = Client( base_url="https://api.example.com", ) # Note that base_url needs to be re-set, as would any shared cookies, headers, etc. -client.set_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030")) +client.set_httpx_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030")) ``` ## Building / publishing this package diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py index 29a60581e..7ec4bdb7c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py @@ -65,7 +65,7 @@ def sync_detailed( common=common, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -93,6 +93,6 @@ async def asyncio_detailed( common=common, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py index 223fbbfd5..10458af4b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py @@ -65,7 +65,7 @@ def sync_detailed( common=common, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -93,6 +93,6 @@ async def asyncio_detailed( common=common, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py index 7a9774a51..04a71a9ae 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py @@ -71,7 +71,7 @@ def sync_detailed( url_query=url_query, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -102,6 +102,6 @@ async def asyncio_detailed( url_query=url_query, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py index 071dd38dc..6adba3293 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py @@ -99,7 +99,7 @@ def sync_detailed( string_enum_header=string_enum_header, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -142,6 +142,6 @@ async def asyncio_detailed( string_enum_header=string_enum_header, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py index 95f5a155c..c10945f98 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py @@ -98,7 +98,7 @@ def sync_detailed( not_null_not_required=not_null_not_required, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -135,6 +135,6 @@ async def asyncio_detailed( not_null_not_required=not_null_not_required, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py index d859a0803..99ab10ccf 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py @@ -94,7 +94,7 @@ def sync_detailed( cookie_param=cookie_param, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -135,6 +135,6 @@ async def asyncio_detailed( cookie_param=cookie_param, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py index 1bd00664a..0d8cc434a 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py @@ -71,7 +71,7 @@ def sync_detailed( param_query=param_query, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -102,6 +102,6 @@ async def asyncio_detailed( param_query=param_query, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py index b6c0923f2..be59702c8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py @@ -73,7 +73,7 @@ def sync_detailed( param_query=param_query, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -106,6 +106,6 @@ async def asyncio_detailed( param_query=param_query, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py index 9e10fc237..fd3720c31 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py @@ -87,7 +87,7 @@ def sync_detailed( param_cookie=param_cookie, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -124,6 +124,6 @@ async def asyncio_detailed( param_cookie=param_cookie, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py index 4842da8b9..e561558b0 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py @@ -75,7 +75,7 @@ def sync_detailed( param3=param3, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -112,6 +112,6 @@ async def asyncio_detailed( param3=param3, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py b/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py index 16765d331..8e90a0e31 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py @@ -60,7 +60,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -102,7 +102,7 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py b/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py index ffb392058..286485e20 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py @@ -50,7 +50,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -72,6 +72,6 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py index f13f5824b..e202312cf 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py @@ -72,7 +72,7 @@ def sync_detailed( json_body=json_body, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -129,7 +129,7 @@ async def asyncio_detailed( json_body=json_body, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index 941eb3462..cef8bc91d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -167,7 +167,7 @@ def sync_detailed( required_model_prop=required_model_prop, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -280,7 +280,7 @@ async def asyncio_detailed( required_model_prop=required_model_prop, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py index 6b415634b..1481d1bbb 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py @@ -53,7 +53,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -78,6 +78,6 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py index 7ce8362b9..e1b991dc2 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py @@ -55,7 +55,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -101,7 +101,7 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py index e36f90d93..9a343bce7 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py @@ -55,7 +55,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -101,7 +101,7 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py index 6b3043fcc..c14ad189b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py @@ -55,7 +55,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -101,7 +101,7 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py index 749623101..0bcc52e32 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py @@ -55,7 +55,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -101,7 +101,7 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py index be88e9b4d..6bdebc5d9 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py @@ -133,7 +133,7 @@ def sync_detailed( some_date=some_date, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -208,7 +208,7 @@ async def asyncio_detailed( some_date=some_date, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py index bdbe17f16..687cd9bbc 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py @@ -75,7 +75,7 @@ def sync_detailed( int_enum=int_enum, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -128,7 +128,7 @@ async def asyncio_detailed( int_enum=int_enum, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py index 7b0fd8e20..551fd4c83 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py @@ -72,7 +72,7 @@ def sync_detailed( json_body=json_body, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -129,7 +129,7 @@ async def asyncio_detailed( json_body=json_body, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py index 231537ff8..6e50a34c5 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py @@ -51,7 +51,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -74,6 +74,6 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py index 528202ffd..a01c9633a 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py @@ -54,7 +54,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -96,7 +96,7 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py index 344e4e88f..51951de83 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py @@ -60,7 +60,7 @@ def sync_detailed( form_data=form_data, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -88,6 +88,6 @@ async def asyncio_detailed( form_data=form_data, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py index 7b567d101..9ea9a41ec 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py @@ -60,7 +60,7 @@ def sync_detailed( form_data=form_data, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -88,6 +88,6 @@ async def asyncio_detailed( form_data=form_data, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py index 6e040b35c..43d1d0592 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py @@ -69,7 +69,7 @@ def sync_detailed( json_body=json_body, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -122,7 +122,7 @@ async def asyncio_detailed( json_body=json_body, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py index a17efbaae..acc3838e1 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py @@ -67,7 +67,7 @@ def sync_detailed( json_body=json_body, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -120,7 +120,7 @@ async def asyncio_detailed( json_body=json_body, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py index 6d71e23c2..5d793bcbf 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py @@ -66,7 +66,7 @@ def sync_detailed( my_token=my_token, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -97,6 +97,6 @@ async def asyncio_detailed( my_token=my_token, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py index 0fbea8c06..fb0b3d863 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py @@ -51,7 +51,7 @@ def sync_detailed( kwargs = _get_kwargs() - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -74,6 +74,6 @@ async def asyncio_detailed( kwargs = _get_kwargs() - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py index 97f64baf7..542d937e8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py @@ -72,7 +72,7 @@ def sync_detailed( multipart_data=multipart_data, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -129,7 +129,7 @@ async def asyncio_detailed( multipart_data=multipart_data, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py index 9ea57fcb7..6344173e8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py @@ -75,7 +75,7 @@ def sync_detailed( multipart_data=multipart_data, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -132,7 +132,7 @@ async def asyncio_detailed( multipart_data=multipart_data, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py b/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py index 283851625..ce06b51e3 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py @@ -65,7 +65,7 @@ def sync_detailed( import_=import_, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -93,6 +93,6 @@ async def asyncio_detailed( import_=import_, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/client.py b/end_to_end_tests/golden-record/my_test_api_client/client.py index f09665339..f36b0fd52 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/client.py +++ b/end_to_end_tests/golden-record/my_test_api_client/client.py @@ -65,7 +65,7 @@ def with_timeout(self, timeout: httpx.Timeout) -> "Client": self._async_client.timeout = timeout return evolve(self, timeout=timeout) - def set_client(self, client: httpx.Client) -> "Client": + def set_httpx_client(self, client: httpx.Client) -> "Client": """Manually the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. @@ -73,7 +73,7 @@ def set_client(self, client: httpx.Client) -> "Client": self._client = client return self - def get_client(self) -> httpx.Client: + def get_httpx_client(self) -> httpx.Client: """Get the underlying httpx.Client, constructing a new one if not previously set""" if self._client is None: self._client = httpx.Client( @@ -88,14 +88,14 @@ def get_client(self) -> httpx.Client: def __enter__(self) -> "Client": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - self.get_client().__enter__() + self.get_httpx_client().__enter__() return self def __exit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.client (see httpx docs)""" - self.get_client().__exit__(*args, **kwargs) + self.get_httpx_client().__exit__(*args, **kwargs) - def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": """Manually the underlying httpx.AsyncClient **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. @@ -103,7 +103,7 @@ def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": self._async_client = async_client return self - def get_async_client(self) -> httpx.AsyncClient: + def get_async_httpx_client(self) -> httpx.AsyncClient: """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" if self._async_client is None: self._async_client = httpx.AsyncClient( @@ -118,12 +118,12 @@ def get_async_client(self) -> httpx.AsyncClient: async def __aenter__(self) -> "Client": """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - await self.get_async_client().__aenter__() + await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.async_client (see httpx docs)""" - await self.get_async_client().__aexit__(*args, **kwargs) + await self.get_async_httpx_client().__aexit__(*args, **kwargs) @define @@ -189,7 +189,7 @@ def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": self._async_client.timeout = timeout return evolve(self, timeout=timeout) - def set_client(self, client: httpx.Client) -> "AuthenticatedClient": + def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": """Manually the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up @@ -198,7 +198,7 @@ def set_client(self, client: httpx.Client) -> "AuthenticatedClient": self._client = client return self - def get_client(self) -> httpx.Client: + def get_httpx_client(self) -> httpx.Client: """Get the underlying httpx.Client, constructing a new one if not previously set""" if self._client is None: self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token @@ -214,14 +214,14 @@ def get_client(self) -> httpx.Client: def __enter__(self) -> "AuthenticatedClient": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - self.get_client().__enter__() + self.get_httpx_client().__enter__() return self def __exit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.client (see httpx docs)""" - self.get_client().__exit__(*args, **kwargs) + self.get_httpx_client().__exit__(*args, **kwargs) - def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": """Manually the underlying httpx.AsyncClient **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up @@ -230,7 +230,7 @@ def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedCli self._async_client = async_client return self - def get_async_client(self) -> httpx.AsyncClient: + def get_async_httpx_client(self) -> httpx.AsyncClient: """Get the underlying httpx.AsyncClient""" if self._async_client is None: self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token @@ -246,9 +246,9 @@ def get_async_client(self) -> httpx.AsyncClient: async def __aenter__(self) -> "AuthenticatedClient": """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - await self.get_async_client().__aenter__() + await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.async_client (see httpx docs)""" - await self.get_async_client().__aexit__(*args, **kwargs) + await self.get_async_httpx_client().__aexit__(*args, **kwargs) diff --git a/integration-tests/integration_tests/api/body/post_body_multipart.py b/integration-tests/integration_tests/api/body/post_body_multipart.py index 54c236cae..12ef45826 100644 --- a/integration-tests/integration_tests/api/body/post_body_multipart.py +++ b/integration-tests/integration_tests/api/body/post_body_multipart.py @@ -75,7 +75,7 @@ def sync_detailed( multipart_data=multipart_data, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -126,7 +126,7 @@ async def asyncio_detailed( multipart_data=multipart_data, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/integration-tests/integration_tests/api/parameters/post_parameters_header.py b/integration-tests/integration_tests/api/parameters/post_parameters_header.py index e60e7ccf2..ab577d6f8 100644 --- a/integration-tests/integration_tests/api/parameters/post_parameters_header.py +++ b/integration-tests/integration_tests/api/parameters/post_parameters_header.py @@ -91,7 +91,7 @@ def sync_detailed( integer_header=integer_header, ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -160,7 +160,7 @@ async def asyncio_detailed( integer_header=integer_header, ) - response = await client.get_async_client().request(**kwargs) + response = await client.get_async_httpx_client().request(**kwargs) return _build_response(client=client, response=response) diff --git a/integration-tests/integration_tests/client.py b/integration-tests/integration_tests/client.py index f09665339..f36b0fd52 100644 --- a/integration-tests/integration_tests/client.py +++ b/integration-tests/integration_tests/client.py @@ -65,7 +65,7 @@ def with_timeout(self, timeout: httpx.Timeout) -> "Client": self._async_client.timeout = timeout return evolve(self, timeout=timeout) - def set_client(self, client: httpx.Client) -> "Client": + def set_httpx_client(self, client: httpx.Client) -> "Client": """Manually the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. @@ -73,7 +73,7 @@ def set_client(self, client: httpx.Client) -> "Client": self._client = client return self - def get_client(self) -> httpx.Client: + def get_httpx_client(self) -> httpx.Client: """Get the underlying httpx.Client, constructing a new one if not previously set""" if self._client is None: self._client = httpx.Client( @@ -88,14 +88,14 @@ def get_client(self) -> httpx.Client: def __enter__(self) -> "Client": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - self.get_client().__enter__() + self.get_httpx_client().__enter__() return self def __exit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.client (see httpx docs)""" - self.get_client().__exit__(*args, **kwargs) + self.get_httpx_client().__exit__(*args, **kwargs) - def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": """Manually the underlying httpx.AsyncClient **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. @@ -103,7 +103,7 @@ def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": self._async_client = async_client return self - def get_async_client(self) -> httpx.AsyncClient: + def get_async_httpx_client(self) -> httpx.AsyncClient: """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" if self._async_client is None: self._async_client = httpx.AsyncClient( @@ -118,12 +118,12 @@ def get_async_client(self) -> httpx.AsyncClient: async def __aenter__(self) -> "Client": """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - await self.get_async_client().__aenter__() + await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.async_client (see httpx docs)""" - await self.get_async_client().__aexit__(*args, **kwargs) + await self.get_async_httpx_client().__aexit__(*args, **kwargs) @define @@ -189,7 +189,7 @@ def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": self._async_client.timeout = timeout return evolve(self, timeout=timeout) - def set_client(self, client: httpx.Client) -> "AuthenticatedClient": + def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": """Manually the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up @@ -198,7 +198,7 @@ def set_client(self, client: httpx.Client) -> "AuthenticatedClient": self._client = client return self - def get_client(self) -> httpx.Client: + def get_httpx_client(self) -> httpx.Client: """Get the underlying httpx.Client, constructing a new one if not previously set""" if self._client is None: self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token @@ -214,14 +214,14 @@ def get_client(self) -> httpx.Client: def __enter__(self) -> "AuthenticatedClient": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - self.get_client().__enter__() + self.get_httpx_client().__enter__() return self def __exit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.client (see httpx docs)""" - self.get_client().__exit__(*args, **kwargs) + self.get_httpx_client().__exit__(*args, **kwargs) - def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": """Manually the underlying httpx.AsyncClient **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up @@ -230,7 +230,7 @@ def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedCli self._async_client = async_client return self - def get_async_client(self) -> httpx.AsyncClient: + def get_async_httpx_client(self) -> httpx.AsyncClient: """Get the underlying httpx.AsyncClient""" if self._async_client is None: self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token @@ -246,9 +246,9 @@ def get_async_client(self) -> httpx.AsyncClient: async def __aenter__(self) -> "AuthenticatedClient": """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - await self.get_async_client().__aenter__() + await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.async_client (see httpx docs)""" - await self.get_async_client().__aexit__(*args, **kwargs) + await self.get_async_httpx_client().__aexit__(*args, **kwargs) diff --git a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py index e6fe535d9..8374e96b4 100644 --- a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py +++ b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py @@ -48,7 +48,7 @@ def test_custom_hooks(client: Client) -> None: mime_type = "application/openapi-python-client" description = "super descriptive thing" - httpx_client = client.get_client() + httpx_client = client.get_httpx_client() request_hook_called = False response_hook_called = False diff --git a/openapi_python_client/templates/README.md.jinja b/openapi_python_client/templates/README.md.jinja index c82d8a7b4..87940cb76 100644 --- a/openapi_python_client/templates/README.md.jinja +++ b/openapi_python_client/templates/README.md.jinja @@ -84,7 +84,7 @@ from {{ package_name }} import Client client = Client( base_url="https://api.example.com", ) -httpx_client = client.get_client() +httpx_client = client.get_httpx_client() def log_request(request): print(f"Request event hook: {request.method} {request.url} - Waiting for response") @@ -105,7 +105,7 @@ client = Client( base_url="https://api.example.com", ) # Note that base_url needs to be re-set, as would any shared cookies, headers, etc. -client.set_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030")) +client.set_httpx_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030")) ``` {% if poetry %} diff --git a/openapi_python_client/templates/client.py.jinja b/openapi_python_client/templates/client.py.jinja index 14f6430f4..5b921ec69 100644 --- a/openapi_python_client/templates/client.py.jinja +++ b/openapi_python_client/templates/client.py.jinja @@ -65,7 +65,7 @@ class Client: self._async_client.timeout = timeout return evolve(self, timeout=timeout) - def set_client(self, client: httpx.Client) -> "Client": + def set_httpx_client(self, client: httpx.Client) -> "Client": """Manually the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. @@ -73,7 +73,7 @@ class Client: self._client = client return self - def get_client(self) -> httpx.Client: + def get_httpx_client(self) -> httpx.Client: """Get the underlying httpx.Client, constructing a new one if not previously set""" if self._client is None: self._client = httpx.Client( @@ -88,14 +88,14 @@ class Client: def __enter__(self) -> "Client": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - self.get_client().__enter__() + self.get_httpx_client().__enter__() return self def __exit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.client (see httpx docs)""" - self.get_client().__exit__(*args, **kwargs) + self.get_httpx_client().__exit__(*args, **kwargs) - def set_async_client(self, async_client: httpx.AsyncClient) -> "Client": + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": """Manually the underlying httpx.AsyncClient **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. @@ -103,7 +103,7 @@ class Client: self._async_client = async_client return self - def get_async_client(self) -> httpx.AsyncClient: + def get_async_httpx_client(self) -> httpx.AsyncClient: """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" if self._async_client is None: self._async_client = httpx.AsyncClient( @@ -118,12 +118,12 @@ class Client: async def __aenter__(self) -> "Client": """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - await self.get_async_client().__aenter__() + await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.async_client (see httpx docs)""" - await self.get_async_client().__aexit__(*args, **kwargs) + await self.get_async_httpx_client().__aexit__(*args, **kwargs) @define @@ -189,7 +189,7 @@ class AuthenticatedClient: self._async_client.timeout = timeout return evolve(self, timeout=timeout) - def set_client(self, client: httpx.Client) -> "AuthenticatedClient": + def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": """Manually the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up @@ -198,7 +198,7 @@ class AuthenticatedClient: self._client = client return self - def get_client(self) -> httpx.Client: + def get_httpx_client(self) -> httpx.Client: """Get the underlying httpx.Client, constructing a new one if not previously set""" if self._client is None: self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token @@ -214,14 +214,14 @@ class AuthenticatedClient: def __enter__(self) -> "AuthenticatedClient": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - self.get_client().__enter__() + self.get_httpx_client().__enter__() return self def __exit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.client (see httpx docs)""" - self.get_client().__exit__(*args, **kwargs) + self.get_httpx_client().__exit__(*args, **kwargs) - def set_async_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": """Manually the underlying httpx.AsyncClient **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up @@ -230,7 +230,7 @@ class AuthenticatedClient: self._async_client = async_client return self - def get_async_client(self) -> httpx.AsyncClient: + def get_async_httpx_client(self) -> httpx.AsyncClient: """Get the underlying httpx.AsyncClient""" if self._async_client is None: self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token @@ -246,9 +246,9 @@ class AuthenticatedClient: async def __aenter__(self) -> "AuthenticatedClient": """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - await self.get_async_client().__aenter__() + await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: """Exit a context manager for self.async_client (see httpx docs)""" - await self.get_async_client().__aexit__(*args, **kwargs) \ No newline at end of file + await self.get_async_httpx_client().__aexit__(*args, **kwargs) \ No newline at end of file diff --git a/openapi_python_client/templates/endpoint_module.py.jinja b/openapi_python_client/templates/endpoint_module.py.jinja index 6f2240871..69f7fedb8 100644 --- a/openapi_python_client/templates/endpoint_module.py.jinja +++ b/openapi_python_client/templates/endpoint_module.py.jinja @@ -98,7 +98,7 @@ def sync_detailed( {{ kwargs(endpoint, include_client=False) }} ) - response = client.get_client().request( + response = client.get_httpx_client().request( **kwargs, ) @@ -124,7 +124,7 @@ async def asyncio_detailed( {{ kwargs(endpoint, include_client=False) }} ) - response = await client.get_async_client().request( + response = await client.get_async_httpx_client().request( **kwargs ) From 3ef087b8aab21818464c205af94d7bbd26364d04 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 6 Jul 2023 15:54:24 -0600 Subject: [PATCH 07/18] Allow AuthenticatedClient anywhere a Client is allowed --- .../api/default/get_common_parameters.py | 10 +++++----- .../api/default/post_common_parameters.py | 10 +++++----- .../api/default/reserved_parameters.py | 12 +++++------ .../api/location/get_location_header_types.py | 10 +++++----- .../get_location_query_optionality.py | 10 +++++----- .../get_parameter_references_path_param.py | 10 +++++----- ...lete_common_parameters_overriding_param.py | 10 +++++----- .../get_common_parameters_overriding_param.py | 12 +++++------ .../get_same_name_multiple_locations_param.py | 10 +++++----- .../parameters/multiple_path_parameters.py | 12 +++++------ ..._responses_unions_simple_before_complex.py | 16 +++++++-------- .../api/tag1/get_tag_with_number.py | 12 +++++------ .../api/tests/callback_test.py | 18 ++++++++++------- .../api/tests/defaults_tests_defaults_post.py | 18 ++++++++++------- .../api/tests/description_with_backslash.py | 12 +++++------ .../api/tests/get_basic_list_of_booleans.py | 16 +++++++-------- .../api/tests/get_basic_list_of_floats.py | 16 +++++++-------- .../api/tests/get_basic_list_of_integers.py | 16 +++++++-------- .../api/tests/get_basic_list_of_strings.py | 16 +++++++-------- .../api/tests/get_user_list.py | 14 ++++++------- .../api/tests/int_enum_tests_int_enum_post.py | 18 ++++++++++------- .../tests/json_body_tests_json_body_post.py | 18 ++++++++++------- .../no_response_tests_no_response_get.py | 12 +++++------ .../octet_stream_tests_octet_stream_get.py | 16 +++++++-------- .../api/tests/post_form_data.py | 12 +++++------ .../api/tests/post_form_data_inline.py | 12 +++++------ .../api/tests/post_tests_json_body_string.py | 18 ++++++++++------- .../api/tests/test_inline_objects.py | 20 +++++++++++-------- ..._with_cookie_auth_token_with_cookie_get.py | 12 +++++------ ...d_content_tests_unsupported_content_get.py | 12 +++++------ .../tests/upload_file_tests_upload_post.py | 18 ++++++++++------- ...upload_multiple_files_tests_upload_post.py | 18 ++++++++++------- .../my_test_api_client/api/true_/false_.py | 12 +++++------ .../api/body/post_body_multipart.py | 14 ++++++------- .../api/parameters/post_parameters_header.py | 14 ++++++------- .../templates/endpoint_macros.py.jinja | 2 +- .../templates/endpoint_module.py.jinja | 4 ++-- 37 files changed, 262 insertions(+), 230 deletions(-) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py index 7ec4bdb7c..6a5d59c1b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response, Unset @@ -26,7 +26,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -35,7 +35,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -46,7 +46,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], common: Union[Unset, None, str] = UNSET, ) -> Response[Any]: """ @@ -74,7 +74,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], common: Union[Unset, None, str] = UNSET, ) -> Response[Any]: """ diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py index 10458af4b..c666d2553 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response, Unset @@ -26,7 +26,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -35,7 +35,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -46,7 +46,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], common: Union[Unset, None, str] = UNSET, ) -> Response[Any]: """ @@ -74,7 +74,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], common: Union[Unset, None, str] = UNSET, ) -> Response[Any]: """ diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py index 04a71a9ae..75e9c9eaf 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/reserved_parameters.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response @@ -29,7 +29,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -38,7 +38,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -49,7 +49,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], client_query: str, url_query: str, ) -> Response[Any]: @@ -80,7 +80,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], client_query: str, url_query: str, ) -> Response[Any]: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py index 6adba3293..b004866ce 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.get_location_header_types_int_enum_header import GetLocationHeaderTypesIntEnumHeader from ...models.get_location_header_types_string_enum_header import GetLocationHeaderTypesStringEnumHeader from ...types import UNSET, Response, Unset @@ -45,7 +45,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -54,7 +54,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -65,7 +65,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], boolean_header: Union[Unset, bool] = UNSET, string_header: Union[Unset, str] = UNSET, number_header: Union[Unset, float] = UNSET, @@ -108,7 +108,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], boolean_header: Union[Unset, bool] = UNSET, string_header: Union[Unset, str] = UNSET, number_header: Union[Unset, float] = UNSET, diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py index c10945f98..c58dcad67 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py @@ -5,7 +5,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response, Unset @@ -50,7 +50,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -59,7 +59,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -70,7 +70,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], not_null_required: datetime.datetime, null_required: Union[Unset, None, datetime.datetime] = UNSET, null_not_required: Union[Unset, None, datetime.datetime] = UNSET, @@ -107,7 +107,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], not_null_required: datetime.datetime, null_required: Union[Unset, None, datetime.datetime] = UNSET, null_not_required: Union[Unset, None, datetime.datetime] = UNSET, diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py index 99ab10ccf..0f9c603f2 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameter_references/get_parameter_references_path_param.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response, Unset @@ -42,7 +42,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -51,7 +51,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -63,7 +63,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( path_param: str, *, - client: Client, + client: Union[AuthenticatedClient, Client], string_param: Union[Unset, None, str] = UNSET, integer_param: Union[Unset, None, int] = 0, header_param: Union[Unset, str] = UNSET, @@ -104,7 +104,7 @@ def sync_detailed( async def asyncio_detailed( path_param: str, *, - client: Client, + client: Union[AuthenticatedClient, Client], string_param: Union[Unset, None, str] = UNSET, integer_param: Union[Unset, None, int] = 0, header_param: Union[Unset, str] = UNSET, diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py index 0d8cc434a..22c847c93 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response, Unset @@ -29,7 +29,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -38,7 +38,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -50,7 +50,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( param_path: str, *, - client: Client, + client: Union[AuthenticatedClient, Client], param_query: Union[Unset, None, str] = UNSET, ) -> Response[Any]: """ @@ -81,7 +81,7 @@ def sync_detailed( async def asyncio_detailed( param_path: str, *, - client: Client, + client: Union[AuthenticatedClient, Client], param_query: Union[Unset, None, str] = UNSET, ) -> Response[Any]: """ diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py index be59702c8..0807f13cd 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response @@ -29,7 +29,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -38,7 +38,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -50,7 +50,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( param_path: str, *, - client: Client, + client: Union[AuthenticatedClient, Client], param_query: str = "overridden_in_GET", ) -> Response[Any]: """Test that if you have an overriding property from `PathItem` in `Operation`, it produces valid code @@ -83,7 +83,7 @@ def sync_detailed( async def asyncio_detailed( param_path: str, *, - client: Client, + client: Union[AuthenticatedClient, Client], param_query: str = "overridden_in_GET", ) -> Response[Any]: """Test that if you have an overriding property from `PathItem` in `Operation`, it produces valid code diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py index fd3720c31..6aa991293 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response, Unset @@ -39,7 +39,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -48,7 +48,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -60,7 +60,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( param_path: str, *, - client: Client, + client: Union[AuthenticatedClient, Client], param_query: Union[Unset, None, str] = UNSET, param_header: Union[Unset, str] = UNSET, param_cookie: Union[Unset, str] = UNSET, @@ -97,7 +97,7 @@ def sync_detailed( async def asyncio_detailed( param_path: str, *, - client: Client, + client: Union[AuthenticatedClient, Client], param_query: Union[Unset, None, str] = UNSET, param_header: Union[Unset, str] = UNSET, param_cookie: Union[Unset, str] = UNSET, diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py index e561558b0..837315e66 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -27,7 +27,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -36,7 +36,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -51,7 +51,7 @@ def sync_detailed( param1: str, param3: int, *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: """ Args: @@ -88,7 +88,7 @@ async def asyncio_detailed( param1: str, param3: int, *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: """ Args: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py b/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py index 8e90a0e31..e38719506 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/responses/post_responses_unions_simple_before_complex.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.post_responses_unions_simple_before_complex_response_200 import ( PostResponsesUnionsSimpleBeforeComplexResponse200, ) @@ -21,7 +21,7 @@ def _get_kwargs() -> Dict[str, Any]: def _parse_response( - *, client: Client, response: httpx.Response + *, client: Union[AuthenticatedClient, Client], response: httpx.Response ) -> Optional[PostResponsesUnionsSimpleBeforeComplexResponse200]: if response.status_code == HTTPStatus.OK: response_200 = PostResponsesUnionsSimpleBeforeComplexResponse200.from_dict(response.json()) @@ -34,7 +34,7 @@ def _parse_response( def _build_response( - *, client: Client, response: httpx.Response + *, client: Union[AuthenticatedClient, Client], response: httpx.Response ) -> Response[PostResponsesUnionsSimpleBeforeComplexResponse200]: return Response( status_code=HTTPStatus(response.status_code), @@ -46,7 +46,7 @@ def _build_response( def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[PostResponsesUnionsSimpleBeforeComplexResponse200]: """Regression test for #603 @@ -69,7 +69,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[PostResponsesUnionsSimpleBeforeComplexResponse200]: """Regression test for #603 @@ -88,7 +88,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[PostResponsesUnionsSimpleBeforeComplexResponse200]: """Regression test for #603 @@ -109,7 +109,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[PostResponsesUnionsSimpleBeforeComplexResponse200]: """Regression test for #603 diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py b/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py index 286485e20..d2fe55457 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -17,7 +17,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -26,7 +26,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -37,7 +37,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: """ Raises: @@ -59,7 +59,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: """ Raises: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py index e202312cf..654d24845 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/callback_test.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.a_model import AModel from ...models.http_validation_error import HTTPValidationError from ...types import Response @@ -25,7 +25,9 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == HTTPStatus.OK: response_200 = cast(Any, response.json()) return response_200 @@ -39,7 +41,9 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Uni return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Union[Any, HTTPValidationError]]: +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, HTTPValidationError]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -50,7 +54,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Uni def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: AModel, ) -> Response[Union[Any, HTTPValidationError]]: """Path with callback @@ -81,7 +85,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: AModel, ) -> Optional[Union[Any, HTTPValidationError]]: """Path with callback @@ -107,7 +111,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: AModel, ) -> Response[Union[Any, HTTPValidationError]]: """Path with callback @@ -136,7 +140,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: AModel, ) -> Optional[Union[Any, HTTPValidationError]]: """Path with callback diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index cef8bc91d..422d36930 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -6,7 +6,7 @@ from dateutil.parser import isoparse from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.an_enum import AnEnum from ...models.http_validation_error import HTTPValidationError from ...models.model_with_union_property import ModelWithUnionProperty @@ -92,7 +92,9 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == HTTPStatus.OK: response_200 = cast(Any, response.json()) return response_200 @@ -106,7 +108,9 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Uni return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Union[Any, HTTPValidationError]]: +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, HTTPValidationError]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -117,7 +121,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Uni def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], string_prop: str = "the default string", date_prop: datetime.date = isoparse("1010-10-10").date(), float_prop: float = 3.14, @@ -176,7 +180,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], string_prop: str = "the default string", date_prop: datetime.date = isoparse("1010-10-10").date(), float_prop: float = 3.14, @@ -230,7 +234,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], string_prop: str = "the default string", date_prop: datetime.date = isoparse("1010-10-10").date(), float_prop: float = 3.14, @@ -287,7 +291,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], string_prop: str = "the default string", date_prop: datetime.date = isoparse("1010-10-10").date(), float_prop: float = 3.14, diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py index 1481d1bbb..91c1dcbb1 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/description_with_backslash.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -17,7 +17,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -26,7 +26,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -37,7 +37,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: r""" Test description with \ @@ -62,7 +62,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: r""" Test description with \ diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py index e1b991dc2..496dbd714 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, List, Optional, cast +from typing import Any, Dict, List, Optional, Union, cast import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -17,7 +17,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[List[bool]]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[List[bool]]: if response.status_code == HTTPStatus.OK: response_200 = cast(List[bool], response.json()) @@ -28,7 +28,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Lis return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[List[bool]]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[List[bool]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -39,7 +39,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Lis def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[List[bool]]: """Get Basic List Of Booleans @@ -64,7 +64,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[List[bool]]: """Get Basic List Of Booleans @@ -85,7 +85,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[List[bool]]: """Get Basic List Of Booleans @@ -108,7 +108,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[List[bool]]: """Get Basic List Of Booleans diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py index 9a343bce7..6f0e78f54 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, List, Optional, cast +from typing import Any, Dict, List, Optional, Union, cast import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -17,7 +17,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[List[float]]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[List[float]]: if response.status_code == HTTPStatus.OK: response_200 = cast(List[float], response.json()) @@ -28,7 +28,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Lis return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[List[float]]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[List[float]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -39,7 +39,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Lis def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[List[float]]: """Get Basic List Of Floats @@ -64,7 +64,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[List[float]]: """Get Basic List Of Floats @@ -85,7 +85,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[List[float]]: """Get Basic List Of Floats @@ -108,7 +108,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[List[float]]: """Get Basic List Of Floats diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py index c14ad189b..180f6251d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, List, Optional, cast +from typing import Any, Dict, List, Optional, Union, cast import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -17,7 +17,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[List[int]]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[List[int]]: if response.status_code == HTTPStatus.OK: response_200 = cast(List[int], response.json()) @@ -28,7 +28,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Lis return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[List[int]]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[List[int]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -39,7 +39,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Lis def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[List[int]]: """Get Basic List Of Integers @@ -64,7 +64,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[List[int]]: """Get Basic List Of Integers @@ -85,7 +85,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[List[int]]: """Get Basic List Of Integers @@ -108,7 +108,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[List[int]]: """Get Basic List Of Integers diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py index 0bcc52e32..824ff5f20 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, List, Optional, cast +from typing import Any, Dict, List, Optional, Union, cast import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -17,7 +17,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[List[str]]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[List[str]]: if response.status_code == HTTPStatus.OK: response_200 = cast(List[str], response.json()) @@ -28,7 +28,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Lis return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[List[str]]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[List[str]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -39,7 +39,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Lis def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[List[str]]: """Get Basic List Of Strings @@ -64,7 +64,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[List[str]]: """Get Basic List Of Strings @@ -85,7 +85,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[List[str]]: """Get Basic List Of Strings @@ -108,7 +108,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[List[str]]: """Get Basic List Of Strings diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py index 6bdebc5d9..840c486dd 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py @@ -5,7 +5,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.a_model import AModel from ...models.an_enum import AnEnum from ...models.an_enum_with_null import AnEnumWithNull @@ -64,7 +64,7 @@ def _get_kwargs( def _parse_response( - *, client: Client, response: httpx.Response + *, client: Union[AuthenticatedClient, Client], response: httpx.Response ) -> Optional[Union[HTTPValidationError, List["AModel"]]]: if response.status_code == HTTPStatus.OK: response_200 = [] @@ -90,7 +90,7 @@ def _parse_response( def _build_response( - *, client: Client, response: httpx.Response + *, client: Union[AuthenticatedClient, Client], response: httpx.Response ) -> Response[Union[HTTPValidationError, List["AModel"]]]: return Response( status_code=HTTPStatus(response.status_code), @@ -102,7 +102,7 @@ def _build_response( def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], an_enum_value: List[AnEnum], an_enum_value_with_null: List[Optional[AnEnumWithNull]], an_enum_value_with_only_null: List[None], @@ -142,7 +142,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], an_enum_value: List[AnEnum], an_enum_value_with_null: List[Optional[AnEnumWithNull]], an_enum_value_with_only_null: List[None], @@ -177,7 +177,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], an_enum_value: List[AnEnum], an_enum_value_with_null: List[Optional[AnEnumWithNull]], an_enum_value_with_only_null: List[None], @@ -215,7 +215,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], an_enum_value: List[AnEnum], an_enum_value_with_null: List[Optional[AnEnumWithNull]], an_enum_value_with_only_null: List[None], diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py index 687cd9bbc..aa6ec8964 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.an_int_enum import AnIntEnum from ...models.http_validation_error import HTTPValidationError from ...types import UNSET, Response @@ -30,7 +30,9 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == HTTPStatus.OK: response_200 = cast(Any, response.json()) return response_200 @@ -44,7 +46,9 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Uni return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Union[Any, HTTPValidationError]]: +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, HTTPValidationError]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -55,7 +59,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Uni def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], int_enum: AnIntEnum, ) -> Response[Union[Any, HTTPValidationError]]: """Int Enum @@ -84,7 +88,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], int_enum: AnIntEnum, ) -> Optional[Union[Any, HTTPValidationError]]: """Int Enum @@ -108,7 +112,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], int_enum: AnIntEnum, ) -> Response[Union[Any, HTTPValidationError]]: """Int Enum @@ -135,7 +139,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], int_enum: AnIntEnum, ) -> Optional[Union[Any, HTTPValidationError]]: """Int Enum diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py index 551fd4c83..cf4e1d48e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.a_model import AModel from ...models.http_validation_error import HTTPValidationError from ...types import Response @@ -25,7 +25,9 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == HTTPStatus.OK: response_200 = cast(Any, response.json()) return response_200 @@ -39,7 +41,9 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Uni return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Union[Any, HTTPValidationError]]: +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, HTTPValidationError]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -50,7 +54,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Uni def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: AModel, ) -> Response[Union[Any, HTTPValidationError]]: """Json Body @@ -81,7 +85,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: AModel, ) -> Optional[Union[Any, HTTPValidationError]]: """Json Body @@ -107,7 +111,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: AModel, ) -> Response[Union[Any, HTTPValidationError]]: """Json Body @@ -136,7 +140,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: AModel, ) -> Optional[Union[Any, HTTPValidationError]]: """Json Body diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py index 6e50a34c5..2b1c4629b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -17,7 +17,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -26,7 +26,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -37,7 +37,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: """No Response @@ -60,7 +60,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: """No Response diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py index a01c9633a..33ae96595 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py @@ -1,11 +1,11 @@ from http import HTTPStatus from io import BytesIO -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import File, Response @@ -18,7 +18,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[File]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[File]: if response.status_code == HTTPStatus.OK: response_200 = File(payload=BytesIO(response.content)) @@ -29,7 +29,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Fil return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[File]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[File]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -40,7 +40,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Fil def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[File]: """Octet Stream @@ -63,7 +63,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[File]: """Octet Stream @@ -82,7 +82,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[File]: """Octet Stream @@ -103,7 +103,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Optional[File]: """Octet Stream diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py index 51951de83..cfbe81076 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.a_form_data import AFormData from ...types import Response @@ -21,7 +21,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -30,7 +30,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -41,7 +41,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], form_data: AFormData, ) -> Response[Any]: """Post form data @@ -69,7 +69,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], form_data: AFormData, ) -> Response[Any]: """Post form data diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py index 9ea9a41ec..919beee20 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data_inline.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.post_form_data_inline_data import PostFormDataInlineData from ...types import Response @@ -21,7 +21,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -30,7 +30,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -41,7 +41,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], form_data: PostFormDataInlineData, ) -> Response[Any]: """Post form data (inline schema) @@ -69,7 +69,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], form_data: PostFormDataInlineData, ) -> Response[Any]: """Post form data (inline schema) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py index 43d1d0592..34f1f413b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.http_validation_error import HTTPValidationError from ...types import Response @@ -24,7 +24,9 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Union[HTTPValidationError, str]]: +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[HTTPValidationError, str]]: if response.status_code == HTTPStatus.OK: response_200 = cast(str, response.json()) return response_200 @@ -38,7 +40,9 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Uni return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Union[HTTPValidationError, str]]: +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[HTTPValidationError, str]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -49,7 +53,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Uni def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: str, ) -> Response[Union[HTTPValidationError, str]]: """Json Body Which is String @@ -78,7 +82,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: str, ) -> Optional[Union[HTTPValidationError, str]]: """Json Body Which is String @@ -102,7 +106,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: str, ) -> Response[Union[HTTPValidationError, str]]: """Json Body Which is String @@ -129,7 +133,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: str, ) -> Optional[Union[HTTPValidationError, str]]: """Json Body Which is String diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py index acc3838e1..ed5c24562 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.test_inline_objects_json_body import TestInlineObjectsJsonBody from ...models.test_inline_objects_response_200 import TestInlineObjectsResponse200 from ...types import Response @@ -25,7 +25,9 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[TestInlineObjectsResponse200]: +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[TestInlineObjectsResponse200]: if response.status_code == HTTPStatus.OK: response_200 = TestInlineObjectsResponse200.from_dict(response.json()) @@ -36,7 +38,9 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Tes return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[TestInlineObjectsResponse200]: +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[TestInlineObjectsResponse200]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -47,7 +51,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Tes def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: TestInlineObjectsJsonBody, ) -> Response[TestInlineObjectsResponse200]: """Test Inline Objects @@ -76,7 +80,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: TestInlineObjectsJsonBody, ) -> Optional[TestInlineObjectsResponse200]: """Test Inline Objects @@ -100,7 +104,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: TestInlineObjectsJsonBody, ) -> Response[TestInlineObjectsResponse200]: """Test Inline Objects @@ -127,7 +131,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], json_body: TestInlineObjectsJsonBody, ) -> Optional[TestInlineObjectsResponse200]: """Test Inline Objects diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py index 5d793bcbf..5820cb934 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -22,7 +22,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if response.status_code == HTTPStatus.UNAUTHORIZED: @@ -33,7 +33,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -44,7 +44,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], my_token: str, ) -> Response[Any]: """TOKEN_WITH_COOKIE @@ -75,7 +75,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], my_token: str, ) -> Response[Any]: """TOKEN_WITH_COOKIE diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py index fb0b3d863..5ece512cb 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import Response @@ -17,7 +17,7 @@ def _get_kwargs() -> Dict[str, Any]: } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -26,7 +26,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -37,7 +37,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: """Unsupported Content @@ -60,7 +60,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], ) -> Response[Any]: """Unsupported Content diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py index 542d937e8..7fd92c0a5 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.body_upload_file_tests_upload_post import BodyUploadFileTestsUploadPost from ...models.http_validation_error import HTTPValidationError from ...types import Response @@ -25,7 +25,9 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == HTTPStatus.OK: response_200 = cast(Any, response.json()) return response_200 @@ -39,7 +41,9 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Uni return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Union[Any, HTTPValidationError]]: +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, HTTPValidationError]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -50,7 +54,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Uni def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: BodyUploadFileTestsUploadPost, ) -> Response[Union[Any, HTTPValidationError]]: """Upload File @@ -81,7 +85,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: BodyUploadFileTestsUploadPost, ) -> Optional[Union[Any, HTTPValidationError]]: """Upload File @@ -107,7 +111,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: BodyUploadFileTestsUploadPost, ) -> Response[Union[Any, HTTPValidationError]]: """Upload File @@ -136,7 +140,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: BodyUploadFileTestsUploadPost, ) -> Optional[Union[Any, HTTPValidationError]]: """Upload File diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py index 6344173e8..cb6d51c88 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.http_validation_error import HTTPValidationError from ...types import File, Response @@ -28,7 +28,9 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == HTTPStatus.OK: response_200 = cast(Any, response.json()) return response_200 @@ -42,7 +44,9 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Uni return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Union[Any, HTTPValidationError]]: +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, HTTPValidationError]]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -53,7 +57,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Uni def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: List[File], ) -> Response[Union[Any, HTTPValidationError]]: """Upload multiple files @@ -84,7 +88,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: List[File], ) -> Optional[Union[Any, HTTPValidationError]]: """Upload multiple files @@ -110,7 +114,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: List[File], ) -> Response[Union[Any, HTTPValidationError]]: """Upload multiple files @@ -139,7 +143,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: List[File], ) -> Optional[Union[Any, HTTPValidationError]]: """Upload multiple files diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py b/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py index ce06b51e3..41dc82ff4 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py @@ -1,10 +1,10 @@ from http import HTTPStatus -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...types import UNSET, Response @@ -26,7 +26,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: if response.status_code == HTTPStatus.OK: return None if client.raise_on_unexpected_status: @@ -35,7 +35,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[Any return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[Any]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -46,7 +46,7 @@ def _build_response(*, client: Client, response: httpx.Response) -> Response[Any def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], import_: str, ) -> Response[Any]: """ @@ -74,7 +74,7 @@ def sync_detailed( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], import_: str, ) -> Response[Any]: """ diff --git a/integration-tests/integration_tests/api/body/post_body_multipart.py b/integration-tests/integration_tests/api/body/post_body_multipart.py index 12ef45826..cdeb2014b 100644 --- a/integration-tests/integration_tests/api/body/post_body_multipart.py +++ b/integration-tests/integration_tests/api/body/post_body_multipart.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.post_body_multipart_multipart_data import PostBodyMultipartMultipartData from ...models.post_body_multipart_response_200 import PostBodyMultipartResponse200 from ...models.public_error import PublicError @@ -27,7 +27,7 @@ def _get_kwargs( def _parse_response( - *, client: Client, response: httpx.Response + *, client: Union[AuthenticatedClient, Client], response: httpx.Response ) -> Optional[Union[PostBodyMultipartResponse200, PublicError]]: if response.status_code == HTTPStatus.OK: response_200 = PostBodyMultipartResponse200.from_dict(response.json()) @@ -44,7 +44,7 @@ def _parse_response( def _build_response( - *, client: Client, response: httpx.Response + *, client: Union[AuthenticatedClient, Client], response: httpx.Response ) -> Response[Union[PostBodyMultipartResponse200, PublicError]]: return Response( status_code=HTTPStatus(response.status_code), @@ -56,7 +56,7 @@ def _build_response( def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: PostBodyMultipartMultipartData, ) -> Response[Union[PostBodyMultipartResponse200, PublicError]]: """ @@ -84,7 +84,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: PostBodyMultipartMultipartData, ) -> Optional[Union[PostBodyMultipartResponse200, PublicError]]: """ @@ -107,7 +107,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: PostBodyMultipartMultipartData, ) -> Response[Union[PostBodyMultipartResponse200, PublicError]]: """ @@ -133,7 +133,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], multipart_data: PostBodyMultipartMultipartData, ) -> Optional[Union[PostBodyMultipartResponse200, PublicError]]: """ diff --git a/integration-tests/integration_tests/api/parameters/post_parameters_header.py b/integration-tests/integration_tests/api/parameters/post_parameters_header.py index ab577d6f8..a68dd841e 100644 --- a/integration-tests/integration_tests/api/parameters/post_parameters_header.py +++ b/integration-tests/integration_tests/api/parameters/post_parameters_header.py @@ -4,7 +4,7 @@ import httpx from ... import errors -from ...client import Client +from ...client import AuthenticatedClient, Client from ...models.post_parameters_header_response_200 import PostParametersHeaderResponse200 from ...models.public_error import PublicError from ...types import Response @@ -34,7 +34,7 @@ def _get_kwargs( def _parse_response( - *, client: Client, response: httpx.Response + *, client: Union[AuthenticatedClient, Client], response: httpx.Response ) -> Optional[Union[PostParametersHeaderResponse200, PublicError]]: if response.status_code == HTTPStatus.OK: response_200 = PostParametersHeaderResponse200.from_dict(response.json()) @@ -51,7 +51,7 @@ def _parse_response( def _build_response( - *, client: Client, response: httpx.Response + *, client: Union[AuthenticatedClient, Client], response: httpx.Response ) -> Response[Union[PostParametersHeaderResponse200, PublicError]]: return Response( status_code=HTTPStatus(response.status_code), @@ -63,7 +63,7 @@ def _build_response( def sync_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], boolean_header: bool, string_header: str, number_header: float, @@ -100,7 +100,7 @@ def sync_detailed( def sync( *, - client: Client, + client: Union[AuthenticatedClient, Client], boolean_header: bool, string_header: str, number_header: float, @@ -132,7 +132,7 @@ def sync( async def asyncio_detailed( *, - client: Client, + client: Union[AuthenticatedClient, Client], boolean_header: bool, string_header: str, number_header: float, @@ -167,7 +167,7 @@ async def asyncio_detailed( async def asyncio( *, - client: Client, + client: Union[AuthenticatedClient, Client], boolean_header: bool, string_header: str, number_header: float, diff --git a/openapi_python_client/templates/endpoint_macros.py.jinja b/openapi_python_client/templates/endpoint_macros.py.jinja index 391ab2e40..2c9b45e03 100644 --- a/openapi_python_client/templates/endpoint_macros.py.jinja +++ b/openapi_python_client/templates/endpoint_macros.py.jinja @@ -93,7 +93,7 @@ params = {k: v for k, v in params.items() if v is not UNSET and v is not None} {% if endpoint.requires_security %} client: AuthenticatedClient, {% else %} -client: Client, +client: Union[AuthenticatedClient, Client], {% endif %} {% endif %} {# Form data if any #} diff --git a/openapi_python_client/templates/endpoint_module.py.jinja b/openapi_python_client/templates/endpoint_module.py.jinja index 69f7fedb8..c2b738ced 100644 --- a/openapi_python_client/templates/endpoint_module.py.jinja +++ b/openapi_python_client/templates/endpoint_module.py.jinja @@ -60,7 +60,7 @@ def _get_kwargs( } -def _parse_response(*, client: Client, response: httpx.Response) -> Optional[{{ return_string }}]: +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[{{ return_string }}]: {% for response in endpoint.responses %} if response.status_code == HTTPStatus.{{ response.status_code.name }}: {% if parsed_responses %}{% import "property_templates/" + response.prop.template as prop_template %} @@ -80,7 +80,7 @@ def _parse_response(*, client: Client, response: httpx.Response) -> Optional[{{ return None -def _build_response(*, client: Client, response: httpx.Response) -> Response[{{ return_string }}]: +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[{{ return_string }}]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, From 156c0f1e172237304d82b8fe1d3d9b0251d70f53 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 6 Jul 2023 16:49:13 -0600 Subject: [PATCH 08/18] Use macros to keep Client/AuthenticatedClient the same --- end_to_end_tests/golden-record/README.md | 11 +- .../my_test_api_client/client.py | 46 +++-- integration-tests/integration_tests/client.py | 46 +++-- .../test_body/test_post_body_multipart.py | 7 +- .../templates/README.md.jinja | 11 +- .../templates/client.py.jinja | 162 ++++-------------- 6 files changed, 113 insertions(+), 170 deletions(-) diff --git a/end_to_end_tests/golden-record/README.md b/end_to_end_tests/golden-record/README.md index 324cd885e..18fb1117d 100644 --- a/end_to_end_tests/golden-record/README.md +++ b/end_to_end_tests/golden-record/README.md @@ -81,10 +81,6 @@ There are more settings on the generated `Client` class which let you control mo ```python from my_test_api_client import Client -client = Client( - base_url="https://api.example.com", -) -httpx_client = client.get_httpx_client() def log_request(request): print(f"Request event hook: {request.method} {request.url} - Waiting for response") @@ -92,7 +88,12 @@ def log_response(response): request = response.request print(f"Response event hook: {request.method} {request.url} - Status {response.status_code}") -httpx_client.event_hooks = {"request": [log_request], "response": [log_response]} +client = Client( + base_url="https://api.example.com", + httpx_args={"event_hooks": {"request": [log_request], "response": [log_response]}}, +) + +# Or get the underlying httpx client to modify directly with client.get_httpx_client() or client.get_async_httpx_client() ``` You can even set the httpx client directly, but beware that this will override any existing settings (e.g., base_url): diff --git a/end_to_end_tests/golden-record/my_test_api_client/client.py b/end_to_end_tests/golden-record/my_test_api_client/client.py index f36b0fd52..74b476ca8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/client.py +++ b/end_to_end_tests/golden-record/my_test_api_client/client.py @@ -25,6 +25,9 @@ class Client: ``follow_redirects``: Whether or not to follow redirects. Default value is False. + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + Attributes: raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a status code that was not documented in the source OpenAPI document. Can also be provided as a keyword @@ -38,6 +41,7 @@ class Client: _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) @@ -83,6 +87,7 @@ def get_httpx_client(self) -> httpx.Client: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._client @@ -92,7 +97,7 @@ def __enter__(self) -> "Client": return self def __exit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.client (see httpx docs)""" + """Exit a context manager for internal httpx.Client (see httpx docs)""" self.get_httpx_client().__exit__(*args, **kwargs) def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": @@ -113,16 +118,17 @@ def get_async_httpx_client(self) -> httpx.AsyncClient: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._async_client async def __aenter__(self) -> "Client": - """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.async_client (see httpx docs)""" + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" await self.get_async_httpx_client().__aexit__(*args, **kwargs) @@ -138,7 +144,7 @@ class AuthenticatedClient: ``headers``: A dictionary of headers to be sent with every request - ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + ``timeout``: The maximum amount of a time a request can take. API functions will raise httpx.TimeoutException if this is exceeded. ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, @@ -146,25 +152,33 @@ class AuthenticatedClient: ``follow_redirects``: Whether or not to follow redirects. Default value is False. + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + Attributes: raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a status code that was not documented in the source OpenAPI document. Can also be provided as a keyword argument to the constructor. + token: The token to use for authentication + prefix: The prefix to use for the Authorization header + auth_header_name: The name of the Authorization header """ raise_on_unexpected_status: bool = field(default=False, kw_only=True) _base_url: str - token: str - prefix: str = "Bearer" - auth_header_name: str = "Authorization" _cookies: Dict[str, str] = field(factory=dict, kw_only=True) _headers: Dict[str, str] = field(factory=dict, kw_only=True) - _timeout: httpx.Timeout = field(default=None, kw_only=True) + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + token: str + prefix: str = "Bearer" + auth_header_name: str = "Authorization" + def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": """Get a new client matching this one with additional headers""" if self._client is not None: @@ -192,8 +206,7 @@ def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": """Manually the underlying httpx.Client - **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up - auth **manually** if using this method. + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. """ self._client = client return self @@ -209,6 +222,7 @@ def get_httpx_client(self) -> httpx.Client: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._client @@ -218,20 +232,19 @@ def __enter__(self) -> "AuthenticatedClient": return self def __exit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.client (see httpx docs)""" + """Exit a context manager for internal httpx.Client (see httpx docs)""" self.get_httpx_client().__exit__(*args, **kwargs) def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": """Manually the underlying httpx.AsyncClient - **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up - auth **manually** if using this method. + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. """ self._async_client = async_client return self def get_async_httpx_client(self) -> httpx.AsyncClient: - """Get the underlying httpx.AsyncClient""" + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" if self._async_client is None: self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token self._async_client = httpx.AsyncClient( @@ -241,14 +254,15 @@ def get_async_httpx_client(self) -> httpx.AsyncClient: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._async_client async def __aenter__(self) -> "AuthenticatedClient": - """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.async_client (see httpx docs)""" + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" await self.get_async_httpx_client().__aexit__(*args, **kwargs) diff --git a/integration-tests/integration_tests/client.py b/integration-tests/integration_tests/client.py index f36b0fd52..74b476ca8 100644 --- a/integration-tests/integration_tests/client.py +++ b/integration-tests/integration_tests/client.py @@ -25,6 +25,9 @@ class Client: ``follow_redirects``: Whether or not to follow redirects. Default value is False. + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + Attributes: raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a status code that was not documented in the source OpenAPI document. Can also be provided as a keyword @@ -38,6 +41,7 @@ class Client: _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) @@ -83,6 +87,7 @@ def get_httpx_client(self) -> httpx.Client: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._client @@ -92,7 +97,7 @@ def __enter__(self) -> "Client": return self def __exit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.client (see httpx docs)""" + """Exit a context manager for internal httpx.Client (see httpx docs)""" self.get_httpx_client().__exit__(*args, **kwargs) def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": @@ -113,16 +118,17 @@ def get_async_httpx_client(self) -> httpx.AsyncClient: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._async_client async def __aenter__(self) -> "Client": - """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.async_client (see httpx docs)""" + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" await self.get_async_httpx_client().__aexit__(*args, **kwargs) @@ -138,7 +144,7 @@ class AuthenticatedClient: ``headers``: A dictionary of headers to be sent with every request - ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise + ``timeout``: The maximum amount of a time a request can take. API functions will raise httpx.TimeoutException if this is exceeded. ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, @@ -146,25 +152,33 @@ class AuthenticatedClient: ``follow_redirects``: Whether or not to follow redirects. Default value is False. + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + Attributes: raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a status code that was not documented in the source OpenAPI document. Can also be provided as a keyword argument to the constructor. + token: The token to use for authentication + prefix: The prefix to use for the Authorization header + auth_header_name: The name of the Authorization header """ raise_on_unexpected_status: bool = field(default=False, kw_only=True) _base_url: str - token: str - prefix: str = "Bearer" - auth_header_name: str = "Authorization" _cookies: Dict[str, str] = field(factory=dict, kw_only=True) _headers: Dict[str, str] = field(factory=dict, kw_only=True) - _timeout: httpx.Timeout = field(default=None, kw_only=True) + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + token: str + prefix: str = "Bearer" + auth_header_name: str = "Authorization" + def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": """Get a new client matching this one with additional headers""" if self._client is not None: @@ -192,8 +206,7 @@ def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": """Manually the underlying httpx.Client - **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up - auth **manually** if using this method. + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. """ self._client = client return self @@ -209,6 +222,7 @@ def get_httpx_client(self) -> httpx.Client: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._client @@ -218,20 +232,19 @@ def __enter__(self) -> "AuthenticatedClient": return self def __exit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.client (see httpx docs)""" + """Exit a context manager for internal httpx.Client (see httpx docs)""" self.get_httpx_client().__exit__(*args, **kwargs) def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": """Manually the underlying httpx.AsyncClient - **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up - auth **manually** if using this method. + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. """ self._async_client = async_client return self def get_async_httpx_client(self) -> httpx.AsyncClient: - """Get the underlying httpx.AsyncClient""" + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" if self._async_client is None: self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token self._async_client = httpx.AsyncClient( @@ -241,14 +254,15 @@ def get_async_httpx_client(self) -> httpx.AsyncClient: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._async_client async def __aenter__(self) -> "AuthenticatedClient": - """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.async_client (see httpx docs)""" + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" await self.get_async_httpx_client().__aexit__(*args, **kwargs) diff --git a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py index 8374e96b4..d81dddab6 100644 --- a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py +++ b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py @@ -41,14 +41,13 @@ def test(client: Client) -> None: assert content.description == description -def test_custom_hooks(client: Client) -> None: +def test_custom_hooks() -> None: a_string = "a test string" payload = b"some file content" file_name = "cool_stuff.txt" mime_type = "application/openapi-python-client" description = "super descriptive thing" - httpx_client = client.get_httpx_client() request_hook_called = False response_hook_called = False @@ -60,7 +59,9 @@ def log_response(*_: Any, **__: Any) -> None: nonlocal response_hook_called response_hook_called = True - httpx_client.event_hooks = {"request": [log_request], "response": [log_response]} + client = Client( + "http://localhost:3000", httpx_args={"event_hooks": {"request": [log_request], "response": [log_response]}} + ) post_body_multipart.sync_detailed( client=client, diff --git a/openapi_python_client/templates/README.md.jinja b/openapi_python_client/templates/README.md.jinja index 87940cb76..7958d60c3 100644 --- a/openapi_python_client/templates/README.md.jinja +++ b/openapi_python_client/templates/README.md.jinja @@ -81,10 +81,6 @@ There are more settings on the generated `Client` class which let you control mo ```python from {{ package_name }} import Client -client = Client( - base_url="https://api.example.com", -) -httpx_client = client.get_httpx_client() def log_request(request): print(f"Request event hook: {request.method} {request.url} - Waiting for response") @@ -92,7 +88,12 @@ def log_response(response): request = response.request print(f"Response event hook: {request.method} {request.url} - Status {response.status_code}") -httpx_client.event_hooks = {"request": [log_request], "response": [log_response]} +client = Client( + base_url="https://api.example.com", + httpx_args={"event_hooks": {"request": [log_request], "response": [log_response]}}, +) + +# Or get the underlying httpx client to modify directly with client.get_httpx_client() or client.get_async_httpx_client() ``` You can even set the httpx client directly, but beware that this will override any existing settings (e.g., base_url): diff --git a/openapi_python_client/templates/client.py.jinja b/openapi_python_client/templates/client.py.jinja index 5b921ec69..132d765fb 100644 --- a/openapi_python_client/templates/client.py.jinja +++ b/openapi_python_client/templates/client.py.jinja @@ -9,6 +9,7 @@ import httpx class Client: """A class for keeping track of data related to the API +{% macro httpx_args_docstring() %} The following are accepted as keyword arguments and will be used to construct httpx Clients internally: ``base_url``: The base URL for the API, all requests are made to a relative path to this URL @@ -25,12 +26,16 @@ class Client: ``follow_redirects``: Whether or not to follow redirects. Default value is False. + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. +{% endmacro %} +{{ httpx_args_docstring() }} + Attributes: raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a status code that was not documented in the source OpenAPI document. Can also be provided as a keyword argument to the constructor. """ - +{% macro attributes() %} raise_on_unexpected_status: bool = field(default=False, kw_only=True) _base_url: str _cookies: Dict[str, str] = field(factory=dict, kw_only=True) @@ -38,10 +43,12 @@ class Client: _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) _follow_redirects: bool = field(default=False, kw_only=True) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True) _client: Optional[httpx.Client] = field(default=None, init=False) _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) - - def with_headers(self, headers: Dict[str, str]) -> "Client": +{% endmacro %}{{ attributes() }} +{% macro builders(self) %} + def with_headers(self, headers: Dict[str, str]) -> "{{ self }}": """Get a new client matching this one with additional headers""" if self._client is not None: self._client.headers.update(headers) @@ -49,7 +56,7 @@ class Client: self._async_client.headers.update(headers) return evolve(self, headers={**self._headers, **headers}) - def with_cookies(self, cookies: Dict[str, str]) -> "Client": + def with_cookies(self, cookies: Dict[str, str]) -> "{{ self }}": """Get a new client matching this one with additional cookies""" if self._client is not None: self._client.cookies.update(cookies) @@ -57,15 +64,16 @@ class Client: self._async_client.cookies.update(cookies) return evolve(self, cookies={**self._cookies, **cookies}) - def with_timeout(self, timeout: httpx.Timeout) -> "Client": + def with_timeout(self, timeout: httpx.Timeout) -> "{{ self }}": """Get a new client matching this one with a new timeout (in seconds)""" if self._client is not None: self._client.timeout = timeout if self._async_client is not None: self._async_client.timeout = timeout return evolve(self, timeout=timeout) - - def set_httpx_client(self, client: httpx.Client) -> "Client": +{% endmacro %}{{ builders("Client") }} +{% macro httpx_stuff(name, custom_constructor=None) %} + def set_httpx_client(self, client: httpx.Client) -> "{{ name }}": """Manually the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. @@ -76,6 +84,9 @@ class Client: def get_httpx_client(self) -> httpx.Client: """Get the underlying httpx.Client, constructing a new one if not previously set""" if self._client is None: + {% if custom_constructor %} + {{ custom_constructor | indent(12) }} + {% endif %} self._client = httpx.Client( base_url=self._base_url, cookies=self._cookies, @@ -83,19 +94,20 @@ class Client: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._client - def __enter__(self) -> "Client": + def __enter__(self) -> "{{ name }}": """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" self.get_httpx_client().__enter__() return self def __exit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.client (see httpx docs)""" + """Exit a context manager for internal httpx.Client (see httpx docs)""" self.get_httpx_client().__exit__(*args, **kwargs) - def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "{{ name }}": """Manually the underlying httpx.AsyncClient **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. @@ -106,6 +118,9 @@ class Client: def get_async_httpx_client(self) -> httpx.AsyncClient: """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" if self._async_client is None: + {% if custom_constructor %} + {{ custom_constructor | indent(12) }} + {% endif %} self._async_client = httpx.AsyncClient( base_url=self._base_url, cookies=self._cookies, @@ -113,142 +128,39 @@ class Client: timeout=self._timeout, verify=self._verify_ssl, follow_redirects=self._follow_redirects, + **self._httpx_args, ) return self._async_client - async def __aenter__(self) -> "Client": - """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" + async def __aenter__(self) -> "{{ name }}": + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" await self.get_async_httpx_client().__aenter__() return self async def __aexit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.async_client (see httpx docs)""" + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" await self.get_async_httpx_client().__aexit__(*args, **kwargs) - +{% endmacro %}{{ httpx_stuff("Client") }} @define class AuthenticatedClient: """A Client which has been authenticated for use on secured endpoints - The following are accepted as keyword arguments and will be used to construct httpx Clients internally: - - ``base_url``: The base URL for the API, all requests are made to a relative path to this URL - - ``cookies``: A dictionary of cookies to be sent with every request - - ``headers``: A dictionary of headers to be sent with every request - - ``timeout``: The maximum amount of a time in seconds a request can take. API functions will raise - httpx.TimeoutException if this is exceeded. - - ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, - but can be set to False for testing purposes. - - ``follow_redirects``: Whether or not to follow redirects. Default value is False. +{{ httpx_args_docstring() }} Attributes: raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a status code that was not documented in the source OpenAPI document. Can also be provided as a keyword argument to the constructor. + token: The token to use for authentication + prefix: The prefix to use for the Authorization header + auth_header_name: The name of the Authorization header """ - raise_on_unexpected_status: bool = field(default=False, kw_only=True) - _base_url: str +{{ attributes() }} token: str prefix: str = "Bearer" auth_header_name: str = "Authorization" - _cookies: Dict[str, str] = field(factory=dict, kw_only=True) - _headers: Dict[str, str] = field(factory=dict, kw_only=True) - _timeout: httpx.Timeout = field(default=None, kw_only=True) - _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) - _follow_redirects: bool = field(default=False, kw_only=True) - _client: Optional[httpx.Client] = field(default=None, init=False) - _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) - - def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": - """Get a new client matching this one with additional headers""" - if self._client is not None: - self._client.headers.update(headers) - if self._async_client is not None: - self._async_client.headers.update(headers) - return evolve(self, headers={**self._headers, **headers}) - - def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient": - """Get a new client matching this one with additional cookies""" - if self._client is not None: - self._client.cookies.update(cookies) - if self._async_client is not None: - self._async_client.cookies.update(cookies) - return evolve(self, cookies={**self._cookies, **cookies}) - - def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": - """Get a new client matching this one with a new timeout (in seconds)""" - if self._client is not None: - self._client.timeout = timeout - if self._async_client is not None: - self._async_client.timeout = timeout - return evolve(self, timeout=timeout) - def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": - """Manually the underlying httpx.Client - - **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up - auth **manually** if using this method. - """ - self._client = client - return self - - def get_httpx_client(self) -> httpx.Client: - """Get the underlying httpx.Client, constructing a new one if not previously set""" - if self._client is None: - self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token - self._client = httpx.Client( - base_url=self._base_url, - cookies=self._cookies, - headers=self._headers, - timeout=self._timeout, - verify=self._verify_ssl, - follow_redirects=self._follow_redirects, - ) - return self._client - - def __enter__(self) -> "AuthenticatedClient": - """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" - self.get_httpx_client().__enter__() - return self - - def __exit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.client (see httpx docs)""" - self.get_httpx_client().__exit__(*args, **kwargs) - - def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": - """Manually the underlying httpx.AsyncClient - - **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. Set up - auth **manually** if using this method. - """ - self._async_client = async_client - return self - - def get_async_httpx_client(self) -> httpx.AsyncClient: - """Get the underlying httpx.AsyncClient""" - if self._async_client is None: - self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token - self._async_client = httpx.AsyncClient( - base_url=self._base_url, - cookies=self._cookies, - headers=self._headers, - timeout=self._timeout, - verify=self._verify_ssl, - follow_redirects=self._follow_redirects, - ) - return self._async_client - - async def __aenter__(self) -> "AuthenticatedClient": - """Enter a context manager for self.async_client—you cannot enter twice (see httpx docs)""" - await self.get_async_httpx_client().__aenter__() - return self - - async def __aexit__(self, *args: Any, **kwargs: Any) -> None: - """Exit a context manager for self.async_client (see httpx docs)""" - await self.get_async_httpx_client().__aexit__(*args, **kwargs) \ No newline at end of file +{{ builders("AuthenticatedClient") }} +{{ httpx_stuff("AuthenticatedClient", "self._headers[self.auth_header_name] = f\"{self.prefix} {self.token}\" if self.prefix else self.token") }} \ No newline at end of file From f9ab1defc201d95defef7c2e2a1fc8620cf1a0fc Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 6 Jul 2023 16:59:23 -0600 Subject: [PATCH 09/18] Add changeset notes --- ...ustomizing_the_underlying_httpx_clients.md | 47 +++++++++++++++++++ ...edclient_no_longer_inherits_from_client.md | 7 +++ ...e_the_newer_attrs_define_and_field_apis.md | 7 +++ ..._now_reuse_connections_between_requests.md | 7 +++ .changeset/connections_dont_close.md | 18 +++++++ ...utes_for_client_and_authenticatedclient.md | 14 ++++++ ...take_an_httpxtimeout_instead_of_a_float.md | 5 ++ 7 files changed, 105 insertions(+) create mode 100644 .changeset/allow_customizing_the_underlying_httpx_clients.md create mode 100644 .changeset/authenticatedclient_no_longer_inherits_from_client.md create mode 100644 .changeset/client_and_authenticatedclient_now_use_the_newer_attrs_define_and_field_apis.md create mode 100644 .changeset/clients_now_reuse_connections_between_requests.md create mode 100644 .changeset/connections_dont_close.md create mode 100644 .changeset/removed_public_attributes_for_client_and_authenticatedclient.md create mode 100644 .changeset/the_timeout_param_and_with_timeout_now_take_an_httpxtimeout_instead_of_a_float.md diff --git a/.changeset/allow_customizing_the_underlying_httpx_clients.md b/.changeset/allow_customizing_the_underlying_httpx_clients.md new file mode 100644 index 000000000..07989a4d2 --- /dev/null +++ b/.changeset/allow_customizing_the_underlying_httpx_clients.md @@ -0,0 +1,47 @@ +--- +default: minor +--- + +#### Allow customizing the underlying `httpx` clients + +There are many use-cases where customizing the underlying `httpx` client directly is necessary. Some examples are: + +- [Event hooks](https://www.python-httpx.org/advanced/#event-hooks) +- [Proxies](https://www.python-httpx.org/advanced/#http-proxying) +- [Custom authentication](https://www.python-httpx.org/advanced/#customizing-authentication) +- [Retries](https://www.python-httpx.org/advanced/#usage_1) + +The new `Client` and `AuthenticatedClient` classes come with several methods to customize underlying clients. You can pass arbitrary arguments to `httpx.Client` or `httpx.AsyncClient` when they are constructed: + +```python +client = Client(base_url="https://api.example.com", httpx_args={"proxies": {"https://": "https://proxy.example.com"}}) +``` + +**The underlying clients are constructed lazily, only when needed. `httpx_args` are stored internally in a dictionary until the first request is made.** + +You can force immediate construction of an underlying client in order to edit it directly: + +```python +import httpx +from my_api import Client + +client = Client(base_url="https://api.example.com") +sync_client: httpx.Client = client.get_httpx_client() +sync_client.timeout = 10 +async_client = client.get_async_httpx_client() +async_client.timeout = 15 +``` + +You can also completely override the underlying clients: + +```python +import httpx +from my_api import Client + +client = Client(base_url="https://api.example.com") +# The params you put in here ^ are discarded when you call set_httpx_client or set_async_httpx_client +sync_client = httpx.Client(base_url="https://api.example.com", timeout=10) +client.set_httpx_client(sync_client) +async_client = httpx.AsyncClient(base_url="https://api.example.com", timeout=15) +client.set_async_httpx_client(async_client) +``` diff --git a/.changeset/authenticatedclient_no_longer_inherits_from_client.md b/.changeset/authenticatedclient_no_longer_inherits_from_client.md new file mode 100644 index 000000000..5c387b266 --- /dev/null +++ b/.changeset/authenticatedclient_no_longer_inherits_from_client.md @@ -0,0 +1,7 @@ +--- +default: major +--- + +#### `AuthenticatedClient` no longer inherits from `Client` + +The API of `AuthenticatedClient` is still a superset of `Client`, but the two classes no longer share a common base class. diff --git a/.changeset/client_and_authenticatedclient_now_use_the_newer_attrs_define_and_field_apis.md b/.changeset/client_and_authenticatedclient_now_use_the_newer_attrs_define_and_field_apis.md new file mode 100644 index 000000000..b06bd7540 --- /dev/null +++ b/.changeset/client_and_authenticatedclient_now_use_the_newer_attrs_define_and_field_apis.md @@ -0,0 +1,7 @@ +--- +default: major +--- + +#### `Client` and `AuthenticatedClient` now use the newer attrs `@define` and `@field` APIs + +See [the attrs docs](https://www.attrs.org/en/stable/names.html#attrs-tng) for more information on how these may affect you. diff --git a/.changeset/clients_now_reuse_connections_between_requests.md b/.changeset/clients_now_reuse_connections_between_requests.md new file mode 100644 index 000000000..542dfa846 --- /dev/null +++ b/.changeset/clients_now_reuse_connections_between_requests.md @@ -0,0 +1,7 @@ +--- +default: minor +--- + +#### Clients now reuse connections between requests + +This happens every time you use the same `Client` or `AuthenticatedClient` instance for multiple requests, however it is best to use a context manager (e.g., `with client as client:`) to ensure the client is closed properly. diff --git a/.changeset/connections_dont_close.md b/.changeset/connections_dont_close.md new file mode 100644 index 000000000..09b7d94d6 --- /dev/null +++ b/.changeset/connections_dont_close.md @@ -0,0 +1,18 @@ +--- +default: major +--- + +#### Connections from clients no longer automatically close (PR [#775](https://github.com/openapi-generators/openapi-python-client/pull/775)) + +`Client` and `AuthenticatedClient` now reuse an internal [`httpx.Client`](https://www.python-httpx.org/advanced/#client-instances) (or `AsyncClient`)—keeping connections open between requests. This will improve performance overall, but may cause resource leaking if clients are not closed properly. The new clients are intended to be used via context managers—though for compatibility they don't _have_ to be used with context managers. If not using a context manager, connections will probably leak. Note that once a client is closed (by leaving the context manager), it can no longer be used—and attempting to do so will raise an exception. + +APIs should now be called like: + +```python +with client as client: + my_api.sync(client) + another_api.sync(client) +# client is closed here and can no longer be used +``` + +Generated READMEs reflect the new syntax, but READMEs for existing generated clients should be updated manually. See [this diff](https://github.com/openapi-generators/openapi-python-client/pull/775/files#diff-62b50316369f84439d58f4981c37538f5b619d344393cb659080dadbda328547) for inspiration. diff --git a/.changeset/removed_public_attributes_for_client_and_authenticatedclient.md b/.changeset/removed_public_attributes_for_client_and_authenticatedclient.md new file mode 100644 index 000000000..0ba1d11f7 --- /dev/null +++ b/.changeset/removed_public_attributes_for_client_and_authenticatedclient.md @@ -0,0 +1,14 @@ +--- +default: major +--- + +#### Removed public attributes for `Client` and `AuthenticatedClient` + +The following attributes have been removed from `Client` and `AuthenticatedClient`: + +- `base_url`—this can now only be set via the initializer +- `cookies`—set at initialization or use `.with_cookies()` +- `headers`—set at initialization or use `.with_headers()` +- `timeout`—set at initialization or use `.with_timeout()` +- `verify_ssl`—this can now only be set via the initializer +- `follow_redirects`—this can now only be set via the initializer diff --git a/.changeset/the_timeout_param_and_with_timeout_now_take_an_httpxtimeout_instead_of_a_float.md b/.changeset/the_timeout_param_and_with_timeout_now_take_an_httpxtimeout_instead_of_a_float.md new file mode 100644 index 000000000..a92969e96 --- /dev/null +++ b/.changeset/the_timeout_param_and_with_timeout_now_take_an_httpxtimeout_instead_of_a_float.md @@ -0,0 +1,5 @@ +--- +default: major +--- + +#### The `timeout` param and `with_timeout` now take an `httpx.Timeout` instead of a float From 0dfb61f4bb5ac75ae96e58c2acc780c231c73cc2 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 6 Jul 2023 17:05:11 -0600 Subject: [PATCH 10/18] Add integration test for minimal httpx version --- .github/workflows/checks.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index d2a40554c..06763523f 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -90,6 +90,11 @@ jobs: integration: name: Integration Tests runs-on: ubuntu-latest + strategy: + matrix: + httpx_version: + - "0.15.4" + - "" services: openapi-test-server: image: ghcr.io/openapi-generators/openapi-test-server:0.0.1 @@ -135,9 +140,13 @@ jobs: python -m venv .venv poetry run python -m pip install --upgrade pip poetry install + - name: Set httpx version + if: matrix.httpx_version != '' + run: poetry run pip install httpx==${{ matrix.httpx_version }} - name: Run Tests run: | cd integration-tests poetry run pytest + mypy . --strict From 1b37b55c362dc7b6cda7d1a936e9e0292b26990f Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 6 Jul 2023 17:08:24 -0600 Subject: [PATCH 11/18] Add mypy to integration tests --- .github/workflows/checks.yml | 2 +- integration-tests/poetry.lock | 241 ++++++++++++++++++------------- integration-tests/pyproject.toml | 1 + 3 files changed, 144 insertions(+), 100 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 06763523f..12b698dc7 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -147,6 +147,6 @@ jobs: run: | cd integration-tests poetry run pytest - mypy . --strict + poetry run mypy . --strict diff --git a/integration-tests/poetry.lock b/integration-tests/poetry.lock index dbb1bb29b..79eb05b2c 100644 --- a/integration-tests/poetry.lock +++ b/integration-tests/poetry.lock @@ -2,100 +2,105 @@ [[package]] name = "anyio" -version = "3.5.0" +version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7" files = [ - {file = "anyio-3.5.0-py3-none-any.whl", hash = "sha256:b5fa16c5ff93fa1046f2eeb5bbff2dad4d3514d6cda61d02816dba34fa8c3c2e"}, - {file = "anyio-3.5.0.tar.gz", hash = "sha256:a0aeffe2fb1fdf374a8e4b471444f0f3ac4fb9f5a5b542b48824475e0042a5a6"}, + {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, + {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, ] [package.dependencies] +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" [package.extras] -doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] -trio = ["trio (>=0.16)"] - -[[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] +doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (<0.22)"] [[package]] name = "attrs" -version = "21.4.0" +version = "23.1.0" description = "Classes Without Boilerplate" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, ] [package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] -docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] -tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, + {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, + {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, ] [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.6" description = "Cross-platform colored terminal text." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "exceptiongroup" +version = "1.1.2" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"}, + {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"}, +] + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "h11" -version = "0.12.0" +version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, - {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] [[package]] name = "httpcore" -version = "0.15.0" +version = "0.17.3" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.7" files = [ - {file = "httpcore-0.15.0-py3-none-any.whl", hash = "sha256:1105b8b73c025f23ff7c36468e4432226cbb959176eab66864b8e31c4ee27fa6"}, - {file = "httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"}, + {file = "httpcore-0.17.3-py3-none-any.whl", hash = "sha256:c2789b767ddddfa2a5782e3199b2b7f6894540b17b16ec26b2c4d8e103510b87"}, + {file = "httpcore-0.17.3.tar.gz", hash = "sha256:a6f30213335e34c1ade7be6ec7c47f19f50c56db36abef1a9dfa3815b1cb3888"}, ] [package.dependencies] -anyio = "==3.*" +anyio = ">=3.0,<5.0" certifi = "*" -h11 = ">=0.11,<0.13" +h11 = ">=0.13,<0.15" sniffio = "==1.*" [package.extras] @@ -104,13 +109,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "httpx" -version = "0.24.0" +version = "0.24.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.7" files = [ - {file = "httpx-0.24.0-py3-none-any.whl", hash = "sha256:447556b50c1921c351ea54b4fe79d91b724ed2b027462ab9a329465d147d5a4e"}, - {file = "httpx-0.24.0.tar.gz", hash = "sha256:507d676fc3e26110d41df7d35ebd8b3b8585052450f4097401c9be59d928c63e"}, + {file = "httpx-0.24.1-py3-none-any.whl", hash = "sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd"}, + {file = "httpx-0.24.1.tar.gz", hash = "sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd"}, ] [package.dependencies] @@ -127,103 +132,130 @@ socks = ["socksio (==1.*)"] [[package]] name = "idna" -version = "3.3" +version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] [[package]] -name = "packaging" -version = "21.3" -description = "Core utilities for Python packages" +name = "mypy" +version = "1.4.1" +description = "Optional static typing for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, + {file = "mypy-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8"}, + {file = "mypy-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878"}, + {file = "mypy-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd"}, + {file = "mypy-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc"}, + {file = "mypy-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1"}, + {file = "mypy-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462"}, + {file = "mypy-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258"}, + {file = "mypy-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2"}, + {file = "mypy-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7"}, + {file = "mypy-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01"}, + {file = "mypy-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b"}, + {file = "mypy-1.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b"}, + {file = "mypy-1.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7"}, + {file = "mypy-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9"}, + {file = "mypy-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042"}, + {file = "mypy-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3"}, + {file = "mypy-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6"}, + {file = "mypy-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f"}, + {file = "mypy-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc"}, + {file = "mypy-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828"}, + {file = "mypy-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3"}, + {file = "mypy-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816"}, + {file = "mypy-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c"}, + {file = "mypy-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f"}, + {file = "mypy-1.4.1-py3-none-any.whl", hash = "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4"}, + {file = "mypy-1.4.1.tar.gz", hash = "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b"}, ] [package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +python2 = ["typed-ast (>=1.4.0,<2)"] +reports = ["lxml"] [[package]] -name = "pluggy" +name = "mypy-extensions" version = "1.0.0" -description = "plugin and hook calling mechanisms for python" +description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=3.6" +python-versions = ">=3.5" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - [[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, ] [[package]] -name = "pyparsing" -version = "3.0.6" -description = "Python parsing module" +name = "pluggy" +version = "1.2.0" +description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, - {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"}, + {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, + {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, ] [package.extras] -diagrams = ["jinja2", "railroad-diagrams"] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "pytest" -version = "7.0.0" +version = "7.4.0" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "pytest-7.0.0-py3-none-any.whl", hash = "sha256:42901e6bd4bd4a0e533358a86e848427a49005a3256f657c5c8f8dd35ef137a9"}, - {file = "pytest-7.0.0.tar.gz", hash = "sha256:dad48ffda394e5ad9aa3b7d7ddf339ed502e5e365b1350e0af65f4a602344b11"}, + {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, + {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, ] [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" @@ -270,27 +302,38 @@ files = [ [[package]] name = "sniffio" -version = "1.2.0" +version = "1.3.0" description = "Sniff out which async library your code is running under" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" files = [ - {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, - {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, ] [[package]] name = "tomli" -version = "2.0.0" +version = "2.0.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.7" files = [ - {file = "tomli-2.0.0-py3-none-any.whl", hash = "sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224"}, - {file = "tomli-2.0.0.tar.gz", hash = "sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1"}, + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, ] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "0cb4dd94817307ed1ec4baf850cf41cdb1d5190463752b5c63836b006e06eb3d" +content-hash = "d427ede8e0a0e883254783779969f5561fa786e4b1cc47a7dc6992471f6c3771" diff --git a/integration-tests/pyproject.toml b/integration-tests/pyproject.toml index 0ac763d5c..851651e8d 100644 --- a/integration-tests/pyproject.toml +++ b/integration-tests/pyproject.toml @@ -17,6 +17,7 @@ python-dateutil = "^2.8.0" [tool.poetry.dev-dependencies] pytest = "^7.0.0" +mypy = "*" [tool.poetry.group.dev.dependencies] pytest-asyncio = "^0.21.0" From d350660404fa49383efe7d1d6f9dc85761e03334 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 6 Jul 2023 17:10:27 -0600 Subject: [PATCH 12/18] Install lower httpx in the right place for integration tests --- .github/workflows/checks.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 12b698dc7..27e3d006d 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -142,7 +142,9 @@ jobs: poetry install - name: Set httpx version if: matrix.httpx_version != '' - run: poetry run pip install httpx==${{ matrix.httpx_version }} + run: | + cd integration-tests + poetry run pip install httpx==${{ matrix.httpx_version }} - name: Run Tests run: | cd integration-tests From 0ff5e55115aea4fd5321413c7bee347df16de565 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Thu, 6 Jul 2023 17:41:18 -0600 Subject: [PATCH 13/18] Update every attrs to use new syntax, raise minimum httpx version --- ...e_the_newer_attrs_define_and_field_apis.md | 2 +- .../minimum_httpx_version_raised_to_020.md | 7 + .github/workflows/checks.yml | 2 +- .../my_test_api_client/models/a_form_data.py | 6 +- .../my_test_api_client/models/a_model.py | 4 +- ...roperties_reference_that_are_not_object.py | 6 +- .../all_of_has_properties_but_no_type.py | 6 +- .../models/all_of_sub_model.py | 6 +- ...h_a_circular_ref_in_items_object_a_item.py | 6 +- ...ems_object_additional_properties_a_item.py | 6 +- ...ems_object_additional_properties_b_item.py | 6 +- ...h_a_circular_ref_in_items_object_b_item.py | 6 +- ...items_object_additional_properties_item.py | 6 +- ...th_a_recursive_ref_in_items_object_item.py | 6 +- .../models/another_all_of_sub_model.py | 6 +- .../body_upload_file_tests_upload_post.py | 6 +- ...e_tests_upload_post_additional_property.py | 6 +- ..._tests_upload_post_some_nullable_object.py | 6 +- ...load_file_tests_upload_post_some_object.py | 6 +- ..._tests_upload_post_some_optional_object.py | 6 +- .../models/free_form_model.py | 6 +- .../models/http_validation_error.py | 4 +- .../my_test_api_client/models/import_.py | 6 +- .../models/model_from_all_of.py | 6 +- .../my_test_api_client/models/model_name.py | 6 +- .../models/model_reference_with_periods.py | 6 +- ...odel_with_additional_properties_inlined.py | 6 +- ..._properties_inlined_additional_property.py | 6 +- .../model_with_additional_properties_refed.py | 6 +- .../models/model_with_any_json_properties.py | 6 +- ...n_properties_additional_property_type_0.py | 6 +- .../model_with_backslash_in_description.py | 6 +- .../models/model_with_circular_ref_a.py | 6 +- .../models/model_with_circular_ref_b.py | 6 +- ...circular_ref_in_additional_properties_a.py | 6 +- ...circular_ref_in_additional_properties_b.py | 6 +- .../models/model_with_date_time_property.py | 6 +- ...el_with_primitive_additional_properties.py | 6 +- ...ive_additional_properties_a_date_holder.py | 6 +- .../models/model_with_property_ref.py | 6 +- .../models/model_with_recursive_ref.py | 6 +- ..._recursive_ref_in_additional_properties.py | 6 +- .../models/model_with_union_property.py | 4 +- .../model_with_union_property_inlined.py | 4 +- ...ith_union_property_inlined_fruit_type_0.py | 6 +- ...ith_union_property_inlined_fruit_type_1.py | 6 +- .../my_test_api_client/models/none.py | 6 +- .../models/post_form_data_inline_data.py | 6 +- ...ions_simple_before_complex_response_200.py | 6 +- ...ple_before_complex_response_200a_type_1.py | 6 +- .../models/test_inline_objects_json_body.py | 4 +- .../test_inline_objects_response_200.py | 4 +- .../models/validation_error.py | 4 +- .../golden-record/my_test_api_client/types.py | 6 +- end_to_end_tests/golden-record/pyproject.toml | 2 +- .../post_body_multipart_multipart_data.py | 6 +- .../post_body_multipart_response_200.py | 6 +- .../post_parameters_header_response_200.py | 6 +- .../integration_tests/models/problem.py | 6 +- .../integration_tests/models/public_error.py | 6 +- integration-tests/integration_tests/types.py | 6 +- openapi_python_client/parser/openapi.py | 4 +- .../parser/properties/__init__.py | 41 +- .../parser/properties/enum_property.py | 6 +- .../parser/properties/model_property.py | 12 +- .../parser/properties/property.py | 10 +- .../parser/properties/schemas.py | 35 +- openapi_python_client/parser/responses.py | 4 +- .../templates/model.py.jinja | 6 +- .../templates/pyproject.toml.jinja | 2 +- .../templates/setup.py.jinja | 2 +- .../templates/types.py.jinja | 6 +- poetry.lock | 982 ++++++++++-------- pyproject.toml | 2 +- tests/test_parser/test_openapi.py | 1 + .../test_parser/test_properties/test_init.py | 11 +- .../test_properties/test_schemas.py | 31 +- 77 files changed, 834 insertions(+), 662 deletions(-) create mode 100644 .changeset/minimum_httpx_version_raised_to_020.md diff --git a/.changeset/client_and_authenticatedclient_now_use_the_newer_attrs_define_and_field_apis.md b/.changeset/client_and_authenticatedclient_now_use_the_newer_attrs_define_and_field_apis.md index b06bd7540..44c351233 100644 --- a/.changeset/client_and_authenticatedclient_now_use_the_newer_attrs_define_and_field_apis.md +++ b/.changeset/client_and_authenticatedclient_now_use_the_newer_attrs_define_and_field_apis.md @@ -2,6 +2,6 @@ default: major --- -#### `Client` and `AuthenticatedClient` now use the newer attrs `@define` and `@field` APIs +#### Generated clients and models now use the newer attrs `@define` and `field` APIs See [the attrs docs](https://www.attrs.org/en/stable/names.html#attrs-tng) for more information on how these may affect you. diff --git a/.changeset/minimum_httpx_version_raised_to_020.md b/.changeset/minimum_httpx_version_raised_to_020.md new file mode 100644 index 000000000..056076a8b --- /dev/null +++ b/.changeset/minimum_httpx_version_raised_to_020.md @@ -0,0 +1,7 @@ +--- +default: major +--- + +#### Minimum httpx version raised to 0.20 + +Some features of generated clients already failed at runtime when using httpx < 0.20, but now the minimum version is enforced at generation time. diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 27e3d006d..fe12926d4 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -93,7 +93,7 @@ jobs: strategy: matrix: httpx_version: - - "0.15.4" + - "0.20.0" - "" services: openapi-test-server: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_form_data.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_form_data.py index 958b24ab5..935cbcdc9 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_form_data.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_form_data.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="AFormData") -@attr.s(auto_attribs=True) +@define class AFormData: """ Attributes: @@ -17,7 +17,7 @@ class AFormData: an_required_field: str an_optional_field: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: an_required_field = self.an_required_field diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 9c1740dc8..398b471be 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -1,7 +1,7 @@ import datetime from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, TypeVar, Union, cast -import attr +from attrs import define from dateutil.parser import isoparse from ..models.an_all_of_enum import AnAllOfEnum @@ -17,7 +17,7 @@ T = TypeVar("T", bound="AModel") -@attr.s(auto_attribs=True) +@define class AModel: """A Model for testing all the ways custom objects can be used diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model_with_properties_reference_that_are_not_object.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model_with_properties_reference_that_are_not_object.py index 1f1c05565..c252fd73b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model_with_properties_reference_that_are_not_object.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model_with_properties_reference_that_are_not_object.py @@ -2,7 +2,7 @@ from io import BytesIO from typing import Any, Dict, List, Type, TypeVar, cast -import attr +from attrs import define, field from dateutil.parser import isoparse from ..models.an_enum import AnEnum @@ -11,7 +11,7 @@ T = TypeVar("T", bound="AModelWithPropertiesReferenceThatAreNotObject") -@attr.s(auto_attribs=True) +@define class AModelWithPropertiesReferenceThatAreNotObject: """ Attributes: @@ -77,7 +77,7 @@ class AModelWithPropertiesReferenceThatAreNotObject: double_property_ref: float file_property_ref: File bytestream_property_ref: str - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: enum_properties_ref = [] diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/all_of_has_properties_but_no_type.py b/end_to_end_tests/golden-record/my_test_api_client/models/all_of_has_properties_but_no_type.py index 90918d021..a0aaa36ba 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/all_of_has_properties_but_no_type.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/all_of_has_properties_but_no_type.py @@ -1,6 +1,6 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..models.all_of_has_properties_but_no_type_type_enum import AllOfHasPropertiesButNoTypeTypeEnum from ..types import UNSET, Unset @@ -8,7 +8,7 @@ T = TypeVar("T", bound="AllOfHasPropertiesButNoType") -@attr.s(auto_attribs=True) +@define class AllOfHasPropertiesButNoType: """ Attributes: @@ -20,7 +20,7 @@ class AllOfHasPropertiesButNoType: a_sub_property: Union[Unset, str] = UNSET type: Union[Unset, str] = UNSET type_enum: Union[Unset, AllOfHasPropertiesButNoTypeTypeEnum] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: a_sub_property = self.a_sub_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/all_of_sub_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/all_of_sub_model.py index 5a46393fd..715b799dd 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/all_of_sub_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/all_of_sub_model.py @@ -1,6 +1,6 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..models.all_of_sub_model_type_enum import AllOfSubModelTypeEnum from ..types import UNSET, Unset @@ -8,7 +8,7 @@ T = TypeVar("T", bound="AllOfSubModel") -@attr.s(auto_attribs=True) +@define class AllOfSubModel: """ Attributes: @@ -20,7 +20,7 @@ class AllOfSubModel: a_sub_property: Union[Unset, str] = UNSET type: Union[Unset, str] = UNSET type_enum: Union[Unset, AllOfSubModelTypeEnum] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: a_sub_property = self.a_sub_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_a_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_a_item.py index 16fcbb88d..522060c3d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_a_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_a_item.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset @@ -11,7 +11,7 @@ T = TypeVar("T", bound="AnArrayWithACircularRefInItemsObjectAItem") -@attr.s(auto_attribs=True) +@define class AnArrayWithACircularRefInItemsObjectAItem: """ Attributes: @@ -19,7 +19,7 @@ class AnArrayWithACircularRefInItemsObjectAItem: """ circular: Union[Unset, List["AnArrayWithACircularRefInItemsObjectBItem"]] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: circular: Union[Unset, List[Dict[str, Any]]] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_a_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_a_item.py index f03a87604..642c0a2c6 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_a_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_a_item.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field if TYPE_CHECKING: from ..models.an_array_with_a_circular_ref_in_items_object_additional_properties_b_item import ( @@ -11,11 +11,11 @@ T = TypeVar("T", bound="AnArrayWithACircularRefInItemsObjectAdditionalPropertiesAItem") -@attr.s(auto_attribs=True) +@define class AnArrayWithACircularRefInItemsObjectAdditionalPropertiesAItem: """ """ - additional_properties: Dict[str, List["AnArrayWithACircularRefInItemsObjectAdditionalPropertiesBItem"]] = attr.ib( + additional_properties: Dict[str, List["AnArrayWithACircularRefInItemsObjectAdditionalPropertiesBItem"]] = field( init=False, factory=dict ) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_b_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_b_item.py index cdff09b4b..b8663c92f 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_b_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_b_item.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field if TYPE_CHECKING: from ..models.an_array_with_a_circular_ref_in_items_object_additional_properties_a_item import ( @@ -11,11 +11,11 @@ T = TypeVar("T", bound="AnArrayWithACircularRefInItemsObjectAdditionalPropertiesBItem") -@attr.s(auto_attribs=True) +@define class AnArrayWithACircularRefInItemsObjectAdditionalPropertiesBItem: """ """ - additional_properties: Dict[str, List["AnArrayWithACircularRefInItemsObjectAdditionalPropertiesAItem"]] = attr.ib( + additional_properties: Dict[str, List["AnArrayWithACircularRefInItemsObjectAdditionalPropertiesAItem"]] = field( init=False, factory=dict ) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_b_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_b_item.py index b15bb0f7b..f544e03cb 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_b_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_b_item.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset @@ -11,7 +11,7 @@ T = TypeVar("T", bound="AnArrayWithACircularRefInItemsObjectBItem") -@attr.s(auto_attribs=True) +@define class AnArrayWithACircularRefInItemsObjectBItem: """ Attributes: @@ -19,7 +19,7 @@ class AnArrayWithACircularRefInItemsObjectBItem: """ circular: Union[Unset, List["AnArrayWithACircularRefInItemsObjectAItem"]] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: circular: Union[Unset, List[Dict[str, Any]]] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_additional_properties_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_additional_properties_item.py index 3c28f9d65..53510fb08 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_additional_properties_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_additional_properties_item.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="AnArrayWithARecursiveRefInItemsObjectAdditionalPropertiesItem") -@attr.s(auto_attribs=True) +@define class AnArrayWithARecursiveRefInItemsObjectAdditionalPropertiesItem: """ """ - additional_properties: Dict[str, List["AnArrayWithARecursiveRefInItemsObjectAdditionalPropertiesItem"]] = attr.ib( + additional_properties: Dict[str, List["AnArrayWithARecursiveRefInItemsObjectAdditionalPropertiesItem"]] = field( init=False, factory=dict ) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_item.py index c14ee07c2..5131c6f5d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_item.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="AnArrayWithARecursiveRefInItemsObjectItem") -@attr.s(auto_attribs=True) +@define class AnArrayWithARecursiveRefInItemsObjectItem: """ Attributes: @@ -15,7 +15,7 @@ class AnArrayWithARecursiveRefInItemsObjectItem: """ recursive: Union[Unset, List["AnArrayWithARecursiveRefInItemsObjectItem"]] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: recursive: Union[Unset, List[Dict[str, Any]]] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/another_all_of_sub_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/another_all_of_sub_model.py index c339eebd3..cb8d859ab 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/another_all_of_sub_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/another_all_of_sub_model.py @@ -1,6 +1,6 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..models.another_all_of_sub_model_type import AnotherAllOfSubModelType from ..models.another_all_of_sub_model_type_enum import AnotherAllOfSubModelTypeEnum @@ -9,7 +9,7 @@ T = TypeVar("T", bound="AnotherAllOfSubModel") -@attr.s(auto_attribs=True) +@define class AnotherAllOfSubModel: """ Attributes: @@ -21,7 +21,7 @@ class AnotherAllOfSubModel: another_sub_property: Union[Unset, str] = UNSET type: Union[Unset, AnotherAllOfSubModelType] = UNSET type_enum: Union[Unset, AnotherAllOfSubModelTypeEnum] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: another_sub_property = self.another_sub_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py index d858be5b6..e12262723 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py @@ -3,7 +3,7 @@ from io import BytesIO from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, TypeVar, Union, cast -import attr +from attrs import define, field from dateutil.parser import isoparse from ..models.different_enum import DifferentEnum @@ -25,7 +25,7 @@ T = TypeVar("T", bound="BodyUploadFileTestsUploadPost") -@attr.s(auto_attribs=True) +@define class BodyUploadFileTestsUploadPost: """ Attributes: @@ -53,7 +53,7 @@ class BodyUploadFileTestsUploadPost: some_array: Union[Unset, List[float]] = UNSET some_optional_object: Union[Unset, "BodyUploadFileTestsUploadPostSomeOptionalObject"] = UNSET some_enum: Union[Unset, DifferentEnum] = UNSET - additional_properties: Dict[str, "BodyUploadFileTestsUploadPostAdditionalProperty"] = attr.ib( + additional_properties: Dict[str, "BodyUploadFileTestsUploadPostAdditionalProperty"] = field( init=False, factory=dict ) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_additional_property.py index 522355858..0344ca91b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_additional_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_additional_property.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="BodyUploadFileTestsUploadPostAdditionalProperty") -@attr.s(auto_attribs=True) +@define class BodyUploadFileTestsUploadPostAdditionalProperty: """ Attributes: @@ -15,7 +15,7 @@ class BodyUploadFileTestsUploadPostAdditionalProperty: """ foo: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: foo = self.foo diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_nullable_object.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_nullable_object.py index e809b413e..118dc4e65 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_nullable_object.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_nullable_object.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="BodyUploadFileTestsUploadPostSomeNullableObject") -@attr.s(auto_attribs=True) +@define class BodyUploadFileTestsUploadPostSomeNullableObject: """ Attributes: @@ -15,7 +15,7 @@ class BodyUploadFileTestsUploadPostSomeNullableObject: """ bar: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: bar = self.bar diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_object.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_object.py index 8a4f123de..6e4fe5b5e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_object.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_object.py @@ -1,11 +1,11 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="BodyUploadFileTestsUploadPostSomeObject") -@attr.s(auto_attribs=True) +@define class BodyUploadFileTestsUploadPostSomeObject: """ Attributes: @@ -15,7 +15,7 @@ class BodyUploadFileTestsUploadPostSomeObject: num: float text: str - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: num = self.num diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_optional_object.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_optional_object.py index a32d5f979..c84222b31 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_optional_object.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_optional_object.py @@ -1,11 +1,11 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="BodyUploadFileTestsUploadPostSomeOptionalObject") -@attr.s(auto_attribs=True) +@define class BodyUploadFileTestsUploadPostSomeOptionalObject: """ Attributes: @@ -13,7 +13,7 @@ class BodyUploadFileTestsUploadPostSomeOptionalObject: """ foo: str - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: foo = self.foo diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py index b22ce2b04..36c751f02 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="FreeFormModel") -@attr.s(auto_attribs=True) +@define class FreeFormModel: """ """ - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py b/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py index 4d8e71670..7e57b8016 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define from ..types import UNSET, Unset @@ -11,7 +11,7 @@ T = TypeVar("T", bound="HTTPValidationError") -@attr.s(auto_attribs=True) +@define class HTTPValidationError: """ Attributes: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/import_.py b/end_to_end_tests/golden-record/my_test_api_client/models/import_.py index 1d09a453f..36c14a4ff 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/import_.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/import_.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="Import") -@attr.s(auto_attribs=True) +@define class Import: """ """ - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_from_all_of.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_from_all_of.py index 3dfc48a36..e6932c37a 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_from_all_of.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_from_all_of.py @@ -1,6 +1,6 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..models.another_all_of_sub_model_type import AnotherAllOfSubModelType from ..models.another_all_of_sub_model_type_enum import AnotherAllOfSubModelTypeEnum @@ -9,7 +9,7 @@ T = TypeVar("T", bound="ModelFromAllOf") -@attr.s(auto_attribs=True) +@define class ModelFromAllOf: """ Attributes: @@ -23,7 +23,7 @@ class ModelFromAllOf: type: Union[Unset, AnotherAllOfSubModelType] = UNSET type_enum: Union[Unset, AnotherAllOfSubModelTypeEnum] = UNSET another_sub_property: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: a_sub_property = self.a_sub_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_name.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_name.py index ccc313a39..c243d6d00 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_name.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_name.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="ModelName") -@attr.s(auto_attribs=True) +@define class ModelName: """ """ - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_reference_with_periods.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_reference_with_periods.py index 618f79d6c..f58db6ca6 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_reference_with_periods.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_reference_with_periods.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="ModelReferenceWithPeriods") -@attr.s(auto_attribs=True) +@define class ModelReferenceWithPeriods: """A Model with periods in its reference""" - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py index fb8ad21a8..fa5e81ae8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset @@ -13,7 +13,7 @@ T = TypeVar("T", bound="ModelWithAdditionalPropertiesInlined") -@attr.s(auto_attribs=True) +@define class ModelWithAdditionalPropertiesInlined: """ Attributes: @@ -21,7 +21,7 @@ class ModelWithAdditionalPropertiesInlined: """ a_number: Union[Unset, float] = UNSET - additional_properties: Dict[str, "ModelWithAdditionalPropertiesInlinedAdditionalProperty"] = attr.ib( + additional_properties: Dict[str, "ModelWithAdditionalPropertiesInlinedAdditionalProperty"] = field( init=False, factory=dict ) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py index 66b487c00..8ab4b7ac5 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="ModelWithAdditionalPropertiesInlinedAdditionalProperty") -@attr.s(auto_attribs=True) +@define class ModelWithAdditionalPropertiesInlinedAdditionalProperty: """ Attributes: @@ -15,7 +15,7 @@ class ModelWithAdditionalPropertiesInlinedAdditionalProperty: """ extra_props_prop: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: extra_props_prop = self.extra_props_prop diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py index 1e962c1c2..05a57116c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py @@ -1,17 +1,17 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field from ..models.an_enum import AnEnum T = TypeVar("T", bound="ModelWithAdditionalPropertiesRefed") -@attr.s(auto_attribs=True) +@define class ModelWithAdditionalPropertiesRefed: """ """ - additional_properties: Dict[str, AnEnum] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, AnEnum] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py index caf78a3ee..2aa80ff96 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union, cast -import attr +from attrs import define, field if TYPE_CHECKING: from ..models.model_with_any_json_properties_additional_property_type_0 import ( @@ -11,13 +11,13 @@ T = TypeVar("T", bound="ModelWithAnyJsonProperties") -@attr.s(auto_attribs=True) +@define class ModelWithAnyJsonProperties: """ """ additional_properties: Dict[ str, Union["ModelWithAnyJsonPropertiesAdditionalPropertyType0", List[str], bool, float, int, str] - ] = attr.ib(init=False, factory=dict) + ] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: from ..models.model_with_any_json_properties_additional_property_type_0 import ( diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py index c272cfb39..91554ccfb 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalPropertyType0") -@attr.s(auto_attribs=True) +@define class ModelWithAnyJsonPropertiesAdditionalPropertyType0: """ """ - additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, str] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_backslash_in_description.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_backslash_in_description.py index 08ec9e878..8b5fa87b9 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_backslash_in_description.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_backslash_in_description.py @@ -1,17 +1,17 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="ModelWithBackslashInDescription") -@attr.s(auto_attribs=True) +@define class ModelWithBackslashInDescription: r""" Description with special character: \ """ - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_a.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_a.py index 11e31983d..444e01a5a 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_a.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_a.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset @@ -11,7 +11,7 @@ T = TypeVar("T", bound="ModelWithCircularRefA") -@attr.s(auto_attribs=True) +@define class ModelWithCircularRefA: """ Attributes: @@ -19,7 +19,7 @@ class ModelWithCircularRefA: """ circular: Union[Unset, "ModelWithCircularRefB"] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: circular: Union[Unset, Dict[str, Any]] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_b.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_b.py index 5fb34f4f4..57f267882 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_b.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_b.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset @@ -11,7 +11,7 @@ T = TypeVar("T", bound="ModelWithCircularRefB") -@attr.s(auto_attribs=True) +@define class ModelWithCircularRefB: """ Attributes: @@ -19,7 +19,7 @@ class ModelWithCircularRefB: """ circular: Union[Unset, "ModelWithCircularRefA"] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: circular: Union[Unset, Dict[str, Any]] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_a.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_a.py index 0d9e0155c..a55ac59f4 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_a.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_a.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field if TYPE_CHECKING: from ..models.model_with_circular_ref_in_additional_properties_b import ModelWithCircularRefInAdditionalPropertiesB @@ -9,11 +9,11 @@ T = TypeVar("T", bound="ModelWithCircularRefInAdditionalPropertiesA") -@attr.s(auto_attribs=True) +@define class ModelWithCircularRefInAdditionalPropertiesA: """ """ - additional_properties: Dict[str, "ModelWithCircularRefInAdditionalPropertiesB"] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, "ModelWithCircularRefInAdditionalPropertiesB"] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: pass diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_b.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_b.py index 0583b40f8..e2a6f8a64 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_b.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_b.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field if TYPE_CHECKING: from ..models.model_with_circular_ref_in_additional_properties_a import ModelWithCircularRefInAdditionalPropertiesA @@ -9,11 +9,11 @@ T = TypeVar("T", bound="ModelWithCircularRefInAdditionalPropertiesB") -@attr.s(auto_attribs=True) +@define class ModelWithCircularRefInAdditionalPropertiesB: """ """ - additional_properties: Dict[str, "ModelWithCircularRefInAdditionalPropertiesA"] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, "ModelWithCircularRefInAdditionalPropertiesA"] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: pass diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_date_time_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_date_time_property.py index 1dfc6d406..f6daa6b8e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_date_time_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_date_time_property.py @@ -1,7 +1,7 @@ import datetime from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from dateutil.parser import isoparse from ..types import UNSET, Unset @@ -9,7 +9,7 @@ T = TypeVar("T", bound="ModelWithDateTimeProperty") -@attr.s(auto_attribs=True) +@define class ModelWithDateTimeProperty: """ Attributes: @@ -17,7 +17,7 @@ class ModelWithDateTimeProperty: """ datetime_: Union[Unset, datetime.datetime] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: datetime_: Union[Unset, str] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py index 89144cfec..1d009fa92 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset @@ -13,7 +13,7 @@ T = TypeVar("T", bound="ModelWithPrimitiveAdditionalProperties") -@attr.s(auto_attribs=True) +@define class ModelWithPrimitiveAdditionalProperties: """ Attributes: @@ -21,7 +21,7 @@ class ModelWithPrimitiveAdditionalProperties: """ a_date_holder: Union[Unset, "ModelWithPrimitiveAdditionalPropertiesADateHolder"] = UNSET - additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, str] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: a_date_holder: Union[Unset, Dict[str, Any]] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py index 0dab6e40c..520b243ad 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py @@ -1,17 +1,17 @@ import datetime from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field from dateutil.parser import isoparse T = TypeVar("T", bound="ModelWithPrimitiveAdditionalPropertiesADateHolder") -@attr.s(auto_attribs=True) +@define class ModelWithPrimitiveAdditionalPropertiesADateHolder: """ """ - additional_properties: Dict[str, datetime.datetime] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, datetime.datetime] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_property_ref.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_property_ref.py index d1b8b2b11..4513579ed 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_property_ref.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_property_ref.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset @@ -11,7 +11,7 @@ T = TypeVar("T", bound="ModelWithPropertyRef") -@attr.s(auto_attribs=True) +@define class ModelWithPropertyRef: """ Attributes: @@ -19,7 +19,7 @@ class ModelWithPropertyRef: """ inner: Union[Unset, "ModelName"] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: inner: Union[Unset, Dict[str, Any]] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref.py index b60e5a100..6b3bb6249 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="ModelWithRecursiveRef") -@attr.s(auto_attribs=True) +@define class ModelWithRecursiveRef: """ Attributes: @@ -15,7 +15,7 @@ class ModelWithRecursiveRef: """ recursive: Union[Unset, "ModelWithRecursiveRef"] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: recursive: Union[Unset, Dict[str, Any]] = UNSET diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref_in_additional_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref_in_additional_properties.py index 35b3015b6..cbe5ca645 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref_in_additional_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref_in_additional_properties.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="ModelWithRecursiveRefInAdditionalProperties") -@attr.s(auto_attribs=True) +@define class ModelWithRecursiveRefInAdditionalProperties: """ """ - additional_properties: Dict[str, "ModelWithRecursiveRefInAdditionalProperties"] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, "ModelWithRecursiveRefInAdditionalProperties"] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index e1fd0cf5b..40b0575b7 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -1,6 +1,6 @@ from typing import Any, Dict, Type, TypeVar, Union -import attr +from attrs import define from ..models.an_enum import AnEnum from ..models.an_int_enum import AnIntEnum @@ -9,7 +9,7 @@ T = TypeVar("T", bound="ModelWithUnionProperty") -@attr.s(auto_attribs=True) +@define class ModelWithUnionProperty: """ Attributes: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py index 0c6cb6d3a..53ec5d916 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union -import attr +from attrs import define from ..types import UNSET, Unset @@ -12,7 +12,7 @@ T = TypeVar("T", bound="ModelWithUnionPropertyInlined") -@attr.s(auto_attribs=True) +@define class ModelWithUnionPropertyInlined: """ Attributes: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_0.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_0.py index 466bfe252..e7cc993bd 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_0.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_0.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitType0") -@attr.s(auto_attribs=True) +@define class ModelWithUnionPropertyInlinedFruitType0: """ Attributes: @@ -15,7 +15,7 @@ class ModelWithUnionPropertyInlinedFruitType0: """ apples: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: apples = self.apples diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_1.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_1.py index a0dae4331..bf616090b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_1.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_1.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitType1") -@attr.s(auto_attribs=True) +@define class ModelWithUnionPropertyInlinedFruitType1: """ Attributes: @@ -15,7 +15,7 @@ class ModelWithUnionPropertyInlinedFruitType1: """ bananas: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: bananas = self.bananas diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/none.py b/end_to_end_tests/golden-record/my_test_api_client/models/none.py index 228bf05d7..4bb03e928 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/none.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/none.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="None_") -@attr.s(auto_attribs=True) +@define class None_: """ """ - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_form_data_inline_data.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_form_data_inline_data.py index baac858b3..673a512fe 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_form_data_inline_data.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_form_data_inline_data.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="PostFormDataInlineData") -@attr.s(auto_attribs=True) +@define class PostFormDataInlineData: """ Attributes: @@ -17,7 +17,7 @@ class PostFormDataInlineData: a_required_field: str an_optional_field: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: a_required_field = self.a_required_field diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py index 579c4dbd6..f7ffbc177 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union, cast -import attr +from attrs import define, field if TYPE_CHECKING: from ..models.post_responses_unions_simple_before_complex_response_200a_type_1 import ( @@ -11,7 +11,7 @@ T = TypeVar("T", bound="PostResponsesUnionsSimpleBeforeComplexResponse200") -@attr.s(auto_attribs=True) +@define class PostResponsesUnionsSimpleBeforeComplexResponse200: """ Attributes: @@ -19,7 +19,7 @@ class PostResponsesUnionsSimpleBeforeComplexResponse200: """ a: Union["PostResponsesUnionsSimpleBeforeComplexResponse200AType1", str] - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: from ..models.post_responses_unions_simple_before_complex_response_200a_type_1 import ( diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py index bdf00654a..137ef64ff 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py @@ -1,15 +1,15 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="PostResponsesUnionsSimpleBeforeComplexResponse200AType1") -@attr.s(auto_attribs=True) +@define class PostResponsesUnionsSimpleBeforeComplexResponse200AType1: """ """ - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py index 66f8ce42c..fe74d1c3e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py @@ -1,13 +1,13 @@ from typing import Any, Dict, Type, TypeVar, Union -import attr +from attrs import define from ..types import UNSET, Unset T = TypeVar("T", bound="TestInlineObjectsJsonBody") -@attr.s(auto_attribs=True) +@define class TestInlineObjectsJsonBody: """ Attributes: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py index 3f9c1c944..1ca5a2261 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py @@ -1,13 +1,13 @@ from typing import Any, Dict, Type, TypeVar, Union -import attr +from attrs import define from ..types import UNSET, Unset T = TypeVar("T", bound="TestInlineObjectsResponse200") -@attr.s(auto_attribs=True) +@define class TestInlineObjectsResponse200: """ Attributes: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py b/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py index e2f6539ee..f2031eaad 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py @@ -1,11 +1,11 @@ from typing import Any, Dict, List, Type, TypeVar, cast -import attr +from attrs import define T = TypeVar("T", bound="ValidationError") -@attr.s(auto_attribs=True) +@define class ValidationError: """ Attributes: diff --git a/end_to_end_tests/golden-record/my_test_api_client/types.py b/end_to_end_tests/golden-record/my_test_api_client/types.py index 599eeb9f5..15700b858 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/types.py +++ b/end_to_end_tests/golden-record/my_test_api_client/types.py @@ -2,7 +2,7 @@ from http import HTTPStatus from typing import BinaryIO, Generic, Literal, MutableMapping, Optional, Tuple, TypeVar -import attr +from attrs import define class Unset: @@ -15,7 +15,7 @@ def __bool__(self) -> Literal[False]: FileJsonType = Tuple[Optional[str], BinaryIO, Optional[str]] -@attr.s(auto_attribs=True) +@define class File: """Contains information for file uploads""" @@ -31,7 +31,7 @@ def to_tuple(self) -> FileJsonType: T = TypeVar("T") -@attr.s(auto_attribs=True) +@define class Response(Generic[T]): """A response from an endpoint""" diff --git a/end_to_end_tests/golden-record/pyproject.toml b/end_to_end_tests/golden-record/pyproject.toml index 31adb2ddc..47e10cbce 100644 --- a/end_to_end_tests/golden-record/pyproject.toml +++ b/end_to_end_tests/golden-record/pyproject.toml @@ -13,7 +13,7 @@ include = ["CHANGELOG.md", "my_test_api_client/py.typed"] [tool.poetry.dependencies] python = "^3.8" -httpx = ">=0.15.4,<0.25.0" +httpx = ">=0.20.0,<0.25.0" attrs = ">=21.3.0" python-dateutil = "^2.8.0" diff --git a/integration-tests/integration_tests/models/post_body_multipart_multipart_data.py b/integration-tests/integration_tests/models/post_body_multipart_multipart_data.py index 1c7f6f651..525243447 100644 --- a/integration-tests/integration_tests/models/post_body_multipart_multipart_data.py +++ b/integration-tests/integration_tests/models/post_body_multipart_multipart_data.py @@ -1,14 +1,14 @@ from io import BytesIO from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, File, Unset T = TypeVar("T", bound="PostBodyMultipartMultipartData") -@attr.s(auto_attribs=True) +@define class PostBodyMultipartMultipartData: """ Attributes: @@ -21,7 +21,7 @@ class PostBodyMultipartMultipartData: a_string: str file: File description: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: a_string = self.a_string diff --git a/integration-tests/integration_tests/models/post_body_multipart_response_200.py b/integration-tests/integration_tests/models/post_body_multipart_response_200.py index 319c25fd0..a29d7161d 100644 --- a/integration-tests/integration_tests/models/post_body_multipart_response_200.py +++ b/integration-tests/integration_tests/models/post_body_multipart_response_200.py @@ -1,11 +1,11 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="PostBodyMultipartResponse200") -@attr.s(auto_attribs=True) +@define class PostBodyMultipartResponse200: """ Attributes: @@ -21,7 +21,7 @@ class PostBodyMultipartResponse200: description: str file_name: str file_content_type: str - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: a_string = self.a_string diff --git a/integration-tests/integration_tests/models/post_parameters_header_response_200.py b/integration-tests/integration_tests/models/post_parameters_header_response_200.py index 772ffad3e..ead8eae42 100644 --- a/integration-tests/integration_tests/models/post_parameters_header_response_200.py +++ b/integration-tests/integration_tests/models/post_parameters_header_response_200.py @@ -1,11 +1,11 @@ from typing import Any, Dict, List, Type, TypeVar -import attr +from attrs import define, field T = TypeVar("T", bound="PostParametersHeaderResponse200") -@attr.s(auto_attribs=True) +@define class PostParametersHeaderResponse200: """ Attributes: @@ -19,7 +19,7 @@ class PostParametersHeaderResponse200: string: str number: float integer: int - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: boolean = self.boolean diff --git a/integration-tests/integration_tests/models/problem.py b/integration-tests/integration_tests/models/problem.py index d343123ab..ad33a5f66 100644 --- a/integration-tests/integration_tests/models/problem.py +++ b/integration-tests/integration_tests/models/problem.py @@ -1,13 +1,13 @@ from typing import Any, Dict, List, Type, TypeVar, Union -import attr +from attrs import define, field from ..types import UNSET, Unset T = TypeVar("T", bound="Problem") -@attr.s(auto_attribs=True) +@define class Problem: """ Attributes: @@ -17,7 +17,7 @@ class Problem: parameter_name: Union[Unset, str] = UNSET description: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: parameter_name = self.parameter_name diff --git a/integration-tests/integration_tests/models/public_error.py b/integration-tests/integration_tests/models/public_error.py index d5281d8ff..a79d3c025 100644 --- a/integration-tests/integration_tests/models/public_error.py +++ b/integration-tests/integration_tests/models/public_error.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union, cast -import attr +from attrs import define, field from ..types import UNSET, Unset @@ -11,7 +11,7 @@ T = TypeVar("T", bound="PublicError") -@attr.s(auto_attribs=True) +@define class PublicError: """ Attributes: @@ -25,7 +25,7 @@ class PublicError: extra_parameters: Union[Unset, List[str]] = UNSET invalid_parameters: Union[Unset, List["Problem"]] = UNSET missing_parameters: Union[Unset, List[str]] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, Any] = field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: errors: Union[Unset, List[str]] = UNSET diff --git a/integration-tests/integration_tests/types.py b/integration-tests/integration_tests/types.py index 599eeb9f5..15700b858 100644 --- a/integration-tests/integration_tests/types.py +++ b/integration-tests/integration_tests/types.py @@ -2,7 +2,7 @@ from http import HTTPStatus from typing import BinaryIO, Generic, Literal, MutableMapping, Optional, Tuple, TypeVar -import attr +from attrs import define class Unset: @@ -15,7 +15,7 @@ def __bool__(self) -> Literal[False]: FileJsonType = Tuple[Optional[str], BinaryIO, Optional[str]] -@attr.s(auto_attribs=True) +@define class File: """Contains information for file uploads""" @@ -31,7 +31,7 @@ def to_tuple(self) -> FileJsonType: T = TypeVar("T") -@attr.s(auto_attribs=True) +@define class Response(Generic[T]): """A response from an endpoint""" diff --git a/openapi_python_client/parser/openapi.py b/openapi_python_client/parser/openapi.py index 90c1e355b..281f528b3 100644 --- a/openapi_python_client/parser/openapi.py +++ b/openapi_python_client/parser/openapi.py @@ -572,7 +572,9 @@ def from_dict(data: Dict[str, Any], *, config: Config) -> Union["GeneratorData", if openapi.components and openapi.components.schemas: schemas = build_schemas(components=openapi.components.schemas, schemas=schemas, config=config) if openapi.components and openapi.components.parameters: - parameters = build_parameters(components=openapi.components.parameters, parameters=parameters) + parameters = build_parameters( + components=openapi.components.parameters, parameters=parameters, config=config + ) endpoint_collections_by_tag, schemas, parameters = EndpointCollection.from_data( data=openapi.paths, schemas=schemas, parameters=parameters, config=config ) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index c4fe245e0..981b586b6 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -14,7 +14,7 @@ from itertools import chain from typing import Any, ClassVar, Dict, Generic, Iterable, List, Optional, Set, Tuple, TypeVar, Union -import attr +from attrs import define, evolve from ... import Config from ... import schema as oai @@ -35,7 +35,7 @@ ) -@attr.s(auto_attribs=True, frozen=True) +@define class AnyProperty(Property): """A property that can be any type (used for empty schemas)""" @@ -43,7 +43,7 @@ class AnyProperty(Property): _json_type_string: ClassVar[str] = "Any" -@attr.s(auto_attribs=True, frozen=True) +@define class NoneProperty(Property): """A property that can only be None""" @@ -51,7 +51,7 @@ class NoneProperty(Property): _json_type_string: ClassVar[str] = "None" -@attr.s(auto_attribs=True, frozen=True) +@define class StringProperty(Property): """A property of type str""" @@ -67,7 +67,7 @@ class StringProperty(Property): } -@attr.s(auto_attribs=True, frozen=True) +@define class DateTimeProperty(Property): """ A property of type datetime.datetime @@ -90,7 +90,7 @@ def get_imports(self, *, prefix: str) -> Set[str]: return imports -@attr.s(auto_attribs=True, frozen=True) +@define class DateProperty(Property): """A property of type datetime.date""" @@ -111,7 +111,7 @@ def get_imports(self, *, prefix: str) -> Set[str]: return imports -@attr.s(auto_attribs=True, frozen=True) +@define class FileProperty(Property): """A property used for uploading files""" @@ -133,7 +133,7 @@ def get_imports(self, *, prefix: str) -> Set[str]: return imports -@attr.s(auto_attribs=True, frozen=True) +@define class FloatProperty(Property): """A property of type float""" @@ -148,7 +148,7 @@ class FloatProperty(Property): template: ClassVar[str] = "float_property.py.jinja" -@attr.s(auto_attribs=True, frozen=True) +@define class IntProperty(Property): """A property of type int""" @@ -163,7 +163,7 @@ class IntProperty(Property): template: ClassVar[str] = "int_property.py.jinja" -@attr.s(auto_attribs=True, frozen=True) +@define class BooleanProperty(Property): """Property for bool""" @@ -181,7 +181,7 @@ class BooleanProperty(Property): InnerProp = TypeVar("InnerProp", bound=Property) -@attr.s(auto_attribs=True, frozen=True) +@define class ListProperty(Property, Generic[InnerProp]): """A property representing a list (array) of other properties""" @@ -218,7 +218,7 @@ def get_lazy_imports(self, *, prefix: str) -> Set[str]: return lazy_imports -@attr.s(auto_attribs=True, frozen=True) +@define class UnionProperty(Property): """A property representing a Union (anyOf) of other properties""" @@ -434,9 +434,9 @@ def build_enum_property( default = get_enum_default(prop, data) if isinstance(default, PropertyError): return default, schemas - prop = attr.evolve(prop, default=default) + prop = evolve(prop, default=default) - schemas = attr.evolve(schemas, classes_by_name={**schemas.classes_by_name, class_info.name: prop}) + schemas = evolve(schemas, classes_by_name={**schemas.classes_by_name, class_info.name: prop}) return prop, schemas @@ -587,19 +587,19 @@ def _property_from_ref( if not existing: return PropertyError(data=data, detail="Could not find reference in parsed models or enums"), schemas - prop = attr.evolve( + prop = evolve( existing, required=required, name=name, python_name=utils.PythonIdentifier(value=name, prefix=config.field_prefix), ) if parent: - prop = attr.evolve(prop, nullable=parent.nullable) + prop = evolve(prop, nullable=parent.nullable) if isinstance(prop, EnumProperty): default = get_enum_default(prop, parent) if isinstance(default, PropertyError): return default, schemas - prop = attr.evolve(prop, default=default) + prop = evolve(prop, default=default) schemas.add_dependencies(ref_path=ref_path, roots=roots) return prop, schemas @@ -730,7 +730,7 @@ def property_from_data( parent_name: str, config: Config, process_properties: bool = True, - roots: Set[Union[ReferencePath, utils.ClassName]] = None, + roots: Optional[Set[Union[ReferencePath, utils.ClassName]]] = None, ) -> Tuple[Union[Property, PropertyError], Schemas]: """ Build a Property from an OpenAPI schema or reference. This Property represents a single input or output for a @@ -880,6 +880,7 @@ def build_parameters( *, components: Dict[str, Union[oai.Reference, oai.Parameter]], parameters: Parameters, + config: Config, ) -> Parameters: """Get a list of Parameters from an OpenAPI dict""" to_process: Iterable[Tuple[str, Union[oai.Reference, oai.Parameter]]] = [] @@ -902,7 +903,9 @@ def build_parameters( if isinstance(ref_path, ParseError): parameters.errors.append(ParameterError(detail=ref_path.detail, data=data)) continue - parameters_or_err = update_parameters_with_data(ref_path=ref_path, data=data, parameters=parameters) + parameters_or_err = update_parameters_with_data( + ref_path=ref_path, data=data, parameters=parameters, config=config + ) if isinstance(parameters_or_err, ParameterError): next_round.append((name, data)) errors.append(parameters_or_err) diff --git a/openapi_python_client/parser/properties/enum_property.py b/openapi_python_client/parser/properties/enum_property.py index 26c4e2ffc..df7c4d822 100644 --- a/openapi_python_client/parser/properties/enum_property.py +++ b/openapi_python_client/parser/properties/enum_property.py @@ -2,7 +2,7 @@ from typing import Any, ClassVar, Dict, List, Optional, Set, Type, Union, cast -import attr +from attrs import define, field from ... import schema as oai from ... import utils @@ -12,14 +12,14 @@ ValueType = Union[str, int] -@attr.s(auto_attribs=True, frozen=True) +@define class EnumProperty(Property): """A property that should use an enum""" values: Dict[str, ValueType] class_info: Class value_type: Type[ValueType] - default: Optional[Any] = attr.ib() + default: Optional[Any] = field() template: ClassVar[str] = "enum_property.py.jinja" diff --git a/openapi_python_client/parser/properties/model_property.py b/openapi_python_client/parser/properties/model_property.py index 38080cd40..39c5ff5c7 100644 --- a/openapi_python_client/parser/properties/model_property.py +++ b/openapi_python_client/parser/properties/model_property.py @@ -3,7 +3,7 @@ from itertools import chain from typing import ClassVar, Dict, List, NamedTuple, Optional, Set, Tuple, Union -import attr +from attrs import define, evolve from ... import Config from ... import schema as oai @@ -14,7 +14,7 @@ from .schemas import Class, ReferencePath, Schemas, parse_reference_path -@attr.s(auto_attribs=True, frozen=True) +@define class ModelProperty(Property): """A property which refers to another Schema""" @@ -158,15 +158,15 @@ def _merge_properties(first: Property, second: Property) -> Union[Property, Prop err = None if first.__class__ == second.__class__: - first = attr.evolve(first, nullable=nullable, required=required) - second = attr.evolve(second, nullable=nullable, required=required) + first = evolve(first, nullable=nullable, required=required) + second = evolve(second, nullable=nullable, required=required) if first == second: return first err = PropertyError(header="Cannot merge properties", detail="Properties has conflicting values") enum_subset = _enum_subset(first, second) if enum_subset is not None: - return attr.evolve(enum_subset, nullable=nullable, required=required) + return evolve(enum_subset, nullable=nullable, required=required) return err or PropertyError( header="Cannot merge properties", @@ -443,5 +443,5 @@ def build_model_property( error = PropertyError(data=data, detail=f'Attempted to generate duplicate models with name "{class_info.name}"') return error, schemas - schemas = attr.evolve(schemas, classes_by_name={**schemas.classes_by_name, class_info.name: prop}) + schemas = evolve(schemas, classes_by_name={**schemas.classes_by_name, class_info.name: prop}) return prop, schemas diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index 4e2aea76c..a7e4c1ae7 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, ClassVar, Optional, Set -import attr +from attrs import define, field from ... import Config from ... import schema as oai @@ -15,7 +15,7 @@ ModelProperty = "ModelProperty" # pylint: disable=invalid-name -@attr.s(auto_attribs=True, frozen=True) +@define class Property: """ Describes a single property for a schema @@ -40,10 +40,10 @@ class Property: oai.ParameterLocation.PATH, oai.ParameterLocation.COOKIE, } - default: Optional[str] = attr.ib() + default: Optional[str] = field() python_name: PythonIdentifier - description: Optional[str] = attr.ib() - example: Optional[str] = attr.ib() + description: Optional[str] = field() + example: Optional[str] = field() template: ClassVar[str] = "any_property.py.jinja" json_is_dict: ClassVar[bool] = False diff --git a/openapi_python_client/parser/properties/schemas.py b/openapi_python_client/parser/properties/schemas.py index f3c27a91e..9a774b6d7 100644 --- a/openapi_python_client/parser/properties/schemas.py +++ b/openapi_python_client/parser/properties/schemas.py @@ -12,7 +12,7 @@ from typing import TYPE_CHECKING, Dict, List, NewType, Set, Tuple, Union, cast from urllib.parse import urlparse -import attr +from attrs import define, evolve, field from ... import Config from ... import schema as oai @@ -43,7 +43,7 @@ def parse_reference_path(ref_path_raw: str) -> Union[ReferencePath, ParseError]: return cast(ReferencePath, parsed.fragment) -@attr.s(auto_attribs=True, frozen=True) +@define class Class: """Represents Python class which will be generated from an OpenAPI schema""" @@ -69,14 +69,14 @@ def from_string(*, string: str, config: Config) -> "Class": return Class(name=class_name, module_name=module_name) -@attr.s(auto_attribs=True, frozen=True) +@define class Schemas: """Structure for containing all defined, shareable, and reusable schemas (attr classes and Enums)""" - classes_by_reference: Dict[ReferencePath, Property] = attr.ib(factory=dict) - dependencies: Dict[ReferencePath, Set[Union[ReferencePath, ClassName]]] = attr.ib(factory=dict) - classes_by_name: Dict[ClassName, Property] = attr.ib(factory=dict) - errors: List[ParseError] = attr.ib(factory=list) + classes_by_reference: Dict[ReferencePath, Property] = field(factory=dict) + dependencies: Dict[ReferencePath, Set[Union[ReferencePath, ClassName]]] = field(factory=dict) + classes_by_name: Dict[ClassName, Property] = field(factory=dict) + errors: List[ParseError] = field(factory=list) def add_dependencies(self, ref_path: ReferencePath, roots: Set[Union[ReferencePath, ClassName]]) -> None: """Record new dependencies on the given ReferencePath @@ -131,17 +131,17 @@ def update_schemas_with_data( ) return prop - schemas = attr.evolve(schemas, classes_by_reference={ref_path: prop, **schemas.classes_by_reference}) + schemas = evolve(schemas, classes_by_reference={ref_path: prop, **schemas.classes_by_reference}) return schemas -@attr.s(auto_attribs=True, frozen=True) +@define class Parameters: """Structure for containing all defined, shareable, and reusable parameters""" - classes_by_reference: Dict[ReferencePath, Parameter] = attr.ib(factory=dict) - classes_by_name: Dict[ClassName, Parameter] = attr.ib(factory=dict) - errors: List[ParseError] = attr.ib(factory=list) + classes_by_reference: Dict[ReferencePath, Parameter] = field(factory=dict) + classes_by_name: Dict[ClassName, Parameter] = field(factory=dict) + errors: List[ParseError] = field(factory=list) def parameter_from_data( @@ -149,6 +149,7 @@ def parameter_from_data( name: str, data: Union[oai.Reference, oai.Parameter], parameters: Parameters, + config: Config, ) -> Tuple[Union[Parameter, ParameterError], Parameters]: """Generates parameters from an OpenAPI Parameter spec.""" @@ -166,12 +167,14 @@ def parameter_from_data( param_schema=data.param_schema, param_in=data.param_in, ) - parameters = attr.evolve(parameters, classes_by_name={**parameters.classes_by_name, name: new_param}) + parameters = evolve( + parameters, classes_by_name={**parameters.classes_by_name, ClassName(name, config.field_prefix): new_param} + ) return new_param, parameters def update_parameters_with_data( - *, ref_path: ReferencePath, data: oai.Parameter, parameters: Parameters + *, ref_path: ReferencePath, data: oai.Parameter, parameters: Parameters, config: Config ) -> Union[Parameters, ParameterError]: """ Update a `Parameters` using some new reference. @@ -187,7 +190,7 @@ def update_parameters_with_data( See Also: - https://swagger.io/docs/specification/using-ref/ """ - param, parameters = parameter_from_data(data=data, name=data.name, parameters=parameters) + param, parameters = parameter_from_data(data=data, name=data.name, parameters=parameters, config=config) if isinstance(param, ParameterError): param.detail = f"{param.header}: {param.detail}" @@ -199,7 +202,7 @@ def update_parameters_with_data( ) return param - parameters = attr.evolve(parameters, classes_by_reference={ref_path: param, **parameters.classes_by_reference}) + parameters = evolve(parameters, classes_by_reference={ref_path: param, **parameters.classes_by_reference}) return parameters diff --git a/openapi_python_client/parser/responses.py b/openapi_python_client/parser/responses.py index e1f2cb49a..722614843 100644 --- a/openapi_python_client/parser/responses.py +++ b/openapi_python_client/parser/responses.py @@ -3,7 +3,7 @@ from http import HTTPStatus from typing import Optional, Tuple, Union -import attr +from attrs import define from .. import Config from .. import schema as oai @@ -12,7 +12,7 @@ from .properties import AnyProperty, Property, Schemas, property_from_data -@attr.s(auto_attribs=True, frozen=True) +@define class Response: """Describes a single response for an endpoint""" diff --git a/openapi_python_client/templates/model.py.jinja b/openapi_python_client/templates/model.py.jinja index 3b2763d68..64d67795d 100644 --- a/openapi_python_client/templates/model.py.jinja +++ b/openapi_python_client/templates/model.py.jinja @@ -5,7 +5,7 @@ from typing import List {% endif %} -import attr +from attrs import define, field {% if model.is_multipart_body %} import json {% endif %} @@ -58,7 +58,7 @@ T = TypeVar("T", bound="{{ class_name }}") {% endfor %}{% endif %} {% endmacro %} -@attr.s(auto_attribs=True) +@define class {{ class_name }}: {{ safe_docstring(class_docstring_content(model)) | indent(4) }} @@ -73,7 +73,7 @@ class {{ class_name }}: {% endif %} {% endfor %} {% if model.additional_properties %} - additional_properties: Dict[str, {{ additional_property_type }}] = attr.ib(init=False, factory=dict) + additional_properties: Dict[str, {{ additional_property_type }}] = field(init=False, factory=dict) {% endif %} {% macro _to_dict(multipart=False) %} diff --git a/openapi_python_client/templates/pyproject.toml.jinja b/openapi_python_client/templates/pyproject.toml.jinja index e3ed7b57e..8f9a8b18e 100644 --- a/openapi_python_client/templates/pyproject.toml.jinja +++ b/openapi_python_client/templates/pyproject.toml.jinja @@ -14,7 +14,7 @@ include = ["CHANGELOG.md", "{{ package_name }}/py.typed"] [tool.poetry.dependencies] python = "^3.8" -httpx = ">=0.15.4,<0.25.0" +httpx = ">=0.20.0,<0.25.0" attrs = ">=21.3.0" python-dateutil = "^2.8.0" diff --git a/openapi_python_client/templates/setup.py.jinja b/openapi_python_client/templates/setup.py.jinja index c2bc949d4..7d81f5116 100644 --- a/openapi_python_client/templates/setup.py.jinja +++ b/openapi_python_client/templates/setup.py.jinja @@ -13,6 +13,6 @@ setup( long_description_content_type="text/markdown", packages=find_packages(), python_requires=">=3.8, <4", - install_requires=["httpx >= 0.15.0, < 0.25.0", "attrs >= 21.3.0", "python-dateutil >= 2.8.0, < 3"], + install_requires=["httpx >= 0.20.0, < 0.25.0", "attrs >= 21.3.0", "python-dateutil >= 2.8.0, < 3"], package_data={"{{ package_name }}": ["py.typed"]}, ) diff --git a/openapi_python_client/templates/types.py.jinja b/openapi_python_client/templates/types.py.jinja index cfb990d85..e49ec9ca2 100644 --- a/openapi_python_client/templates/types.py.jinja +++ b/openapi_python_client/templates/types.py.jinja @@ -2,7 +2,7 @@ from http import HTTPStatus from typing import Any, BinaryIO, Generic, MutableMapping, Optional, Tuple, TypeVar, Literal -import attr +from attrs import define class Unset: @@ -16,7 +16,7 @@ UNSET: Unset = Unset() FileJsonType = Tuple[Optional[str], BinaryIO, Optional[str]] -@attr.s(auto_attribs=True) +@define class File: """ Contains information for file uploads """ @@ -32,7 +32,7 @@ class File: T = TypeVar("T") -@attr.s(auto_attribs=True) +@define class Response(Generic[T]): """ A response from an endpoint """ diff --git a/poetry.lock b/poetry.lock index 49c2029ba..1e451eec8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,39 +1,40 @@ -# This file is automatically @generated by Poetry 1.5.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "anyio" -version = "3.3.0" +version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7" files = [ - {file = "anyio-3.3.0-py3-none-any.whl", hash = "sha256:929a6852074397afe1d989002aa96d457e3e1e5441357c60d03e7eea0e65e1b0"}, - {file = "anyio-3.3.0.tar.gz", hash = "sha256:ae57a67583e5ff8b4af47666ff5651c3732d45fd26c929253748e796af860374"}, + {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, + {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, ] [package.dependencies] +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" [package.extras] -doc = ["sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] -trio = ["trio (>=0.16)"] +doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (<0.22)"] [[package]] name = "astroid" -version = "2.12.13" +version = "2.15.5" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.12.13-py3-none-any.whl", hash = "sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907"}, - {file = "astroid-2.12.13.tar.gz", hash = "sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7"}, + {file = "astroid-2.15.5-py3-none-any.whl", hash = "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324"}, + {file = "astroid-2.15.5.tar.gz", hash = "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f"}, ] [package.dependencies] lazy-object-proxy = ">=1.4.0" -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} wrapt = [ {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, @@ -41,30 +42,31 @@ wrapt = [ [[package]] name = "attrs" -version = "21.4.0" +version = "23.1.0" description = "Classes Without Boilerplate" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, ] [package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] -docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] -tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] [[package]] name = "autoflake" -version = "2.0.0" +version = "2.2.0" description = "Removes unused imports and unused variables" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "autoflake-2.0.0-py3-none-any.whl", hash = "sha256:d58ed4187c6b4f623a942b9a90c43ff84bf6a266f3682f407b42ca52073c9678"}, - {file = "autoflake-2.0.0.tar.gz", hash = "sha256:7185b596e70d8970c6d4106c112ef41921e472bd26abf3613db99eca88cc8c2a"}, + {file = "autoflake-2.2.0-py3-none-any.whl", hash = "sha256:de409b009a34c1c2a7cc2aae84c4c05047f9773594317c6a6968bd497600d4a0"}, + {file = "autoflake-2.2.0.tar.gz", hash = "sha256:62e1f74a0fdad898a96fee6f99fe8241af90ad99c7110c884b35855778412251"}, ] [package.dependencies] @@ -122,38 +124,108 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, + {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, + {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, ] [[package]] name = "charset-normalizer" -version = "2.0.4" +version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false -python-versions = ">=3.5.0" +python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-2.0.4.tar.gz", hash = "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"}, - {file = "charset_normalizer-2.0.4-py3-none-any.whl", hash = "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b"}, + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, ] -[package.extras] -unicode-backport = ["unicodedata2"] - [[package]] name = "click" -version = "8.0.3" +version = "8.1.4" description = "Composable command line interface toolkit" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, - {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, + {file = "click-8.1.4-py3-none-any.whl", hash = "sha256:2739815aaa5d2c986a88f1e9230c55e17f0caad3d958a5e13ad0797c166db9e3"}, + {file = "click-8.1.4.tar.gz", hash = "sha256:b97d0c74955da062a7d4ef92fadb583806a585b2ea81958a81bd72726cbb8e37"}, ] [package.dependencies] @@ -172,61 +244,71 @@ files = [ [[package]] name = "coverage" -version = "6.5.0" +version = "7.2.7" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.7" files = [ - {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, - {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, - {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, - {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, - {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, - {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, - {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, - {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, - {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, - {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, - {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, - {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, - {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, - {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, - {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, - {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, + {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, + {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, + {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, + {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, + {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"}, + {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, + {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, + {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, + {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, + {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, + {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, + {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, + {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, + {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, + {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"}, + {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, + {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, + {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, + {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, + {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, + {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, + {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, + {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, + {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"}, + {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, + {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, + {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, + {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, + {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, + {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, + {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, + {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, + {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"}, + {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, + {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, + {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, + {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, + {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, + {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, + {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, + {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, + {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, + {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"}, + {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, + {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, + {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, + {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, + {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, + {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, + {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, + {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, + {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, + {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"}, + {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, + {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, + {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, + {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, + {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, + {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, + {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"}, ] [package.dependencies] @@ -251,32 +333,32 @@ graph = ["objgraph (>=1.7.2)"] [[package]] name = "dparse" -version = "0.5.1" +version = "0.6.3" description = "A parser for Python dependency files" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"}, - {file = "dparse-0.5.1.tar.gz", hash = "sha256:a1b5f169102e1c894f9a7d5ccf6f9402a836a5d24be80a986c7ce9eaed78f367"}, + {file = "dparse-0.6.3-py3-none-any.whl", hash = "sha256:0d8fe18714056ca632d98b24fbfc4e9791d4e47065285ab486182288813a5318"}, + {file = "dparse-0.6.3.tar.gz", hash = "sha256:27bb8b4bcaefec3997697ba3f6e06b2447200ba273c0b085c3d012a04571b528"}, ] [package.dependencies] packaging = "*" -pyyaml = "*" -toml = "*" +tomli = {version = "*", markers = "python_version < \"3.11\""} [package.extras] -pipenv = ["pipenv"] +conda = ["pyyaml"] +pipenv = ["pipenv (<=2022.12.19)"] [[package]] name = "exceptiongroup" -version = "1.0.1" +version = "1.1.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.0.1-py3-none-any.whl", hash = "sha256:4d6c0aa6dd825810941c792f53d7b8d71da26f5e5f84f20f9508e8f2d33b140a"}, - {file = "exceptiongroup-1.0.1.tar.gz", hash = "sha256:73866f7f842ede6cb1daa42c4af078e2035e5f7607f0e2c762cc51bb31bbe7b2"}, + {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"}, + {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"}, ] [package.extras] @@ -284,30 +366,30 @@ test = ["pytest (>=6)"] [[package]] name = "h11" -version = "0.12.0" +version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, - {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] [[package]] name = "httpcore" -version = "0.15.0" +version = "0.17.3" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.7" files = [ - {file = "httpcore-0.15.0-py3-none-any.whl", hash = "sha256:1105b8b73c025f23ff7c36468e4432226cbb959176eab66864b8e31c4ee27fa6"}, - {file = "httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"}, + {file = "httpcore-0.17.3-py3-none-any.whl", hash = "sha256:c2789b767ddddfa2a5782e3199b2b7f6894540b17b16ec26b2c4d8e103510b87"}, + {file = "httpcore-0.17.3.tar.gz", hash = "sha256:a6f30213335e34c1ade7be6ec7c47f19f50c56db36abef1a9dfa3815b1cb3888"}, ] [package.dependencies] -anyio = "==3.*" +anyio = ">=3.0,<5.0" certifi = "*" -h11 = ">=0.11,<0.13" +h11 = ">=0.13,<0.15" sniffio = "==1.*" [package.extras] @@ -316,13 +398,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "httpx" -version = "0.24.0" +version = "0.24.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.7" files = [ - {file = "httpx-0.24.0-py3-none-any.whl", hash = "sha256:447556b50c1921c351ea54b4fe79d91b724ed2b027462ab9a329465d147d5a4e"}, - {file = "httpx-0.24.0.tar.gz", hash = "sha256:507d676fc3e26110d41df7d35ebd8b3b8585052450f4097401c9be59d928c63e"}, + {file = "httpx-0.24.1-py3-none-any.whl", hash = "sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd"}, + {file = "httpx-0.24.1.tar.gz", hash = "sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd"}, ] [package.dependencies] @@ -339,52 +421,52 @@ socks = ["socksio (==1.*)"] [[package]] name = "idna" -version = "3.2" +version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"}, - {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"}, + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] [[package]] name = "isort" -version = "5.10.1" +version = "5.12.0" description = "A Python utility / library to sort Python imports." optional = false -python-versions = ">=3.6.1,<4.0" +python-versions = ">=3.8.0" files = [ - {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, - {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, ] [package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] plugins = ["setuptools"] requirements-deprecated-finder = ["pip-api", "pipreqs"] [[package]] name = "jinja2" -version = "3.0.1" +version = "3.1.2" description = "A very fast and expressive template engine." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"}, - {file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"}, + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, ] [package.dependencies] @@ -395,122 +477,117 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "lazy-object-proxy" -version = "1.6.0" +version = "1.9.0" description = "A fast and thorough lazy object proxy." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7" files = [ - {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"}, - {file = "lazy_object_proxy-1.6.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b"}, - {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win32.whl", hash = "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e"}, - {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93"}, - {file = "lazy_object_proxy-1.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741"}, - {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587"}, - {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4"}, - {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f"}, - {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3"}, - {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981"}, - {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2"}, - {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd"}, - {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837"}, - {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653"}, - {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3"}, - {file = "lazy_object_proxy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8"}, - {file = "lazy_object_proxy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"}, + {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, ] [[package]] name = "markupsafe" -version = "2.0.1" +version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {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"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] [[package]] name = "mccabe" -version = "0.6.1" +version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] [[package]] @@ -526,51 +603,59 @@ files = [ [[package]] name = "mypy" -version = "0.931" +version = "1.4.1" description = "Optional static typing for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "mypy-0.931-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c5b42d0815e15518b1f0990cff7a705805961613e701db60387e6fb663fe78a"}, - {file = "mypy-0.931-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c89702cac5b302f0c5d33b172d2b55b5df2bede3344a2fbed99ff96bddb2cf00"}, - {file = "mypy-0.931-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:300717a07ad09525401a508ef5d105e6b56646f7942eb92715a1c8d610149714"}, - {file = "mypy-0.931-cp310-cp310-win_amd64.whl", hash = "sha256:7b3f6f557ba4afc7f2ce6d3215d5db279bcf120b3cfd0add20a5d4f4abdae5bc"}, - {file = "mypy-0.931-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1bf752559797c897cdd2c65f7b60c2b6969ffe458417b8d947b8340cc9cec08d"}, - {file = "mypy-0.931-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4365c60266b95a3f216a3047f1d8e3f895da6c7402e9e1ddfab96393122cc58d"}, - {file = "mypy-0.931-cp36-cp36m-win_amd64.whl", hash = "sha256:1b65714dc296a7991000b6ee59a35b3f550e0073411ac9d3202f6516621ba66c"}, - {file = "mypy-0.931-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e839191b8da5b4e5d805f940537efcaa13ea5dd98418f06dc585d2891d228cf0"}, - {file = "mypy-0.931-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:50c7346a46dc76a4ed88f3277d4959de8a2bd0a0fa47fa87a4cde36fe247ac05"}, - {file = "mypy-0.931-cp37-cp37m-win_amd64.whl", hash = "sha256:d8f1ff62f7a879c9fe5917b3f9eb93a79b78aad47b533911b853a757223f72e7"}, - {file = "mypy-0.931-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9fe20d0872b26c4bba1c1be02c5340de1019530302cf2dcc85c7f9fc3252ae0"}, - {file = "mypy-0.931-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1b06268df7eb53a8feea99cbfff77a6e2b205e70bf31743e786678ef87ee8069"}, - {file = "mypy-0.931-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8c11003aaeaf7cc2d0f1bc101c1cc9454ec4cc9cb825aef3cafff8a5fdf4c799"}, - {file = "mypy-0.931-cp38-cp38-win_amd64.whl", hash = "sha256:d9d2b84b2007cea426e327d2483238f040c49405a6bf4074f605f0156c91a47a"}, - {file = "mypy-0.931-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ff3bf387c14c805ab1388185dd22d6b210824e164d4bb324b195ff34e322d166"}, - {file = "mypy-0.931-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b56154f8c09427bae082b32275a21f500b24d93c88d69a5e82f3978018a0266"}, - {file = "mypy-0.931-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ca7f8c4b1584d63c9a0f827c37ba7a47226c19a23a753d52e5b5eddb201afcd"}, - {file = "mypy-0.931-cp39-cp39-win_amd64.whl", hash = "sha256:74f7eccbfd436abe9c352ad9fb65872cc0f1f0a868e9d9c44db0893440f0c697"}, - {file = "mypy-0.931-py3-none-any.whl", hash = "sha256:1171f2e0859cfff2d366da2c7092b06130f232c636a3f7301e3feb8b41f6377d"}, - {file = "mypy-0.931.tar.gz", hash = "sha256:0038b21890867793581e4cb0d810829f5fd4441aa75796b53033af3aa30430ce"}, + {file = "mypy-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8"}, + {file = "mypy-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878"}, + {file = "mypy-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd"}, + {file = "mypy-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc"}, + {file = "mypy-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1"}, + {file = "mypy-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462"}, + {file = "mypy-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258"}, + {file = "mypy-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2"}, + {file = "mypy-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7"}, + {file = "mypy-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01"}, + {file = "mypy-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b"}, + {file = "mypy-1.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b"}, + {file = "mypy-1.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7"}, + {file = "mypy-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9"}, + {file = "mypy-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042"}, + {file = "mypy-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3"}, + {file = "mypy-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6"}, + {file = "mypy-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f"}, + {file = "mypy-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc"}, + {file = "mypy-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828"}, + {file = "mypy-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3"}, + {file = "mypy-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816"}, + {file = "mypy-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c"}, + {file = "mypy-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f"}, + {file = "mypy-1.4.1-py3-none-any.whl", hash = "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4"}, + {file = "mypy-1.4.1.tar.gz", hash = "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b"}, ] [package.dependencies] -mypy-extensions = ">=0.4.3" -tomli = ">=1.1.0" -typing-extensions = ">=3.10" +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" [package.extras] dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] python2 = ["typed-ast (>=1.4.0,<2)"] +reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {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"}, + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] @@ -586,131 +671,118 @@ files = [ [[package]] name = "pathspec" -version = "0.9.0" +version = "0.11.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" files = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, + {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, + {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, ] [[package]] name = "platformdirs" -version = "2.2.0" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "3.8.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "platformdirs-2.2.0-py3-none-any.whl", hash = "sha256:4666d822218db6a262bdfdc9c39d21f23b4cfdb08af331a81e92751daf6c866c"}, - {file = "platformdirs-2.2.0.tar.gz", hash = "sha256:632daad3ab546bd8e6af0537d09805cec458dce201bccfe23012df73332e181e"}, + {file = "platformdirs-3.8.0-py3-none-any.whl", hash = "sha256:ca9ed98ce73076ba72e092b23d3c93ea6c4e186b3f1c3dad6edd98ff6ffcca2e"}, + {file = "platformdirs-3.8.0.tar.gz", hash = "sha256:b0cabcb11063d21a0b261d557acb0a9d2126350e63b70cdf7db6347baea456dc"}, ] [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 (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" -version = "0.13.1" +version = "1.2.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.7" files = [ - {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, - {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, + {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, + {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, ] [package.extras] dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "psutil" -version = "5.8.0" +version = "5.9.5" description = "Cross-platform lib for process and system monitoring in Python." optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"}, - {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c"}, - {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df"}, - {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131"}, - {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60"}, - {file = "psutil-5.8.0-cp27-none-win32.whl", hash = "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876"}, - {file = "psutil-5.8.0-cp27-none-win_amd64.whl", hash = "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65"}, - {file = "psutil-5.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8"}, - {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6"}, - {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac"}, - {file = "psutil-5.8.0-cp36-cp36m-win32.whl", hash = "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2"}, - {file = "psutil-5.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d"}, - {file = "psutil-5.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935"}, - {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d"}, - {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023"}, - {file = "psutil-5.8.0-cp37-cp37m-win32.whl", hash = "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394"}, - {file = "psutil-5.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563"}, - {file = "psutil-5.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef"}, - {file = "psutil-5.8.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28"}, - {file = "psutil-5.8.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b"}, - {file = "psutil-5.8.0-cp38-cp38-win32.whl", hash = "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d"}, - {file = "psutil-5.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d"}, - {file = "psutil-5.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7"}, - {file = "psutil-5.8.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4"}, - {file = "psutil-5.8.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b"}, - {file = "psutil-5.8.0-cp39-cp39-win32.whl", hash = "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0"}, - {file = "psutil-5.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3"}, - {file = "psutil-5.8.0.tar.gz", hash = "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6"}, + {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, + {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, + {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, + {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, + {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, + {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, + {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, + {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, ] [package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "unittest2", "wmi"] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] [[package]] name = "pydantic" -version = "1.10.2" +version = "1.10.11" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"}, - {file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"}, - {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"}, - {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"}, - {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"}, - {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"}, - {file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"}, - {file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"}, - {file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"}, - {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"}, - {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"}, - {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"}, - {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"}, - {file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"}, - {file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"}, - {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"}, - {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"}, - {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"}, - {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"}, - {file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"}, - {file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"}, - {file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"}, - {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"}, - {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"}, - {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"}, - {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"}, - {file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"}, - {file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"}, - {file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"}, - {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"}, - {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"}, - {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"}, - {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"}, - {file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"}, - {file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"}, - {file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"}, + {file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"}, + {file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"}, + {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"}, + {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"}, + {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"}, + {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"}, + {file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"}, + {file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"}, + {file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"}, + {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"}, + {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"}, + {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"}, + {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"}, + {file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"}, + {file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"}, + {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"}, + {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"}, + {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"}, + {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"}, + {file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"}, + {file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"}, + {file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"}, + {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"}, + {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"}, + {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"}, + {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"}, + {file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"}, + {file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"}, + {file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"}, + {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"}, + {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"}, + {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"}, + {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"}, + {file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"}, + {file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"}, + {file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"}, ] [package.dependencies] -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.2.0" [package.extras] dotenv = ["python-dotenv (>=0.10.4)"] @@ -729,19 +801,22 @@ files = [ [[package]] name = "pylint" -version = "2.15.7" +version = "2.17.4" description = "python code static checker" optional = false python-versions = ">=3.7.2" files = [ - {file = "pylint-2.15.7-py3-none-any.whl", hash = "sha256:1d561d1d3e8be9dd880edc685162fbdaa0409c88b9b7400873c0cf345602e326"}, - {file = "pylint-2.15.7.tar.gz", hash = "sha256:91e4776dbcb4b4d921a3e4b6fec669551107ba11f29d9199154a01622e460a57"}, + {file = "pylint-2.17.4-py3-none-any.whl", hash = "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"}, + {file = "pylint-2.17.4.tar.gz", hash = "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1"}, ] [package.dependencies] -astroid = ">=2.12.13,<=2.14.0-dev0" +astroid = ">=2.15.4,<=2.17.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = ">=0.2" +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, +] isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" @@ -755,17 +830,16 @@ testutils = ["gitpython (>3)"] [[package]] name = "pytest" -version = "7.2.0" +version = "7.4.0" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, + {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, + {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, ] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" @@ -774,17 +848,17 @@ pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" -version = "4.0.0" +version = "4.1.0" description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, - {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, ] [package.dependencies] @@ -796,13 +870,13 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pytest-mock" -version = "3.6.1" +version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "pytest-mock-3.6.1.tar.gz", hash = "sha256:40217a058c52a63f1042f0784f62009e976ba824c418cced42e88d5f40ab0e62"}, - {file = "pytest_mock-3.6.1-py3-none-any.whl", hash = "sha256:30c2f2cc9759e76eee674b81ea28c9f0b94f8f0445a1b87762cadf774f0df7e3"}, + {file = "pytest-mock-3.11.1.tar.gz", hash = "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f"}, + {file = "pytest_mock-3.11.1-py3-none-any.whl", hash = "sha256:21c279fff83d70763b05f8874cc9cfb3fcacd6d354247a976f9529d19f9acf39"}, ] [package.dependencies] @@ -827,16 +901,17 @@ six = ">=1.5" [[package]] name = "python-multipart" -version = "0.0.5" +version = "0.0.6" description = "A streaming multipart parser for Python" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, + {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, + {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, ] -[package.dependencies] -six = ">=1.4.0" +[package.extras] +dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] [[package]] name = "pyyaml" @@ -909,48 +984,117 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] -name = "safety" -version = "1.10.3" -description = "Checks installed dependencies for known vulnerabilities." +name = "ruamel-yaml" +version = "0.17.32" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +optional = false +python-versions = ">=3" +files = [ + {file = "ruamel.yaml-0.17.32-py3-none-any.whl", hash = "sha256:23cd2ed620231677564646b0c6a89d138b6822a0d78656df7abda5879ec4f447"}, + {file = "ruamel.yaml-0.17.32.tar.gz", hash = "sha256:ec939063761914e14542972a5cba6d33c23b0859ab6342f61cf070cfc600efc2"}, +] + +[package.dependencies] +"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.12\""} + +[package.extras] +docs = ["ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.7" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" optional = false python-versions = ">=3.5" files = [ - {file = "safety-1.10.3-py2.py3-none-any.whl", hash = "sha256:5f802ad5df5614f9622d8d71fedec2757099705c2356f862847c58c6dfe13e84"}, - {file = "safety-1.10.3.tar.gz", hash = "sha256:30e394d02a20ac49b7f65292d19d38fa927a8f9582cdfd3ad1adbbc66c641ad5"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"}, + {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, +] + +[[package]] +name = "safety" +version = "2.3.4" +description = "Checks installed dependencies for known vulnerabilities and licenses." +optional = false +python-versions = "*" +files = [ + {file = "safety-2.3.4-py3-none-any.whl", hash = "sha256:6224dcd9b20986a2b2c5e7acfdfba6bca42bb11b2783b24ed04f32317e5167ea"}, + {file = "safety-2.3.4.tar.gz", hash = "sha256:b9e74e794e82f54d11f4091c5d820c4d2d81de9f953bf0b4f33ac8bc402ae72c"}, ] [package.dependencies] -Click = ">=6.0" -dparse = ">=0.5.1" -packaging = "*" +Click = ">=8.0.2" +dparse = ">=0.6.2" +packaging = ">=21.0" requests = "*" -setuptools = "*" +"ruamel.yaml" = ">=0.17.21" +setuptools = ">=19.3" + +[package.extras] +github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"] +gitlab = ["python-gitlab (>=1.3.0)"] [[package]] name = "setuptools" -version = "65.5.1" +version = "68.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.7" files = [ - {file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"}, - {file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"}, + {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"}, + {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shellingham" -version = "1.4.0" +version = "1.5.0.post1" description = "Tool to Detect Surrounding Shell" optional = false -python-versions = "!=3.0,!=3.1,!=3.2,!=3.3,>=2.6" +python-versions = ">=3.7" files = [ - {file = "shellingham-1.4.0-py2.py3-none-any.whl", hash = "sha256:536b67a0697f2e4af32ab176c00a50ac2899c5a05e0d8e2dadac8e58888283f9"}, - {file = "shellingham-1.4.0.tar.gz", hash = "sha256:4855c2458d6904829bd34c299f11fdeed7cfefbf8a2c522e4caea6cd76b3171e"}, + {file = "shellingham-1.5.0.post1-py2.py3-none-any.whl", hash = "sha256:368bf8c00754fd4f55afb7bbb86e272df77e4dc76ac29dbcbb81a59e9fc15744"}, + {file = "shellingham-1.5.0.post1.tar.gz", hash = "sha256:823bc5fb5c34d60f285b624e7264f4dda254bc803a3774a147bf99c0e3004a28"}, ] [[package]] @@ -966,42 +1110,31 @@ files = [ [[package]] name = "sniffio" -version = "1.2.0" +version = "1.3.0" description = "Sniff out which async library your code is running under" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" files = [ - {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, - {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, ] [[package]] name = "taskipy" -version = "1.8.1" +version = "1.11.0" description = "tasks runner for python projects" optional = false python-versions = ">=3.6,<4.0" files = [ - {file = "taskipy-1.8.1-py3-none-any.whl", hash = "sha256:2b98f499966e40175d1f1306a64587f49dfa41b90d0d86c8f28b067cc58d0a56"}, - {file = "taskipy-1.8.1.tar.gz", hash = "sha256:7a2404125817e45d80e13fa663cae35da6e8ba590230094e815633653e25f98f"}, + {file = "taskipy-1.11.0-py3-none-any.whl", hash = "sha256:4e40cd41747a54bc8a9b3c21057c25cac645309c2d8ac897bdc1e7235e9c900e"}, + {file = "taskipy-1.11.0.tar.gz", hash = "sha256:521e8b3b65dc1ff9bb036cae989dbe5aec1626a61cf4744e5c0d0d2450c7fcb4"}, ] [package.dependencies] colorama = ">=0.4.4,<0.5.0" -mslex = ">=0.3.0,<0.4.0" +mslex = {version = ">=0.3.0,<0.4.0", markers = "sys_platform == \"win32\""} psutil = ">=5.7.2,<6.0.0" -toml = ">=0.10.0,<0.11.0" - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] +tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version >= \"3.7\" and python_version < \"4.0\""} [[package]] name = "tomli" @@ -1016,13 +1149,13 @@ files = [ [[package]] name = "tomlkit" -version = "0.11.6" +version = "0.11.8" description = "Style preserving TOML library" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"}, - {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"}, + {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, + {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, ] [[package]] @@ -1059,52 +1192,53 @@ files = [ [[package]] name = "types-python-dateutil" -version = "2.8.0" +version = "2.8.19.13" description = "Typing stubs for python-dateutil" optional = false python-versions = "*" files = [ - {file = "types-python-dateutil-2.8.0.tar.gz", hash = "sha256:540c6c53c3a52433d7088254e3afdc3f6c86b5ae452aaa1b796c26d01c9fd73c"}, - {file = "types_python_dateutil-2.8.0-py3-none-any.whl", hash = "sha256:9954d87dc982344bb2aad73a7fe505bdca72f89088ef653c4c40f52649183437"}, + {file = "types-python-dateutil-2.8.19.13.tar.gz", hash = "sha256:09a0275f95ee31ce68196710ed2c3d1b9dc42e0b61cc43acc369a42cb939134f"}, + {file = "types_python_dateutil-2.8.19.13-py3-none-any.whl", hash = "sha256:0b0e7c68e7043b0354b26a1e0225cb1baea7abb1b324d02b50e2d08f1221043f"}, ] [[package]] name = "types-pyyaml" -version = "6.0.3" +version = "6.0.12.10" description = "Typing stubs for PyYAML" optional = false python-versions = "*" files = [ - {file = "types-PyYAML-6.0.3.tar.gz", hash = "sha256:6ea4eefa8579e0ce022f785a62de2bcd647fad4a81df5cf946fd67e4b059920b"}, - {file = "types_PyYAML-6.0.3-py3-none-any.whl", hash = "sha256:8b50294b55a9db89498cdc5a65b1b4545112b6cd1cf4465bd693d828b0282a17"}, + {file = "types-PyYAML-6.0.12.10.tar.gz", hash = "sha256:ebab3d0700b946553724ae6ca636ea932c1b0868701d4af121630e78d695fc97"}, + {file = "types_PyYAML-6.0.12.10-py3-none-any.whl", hash = "sha256:662fa444963eff9b68120d70cda1af5a5f2aa57900003c2006d7626450eaae5f"}, ] [[package]] name = "typing-extensions" -version = "4.3.0" +version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, - {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, ] [[package]] name = "urllib3" -version = "1.26.6" +version = "2.0.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +python-versions = ">=3.7" files = [ - {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"}, - {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, + {file = "urllib3-2.0.3-py3-none-any.whl", hash = "sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"}, + {file = "urllib3-2.0.3.tar.gz", hash = "sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"}, ] [package.extras] -brotli = ["brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "wrapt" @@ -1193,4 +1327,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "c770684b87ee96fafeb7000141019738a6153422d50661b3f23efee6fc3c6a09" +content-hash = "5b48e9918876e2f6346ccc4d606e67c05127a24ca31b4a815e6ff22a0ef273bb" diff --git a/pyproject.toml b/pyproject.toml index 2c962d3fa..82e9e5ab7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ isort = "^5.0.5" pydantic = "^1.6.1" attrs = ">=21.3.0" python-dateutil = "^2.8.1" -httpx = ">=0.15.4,<0.25.0" +httpx = ">=0.20.0,<0.25.0" autoflake = "^1.4 || ^2.0.0" PyYAML = "^6.0" diff --git a/tests/test_parser/test_openapi.py b/tests/test_parser/test_openapi.py index 8ef6b0a6a..5567c4342 100644 --- a/tests/test_parser/test_openapi.py +++ b/tests/test_parser/test_openapi.py @@ -44,6 +44,7 @@ def test_from_dict(self, mocker, model_property_factory, enum_property_factory): build_parameters.assert_called_once_with( components=openapi.components.parameters, parameters=parameters, + config=config, ) EndpointCollection.from_data.assert_called_once_with( data=openapi.paths, diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 85ffe8570..729a73c38 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -1380,7 +1380,8 @@ def test_skips_references_and_keeps_going(self, mocker): update_parameters_with_data = mocker.patch(f"{MODULE_NAME}.update_parameters_with_data") parse_reference_path = mocker.patch(f"{MODULE_NAME}.parse_reference_path") - result = build_parameters(components=parameters, parameters=Parameters()) + config = Config() + result = build_parameters(components=parameters, parameters=Parameters(), config=Config()) # Should not even try to parse a path for the Reference parse_reference_path.assert_called_once_with("#/components/parameters/defined") update_parameters_with_data.assert_called_once_with( @@ -1389,6 +1390,7 @@ def test_skips_references_and_keeps_going(self, mocker): parameters=Parameters( errors=[ParameterError(detail="Reference parameters are not supported.", data=parameters["reference"])] ), + config=config, ) assert result == update_parameters_with_data.return_value @@ -1402,7 +1404,8 @@ def test_records_bad_uris_and_keeps_going(self, mocker): f"{MODULE_NAME}.parse_reference_path", side_effect=[ParameterError(detail="some details"), "a_path"] ) - result = build_parameters(components=parameters, parameters=Parameters()) + config = Config() + result = build_parameters(components=parameters, parameters=Parameters(), config=config) parse_reference_path.assert_has_calls( [ call("#/components/parameters/first"), @@ -1413,6 +1416,7 @@ def test_records_bad_uris_and_keeps_going(self, mocker): ref_path="a_path", data=parameters["second"], parameters=Parameters(errors=[ParameterError(detail="some details", data=parameters["first"])]), + config=config, ) assert result == update_parameters_with_data.return_value @@ -1426,7 +1430,8 @@ def test_retries_failing_parameters_while_making_progress(self, mocker): ) parse_reference_path = mocker.patch(f"{MODULE_NAME}.parse_reference_path") - result = build_parameters(components=parameters, parameters=Parameters()) + config = Config() + result = build_parameters(components=parameters, parameters=Parameters(), config=config) parse_reference_path.assert_has_calls( [ call("#/components/parameters/first"), diff --git a/tests/test_parser/test_properties/test_schemas.py b/tests/test_parser/test_properties/test_schemas.py index 13e23fe1f..229663e08 100644 --- a/tests/test_parser/test_properties/test_schemas.py +++ b/tests/test_parser/test_properties/test_schemas.py @@ -1,9 +1,11 @@ import pytest +from openapi_python_client import Config from openapi_python_client.parser.errors import ParameterError from openapi_python_client.parser.properties import Class, Parameters from openapi_python_client.parser.properties.schemas import parameter_from_reference from openapi_python_client.schema import Parameter, Reference +from openapi_python_client.utils import ClassName MODULE_NAME = "openapi_python_client.parser.properties.schemas" @@ -48,18 +50,24 @@ def test_cannot_parse_parameters_by_reference(self): ref = Reference.construct(ref="#/components/parameters/a_param") parameters = Parameters() - param_or_error, new_parameters = parameter_from_data(name="a_param", data=ref, parameters=parameters) + config = Config() + param_or_error, new_parameters = parameter_from_data( + name="a_param", data=ref, parameters=parameters, config=config + ) assert param_or_error == ParameterError("Unable to resolve another reference") assert new_parameters == parameters def test_parameters_without_schema_are_ignored(self): from openapi_python_client.parser.properties import Parameters from openapi_python_client.parser.properties.schemas import parameter_from_data - from openapi_python_client.schema import ParameterLocation, Schema + from openapi_python_client.schema import ParameterLocation param = Parameter(name="a_schemaless_param", param_in=ParameterLocation.QUERY) parameters = Parameters() - param_or_error, new_parameters = parameter_from_data(name=param.name, data=param, parameters=parameters) + config = Config() + param_or_error, new_parameters = parameter_from_data( + name=param.name, data=param, parameters=parameters, config=config + ) assert param_or_error == ParameterError("Parameter has no schema") assert new_parameters == parameters @@ -70,9 +78,12 @@ def test_registers_new_parameters(self): param = Parameter.construct(name="a_param", param_in=ParameterLocation.QUERY, param_schema=Schema.construct()) parameters = Parameters() - param_or_error, new_parameters = parameter_from_data(name=param.name, data=param, parameters=parameters) + config = Config() + param_or_error, new_parameters = parameter_from_data( + name=param.name, data=param, parameters=parameters, config=config + ) assert param_or_error == param - assert new_parameters.classes_by_name[param.name] == param + assert new_parameters.classes_by_name[ClassName(param.name, prefix=config.field_prefix)] == param class TestParameterFromReference: @@ -119,7 +130,10 @@ def test_reports_parameters_with_errors(self, mocker): f"{MODULE_NAME}.parameter_from_data", side_effect=[(ParameterError(), parameters)] ) ref_path = Reference.construct(ref="#/components/parameters/a_param") - new_parameters_or_error = update_parameters_with_data(ref_path=ref_path.ref, data=param, parameters=parameters) + config = Config() + new_parameters_or_error = update_parameters_with_data( + ref_path=ref_path.ref, data=param, parameters=parameters, config=config + ) parameter_from_data.assert_called_once() assert new_parameters_or_error == ParameterError( @@ -135,7 +149,10 @@ def test_records_references_to_parameters(self, mocker): param = Parameter.construct(name="a_param", param_in=ParameterLocation.QUERY, param_schema=Schema.construct()) parameter_from_data = mocker.patch(f"{MODULE_NAME}.parameter_from_data", side_effect=[(param, parameters)]) ref_path = "#/components/parameters/a_param" - new_parameters = update_parameters_with_data(ref_path=ref_path, data=param, parameters=parameters) + config = Config() + new_parameters = update_parameters_with_data( + ref_path=ref_path, data=param, parameters=parameters, config=config + ) parameter_from_data.assert_called_once() assert new_parameters.classes_by_reference[ref_path] == param From 7c411c5749b720ef5d7ce8b347de471f263b087a Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Fri, 7 Jul 2023 14:47:09 -0600 Subject: [PATCH 14/18] More release dry runs and prerelease action --- .github/renovate.json | 3 ++- .github/workflows/prerelease.yml | 37 +++++++++++++++++++++++++++ .github/workflows/release-dry-run.yml | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/prerelease.yml diff --git a/.github/renovate.json b/.github/renovate.json index 6022fecdc..33c146b34 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -7,7 +7,8 @@ "regexManagers": [ { "fileMatch": [ - "release.*\\.yml" + "release.*\\.yml", + "prerelease.yml" ], "matchStrings": [ "version:\\s*(?.*)" diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml new file mode 100644 index 000000000..f191fef40 --- /dev/null +++ b/.github/workflows/prerelease.yml @@ -0,0 +1,37 @@ +name: Prerelease + +on: + workflow_dispatch: + inputs: + label: + description: 'Prerelease label for the release' + required: true + +jobs: + create-release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: ${{ secrets.PAT }} + - uses: Swatinem/rust-cache@v2 + - name: Import GPG key + uses: crazy-max/ghaction-import-gpg@v5 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + git_user_signingkey: true + git_commit_gpgsign: true + git_push_gpgsign: false + - name: Install Knope + uses: knope-dev/action@v1 + with: + version: 0.8.0 + - name: Bump Version & Create GitHub Release + run: knope release --prerelease-label="${{ github.event.inputs.label }}" + env: + GITHUB_TOKEN: ${{ secrets.PAT }} + - name: Install Poetry + run: pip install --upgrade poetry + - name: Push to PyPI + run: poetry publish --build -u __token__ -p ${{ secrets.PYPI_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release-dry-run.yml b/.github/workflows/release-dry-run.yml index 1809ecb81..3ab59cc14 100644 --- a/.github/workflows/release-dry-run.yml +++ b/.github/workflows/release-dry-run.yml @@ -4,7 +4,7 @@ on: push: branches: - main - + pull_request: jobs: release: runs-on: ubuntu-latest From 8cab8e0f34a8be3fd02e88abfe361d29f91ba2aa Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Fri, 7 Jul 2023 14:49:55 -0600 Subject: [PATCH 15/18] Put back missing tabs --- openapi_python_client/templates/README.md.jinja | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openapi_python_client/templates/README.md.jinja b/openapi_python_client/templates/README.md.jinja index 7958d60c3..ea31c83d7 100644 --- a/openapi_python_client/templates/README.md.jinja +++ b/openapi_python_client/templates/README.md.jinja @@ -65,10 +65,10 @@ client = AuthenticatedClient( Things to know: 1. Every path/method combo becomes a Python module with four functions: -1. `sync`: Blocking request that returns parsed data (if successful) or `None` -1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. -1. `asyncio`: Like `sync` but async instead of blocking -1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking + 1. `sync`: Blocking request that returns parsed data (if successful) or `None` + 1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. + 1. `asyncio`: Like `sync` but async instead of blocking + 1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking 1. All path/query params, and bodies become method arguments. 1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above) From ea0f53a226d37d51aacb42d43cfd3604f4b1f2df Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Fri, 7 Jul 2023 14:50:49 -0600 Subject: [PATCH 16/18] Put back missing tabs --- end_to_end_tests/golden-record/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/end_to_end_tests/golden-record/README.md b/end_to_end_tests/golden-record/README.md index 18fb1117d..79b20f411 100644 --- a/end_to_end_tests/golden-record/README.md +++ b/end_to_end_tests/golden-record/README.md @@ -65,10 +65,10 @@ client = AuthenticatedClient( Things to know: 1. Every path/method combo becomes a Python module with four functions: -1. `sync`: Blocking request that returns parsed data (if successful) or `None` -1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. -1. `asyncio`: Like `sync` but async instead of blocking -1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking + 1. `sync`: Blocking request that returns parsed data (if successful) or `None` + 1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. + 1. `asyncio`: Like `sync` but async instead of blocking + 1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking 1. All path/query params, and bodies become method arguments. 1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above) From e5e4cd5526207379ee8aff4aa2079ade2dc9d359 Mon Sep 17 00:00:00 2001 From: Dylan Anthony <43723790+dbanty@users.noreply.github.com> Date: Fri, 7 Jul 2023 15:24:04 -0600 Subject: [PATCH 17/18] Update end_to_end_tests/golden-record/my_test_api_client/client.py Co-authored-by: Ethan Mann --- end_to_end_tests/golden-record/my_test_api_client/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/end_to_end_tests/golden-record/my_test_api_client/client.py b/end_to_end_tests/golden-record/my_test_api_client/client.py index 74b476ca8..a90d743e1 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/client.py +++ b/end_to_end_tests/golden-record/my_test_api_client/client.py @@ -70,7 +70,7 @@ def with_timeout(self, timeout: httpx.Timeout) -> "Client": return evolve(self, timeout=timeout) def set_httpx_client(self, client: httpx.Client) -> "Client": - """Manually the underlying httpx.Client + """Manually set the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. """ From 88b425990f31b8cd37513f89e93cd0686118bee4 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Fri, 7 Jul 2023 16:53:23 -0600 Subject: [PATCH 18/18] Regen --- end_to_end_tests/golden-record/my_test_api_client/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/end_to_end_tests/golden-record/my_test_api_client/client.py b/end_to_end_tests/golden-record/my_test_api_client/client.py index a90d743e1..74b476ca8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/client.py +++ b/end_to_end_tests/golden-record/my_test_api_client/client.py @@ -70,7 +70,7 @@ def with_timeout(self, timeout: httpx.Timeout) -> "Client": return evolve(self, timeout=timeout) def set_httpx_client(self, client: httpx.Client) -> "Client": - """Manually set the underlying httpx.Client + """Manually the underlying httpx.Client **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. """