From 1eba6237b7896f1b69b464ea95f40c1356c0c48b Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Mon, 14 Feb 2022 17:23:40 +0000 Subject: [PATCH 01/13] Replace requests-oauthlib with requests-auth - Switch session creation - Update some tests (2 are failing) --- poetry.lock | 110 ++++++++++------------- pyproject.toml | 6 +- src/ansys/openapi/common/_oidc.py | 129 ++++++++------------------- src/ansys/openapi/common/_session.py | 10 +-- tests/test_oidc.py | 24 ++--- tests/test_session_creation.py | 2 +- 6 files changed, 105 insertions(+), 176 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5790293e..2caca695 100644 --- a/poetry.lock +++ b/poetry.lock @@ -37,11 +37,11 @@ gssapi = ">=1.7.0" [[package]] name = "asgiref" -version = "3.4.1" +version = "3.5.0" description = "ASGI specs, helper code, and adapters" category = "main" optional = true -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] typing-extensions = {version = "*", markers = "python_version < \"3.8\""} @@ -118,7 +118,7 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "2.0.10" +version = "2.0.12" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false @@ -235,12 +235,15 @@ decorator = "*" [[package]] name = "h11" -version = "0.12.0" +version = "0.13.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" category = "main" optional = true python-versions = ">=3.6" +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + [[package]] name = "idna" version = "3.3" @@ -259,7 +262,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" -version = "4.10.1" +version = "4.11.0" description = "Read metadata from Python packages" category = "main" optional = false @@ -368,19 +371,6 @@ sphinx = ">=1.8" [package.extras] testing = ["pytest", "pytest-cov", "matplotlib"] -[[package]] -name = "oauthlib" -version = "3.1.1" -description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -category = "main" -optional = true -python-versions = ">=3.6" - -[package.extras] -rsa = ["cryptography (>=3.0.0,<4)"] -signals = ["blinker (>=1.4.0)"] -signedtoken = ["cryptography (>=3.0.0,<4)", "pyjwt (>=2.0.0,<3)"] - [[package]] name = "packaging" version = "21.3" @@ -516,7 +506,7 @@ yaml = ["ruamel.yaml"] [[package]] name = "pytest" -version = "7.0.0" +version = "7.0.1" description = "pytest: simple powerful testing with Python" category = "main" optional = true @@ -618,6 +608,20 @@ urllib3 = ">=1.21.1,<1.27" socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] +[[package]] +name = "requests-auth" +version = "6.0.0" +description = "Authentication for Requests" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +requests = ">=2.0.0,<3.0.0" + +[package.extras] +testing = ["pyjwt (>=2.0.0,<3.0.0)", "pytest-responses (>=0.5.0,<0.6.0)", "pytest-cov (>=3.0.0,<4.0.0)"] + [[package]] name = "requests-kerberos" version = "0.13.0" @@ -675,21 +679,6 @@ cryptography = ">=1.3" ntlm-auth = ">=1.0.2" requests = ">=2.0.0" -[[package]] -name = "requests-oauthlib" -version = "1.3.1" -description = "OAuthlib authentication support for Requests." -category = "main" -optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -oauthlib = ">=3.0.0" -requests = ">=2.0.0" - -[package.extras] -rsa = ["oauthlib[signedtoken] (>=3.0.0)"] - [[package]] name = "secretstorage" version = "3.3.1" @@ -891,7 +880,7 @@ full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] [[package]] name = "tomli" -version = "2.0.0" +version = "2.0.1" description = "A lil' TOML parser" category = "main" optional = true @@ -899,11 +888,11 @@ python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "3.10.0.2" -description = "Backported and Experimental Type Hints for Python 3.5+" +version = "4.1.1" +description = "Backported and Experimental Type Hints for Python 3.6+" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "urllib3" @@ -950,13 +939,13 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [extras] doc = ["pyansys-sphinx-theme", "numpydoc", "sphinx", "sphinx_autodoc_typehints", "sphinx-notfound-page", "sphinx-copybutton"] linux-kerberos = ["requests-kerberos"] -oidc = ["requests_oauthlib", "keyring"] +oidc = ["requests_auth", "keyring"] test = ["pytest", "pytest-cov", "uvicorn", "fastapi", "pydantic", "requests-mock", "pytest-mock", "covertable", "asgi_gssapi"] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "6189005c8721d37e31a16bfd4a66f2665df26d791164a7a78598d5cd4a105a8b" +content-hash = "5e4aef7fa292176483bbc493b7332646ba56aea2bc46251190a184344834f7a6" [metadata.files] alabaster = [ @@ -972,8 +961,8 @@ asgi-gssapi = [ {file = "ASGI_GSSAPI-0.1.1-py3-none-any.whl", hash = "sha256:adea2ed92f26d303f9fc59b296d56009deac19fcbf959c6bfe10316ee76da32a"}, ] asgiref = [ - {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, - {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, + {file = "asgiref-3.5.0-py3-none-any.whl", hash = "sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"}, + {file = "asgiref-3.5.0.tar.gz", hash = "sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0"}, ] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, @@ -1048,8 +1037,8 @@ cffi = [ {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"}, - {file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"}, + {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, + {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, ] click = [ {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, @@ -1162,8 +1151,8 @@ gssapi = [ {file = "gssapi-1.7.2.tar.gz", hash = "sha256:748efbcf7cfb31183cd75e5314493e79fe3521b3ec00d090a77e23f7c75fa59d"}, ] h11 = [ - {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.13.0-py3-none-any.whl", hash = "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"}, + {file = "h11-0.13.0.tar.gz", hash = "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06"}, ] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, @@ -1174,8 +1163,8 @@ imagesize = [ {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.10.1-py3-none-any.whl", hash = "sha256:899e2a40a8c4a1aec681feef45733de8a6c58f3f6a0dbed2eb6574b4387a77b6"}, - {file = "importlib_metadata-4.10.1.tar.gz", hash = "sha256:951f0d8a5b7260e9db5e41d429285b5f451e928479f19d80818878527d36e95e"}, + {file = "importlib_metadata-4.11.0-py3-none-any.whl", hash = "sha256:6affcdb3aec542dd98df8211e730bba6c5f2bec8288d47bacacde898f548c9ad"}, + {file = "importlib_metadata-4.11.0.tar.gz", hash = "sha256:9e5e553bbba1843cb4a00823014b907616be46ee503d2b9ba001d214a8da218f"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, @@ -1283,10 +1272,6 @@ numpydoc = [ {file = "numpydoc-1.2-py3-none-any.whl", hash = "sha256:3ecbb9feae080031714b63128912988ebdfd4c582a085d25b8d9f7ac23c2d9ef"}, {file = "numpydoc-1.2.tar.gz", hash = "sha256:0cec233740c6b125913005d16e8a9996e060528afcb8b7cad3f2706629dfd6f7"}, ] -oauthlib = [ - {file = "oauthlib-3.1.1-py2.py3-none-any.whl", hash = "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc"}, - {file = "oauthlib-3.1.1.tar.gz", hash = "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3"}, -] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, @@ -1374,8 +1359,8 @@ pyspnego = [ {file = "pyspnego-0.3.1.tar.gz", hash = "sha256:ccb8d9cea310f1715d5ed3d2d092db9bf50ff2762cf94a0dd9dfab7774a727fe"}, ] pytest = [ - {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.0.1-py3-none-any.whl", hash = "sha256:9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db"}, + {file = "pytest-7.0.1.tar.gz", hash = "sha256:e30905a0c131d3d94b89624a1cc5afec3e0ba2fbdb151867d8e0ebd49850f171"}, ] pytest-cov = [ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, @@ -1415,6 +1400,10 @@ requests = [ {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, ] +requests-auth = [ + {file = "requests_auth-6.0.0-py3-none-any.whl", hash = "sha256:77214cbbe067a209881735e24ca3a4366dabdff5c96c2b8179e961f108e9ca3e"}, + {file = "requests_auth-6.0.0.tar.gz", hash = "sha256:ef8b5d4c79edcecb919d2ee8001bd4c57d2e81601990542e808173f272b85772"}, +] requests-kerberos = [ {file = "requests-kerberos-0.13.0.tar.gz", hash = "sha256:477e153773cc430c514d0a679e1f5ea89a0e675ac2342c413866e03d1e82a817"}, {file = "requests_kerberos-0.13.0-py2.py3-none-any.whl", hash = "sha256:12766e209b975e081916b550b77b7a8b084c43f98beba1407182ef9a7bef88d5"}, @@ -1430,10 +1419,6 @@ requests-ntlm = [ {file = "requests_ntlm-1.1.0-py2.py3-none-any.whl", hash = "sha256:1eb43d1026b64d431a8e0f1e8a8c8119ac698e72e9b95102018214411a8463ea"}, {file = "requests_ntlm-1.1.0.tar.gz", hash = "sha256:9189c92e8c61ae91402a64b972c4802b2457ce6a799d658256ebf084d5c7eb71"}, ] -requests-oauthlib = [ - {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, - {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, -] secretstorage = [ {file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"}, {file = "SecretStorage-3.3.1.tar.gz", hash = "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"}, @@ -1499,13 +1484,12 @@ starlette = [ {file = "starlette-0.17.1.tar.gz", hash = "sha256:57eab3cc975a28af62f6faec94d355a410634940f10b30d68d31cb5ec1b44ae8"}, ] tomli = [ - {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"}, ] typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, + {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, + {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, ] urllib3 = [ {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, diff --git a/pyproject.toml b/pyproject.toml index e1674f9c..2821fd4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,10 +44,10 @@ requests-negotiate-sspi = { version = "^0.5.2", markers = "sys_platform == 'win3 requests-ntlm = "^1.1.0" pyparsing = "^3.0" python-dateutil ="^2.6.1" -typing-extensions = { version = "^3.7", python = "<3.8" } +typing-extensions = { version = "^4.0", python = "<3.8" } # Packages for oidc extra -requests_oauthlib = { version = "^1.3", optional = true } +requests_auth = { version = "^6.0", optional = true } keyring = { version = "^22.0", optional = true } # Packages for linux-kerberos extra @@ -74,7 +74,7 @@ sphinx-copybutton = { version = "0.5.0", optional = true } [tool.poetry.extras] oidc = [ - "requests_oauthlib", + "requests_auth", "keyring" ] diff --git a/src/ansys/openapi/common/_oidc.py b/src/ansys/openapi/common/_oidc.py index 8ac113dc..52cc015b 100644 --- a/src/ansys/openapi/common/_oidc.py +++ b/src/ansys/openapi/common/_oidc.py @@ -1,16 +1,13 @@ -import asyncio import os -import threading -import webbrowser -from typing import Dict, Optional, Any +from typing import Optional import keyring import requests from requests.models import CaseInsensitiveDict -from requests_oauthlib import OAuth2Session # type: ignore +from requests_auth import OAuth2AuthorizationCodePKCE, InvalidGrantRequest +from requests_auth.authentication import OAuth2 from ._util import ( - OIDCCallbackHTTPServer, parse_authenticate, SessionConfiguration, set_session_kwargs, @@ -61,9 +58,7 @@ def __init__( api_session_configuration: Optional[SessionConfiguration] = None, idp_session_configuration: Optional[SessionConfiguration] = None, ) -> None: - self._callback_server: "OIDCCallbackHTTPServer" self._initial_session = initial_session - self._oauth_session: OAuth2Session self._api_url = initial_response.url logger.debug("Creating OIDC session handler...") @@ -88,7 +83,6 @@ def __init__( self._idp_session_configuration = OIDCSessionFactory._override_idp_header( idp_session_configuration.get_configuration_for_requests() ) - self._well_known_parameters = self._fetch_and_parse_well_known( self._authenticate_parameters["authority"] ) @@ -101,54 +95,58 @@ def __init__( if "scope" in self._authenticate_parameters else [] ) - self._oauth_session = OAuth2Session( + + self._auth = OAuth2AuthorizationCodePKCE( + authorization_url=self._well_known_parameters["authorization_endpoint"], + token_url=self._well_known_parameters["token_endpoint"], + redirect_uri_port=32284, + audience=self._authenticate_parameters["apiAudience"] if "apiAudience" in self._authenticate_parameters else None, client_id=self._authenticate_parameters["clientid"], - redirect_uri=self._authenticate_parameters["redirecturi"], scope=scopes, + session=self._initial_session ) - set_session_kwargs(self._oauth_session, self._api_session_configuration) - if "offline_access" in scopes: - self._configure_token_refresh() + self._auth.refresh_data.pop('audience', None) + + self._authorized_session = requests.Session() + + set_session_kwargs(self._authorized_session, self._api_session_configuration) - self._callback_server = OIDCCallbackHTTPServer() logger.info("Configuration complete.") def get_session_with_provided_token( - self, refresh_token: str, access_token: Optional[str] = None - ) -> OAuth2Session: + self, refresh_token: str + ): """Create a :class:`OAuth2Session` object with provided tokens. - This method configures a session to request an access token with the provided refresh token. - This will happen automatically when the first request is sent to the server. Alternatively, - an access token can be provided, and it will be used until it expires. After it expires, - the refresh token will be used to request a new access token. + This method configures a session to request an access token with the provided refresh token, + an access token will be requested immediately. Parameters ---------- refresh_token : str Refresh token for the API server, typically a Base64-encoded JSON Web Token. - access_token : Optional[str] - Access token for the API server, typically a Base64-encoded JSON web token. """ logger.info("Setting tokens...") - if access_token is not None: - if _log_tokens: - logger.debug(f"Setting access token: {access_token}") - self._oauth_session.token = { - "token_type": "bearer", - "access_token": access_token, - } if refresh_token is not None: if _log_tokens: logger.debug(f"Setting refresh token: {refresh_token}") - # noinspection PyProtectedMember - self._oauth_session._client.refresh_token = refresh_token - return self._oauth_session + try: + state, token, expires_in, new_refresh_token = self._auth.refresh_token(refresh_token) + except InvalidGrantRequest as excinfo: + logger.debug(str(excinfo)) + raise ValueError("The provided refresh token was invalid, please request a new token.") + with OAuth2.token_cache.forbid_concurrent_missing_token_function_call: + # noinspection PyProtectedMember + if new_refresh_token is None: + new_refresh_token = refresh_token + OAuth2.token_cache._add_access_token(state, token, expires_in, new_refresh_token) + self._authorized_session.auth = self._auth + return self._authorized_session def get_session_with_stored_token( self, token_name: str = "ansys-openapi-common-oidc" - ) -> OAuth2Session: + ): """Create a :class:`OAuth2Session` object with a stored token. This method uses a token stored in the system keyring to authenticate the session. It requires a correctly @@ -172,7 +170,7 @@ def get_session_with_stored_token( def get_session_with_interactive_authorization( self, login_timeout: int = 60 - ) -> OAuth2Session: + ): """Create a :class:`OAuth2Session` object, authorizing the user via the system web browser. Parameters @@ -181,61 +179,10 @@ def get_session_with_interactive_authorization( Number of seconds to wait for the user to authenticate. The default is ``60s``. """ - async def await_callback() -> Any: - thread = threading.Thread(target=self._callback_server.serve_forever) - thread.daemon = True - thread.start() - return await self._callback_server.get_auth_code() - - authorization_url, state = self._oauth_session.authorization_url( - self._well_known_parameters["authorization_endpoint"] - ) - logger.info("Authenticating user...") - logger.debug(f"Opening web browser with URL {authorization_url}") - webbrowser.open(authorization_url) - loop = asyncio.get_event_loop() - auth_code_task = asyncio.wait_for(await_callback(), login_timeout) - auth_code = loop.run_until_complete(auth_code_task) - loop.close() - logger.info("Authentication complete, fetching token...") - if _log_tokens: - logger.debug(f"Received authorization code: {auth_code}") - self._callback_server.shutdown() - - _ = self._oauth_session.fetch_token( - self._well_known_parameters["token_endpoint"], - authorization_response=auth_code, - include_client_id=True, - **self._idp_session_configuration, - ) - if _log_tokens: - logger.debug(f"Access token: {self._oauth_session.token}") - if self._oauth_session.auto_refresh_url is not None: - # noinspection PyProtectedMember - logger.debug( - f"Refresh token: {self._oauth_session._client.refresh_token}" - ) - logger.info("Tokens retrieved successfully. Authentication complete.") - return self._oauth_session - - def _configure_token_refresh(self) -> None: - """Configure automatic token refresh, if available. - - This method only supports Authorization Code Flow currently. - """ - - def token_updater(token: Dict[str, str]) -> None: - self.token = token - self.access_token = token["access_token"] - - logger.info("Refresh tokens supported, configuring...") - self._oauth_session.auto_refresh_url = self._well_known_parameters[ - "token_endpoint" - ] - self._oauth_session.auto_refresh_kwargs = { - "client_id": self._authenticate_parameters["clientid"] - } - self._oauth_session.token_updater = token_updater + self._auth.timeout = login_timeout + self._authorized_session.auth = self._auth + self._authorized_session.get(self._api_url) + return self._authorized_session @staticmethod def _parse_unauthorized_header( @@ -343,7 +290,7 @@ def _override_idp_header( requests_configuration: RequestsConfiguration, ) -> RequestsConfiguration: """Override user-provided ``Accept`` and ``Content-Type`` headers to ensure correct - response from the OpenID identity povider. + response from the OpenID identity provider. Parameters ---------- diff --git a/src/ansys/openapi/common/_session.py b/src/ansys/openapi/common/_session.py index 2ab81f72..9d5df593 100644 --- a/src/ansys/openapi/common/_session.py +++ b/src/ansys/openapi/common/_session.py @@ -29,7 +29,7 @@ try: # noinspection PyUnresolvedReferences - import requests_oauthlib # type: ignore + import requests_auth import keyring from ._oidc import OIDCSessionFactory except ImportError: @@ -430,9 +430,9 @@ def with_stored_token( return self.with_token(refresh_token=refresh_token) def with_token( - self, refresh_token: str, access_token: Optional[str] = None + self, refresh_token: str ) -> ApiClientFactory: - """Use a provided access token or refresh token to authenticate the session. + """Use a provided refresh token to authenticate the session. If an access token is provided, it will be used immediately. When it expires, the token will be refreshed. If no access token is provided, the refresh token is used immediately to fetch an @@ -442,8 +442,6 @@ def with_token( ---------- refresh_token : str Refresh token. - access_token : str - Access token. Returns ------- @@ -454,7 +452,7 @@ def with_token( return self._client_factory self._client_factory._session = ( self._session_factory.get_session_with_provided_token( - access_token=access_token, refresh_token=refresh_token + refresh_token=refresh_token ) ) self._client_factory._configured = True diff --git a/tests/test_oidc.py b/tests/test_oidc.py index 039d7364..4b71e12f 100644 --- a/tests/test_oidc.py +++ b/tests/test_oidc.py @@ -3,7 +3,8 @@ import pytest import requests import requests_mock -from unittest.mock import Mock +from requests_auth.authentication import OAuth2 +from unittest.mock import Mock, MagicMock from covertable import make from ansys.openapi.common import ApiClientFactory @@ -169,17 +170,16 @@ def test_override_idp_configuration_with_no_headers_does_nothing(): assert response == configuration -@pytest.mark.parametrize("access_token", [None, "dGhpcyBpcyBhIHRva2VuLCBob25lc3Qh"]) -def test_setting_tokens_sets_tokens(access_token): +def test_setting_refresh_token_sets_refresh_token(): mock_factory = Mock() refresh_token = "dGhpcyBpcyBhIHRva2VuLCBob25lc3Qh" + mock_factory._auth = Mock() + mock_factory._auth.refresh_token = MagicMock(return_value=(0, "token", 1, refresh_token)) session = OIDCSessionFactory.get_session_with_provided_token( - mock_factory, refresh_token, access_token + mock_factory, refresh_token ) - if access_token: - assert "access_token" in session.token - assert session.token["access_token"] == access_token - assert session._client.refresh_token == refresh_token + session.auth.refresh_token.assert_called_once_with(refresh_token) + assert OAuth2.token_cache.tokens[0][2] == refresh_token def test_endpoint_with_refresh_configures_correctly(): @@ -211,7 +211,7 @@ def test_endpoint_with_refresh_configures_correctly(): ) session = ApiClientFactory(secure_servicelayer_url).with_oidc() - oidc_factory = session._session_factory._oauth_session - assert oidc_factory.auto_refresh_url == f"{authority_url}token" - assert oidc_factory.auto_refresh_kwargs["client_id"] == client_id - session._session_factory._callback_server.server_close() + auth = session._session_factory._auth + + assert auth.token_url == f"{authority_url}token" + assert auth.refresh_data['client_id'] == client_id diff --git a/tests/test_session_creation.py b/tests/test_session_creation.py index 1266fd5a..8a25e213 100644 --- a/tests/test_session_creation.py +++ b/tests/test_session_creation.py @@ -256,7 +256,7 @@ def test_can_connect_with_oidc_using_token(): session = ( ApiClientFactory(SECURE_SERVICELAYER_URL) .with_oidc() - .with_token(access_token=ACCESS_TOKEN, refresh_token="") + .with_token(refresh_token="") .connect() ) resp = session.rest_client.get(SECURE_SERVICELAYER_URL) From 07560e3bdc7454c000b29f7d30d45f4993ee5b1d Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Tue, 15 Feb 2022 10:46:21 +0000 Subject: [PATCH 02/13] Fixup remaining tests --- tests/test_missing_imports.py | 2 +- tests/test_session_creation.py | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tests/test_missing_imports.py b/tests/test_missing_imports.py index 1292fdda..90bdd14e 100644 --- a/tests/test_missing_imports.py +++ b/tests/test_missing_imports.py @@ -26,7 +26,7 @@ def mocked_import(self, name, *args): return self.real_import(name, *args) def test_create_oidc_with_no_extra_throws(self, mocker): - self.blocked_import = "requests_oauthlib" + self.blocked_import = "requests_auth" mocker.patch("builtins.__import__", side_effect=self.mocked_import) from ansys.openapi.common import ApiClientFactory diff --git a/tests/test_session_creation.py b/tests/test_session_creation.py index 8a25e213..5f30b1f0 100644 --- a/tests/test_session_creation.py +++ b/tests/test_session_creation.py @@ -1,6 +1,7 @@ import json import os from functools import wraps +from urllib.parse import parse_qs import pytest import requests_mock @@ -230,6 +231,7 @@ def test_can_connect_with_oidc_using_token(): redirect_uri = "https://www.example.com/login/" authority_url = "https://www.example.com/authority/" client_id = "b4e44bfa-6b73-4d6a-9df6-8055216a5836" + refresh_token = "RrRNWQCQok6sXRn8eAGY4QXus1zq8fk9ZfDN-BeWEmUes" authenticate_header = f'Bearer redirecturi="{redirect_uri}", authority="{authority_url}", clientid="{client_id}"' well_known_response = json.dumps( { @@ -237,12 +239,36 @@ def test_can_connect_with_oidc_using_token(): "authorization_endpoint": f"{authority_url}authorization", } ) + token_response = json.dumps( + { + "access_token": ACCESS_TOKEN, + "expires_in": 3600, + "refresh_token": refresh_token + } + ) + + def match_token_request(request): + if request.text is None: + return False + data = parse_qs(request.text) + return ( + data.get("client_id", "") == [client_id] + and data.get("grant_type", "") == ["refresh_token"] + and data.get("refresh_token", "") == [refresh_token] + ) + with requests_mock.Mocker() as m: m.get( f"{authority_url}.well-known/openid-configuration", status_code=200, text=well_known_response, ) + m.post( + f"{authority_url}token", + status_code=200, + additional_matcher=match_token_request, + text=token_response + ) m.get( SECURE_SERVICELAYER_URL, status_code=401, @@ -256,7 +282,7 @@ def test_can_connect_with_oidc_using_token(): session = ( ApiClientFactory(SECURE_SERVICELAYER_URL) .with_oidc() - .with_token(refresh_token="") + .with_token(refresh_token=refresh_token) .connect() ) resp = session.rest_client.get(SECURE_SERVICELAYER_URL) From 36caeafe9f0fe1134925d50c2407870f8c447eca Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Tue, 15 Feb 2022 10:54:46 +0000 Subject: [PATCH 03/13] Fix docstrings --- src/ansys/openapi/common/_oidc.py | 4 ---- src/ansys/openapi/common/_session.py | 5 ++--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/ansys/openapi/common/_oidc.py b/src/ansys/openapi/common/_oidc.py index 52cc015b..4d958c1f 100644 --- a/src/ansys/openapi/common/_oidc.py +++ b/src/ansys/openapi/common/_oidc.py @@ -30,10 +30,6 @@ class OIDCSessionFactory: Creates an OpenID Connect session with the configuration fetched from the API server. This class uses either the provided token credentials or authorizes a user with a browser-based interactive prompt. - If your identity provider does not provide the exact scopes requested by your API server, you will be unable to - connect for security reasons. To force the client to proceed with non-matching scopes, set the environment variable - ``OAUTHLIB_RELAX_TOKEN_SCOPE`` to ``TRUE``. - Parameters ---------- initial_session : requests.Session diff --git a/src/ansys/openapi/common/_session.py b/src/ansys/openapi/common/_session.py index 9d5df593..69d49102 100644 --- a/src/ansys/openapi/common/_session.py +++ b/src/ansys/openapi/common/_session.py @@ -434,9 +434,8 @@ def with_token( ) -> ApiClientFactory: """Use a provided refresh token to authenticate the session. - If an access token is provided, it will be used immediately. When it expires, the token will - be refreshed. If no access token is provided, the refresh token is used immediately to fetch an - access token. + The refresh token will be used to request a new access token from the Identity Provider, + this will be automatically refreshed shortly before expiration. Parameters ---------- From f29aea0c3199ed3229b7422b1879c536d462a66f Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Tue, 15 Feb 2022 14:32:54 +0000 Subject: [PATCH 04/13] Review comments --- src/ansys/openapi/common/_oidc.py | 42 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/ansys/openapi/common/_oidc.py b/src/ansys/openapi/common/_oidc.py index 4d958c1f..16e4774a 100644 --- a/src/ansys/openapi/common/_oidc.py +++ b/src/ansys/openapi/common/_oidc.py @@ -102,17 +102,19 @@ def __init__( session=self._initial_session ) + # If using Auth0 we cannot provide an audience with requests + # to the token endpoint with grant_type=refresh_token. This + # causes the token to be returned without the audience + # required to access the user_info endpoint. self._auth.refresh_data.pop('audience', None) self._authorized_session = requests.Session() - set_session_kwargs(self._authorized_session, self._api_session_configuration) - logger.info("Configuration complete.") def get_session_with_provided_token( self, refresh_token: str - ): + ) -> requests.Session: """Create a :class:`OAuth2Session` object with provided tokens. This method configures a session to request an access token with the provided refresh token, @@ -124,25 +126,29 @@ def get_session_with_provided_token( Refresh token for the API server, typically a Base64-encoded JSON Web Token. """ logger.info("Setting tokens...") - if refresh_token is not None: - if _log_tokens: - logger.debug(f"Setting refresh token: {refresh_token}") - try: - state, token, expires_in, new_refresh_token = self._auth.refresh_token(refresh_token) - except InvalidGrantRequest as excinfo: - logger.debug(str(excinfo)) - raise ValueError("The provided refresh token was invalid, please request a new token.") - with OAuth2.token_cache.forbid_concurrent_missing_token_function_call: - # noinspection PyProtectedMember - if new_refresh_token is None: - new_refresh_token = refresh_token - OAuth2.token_cache._add_access_token(state, token, expires_in, new_refresh_token) + if refresh_token is None: + raise ValueError("Must provide a value for 'refresh_token', not None") + if _log_tokens: + logger.debug(f"Setting refresh token: {refresh_token}") + try: + state, token, expires_in, new_refresh_token = self._auth.refresh_token(refresh_token) + except InvalidGrantRequest as excinfo: + logger.debug(str(excinfo)) + raise ValueError("The provided refresh token was invalid, please request a new token.") + with OAuth2.token_cache.forbid_concurrent_missing_token_function_call: + # If we were provided with a new refresh token it's likely that the Identity + # Provider is configured to rotate refresh tokens. Store the new one and + # discard the old one. Otherwise use the existing refresh token. + if new_refresh_token is not None: + refresh_token = new_refresh_token + # noinspection PyProtectedMember + OAuth2.token_cache._add_access_token(state, token, expires_in, refresh_token) self._authorized_session.auth = self._auth return self._authorized_session def get_session_with_stored_token( self, token_name: str = "ansys-openapi-common-oidc" - ): + ) -> requests.Session: """Create a :class:`OAuth2Session` object with a stored token. This method uses a token stored in the system keyring to authenticate the session. It requires a correctly @@ -166,7 +172,7 @@ def get_session_with_stored_token( def get_session_with_interactive_authorization( self, login_timeout: int = 60 - ): + ) -> requests.Session: """Create a :class:`OAuth2Session` object, authorizing the user via the system web browser. Parameters From bdd37f63954af3a21d291644ab46b91df3b7aae7 Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Tue, 15 Feb 2022 14:34:42 +0000 Subject: [PATCH 05/13] Delint --- src/ansys/openapi/common/_oidc.py | 28 +++++++++++++++++----------- src/ansys/openapi/common/_session.py | 10 ++++------ tests/test_oidc.py | 6 ++++-- tests/test_session_creation.py | 10 +++++----- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/ansys/openapi/common/_oidc.py b/src/ansys/openapi/common/_oidc.py index 16e4774a..94ac69bb 100644 --- a/src/ansys/openapi/common/_oidc.py +++ b/src/ansys/openapi/common/_oidc.py @@ -4,8 +4,8 @@ import keyring import requests from requests.models import CaseInsensitiveDict -from requests_auth import OAuth2AuthorizationCodePKCE, InvalidGrantRequest -from requests_auth.authentication import OAuth2 +from requests_auth import OAuth2AuthorizationCodePKCE, InvalidGrantRequest # type: ignore[import] +from requests_auth.authentication import OAuth2 # type: ignore[import] from ._util import ( parse_authenticate, @@ -96,25 +96,25 @@ def __init__( authorization_url=self._well_known_parameters["authorization_endpoint"], token_url=self._well_known_parameters["token_endpoint"], redirect_uri_port=32284, - audience=self._authenticate_parameters["apiAudience"] if "apiAudience" in self._authenticate_parameters else None, + audience=self._authenticate_parameters["apiAudience"] + if "apiAudience" in self._authenticate_parameters + else None, client_id=self._authenticate_parameters["clientid"], scope=scopes, - session=self._initial_session + session=self._initial_session, ) # If using Auth0 we cannot provide an audience with requests # to the token endpoint with grant_type=refresh_token. This # causes the token to be returned without the audience # required to access the user_info endpoint. - self._auth.refresh_data.pop('audience', None) + self._auth.refresh_data.pop("audience", None) self._authorized_session = requests.Session() set_session_kwargs(self._authorized_session, self._api_session_configuration) logger.info("Configuration complete.") - def get_session_with_provided_token( - self, refresh_token: str - ) -> requests.Session: + def get_session_with_provided_token(self, refresh_token: str) -> requests.Session: """Create a :class:`OAuth2Session` object with provided tokens. This method configures a session to request an access token with the provided refresh token, @@ -131,10 +131,14 @@ def get_session_with_provided_token( if _log_tokens: logger.debug(f"Setting refresh token: {refresh_token}") try: - state, token, expires_in, new_refresh_token = self._auth.refresh_token(refresh_token) + state, token, expires_in, new_refresh_token = self._auth.refresh_token( + refresh_token + ) except InvalidGrantRequest as excinfo: logger.debug(str(excinfo)) - raise ValueError("The provided refresh token was invalid, please request a new token.") + raise ValueError( + "The provided refresh token was invalid, please request a new token." + ) with OAuth2.token_cache.forbid_concurrent_missing_token_function_call: # If we were provided with a new refresh token it's likely that the Identity # Provider is configured to rotate refresh tokens. Store the new one and @@ -142,7 +146,9 @@ def get_session_with_provided_token( if new_refresh_token is not None: refresh_token = new_refresh_token # noinspection PyProtectedMember - OAuth2.token_cache._add_access_token(state, token, expires_in, refresh_token) + OAuth2.token_cache._add_access_token( + state, token, expires_in, refresh_token + ) self._authorized_session.auth = self._auth return self._authorized_session diff --git a/src/ansys/openapi/common/_session.py b/src/ansys/openapi/common/_session.py index 69d49102..c05cc901 100644 --- a/src/ansys/openapi/common/_session.py +++ b/src/ansys/openapi/common/_session.py @@ -3,10 +3,10 @@ from typing import Tuple, Union, Container, Optional, Mapping, TypeVar, Any import requests -from urllib3.util.retry import Retry +from urllib3.util.retry import Retry # type: ignore[import] from requests.adapters import HTTPAdapter from requests.auth import HTTPBasicAuth -from requests_ntlm import HttpNtlmAuth # type: ignore +from requests_ntlm import HttpNtlmAuth # type: ignore[import] from . import __version__ from ._api_client import ApiClient @@ -29,7 +29,7 @@ try: # noinspection PyUnresolvedReferences - import requests_auth + import requests_auth # type: ignore[import] import keyring from ._oidc import OIDCSessionFactory except ImportError: @@ -429,9 +429,7 @@ def with_stored_token( return self.with_token(refresh_token=refresh_token) - def with_token( - self, refresh_token: str - ) -> ApiClientFactory: + def with_token(self, refresh_token: str) -> ApiClientFactory: """Use a provided refresh token to authenticate the session. The refresh token will be used to request a new access token from the Identity Provider, diff --git a/tests/test_oidc.py b/tests/test_oidc.py index 4b71e12f..397ffc75 100644 --- a/tests/test_oidc.py +++ b/tests/test_oidc.py @@ -174,7 +174,9 @@ def test_setting_refresh_token_sets_refresh_token(): mock_factory = Mock() refresh_token = "dGhpcyBpcyBhIHRva2VuLCBob25lc3Qh" mock_factory._auth = Mock() - mock_factory._auth.refresh_token = MagicMock(return_value=(0, "token", 1, refresh_token)) + mock_factory._auth.refresh_token = MagicMock( + return_value=(0, "token", 1, refresh_token) + ) session = OIDCSessionFactory.get_session_with_provided_token( mock_factory, refresh_token ) @@ -214,4 +216,4 @@ def test_endpoint_with_refresh_configures_correctly(): auth = session._session_factory._auth assert auth.token_url == f"{authority_url}token" - assert auth.refresh_data['client_id'] == client_id + assert auth.refresh_data["client_id"] == client_id diff --git a/tests/test_session_creation.py b/tests/test_session_creation.py index 5f30b1f0..893d465e 100644 --- a/tests/test_session_creation.py +++ b/tests/test_session_creation.py @@ -243,7 +243,7 @@ def test_can_connect_with_oidc_using_token(): { "access_token": ACCESS_TOKEN, "expires_in": 3600, - "refresh_token": refresh_token + "refresh_token": refresh_token, } ) @@ -252,9 +252,9 @@ def match_token_request(request): return False data = parse_qs(request.text) return ( - data.get("client_id", "") == [client_id] - and data.get("grant_type", "") == ["refresh_token"] - and data.get("refresh_token", "") == [refresh_token] + data.get("client_id", "") == [client_id] + and data.get("grant_type", "") == ["refresh_token"] + and data.get("refresh_token", "") == [refresh_token] ) with requests_mock.Mocker() as m: @@ -267,7 +267,7 @@ def match_token_request(request): f"{authority_url}token", status_code=200, additional_matcher=match_token_request, - text=token_response + text=token_response, ) m.get( SECURE_SERVICELAYER_URL, From f6ce3df63f5d5bc3bcdc75bd24b41bc499dbf713 Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Tue, 15 Feb 2022 14:39:41 +0000 Subject: [PATCH 06/13] Remove OIDC authentication things that are now superfluous - Remove OIDCCallbackHTTPServer and tests - Remove HTTPResponseHandler and tests --- src/ansys/openapi/common/_util.py | 62 ------------------------------- tests/test_utils_misc.py | 47 ----------------------- 2 files changed, 109 deletions(-) diff --git a/src/ansys/openapi/common/_util.py b/src/ansys/openapi/common/_util.py index 7eb08e6d..96555671 100644 --- a/src/ansys/openapi/common/_util.py +++ b/src/ansys/openapi/common/_util.py @@ -181,68 +181,6 @@ def set_session_kwargs( session.__dict__[k] = v -class ResponseHandler(BaseHTTPRequestHandler): - """Provides an OpenID Connect callback handler. This class returns a page indicating authentication - completion when the authentication flow completes. - - Attributes - ---------- - _response_html : str - User-facing HTML to render when redirected after successful authentication with the identity provider. - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - self._response_html = ( - r"" - r' ' - r" " - r' ' - r" {title}" - r" " - r" " - r"

{title}

" - r"

{paragraph}

" - r" " - r"".format( - title="Login successful", paragraph="You can now close this tab." - ).encode("utf-8") - ) - super().__init__(*args, **kwargs) - - # noinspection PyPep8Naming - def do_GET(self) -> None: - """Handle GET requests to the callback URL.""" - self.send_response(200) - self.send_header("Content-Type", "text/html; charset=utf-8") - self.end_headers() - - self.wfile.write(self._response_html) - # noinspection PyProtectedMember - self.server._auth_code.put("https://localhost{}".format(self.path)) # type: ignore[attr-defined] - - -class OIDCCallbackHTTPServer(HTTPServer): - """Provides the HTTP Server that is to handle callback requests on successful OpenID Connect authentication. - - Attributes - ---------- - _auth_code : Queue - Store for authentication code received from the user's browser when authentication completes. - """ - - def __init__(self) -> None: - from queue import Queue - - super().__init__(("", 32284), ResponseHandler) - self._auth_code: Queue = Queue() - - async def get_auth_code(self) -> Any: - return self._auth_code.get(block=True) - - def __del__(self) -> None: - self.server_close() - - class RequestsConfiguration(TypedDict): cert: Union[None, str, Tuple[str, str]] verify: Union[None, str, bool] diff --git a/tests/test_utils_misc.py b/tests/test_utils_misc.py index 97d63f48..57885548 100644 --- a/tests/test_utils_misc.py +++ b/tests/test_utils_misc.py @@ -1,13 +1,7 @@ -import asyncio -import secrets -import threading - import pytest -import requests from ansys.openapi.common._util import ( CaseInsensitiveOrderedDict, - OIDCCallbackHTTPServer, ) @@ -86,44 +80,3 @@ def test_repr(self): repr = self.example_dict.__repr__() dict_from_repr = eval(repr) assert dict_from_repr == self.example_dict - - -class TestOIDCHTTPServer: - def test_authorize_returns_200(self): - callback_server = OIDCCallbackHTTPServer() - session = requests.Session() - - thread = threading.Thread(target=callback_server.serve_forever) - thread.daemon = True - thread.start() - - resp = session.get("http://localhost:32284") - - callback_server.shutdown() - del callback_server - del thread - - assert resp.status_code == 200 - assert "Login successful" in resp.text - assert "Content-Type" in resp.headers - assert "text/html" in resp.headers["Content-Type"] - - def test_authorize_with_code_parses_code(self): - callback_server = OIDCCallbackHTTPServer() - session = requests.Session() - - test_code = secrets.token_hex(32) - - thread = threading.Thread(target=callback_server.serve_forever) - thread.daemon = True - thread.start() - - resp = session.get(f"http://localhost:32284?code={test_code}") - - loop = asyncio.get_event_loop() - code = loop.run_until_complete(callback_server.get_auth_code()) - callback_server.shutdown() - del callback_server - - assert resp.status_code == 200 - assert test_code in code From 481aa50262a1b6f3845f4fb3993ffd0af7d99b49 Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Tue, 15 Feb 2022 14:51:21 +0000 Subject: [PATCH 07/13] Import Retry via requests to make mypy happy --- src/ansys/openapi/common/_session.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/openapi/common/_session.py b/src/ansys/openapi/common/_session.py index c05cc901..71b1b8de 100644 --- a/src/ansys/openapi/common/_session.py +++ b/src/ansys/openapi/common/_session.py @@ -3,7 +3,7 @@ from typing import Tuple, Union, Container, Optional, Mapping, TypeVar, Any import requests -from urllib3.util.retry import Retry # type: ignore[import] +from requests.packages.urllib3.util.retry import Retry from requests.adapters import HTTPAdapter from requests.auth import HTTPBasicAuth from requests_ntlm import HttpNtlmAuth # type: ignore[import] From 831c3cbdead0cf7ac508d54a98cf1f089ea93e0f Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Tue, 15 Feb 2022 14:56:30 +0000 Subject: [PATCH 08/13] Revert change to import --- src/ansys/openapi/common/_session.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/openapi/common/_session.py b/src/ansys/openapi/common/_session.py index 71b1b8de..680cf5bc 100644 --- a/src/ansys/openapi/common/_session.py +++ b/src/ansys/openapi/common/_session.py @@ -3,7 +3,7 @@ from typing import Tuple, Union, Container, Optional, Mapping, TypeVar, Any import requests -from requests.packages.urllib3.util.retry import Retry +from urllib3.util.retry import Retry from requests.adapters import HTTPAdapter from requests.auth import HTTPBasicAuth from requests_ntlm import HttpNtlmAuth # type: ignore[import] From c80e82953677c75bb865da5bd5a3dffed86e628c Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Tue, 15 Feb 2022 15:22:44 +0000 Subject: [PATCH 09/13] Add two tests for missed lines in coverage report --- tests/test_oidc.py | 55 ++++++++++++++++++++++++++++++ tests/test_session_creation.py | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/tests/test_oidc.py b/tests/test_oidc.py index 397ffc75..a39530ac 100644 --- a/tests/test_oidc.py +++ b/tests/test_oidc.py @@ -1,4 +1,5 @@ import json +from urllib.parse import parse_qs import pytest import requests @@ -170,6 +171,12 @@ def test_override_idp_configuration_with_no_headers_does_nothing(): assert response == configuration +def test_setting_refresh_token_with_no_token_throws(): + mock_factory = Mock() + with pytest.raises(ValueError): + OIDCSessionFactory.get_session_with_provided_token(mock_factory, None) + + def test_setting_refresh_token_sets_refresh_token(): mock_factory = Mock() refresh_token = "dGhpcyBpcyBhIHRva2VuLCBob25lc3Qh" @@ -184,6 +191,54 @@ def test_setting_refresh_token_sets_refresh_token(): assert OAuth2.token_cache.tokens[0][2] == refresh_token +def test_invalid_refresh_token_throws(): + api_url = "https://mi-api.com/api" + authority_url = "https://www.example.com/authority/" + client_id = "b4e44bfa-6b73-4d6a-9df6-8055216a5836" + refresh_token = "RrRNWQCQok6sXRn8eAGY4QXus1zq8fk9ZfDN-BeWEmUes" + redirect_uri = "https://www.example.com/login/" + authenticate_header = f'Bearer redirecturi="{redirect_uri}", authority="{authority_url}", clientid="{client_id}"' + well_known_response = json.dumps( + { + "token_endpoint": f"{authority_url}token", + "authorization_endpoint": f"{authority_url}authorization", + } + ) + + def match_token_request(request): + if request.text is None: + return False + data = parse_qs(request.text) + return ( + data.get("client_id", "") == [client_id] + and data.get("grant_type", "") == ["refresh_token"] + and data.get("refresh_token", "") == [refresh_token] + ) + + with requests_mock.Mocker() as m: + m.get( + api_url, + status_code=401, + headers={"WWW-Authenticate": authenticate_header}, + ) + m.get( + f"{authority_url}.well-known/openid-configuration", + status_code=200, + text=well_known_response, + ) + m.post( + f"{authority_url}token", + status_code=401, + additional_matcher=match_token_request, + headers={"WWW-Authenticate": "Bearer error=invalid_token"}, + ) + with pytest.raises(ValueError) as exception_info: + ApiClientFactory(api_url).with_oidc().with_token( + refresh_token=refresh_token + ) + assert "refresh token was invalid" in str(exception_info) + + def test_endpoint_with_refresh_configures_correctly(): secure_servicelayer_url = "https://localhost/mi_servicelayer" redirect_uri = "https://www.example.com/login/" diff --git a/tests/test_session_creation.py b/tests/test_session_creation.py index 893d465e..bcd38ad1 100644 --- a/tests/test_session_creation.py +++ b/tests/test_session_creation.py @@ -289,6 +289,68 @@ def match_token_request(request): assert resp.status_code == 200 +def test_can_connect_with_oidc_using_token(): + redirect_uri = "https://www.example.com/login/" + authority_url = "https://www.example.com/authority/" + client_id = "b4e44bfa-6b73-4d6a-9df6-8055216a5836" + refresh_token = "RrRNWQCQok6sXRn8eAGY4QXus1zq8fk9ZfDN-BeWEmUes" + authenticate_header = f'Bearer redirecturi="{redirect_uri}", authority="{authority_url}", clientid="{client_id}"' + well_known_response = json.dumps( + { + "token_endpoint": f"{authority_url}token", + "authorization_endpoint": f"{authority_url}authorization", + } + ) + token_response = json.dumps( + { + "access_token": ACCESS_TOKEN, + "expires_in": 3600, + "refresh_token": refresh_token, + } + ) + + def match_token_request(request): + if request.text is None: + return False + data = parse_qs(request.text) + return ( + data.get("client_id", "") == [client_id] + and data.get("grant_type", "") == ["refresh_token"] + and data.get("refresh_token", "") == [refresh_token] + ) + + with requests_mock.Mocker() as m: + m.get( + f"{authority_url}.well-known/openid-configuration", + status_code=200, + text=well_known_response, + ) + m.post( + f"{authority_url}token", + status_code=200, + additional_matcher=match_token_request, + text=token_response, + ) + m.get( + SECURE_SERVICELAYER_URL, + status_code=401, + headers={"WWW-Authenticate": authenticate_header}, + ) + m.get( + SECURE_SERVICELAYER_URL, + status_code=200, + request_headers={"Authorization": f"Bearer {ACCESS_TOKEN}"}, + ) + session = ( + ApiClientFactory(SECURE_SERVICELAYER_URL) + .with_oidc() + .with_token(refresh_token=refresh_token) + .connect() + ) + resp = session.rest_client.get(SECURE_SERVICELAYER_URL) + assert resp.status_code == 200 + + def test_neither_basic_nor_ntlm_throws(): with requests_mock.Mocker() as m: m.get(SERVICELAYER_URL, status_code=401, headers={"WWW-Authenticate": "Bearer"}) From 4e9930d2e5e89077ed27dcbd04f461b562ea40e8 Mon Sep 17 00:00:00 2001 From: Andy Grigg Date: Thu, 14 Jul 2022 09:47:01 -0400 Subject: [PATCH 10/13] Add lock file --- poetry.lock | 1176 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1176 insertions(+) create mode 100644 poetry.lock diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..79bc160a --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1176 @@ +[[package]] +name = "alabaster" +version = "0.7.12" +description = "A configurable sidebar-enabled Sphinx theme" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "anyio" +version = "3.6.1" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "main" +optional = true +python-versions = ">=3.6.2" + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + +[package.extras] +doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] +trio = ["trio (>=0.16)"] + +[[package]] +name = "asgi-gssapi" +version = "0.1.2" +description = "GSSAPI Kerberos authentication support in ASGI Middleware" +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +gssapi = ">=1.7.0" + +[[package]] +name = "atomicwrites" +version = "1.4.1" +description = "Atomic file writes." +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "attrs" +version = "21.4.0" +description = "Classes Without Boilerplate" +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] + +[[package]] +name = "babel" +version = "2.10.3" +description = "Internationalization utilities" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +pytz = ">=2015.7" + +[[package]] +name = "beautifulsoup4" +version = "4.11.1" +description = "Screen-scraping library" +category = "main" +optional = true +python-versions = ">=3.6.0" + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "certifi" +version = "2022.6.15" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "cffi" +version = "1.15.1" +description = "Foreign Function Interface for Python calling C code." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "charset-normalizer" +version = "2.1.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} + +[[package]] +name = "colorama" +version = "0.4.5" +description = "Cross-platform colored terminal text." +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "coverage" +version = "6.4.2" +description = "Code coverage measurement for Python" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "covertable" +version = "2.0.1" +description = "It makes combinations covering pairs for pairwise testing." +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "cryptography" +version = "37.0.4" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +cffi = ">=1.12" + +[package.extras] +docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] +docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] +sdist = ["setuptools_rust (>=0.11.4)"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +category = "main" +optional = true +python-versions = ">=3.5" + +[[package]] +name = "docutils" +version = "0.17.1" +description = "Docutils -- Python Documentation Utilities" +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "fastapi" +version = "0.78.0" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +category = "main" +optional = true +python-versions = ">=3.6.1" + +[package.dependencies] +pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" +starlette = "0.19.1" + +[package.extras] +all = ["requests (>=2.24.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<3.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.18.0)"] +dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.18.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "typer (>=0.4.1,<0.5.0)", "pyyaml (>=5.3.1,<7.0.0)"] +test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "mypy (==0.910)", "flake8 (>=3.8.3,<4.0.0)", "black (==22.3.0)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.19.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.6.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "flask (>=1.1.2,<3.0.0)", "anyio[trio] (>=3.2.1,<4.0.0)", "types-ujson (==4.2.1)", "types-orjson (==3.6.2)", "types-dataclasses (==0.6.5)"] + +[[package]] +name = "gssapi" +version = "1.7.3" +description = "Python GSSAPI Wrapper" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +decorator = "*" + +[[package]] +name = "h11" +version = "0.13.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "importlib-metadata" +version = "4.12.0" +description = "Read metadata from Python packages" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +perf = ["ipython"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "jeepney" +version = "0.8.0" +description = "Low-level, pure Python DBus protocol wrapper." +category = "main" +optional = true +python-versions = ">=3.7" + +[package.extras] +test = ["pytest", "pytest-trio", "pytest-asyncio (>=0.17)", "testpath", "trio", "async-timeout"] +trio = ["trio", "async-generator"] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "keyring" +version = "23.7.0" +description = "Store and access your passwords safely." +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} +jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} +pywin32-ctypes = {version = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1", markers = "sys_platform == \"win32\""} +SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] + +[[package]] +name = "krb5" +version = "0.3.0" +description = "Kerberos API bindings for Python" +category = "main" +optional = true +python-versions = ">=3.6" + +[[package]] +name = "markupsafe" +version = "2.1.1" +description = "Safely add untrusted strings to HTML/XML markup." +category = "main" +optional = true +python-versions = ">=3.7" + +[[package]] +name = "ntlm-auth" +version = "1.5.0" +description = "Creates NTLM authentication structures" +category = "main" +optional = false +python-versions = ">=2.6,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" + +[package.extras] +cryptography = ["cryptography (<2.2)", "cryptography"] + +[[package]] +name = "numpydoc" +version = "1.4.0" +description = "Sphinx extension to support docstrings in Numpy format" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +Jinja2 = ">=2.10" +sphinx = ">=3.0" + +[package.extras] +testing = ["pytest", "pytest-cov", "matplotlib"] + +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} + +[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" +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pyansys-sphinx-theme" +version = "0.3.1" +description = "This is the pyansys-sphinx-theme module." +category = "main" +optional = true +python-versions = ">=3.5" + +[package.dependencies] +Jinja2 = ">=3.1.2" +pydata-sphinx-theme = "0.8.1" +Sphinx = ">=4.0.0" + +[[package]] +name = "pycparser" +version = "2.21" +description = "C parser in Python" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pydantic" +version = "1.9.1" +description = "Data validation and settings management using python type hints" +category = "main" +optional = true +python-versions = ">=3.6.1" + +[package.dependencies] +typing-extensions = ">=3.7.4.3" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pydata-sphinx-theme" +version = "0.8.1" +description = "Bootstrap-based Sphinx theme from the PyData community" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +beautifulsoup4 = "*" +docutils = "!=0.17.0" +packaging = "*" +sphinx = ">=3.5.4,<5" + +[package.extras] +doc = ["numpydoc", "myst-parser", "pandas", "pytest", "pytest-regressions", "sphinxext-rediraffe", "sphinx-sitemap", "jupyter-sphinx", "plotly", "numpy", "xarray"] +test = ["pytest", "pydata-sphinx-theme"] +coverage = ["pytest-cov", "codecov", "pydata-sphinx-theme"] +dev = ["pyyaml", "pre-commit", "nox", "pydata-sphinx-theme"] + +[[package]] +name = "pygments" +version = "2.12.0" +description = "Pygments is a syntax highlighting package written in Python." +category = "main" +optional = true +python-versions = ">=3.6" + +[[package]] +name = "pyparsing" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "main" +optional = false +python-versions = ">=3.6.8" + +[package.extras] +diagrams = ["railroad-diagrams", "jinja2"] + +[[package]] +name = "pypiwin32" +version = "223" +description = "" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pywin32 = ">=223" + +[[package]] +name = "pyspnego" +version = "0.5.3" +description = "Windows Negotiate Authentication Client and Server" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +cryptography = "*" +gssapi = {version = ">=1.5.0", optional = true, markers = "sys_platform != \"win32\" and extra == \"kerberos\""} +krb5 = {version = ">=0.3.0", optional = true, markers = "sys_platform != \"win32\" and extra == \"kerberos\""} + +[package.extras] +kerberos = ["gssapi (>=1.5.0)", "krb5 (>=0.3.0)"] +yaml = ["ruamel.yaml"] + +[[package]] +name = "pytest" +version = "7.1.2" +description = "pytest: simple powerful testing with Python" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +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" +py = ">=1.8.2" +tomli = ">=1.0.0" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "3.0.0" +description = "Pytest plugin for measuring coverage." +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-mock" +version = "3.8.2" +description = "Thin-wrapper around the mock package for easier use with pytest" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "tox", "pytest-asyncio"] + +[[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" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2022.1" +description = "World timezone definitions, modern and historical" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "pywin32" +version = "304" +description = "Python for Window Extensions" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "pywin32-ctypes" +version = "0.2.0" +description = "" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "requests" +version = "2.28.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7, <4" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-auth" +version = "6.0.0" +description = "Authentication for Requests" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +requests = ">=2.0.0,<3.0.0" + +[package.extras] +testing = ["pyjwt (>=2.0.0,<3.0.0)", "pytest-responses (>=0.5.0,<0.6.0)", "pytest-cov (>=3.0.0,<4.0.0)"] + +[[package]] +name = "requests-kerberos" +version = "0.13.0" +description = "A Kerberos authentication handler for python-requests" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +cryptography = ">=1.3" +pyspnego = {version = "*", extras = ["kerberos"]} +requests = ">=1.1.0" + +[[package]] +name = "requests-mock" +version = "1.9.3" +description = "Mock out responses from the requests package" +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +requests = ">=2.3,<3" +six = "*" + +[package.extras] +fixture = ["fixtures"] +test = ["fixtures", "mock", "purl", "pytest", "sphinx", "testrepository (>=0.0.18)", "testtools"] + +[[package]] +name = "requests-negotiate-sspi" +version = "0.5.2" +description = "This package allows for Single-Sign On HTTP Negotiate authentication using the requests library on Windows." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pypiwin32 = ">=223" +requests = ">=2.0" + +[package.extras] +dev = ["setuptools-version-command"] + +[[package]] +name = "requests-ntlm" +version = "1.1.0" +description = "This package allows for HTTP NTLM authentication using the requests library." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +cryptography = ">=1.3" +ntlm-auth = ">=1.0.2" +requests = ">=2.0.0" + +[[package]] +name = "secretstorage" +version = "3.3.2" +description = "Python bindings to FreeDesktop.org Secret Service API" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +cryptography = ">=2.0" +jeepney = ">=0.6" + +[[package]] +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.*" + +[[package]] +name = "sniffio" +version = "1.2.0" +description = "Sniff out which async library your code is running under" +category = "main" +optional = true +python-versions = ">=3.5" + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "soupsieve" +version = "2.3.2.post1" +description = "A modern CSS selector implementation for Beautiful Soup." +category = "main" +optional = true +python-versions = ">=3.6" + +[[package]] +name = "sphinx" +version = "4.5.0" +description = "Python documentation generator" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=1.3" +colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.14,<0.18" +imagesize = "*" +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +Jinja2 = ">=2.3" +packaging = "*" +Pygments = ">=2.0" +requests = ">=2.5.0" +snowballstemmer = ">=1.1" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.931)", "docutils-stubs", "types-typed-ast", "types-requests"] +test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "1.18.3" +description = "Type hints (PEP 484) support for the Sphinx autodoc extension" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +Sphinx = ">=4.5" + +[package.extras] +testing = ["covdefaults (>=2.2)", "coverage (>=6.3)", "diff-cover (>=6.4)", "nptyping (>=2.1.2)", "pytest (>=7.1)", "pytest-cov (>=3)", "sphobjinv (>=2)", "typing-extensions (>=4.1)"] +type_comments = ["typed-ast (>=1.5.2)"] + +[[package]] +name = "sphinx-copybutton" +version = "0.5.0" +description = "Add a copy button to each of your code cells." +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +sphinx = ">=1.8" + +[package.extras] +code_style = ["pre-commit (==2.12.1)"] +rtd = ["sphinx", "ipython", "myst-nb", "sphinx-book-theme"] + +[[package]] +name = "sphinx-notfound-page" +version = "0.8" +description = "Sphinx extension to build a 404 page with absolute URLs" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.2" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +category = "main" +optional = true +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "main" +optional = true +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.0" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest", "html5lib"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "main" +optional = true +python-versions = ">=3.5" + +[package.extras] +test = ["pytest", "flake8", "mypy"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "main" +optional = true +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "main" +optional = true +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "starlette" +version = "0.19.1" +description = "The little ASGI library that shines." +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +anyio = ">=3.4.0,<5" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "main" +optional = true +python-versions = ">=3.7" + +[[package]] +name = "typing-extensions" +version = "4.3.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "urllib3" +version = "1.26.10" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" + +[package.extras] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "uvicorn" +version = "0.18.2" +description = "The lightning-fast ASGI server." +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + +[package.extras] +standard = ["websockets (>=10.0)", "httptools (>=0.4.0)", "watchfiles (>=0.13)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] + +[[package]] +name = "zipp" +version = "3.8.1" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] + +[extras] +doc = ["pyansys-sphinx-theme", "numpydoc", "sphinx", "sphinx_autodoc_typehints", "sphinx-notfound-page", "sphinx-copybutton"] +linux-kerberos = ["requests-kerberos"] +oidc = ["requests_auth", "keyring"] +test = ["pytest", "pytest-cov", "uvicorn", "fastapi", "pydantic", "requests-mock", "pytest-mock", "covertable", "asgi_gssapi"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.7" +content-hash = "0a8e400cb9a33ad3b476be9e6363b1b834179adf609909c69eca9d8e202550a1" + +[metadata.files] +alabaster = [ + {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, + {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, +] +anyio = [] +asgi-gssapi = [] +atomicwrites = [] +attrs = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] +babel = [] +beautifulsoup4 = [ + {file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"}, + {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"}, +] +certifi = [] +cffi = [] +charset-normalizer = [] +click = [] +colorama = [] +coverage = [] +covertable = [] +cryptography = [] +decorator = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] +docutils = [] +fastapi = [] +gssapi = [] +h11 = [] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +imagesize = [] +importlib-metadata = [] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +jeepney = [] +jinja2 = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] +keyring = [] +krb5 = [] +markupsafe = [ + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, + {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, +] +ntlm-auth = [ + {file = "ntlm-auth-1.5.0.tar.gz", hash = "sha256:c9667d361dc09f6b3750283d503c689070ff7d89f2f6ff0d38088d5436ff8543"}, + {file = "ntlm_auth-1.5.0-py2.py3-none-any.whl", hash = "sha256:f1527c581dbf149349134fc2d789d50af2a400e193206956fa0ab456ccc5a8ba"}, +] +numpydoc = [] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pyansys-sphinx-theme = [] +pycparser = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] +pydantic = [] +pydata-sphinx-theme = [] +pygments = [ + {file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"}, + {file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"}, +] +pyparsing = [] +pypiwin32 = [ + {file = "pypiwin32-223-py3-none-any.whl", hash = "sha256:67adf399debc1d5d14dffc1ab5acacb800da569754fafdc576b2a039485aa775"}, + {file = "pypiwin32-223.tar.gz", hash = "sha256:71be40c1fbd28594214ecaecb58e7aa8b708eabfa0125c8a109ebd51edbd776a"}, +] +pyspnego = [] +pytest = [ + {file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"}, + {file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"}, +] +pytest-cov = [ + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, +] +pytest-mock = [] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] +pytz = [ + {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, + {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, +] +pywin32 = [ + {file = "pywin32-304-cp310-cp310-win32.whl", hash = "sha256:3c7bacf5e24298c86314f03fa20e16558a4e4138fc34615d7de4070c23e65af3"}, + {file = "pywin32-304-cp310-cp310-win_amd64.whl", hash = "sha256:4f32145913a2447736dad62495199a8e280a77a0ca662daa2332acf849f0be48"}, + {file = "pywin32-304-cp310-cp310-win_arm64.whl", hash = "sha256:d3ee45adff48e0551d1aa60d2ec066fec006083b791f5c3527c40cd8aefac71f"}, + {file = "pywin32-304-cp311-cp311-win32.whl", hash = "sha256:30c53d6ce44c12a316a06c153ea74152d3b1342610f1b99d40ba2795e5af0269"}, + {file = "pywin32-304-cp311-cp311-win_amd64.whl", hash = "sha256:7ffa0c0fa4ae4077e8b8aa73800540ef8c24530057768c3ac57c609f99a14fd4"}, + {file = "pywin32-304-cp311-cp311-win_arm64.whl", hash = "sha256:cbbe34dad39bdbaa2889a424d28752f1b4971939b14b1bb48cbf0182a3bcfc43"}, + {file = "pywin32-304-cp36-cp36m-win32.whl", hash = "sha256:be253e7b14bc601718f014d2832e4c18a5b023cbe72db826da63df76b77507a1"}, + {file = "pywin32-304-cp36-cp36m-win_amd64.whl", hash = "sha256:de9827c23321dcf43d2f288f09f3b6d772fee11e809015bdae9e69fe13213988"}, + {file = "pywin32-304-cp37-cp37m-win32.whl", hash = "sha256:f64c0377cf01b61bd5e76c25e1480ca8ab3b73f0c4add50538d332afdf8f69c5"}, + {file = "pywin32-304-cp37-cp37m-win_amd64.whl", hash = "sha256:bb2ea2aa81e96eee6a6b79d87e1d1648d3f8b87f9a64499e0b92b30d141e76df"}, + {file = "pywin32-304-cp38-cp38-win32.whl", hash = "sha256:94037b5259701988954931333aafd39cf897e990852115656b014ce72e052e96"}, + {file = "pywin32-304-cp38-cp38-win_amd64.whl", hash = "sha256:ead865a2e179b30fb717831f73cf4373401fc62fbc3455a0889a7ddac848f83e"}, + {file = "pywin32-304-cp39-cp39-win32.whl", hash = "sha256:25746d841201fd9f96b648a248f731c1dec851c9a08b8e33da8b56148e4c65cc"}, + {file = "pywin32-304-cp39-cp39-win_amd64.whl", hash = "sha256:d24a3382f013b21aa24a5cfbfad5a2cd9926610c0affde3e8ab5b3d7dbcf4ac9"}, +] +pywin32-ctypes = [] +requests = [] +requests-auth = [] +requests-kerberos = [] +requests-mock = [ + {file = "requests-mock-1.9.3.tar.gz", hash = "sha256:8d72abe54546c1fc9696fa1516672f1031d72a55a1d66c85184f972a24ba0eba"}, + {file = "requests_mock-1.9.3-py2.py3-none-any.whl", hash = "sha256:0a2d38a117c08bb78939ec163522976ad59a6b7fdd82b709e23bb98004a44970"}, +] +requests-negotiate-sspi = [ + {file = "requests_negotiate_sspi-0.5.2-py2.py3-none-any.whl", hash = "sha256:84ca9e81cfd3f2bd5eede5f8eddec1d5b58d957efac5e7fc078a3b323d296b77"}, +] +requests-ntlm = [ + {file = "requests_ntlm-1.1.0-py2.py3-none-any.whl", hash = "sha256:1eb43d1026b64d431a8e0f1e8a8c8119ac698e72e9b95102018214411a8463ea"}, + {file = "requests_ntlm-1.1.0.tar.gz", hash = "sha256:9189c92e8c61ae91402a64b972c4802b2457ce6a799d658256ebf084d5c7eb71"}, +] +secretstorage = [] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +sniffio = [ + {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, + {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, +] +snowballstemmer = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] +soupsieve = [ + {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, + {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, +] +sphinx = [ + {file = "Sphinx-4.5.0-py3-none-any.whl", hash = "sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226"}, + {file = "Sphinx-4.5.0.tar.gz", hash = "sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6"}, +] +sphinx-autodoc-typehints = [] +sphinx-copybutton = [ + {file = "sphinx-copybutton-0.5.0.tar.gz", hash = "sha256:a0c059daadd03c27ba750da534a92a63e7a36a7736dcf684f26ee346199787f6"}, + {file = "sphinx_copybutton-0.5.0-py3-none-any.whl", hash = "sha256:9684dec7434bd73f0eea58dda93f9bb879d24bff2d8b187b1f2ec08dfe7b5f48"}, +] +sphinx-notfound-page = [ + {file = "sphinx-notfound-page-0.8.tar.gz", hash = "sha256:39bf5b99e1fbf6164631ecac2b58038f08e0ab9278c563076aadd1cf04b6bb7a"}, + {file = "sphinx_notfound_page-0.8-py3-none-any.whl", hash = "sha256:1901e01df9931922e87ef1f967042322b06a65790132cbd393861261e023b974"}, +] +sphinxcontrib-applehelp = [ + {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, + {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, +] +sphinxcontrib-devhelp = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] +sphinxcontrib-htmlhelp = [ + {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, + {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, +] +sphinxcontrib-jsmath = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] +sphinxcontrib-qthelp = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] +sphinxcontrib-serializinghtml = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] +starlette = [] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +typing-extensions = [] +urllib3 = [] +uvicorn = [] +zipp = [] From 509dc1b8767e92c6923b27db11f85e26bccf4be6 Mon Sep 17 00:00:00 2001 From: Andy Grigg Date: Thu, 14 Jul 2022 13:18:52 -0400 Subject: [PATCH 11/13] Fix mypy --- src/ansys/openapi/common/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/openapi/common/__init__.py b/src/ansys/openapi/common/__init__.py index 19121ea5..329782d1 100644 --- a/src/ansys/openapi/common/__init__.py +++ b/src/ansys/openapi/common/__init__.py @@ -5,7 +5,7 @@ __version__ = metadata.version("ansys-openapi-common") except ImportError: - from importlib_metadata import metadata as metadata_backport + from importlib_metadata import metadata as metadata_backport # type: ignore[import] __version__ = metadata_backport("ansys-openapi-common")["version"] From 672df9cf6fbe2c533d929d6c8d95be435d30184a Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Mon, 18 Jul 2022 15:58:37 +0100 Subject: [PATCH 12/13] Regenerate lock file --- poetry.lock | 105 +++++++++++----------------------------------------- 1 file changed, 21 insertions(+), 84 deletions(-) diff --git a/poetry.lock b/poetry.lock index 267ce416..2800bdf0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -357,19 +357,6 @@ sphinx = ">=3.0" [package.extras] testing = ["pytest", "pytest-cov", "matplotlib"] -[[package]] -name = "oauthlib" -version = "3.2.0" -description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -category = "main" -optional = true -python-versions = ">=3.6" - -[package.extras] -rsa = ["cryptography (>=3.0.0)"] -signals = ["blinker (>=1.4.0)"] -signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] - [[package]] name = "packaging" version = "21.3" @@ -396,17 +383,6 @@ importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "psutil" -version = "5.9.1" -description = "Cross-platform lib for process and system monitoring in Python." -category = "main" -optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.extras] -test = ["ipaddress", "mock", "enum34", "pywin32", "wmi"] - [[package]] name = "py" version = "1.11.0" @@ -622,6 +598,20 @@ urllib3 = ">=1.21.1,<1.27" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "requests-auth" +version = "6.0.0" +description = "Authentication for Requests" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +requests = ">=2.0.0,<3.0.0" + +[package.extras] +testing = ["pyjwt (>=2.0.0,<3.0.0)", "pytest-responses (>=0.5.0,<0.6.0)", "pytest-cov (>=3.0.0,<4.0.0)"] + [[package]] name = "requests-kerberos" version = "0.13.0" @@ -679,21 +669,6 @@ cryptography = ">=1.3" ntlm-auth = ">=1.0.2" requests = ">=2.0.0" -[[package]] -name = "requests-oauthlib" -version = "1.3.1" -description = "OAuthlib authentication support for Requests." -category = "main" -optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -oauthlib = ">=3.0.0" -requests = ">=2.0.0" - -[package.extras] -rsa = ["oauthlib[signedtoken] (>=3.0.0)"] - [[package]] name = "secretstorage" version = "3.3.1" @@ -961,13 +936,13 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [extras] doc = ["pyansys-sphinx-theme", "numpydoc", "sphinx", "sphinx_autodoc_typehints", "sphinx-notfound-page", "sphinx-copybutton"] linux-kerberos = ["requests-kerberos"] -oidc = ["requests_oauthlib", "keyring"] -test = ["pytest", "pytest-cov", "uvicorn", "fastapi", "pydantic", "requests-mock", "pytest-mock", "covertable", "asgi_gssapi", "psutil"] +oidc = ["requests_auth", "keyring"] +test = ["pytest", "pytest-cov", "uvicorn", "fastapi", "pydantic", "requests-mock", "pytest-mock", "covertable", "asgi_gssapi"] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "502f43c179f14bfa323ed1e2c6be0d65599ca16ad8634faf0ec2a4ce9daf1f6a" +content-hash = "bbafa52b84037293c139da42484508793e99f0b05884d67b648be96c161c7cb9" [metadata.files] alabaster = [ @@ -1261,10 +1236,6 @@ numpydoc = [ {file = "numpydoc-1.4.0-py3-none-any.whl", hash = "sha256:fd26258868ebcc75c816fe68e1d41e3b55bd410941acfb969dee3eef6e5cf260"}, {file = "numpydoc-1.4.0.tar.gz", hash = "sha256:9494daf1c7612f59905fa09e65c9b8a90bbacb3804d91f7a94e778831e6fcfa5"}, ] -oauthlib = [ - {file = "oauthlib-3.2.0-py3-none-any.whl", hash = "sha256:6db33440354787f9b7f3a6dbd4febf5d0f93758354060e802f6c06cb493022fe"}, - {file = "oauthlib-3.2.0.tar.gz", hash = "sha256:23a8208d75b902797ea29fd31fa80a15ed9dc2c6c16fe73f5d346f83f6fa27a2"}, -] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, @@ -1273,40 +1244,6 @@ pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -psutil = [ - {file = "psutil-5.9.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:799759d809c31aab5fe4579e50addf84565e71c1dc9f1c31258f159ff70d3f87"}, - {file = "psutil-5.9.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9272167b5f5fbfe16945be3db475b3ce8d792386907e673a209da686176552af"}, - {file = "psutil-5.9.1-cp27-cp27m-win32.whl", hash = "sha256:0904727e0b0a038830b019551cf3204dd48ef5c6868adc776e06e93d615fc5fc"}, - {file = "psutil-5.9.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e7e10454cb1ab62cc6ce776e1c135a64045a11ec4c6d254d3f7689c16eb3efd2"}, - {file = "psutil-5.9.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:56960b9e8edcca1456f8c86a196f0c3d8e3e361320071c93378d41445ffd28b0"}, - {file = "psutil-5.9.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:44d1826150d49ffd62035785a9e2c56afcea66e55b43b8b630d7706276e87f22"}, - {file = "psutil-5.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7be9d7f5b0d206f0bbc3794b8e16fb7dbc53ec9e40bbe8787c6f2d38efcf6c9"}, - {file = "psutil-5.9.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd9246e4cdd5b554a2ddd97c157e292ac11ef3e7af25ac56b08b455c829dca8"}, - {file = "psutil-5.9.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29a442e25fab1f4d05e2655bb1b8ab6887981838d22effa2396d584b740194de"}, - {file = "psutil-5.9.1-cp310-cp310-win32.whl", hash = "sha256:20b27771b077dcaa0de1de3ad52d22538fe101f9946d6dc7869e6f694f079329"}, - {file = "psutil-5.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:58678bbadae12e0db55186dc58f2888839228ac9f41cc7848853539b70490021"}, - {file = "psutil-5.9.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3a76ad658641172d9c6e593de6fe248ddde825b5866464c3b2ee26c35da9d237"}, - {file = "psutil-5.9.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6a11e48cb93a5fa606306493f439b4aa7c56cb03fc9ace7f6bfa21aaf07c453"}, - {file = "psutil-5.9.1-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:068935df39055bf27a29824b95c801c7a5130f118b806eee663cad28dca97685"}, - {file = "psutil-5.9.1-cp36-cp36m-win32.whl", hash = "sha256:0f15a19a05f39a09327345bc279c1ba4a8cfb0172cc0d3c7f7d16c813b2e7d36"}, - {file = "psutil-5.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:db417f0865f90bdc07fa30e1aadc69b6f4cad7f86324b02aa842034efe8d8c4d"}, - {file = "psutil-5.9.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:91c7ff2a40c373d0cc9121d54bc5f31c4fa09c346528e6a08d1845bce5771ffc"}, - {file = "psutil-5.9.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fea896b54f3a4ae6f790ac1d017101252c93f6fe075d0e7571543510f11d2676"}, - {file = "psutil-5.9.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3054e923204b8e9c23a55b23b6df73a8089ae1d075cb0bf711d3e9da1724ded4"}, - {file = "psutil-5.9.1-cp37-cp37m-win32.whl", hash = "sha256:d2d006286fbcb60f0b391741f520862e9b69f4019b4d738a2a45728c7e952f1b"}, - {file = "psutil-5.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b14ee12da9338f5e5b3a3ef7ca58b3cba30f5b66f7662159762932e6d0b8f680"}, - {file = "psutil-5.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:19f36c16012ba9cfc742604df189f2f28d2720e23ff7d1e81602dbe066be9fd1"}, - {file = "psutil-5.9.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:944c4b4b82dc4a1b805329c980f270f170fdc9945464223f2ec8e57563139cf4"}, - {file = "psutil-5.9.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b6750a73a9c4a4e689490ccb862d53c7b976a2a35c4e1846d049dcc3f17d83b"}, - {file = "psutil-5.9.1-cp38-cp38-win32.whl", hash = "sha256:a8746bfe4e8f659528c5c7e9af5090c5a7d252f32b2e859c584ef7d8efb1e689"}, - {file = "psutil-5.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:79c9108d9aa7fa6fba6e668b61b82facc067a6b81517cab34d07a84aa89f3df0"}, - {file = "psutil-5.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:28976df6c64ddd6320d281128817f32c29b539a52bdae5e192537bc338a9ec81"}, - {file = "psutil-5.9.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b88f75005586131276634027f4219d06e0561292be8bd6bc7f2f00bdabd63c4e"}, - {file = "psutil-5.9.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:645bd4f7bb5b8633803e0b6746ff1628724668681a434482546887d22c7a9537"}, - {file = "psutil-5.9.1-cp39-cp39-win32.whl", hash = "sha256:32c52611756096ae91f5d1499fe6c53b86f4a9ada147ee42db4991ba1520e574"}, - {file = "psutil-5.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:f65f9a46d984b8cd9b3750c2bdb419b2996895b005aefa6cbaba9a143b1ce2c5"}, - {file = "psutil-5.9.1.tar.gz", hash = "sha256:57f1819b5d9e95cdfb0c881a8a5b7d542ed0b7c522d575706a80bedc848c8954"}, -] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -1428,6 +1365,10 @@ requests = [ {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] +requests-auth = [ + {file = "requests_auth-6.0.0-py3-none-any.whl", hash = "sha256:77214cbbe067a209881735e24ca3a4366dabdff5c96c2b8179e961f108e9ca3e"}, + {file = "requests_auth-6.0.0.tar.gz", hash = "sha256:ef8b5d4c79edcecb919d2ee8001bd4c57d2e81601990542e808173f272b85772"}, +] requests-kerberos = [ {file = "requests-kerberos-0.13.0.tar.gz", hash = "sha256:477e153773cc430c514d0a679e1f5ea89a0e675ac2342c413866e03d1e82a817"}, {file = "requests_kerberos-0.13.0-py2.py3-none-any.whl", hash = "sha256:12766e209b975e081916b550b77b7a8b084c43f98beba1407182ef9a7bef88d5"}, @@ -1443,10 +1384,6 @@ requests-ntlm = [ {file = "requests_ntlm-1.1.0-py2.py3-none-any.whl", hash = "sha256:1eb43d1026b64d431a8e0f1e8a8c8119ac698e72e9b95102018214411a8463ea"}, {file = "requests_ntlm-1.1.0.tar.gz", hash = "sha256:9189c92e8c61ae91402a64b972c4802b2457ce6a799d658256ebf084d5c7eb71"}, ] -requests-oauthlib = [ - {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, - {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, -] secretstorage = [ {file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"}, {file = "SecretStorage-3.3.1.tar.gz", hash = "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"}, From eefc8031c45c59ff7defae60fbfdebe05e0db103 Mon Sep 17 00:00:00 2001 From: Doug Addy Date: Mon, 18 Jul 2022 16:18:09 +0100 Subject: [PATCH 13/13] Remove extra typing: ignore directive --- src/ansys/openapi/common/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/openapi/common/__init__.py b/src/ansys/openapi/common/__init__.py index 329782d1..19121ea5 100644 --- a/src/ansys/openapi/common/__init__.py +++ b/src/ansys/openapi/common/__init__.py @@ -5,7 +5,7 @@ __version__ = metadata.version("ansys-openapi-common") except ImportError: - from importlib_metadata import metadata as metadata_backport # type: ignore[import] + from importlib_metadata import metadata as metadata_backport __version__ = metadata_backport("ansys-openapi-common")["version"]