diff --git a/.gitleaksignore b/.gitleaksignore index 0428d624a..90de41c16 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -89,3 +89,27 @@ b6a2e217be5dceb6c85332d2e193619894d3a36e:README.md:generic-api-key:1349 b6a2e217be5dceb6c85332d2e193619894d3a36e:README.md:generic-api-key:1372 c751b1e9df5dcb6e6b3a62601174065ebf03144f:README.md:generic-api-key:1358 c751b1e9df5dcb6e6b3a62601174065ebf03144f:README.md:generic-api-key:1381 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_oauth.py:jwt:204 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_password.py:jwt:99 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_password.py:jwt:194 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_sso.py:jwt:228 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_password.py:jwt:403 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_password.py:jwt:516 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_totp.py:jwt:140 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_totp.py:jwt:309 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_webauthn.py:jwt:211 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_webauthn.py:jwt:419 +7c7b8abe49e30e1aed5f72fb59353dc187c9375a:tests/test_webauthn.py:jwt:654 +3630de2df01d6c4fd7b0c6cf8c8fd835df220918:tests/test_totp.py:jwt:132 +3630de2df01d6c4fd7b0c6cf8c8fd835df220918:tests/test_totp.py:jwt:289 +3630de2df01d6c4fd7b0c6cf8c8fd835df220918:tests/test_webauthn.py:jwt:144 +3630de2df01d6c4fd7b0c6cf8c8fd835df220918:tests/test_webauthn.py:jwt:312 +3630de2df01d6c4fd7b0c6cf8c8fd835df220918:tests/test_webauthn.py:jwt:482 +cc88fb407157fa23a672e03ec07e26bdce6fe170:tests/test_password.py:jwt:104 +cc88fb407157fa23a672e03ec07e26bdce6fe170:tests/test_oauth.py:jwt:217 +cc88fb407157fa23a672e03ec07e26bdce6fe170:tests/test_password.py:jwt:205 +cc88fb407157fa23a672e03ec07e26bdce6fe170:tests/test_password.py:jwt:426 +cc88fb407157fa23a672e03ec07e26bdce6fe170:tests/test_password.py:jwt:547 +cc88fb407157fa23a672e03ec07e26bdce6fe170:tests/test_sso.py:jwt:238 +3ce967512fed2bae5e89dc9ff973e67ff9bc3084:README.md:hashicorp-tf-password:248 +04146e7a83d6212e407c5a46008324d646878fc1:tests/test_auth.py:jwt:257 \ No newline at end of file diff --git a/descope/__init__.py b/descope/__init__.py index 7e71f2f6e..5cd79beac 100644 --- a/descope/__init__.py +++ b/descope/__init__.py @@ -39,3 +39,37 @@ UserPasswordFirebase, UserPasswordPbkdf2, ) + +__all__ = [ + "COOKIE_DATA_NAME", + "REFRESH_SESSION_COOKIE_NAME", + "REFRESH_SESSION_TOKEN_NAME", + "SESSION_COOKIE_NAME", + "SESSION_TOKEN_NAME", + "AccessKeyLoginOptions", + "DeliveryMethod", + "LoginOptions", + "SignUpOptions", + "DescopeClient", + "API_RATE_LIMIT_RETRY_AFTER_HEADER", + "ERROR_TYPE_API_RATE_LIMIT", + "ERROR_TYPE_SERVER_ERROR", + "AuthException", + "RateLimitException", + "AssociatedTenant", + "SAMLIDPAttributeMappingInfo", + "SAMLIDPGroupsMappingInfo", + "SAMLIDPRoleGroupMappingInfo", + "AttributeMapping", + "OIDCAttributeMapping", + "RoleMapping", + "SSOOIDCSettings", + "SSOSAMLSettings", + "SSOSAMLSettingsByMetadata", + "UserObj", + "UserPassword", + "UserPasswordBcrypt", + "UserPasswordDjango", + "UserPasswordFirebase", + "UserPasswordPbkdf2", +] diff --git a/descope/auth.py b/descope/auth.py index 36c9d4401..eca29130b 100644 --- a/descope/auth.py +++ b/descope/auth.py @@ -6,8 +6,10 @@ import platform import re from http import HTTPStatus +import ssl from threading import Lock from typing import Iterable +import certifi import jwt @@ -16,7 +18,7 @@ except ImportError: from pkg_resources import get_distribution -import requests +import httpx from email_validator import EmailNotValidError, validate_email from jwt import ExpiredSignatureError, ImmatureSignatureError @@ -110,6 +112,20 @@ def __init__( kid, pub_key, alg = self._validate_and_load_public_key(public_key) self.public_keys = {kid: (pub_key, alg)} + self.client_timeout = timeout_seconds + self.client_verify: bool | ssl.SSLContext = False + if not skip_verify: + # Backwards compatibility with requests + ssl_ctx = ssl.create_default_context( + cafile=os.environ.get("SSL_CERT_FILE", certifi.where()), + capath=os.environ.get("SSL_CERT_DIR"), + ) + if os.environ.get("REQUESTS_CA_BUNDLE"): + # ignore - is valid string + ssl_ctx.load_cert_chain(certfile=os.environ.get("REQUESTS_CA_BUNDLE")) # type: ignore[arg-type] + self.client_verify = ssl_ctx + # ignore - is valid string + def _raise_rate_limit_exception(self, response): try: resp = response.json() @@ -144,16 +160,16 @@ def do_get( self, uri: str, params=None, - allow_redirects=None, + follow_redirects=None, pswd: str | None = None, - ) -> requests.Response: - response = requests.get( + ) -> httpx.Response: + response = httpx.get( f"{self.base_url}{uri}", headers=self._get_default_headers(pswd), params=params, - allow_redirects=allow_redirects, - verify=self.secure, - timeout=self.timeout_seconds, + follow_redirects=follow_redirects, + verify=self.client_verify, + timeout=self.client_timeout, ) self._raise_from_response(response) return response @@ -164,15 +180,15 @@ def do_post( body: dict | list[dict] | list[str] | None, params=None, pswd: str | None = None, - ) -> requests.Response: - response = requests.post( + ) -> httpx.Response: + response = httpx.post( f"{self.base_url}{uri}", headers=self._get_default_headers(pswd), json=body, - allow_redirects=False, - verify=self.secure, + follow_redirects=False, + verify=self.client_verify, params=params, - timeout=self.timeout_seconds, + timeout=self.client_timeout, ) self._raise_from_response(response) return response @@ -183,29 +199,29 @@ def do_patch( body: dict | list[dict] | list[str] | None, params=None, pswd: str | None = None, - ) -> requests.Response: - response = requests.patch( + ) -> httpx.Response: + response = httpx.patch( f"{self.base_url}{uri}", headers=self._get_default_headers(pswd), json=body, - allow_redirects=False, - verify=self.secure, + follow_redirects=False, + verify=self.client_verify, params=params, - timeout=self.timeout_seconds, + timeout=self.client_timeout, ) self._raise_from_response(response) return response def do_delete( self, uri: str, params=None, pswd: str | None = None - ) -> requests.Response: - response = requests.delete( + ) -> httpx.Response: + response = httpx.delete( f"{self.base_url}{uri}", params=params, headers=self._get_default_headers(pswd), - allow_redirects=False, - verify=self.secure, - timeout=self.timeout_seconds, + follow_redirects=False, + verify=self.client_verify, + timeout=self.client_timeout, ) self._raise_from_response(response) return response @@ -217,20 +233,20 @@ def do_post_with_custom_base_url( custom_base_url: str | None = None, params=None, pswd: str | None = None, - ) -> requests.Response: + ) -> httpx.Response: """ Post request with optional custom base URL. If base_url is provided, use it instead of self.base_url. """ effective_base_url = custom_base_url if custom_base_url else self.base_url - response = requests.post( + response = httpx.post( f"{effective_base_url}{uri}", headers=self._get_default_headers(pswd), json=body, - allow_redirects=False, - verify=self.secure, + follow_redirects=False, + verify=self.client_verify, params=params, - timeout=self.timeout_seconds, + timeout=self.client_timeout, ) self._raise_from_response(response) return response @@ -450,9 +466,9 @@ def _validate_and_load_public_key(public_key) -> tuple[str, jwt.PyJWK, str]: f"Unable to load public key {e}", ) - def _raise_from_response(self, response): + def _raise_from_response(self, response: httpx.Response): """Raise appropriate exception from response, does nothing if response.ok is True.""" - if response.ok: + if response.is_success: return if response.status_code == HTTPStatus.TOO_MANY_REQUESTS: @@ -466,10 +482,10 @@ def _raise_from_response(self, response): def _fetch_public_keys(self) -> None: # This function called under mutex protection so no need to acquire it once again - response = requests.get( + response = httpx.get( f"{self.base_url}{EndpointsV2.public_key_path}/{self.project_id}", headers=self._get_default_headers(), - verify=self.secure, + verify=self.client_verify, timeout=self.timeout_seconds, ) self._raise_from_response(response) diff --git a/descope/authmethod/enchantedlink.py b/descope/authmethod/enchantedlink.py index 9b78db860..179ac433c 100644 --- a/descope/authmethod/enchantedlink.py +++ b/descope/authmethod/enchantedlink.py @@ -1,6 +1,6 @@ from __future__ import annotations -import requests +import httpx from descope._auth_base import AuthBase from descope.auth import Auth @@ -212,5 +212,5 @@ def _compose_get_session_body(pending_ref: str) -> dict: return {"pendingRef": pending_ref} @staticmethod - def _get_pending_ref_from_response(response: requests.Response) -> dict: + def _get_pending_ref_from_response(response: httpx.Response) -> dict: return response.json() diff --git a/descope/authmethod/webauthn.py b/descope/authmethod/webauthn.py index 9f3f89b29..df72362e1 100644 --- a/descope/authmethod/webauthn.py +++ b/descope/authmethod/webauthn.py @@ -1,6 +1,6 @@ from typing import Iterable, Optional, Union -from requests import Response +from httpx import Response from descope._auth_base import AuthBase from descope.common import ( diff --git a/descope/descope_client.py b/descope/descope_client.py index fa67fdb20..2439717ac 100644 --- a/descope/descope_client.py +++ b/descope/descope_client.py @@ -2,7 +2,7 @@ from typing import Iterable -import requests +import httpx from descope.auth import Auth # noqa: F401 from descope.authmethod.enchantedlink import EnchantedLink # noqa: F401 @@ -362,7 +362,7 @@ def validate_and_refresh_session( session_token, refresh_token, audience ) - def logout(self, refresh_token: str) -> requests.Response: + def logout(self, refresh_token: str) -> httpx.Response: """ Logout user from current session and revoke the refresh_token. After calling this function, you must invalidate or remove any cookies you have created. @@ -370,7 +370,7 @@ def logout(self, refresh_token: str) -> requests.Response: Args: refresh_token (str): The refresh token - Return value (requests.Response): returns the response from the Descope server + Return value (httpx.Response): returns the response from the Descope server Raise: AuthException: Exception is raised if session is not authorized or another error occurs @@ -385,7 +385,7 @@ def logout(self, refresh_token: str) -> requests.Response: uri = EndpointsV1.logout_path return self._auth.do_post(uri, {}, None, refresh_token) - def logout_all(self, refresh_token: str) -> requests.Response: + def logout_all(self, refresh_token: str) -> httpx.Response: """ Logout user from all active sessions and revoke the refresh_token. After calling this function, you must invalidate or remove any cookies you have created. @@ -393,7 +393,7 @@ def logout_all(self, refresh_token: str) -> requests.Response: Args: refresh_token (str): The refresh token - Return value (requests.Response): returns the response from the Descope server + Return value (httpx.Response): returns the response from the Descope server Raise: AuthException: Exception is raised if session is not authorized or another error occurs @@ -431,7 +431,7 @@ def me(self, refresh_token: str) -> dict: uri = EndpointsV1.me_path response = self._auth.do_get( - uri=uri, params=None, allow_redirects=None, pswd=refresh_token + uri=uri, params=None, follow_redirects=None, pswd=refresh_token ) return response.json() @@ -513,7 +513,7 @@ def history(self, refresh_token: str) -> list[dict]: uri = EndpointsV1.history_path response = self._auth.do_get( - uri=uri, params=None, allow_redirects=None, pswd=refresh_token + uri=uri, params=None, follow_redirects=None, pswd=refresh_token ) return response.json() diff --git a/poetry.lock b/poetry.lock index 0a710fb6e..ec8cb0a3e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,27 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. + +[[package]] +name = "anyio" +version = "4.5.2" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "anyio-4.5.2-py3-none-any.whl", hash = "sha256:c011ee36bc1e8ba40e5a81cb9df91925c218fe9b778554e0b56a21e1b5d4716f"}, + {file = "anyio-4.5.2.tar.gz", hash = "sha256:23009af4ed04ce05991845451e11ef02fc7c5ed29179ac9a420e5ad0ac7ddc5b"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} + +[package.extras] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21.0b1) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\""] +trio = ["trio (>=0.26.1)"] [[package]] name = "attrs" @@ -6,18 +29,19 @@ version = "25.3.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, ] [package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] [[package]] name = "black" @@ -25,6 +49,8 @@ version = "24.8.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" +groups = ["format"] +markers = "python_version < \"3.9\"" files = [ {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, @@ -61,7 +87,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +d = ["aiohttp (>=3.7.4) ; sys_platform != \"win32\" or implementation_name != \"pypy\"", "aiohttp (>=3.7.4,!=3.9.0) ; sys_platform == \"win32\" and implementation_name == \"pypy\""] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -71,6 +97,8 @@ version = "24.10.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.9" +groups = ["format"] +markers = "python_version >= \"3.9\"" files = [ {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, @@ -117,6 +145,8 @@ version = "1.8.2" description = "Fast, simple object-to-object and broadcast signaling" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"flask\"" files = [ {file = "blinker-1.8.2-py3-none-any.whl", hash = "sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01"}, {file = "blinker-1.8.2.tar.gz", hash = "sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"}, @@ -128,6 +158,7 @@ version = "5.5.2" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"}, {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"}, @@ -139,6 +170,7 @@ version = "2025.8.3" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, @@ -150,6 +182,8 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -229,6 +263,7 @@ version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, @@ -240,109 +275,24 @@ version = "5.2.0" description = "Universal encoding detector for Python 3" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, ] -[[package]] -name = "charset-normalizer" -version = "3.4.3" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -files = [ - {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"}, - {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"}, - {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"}, -] - [[package]] name = "click" version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["main", "format"] files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, ] +markers = {main = "extra == \"flask\""} [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -353,10 +303,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev", "format", "tests"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "extra == \"flask\" and platform_system == \"Windows\"", format = "platform_system == \"Windows\"", tests = "sys_platform == \"win32\""} [[package]] name = "coverage" @@ -364,6 +316,7 @@ version = "7.6.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" +groups = ["tests"] files = [ {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, @@ -443,7 +396,7 @@ files = [ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" @@ -451,6 +404,7 @@ version = "43.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, @@ -500,6 +454,7 @@ version = "0.4.0" description = "Distribution utilities" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, @@ -511,6 +466,7 @@ version = "2.6.1" description = "DNS toolkit" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, @@ -531,6 +487,7 @@ version = "2.3.0" description = "A robust email address syntax and deliverability validation library." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4"}, {file = "email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426"}, @@ -546,6 +503,8 @@ version = "1.3.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main", "tests"] +markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, @@ -563,6 +522,7 @@ version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, @@ -571,7 +531,7 @@ files = [ [package.extras] docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] -typing = ["typing-extensions (>=4.12.2)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] [[package]] name = "flake8" @@ -579,6 +539,7 @@ version = "7.1.2" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.8.1" +groups = ["dev"] files = [ {file = "flake8-7.1.2-py2.py3-none-any.whl", hash = "sha256:1cbc62e65536f65e6d754dfe6f1bada7f5cf392d6f5db3c2b85892466c3e7c1a"}, {file = "flake8-7.1.2.tar.gz", hash = "sha256:c586ffd0b41540951ae41af572e6790dbd49fc12b3aa2541685d253d9bd504bd"}, @@ -595,6 +556,7 @@ version = "24.12.12" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." optional = false python-versions = ">=3.8.1" +groups = ["dev"] files = [ {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, @@ -613,6 +575,7 @@ version = "1.2.3" description = "Flake8 plug-in loading the configuration from pyproject.toml" optional = false python-versions = ">= 3.6" +groups = ["dev"] files = [ {file = "flake8_pyproject-1.2.3-py3-none-any.whl", hash = "sha256:6249fe53545205af5e76837644dc80b4c10037e73a0e5db87ff562d75fb5bd4a"}, ] @@ -630,6 +593,8 @@ version = "3.0.3" description = "A simple framework for building complex web applications." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"flask\"" files = [ {file = "flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3"}, {file = "flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"}, @@ -647,12 +612,74 @@ Werkzeug = ">=3.0.0" async = ["asgiref (>=3.2)"] dotenv = ["python-dotenv"] +[[package]] +name = "h11" +version = "0.16.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.16" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.27.2" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, + {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "identify" version = "2.6.1" description = "File identification library for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version < \"3.9\"" files = [ {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, @@ -667,6 +694,8 @@ version = "2.6.14" description = "File identification library for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version >= \"3.9\"" files = [ {file = "identify-2.6.14-py2.py3-none-any.whl", hash = "sha256:11a073da82212c6646b1f39bb20d4483bfb9543bd5566fec60053c4bb309bf2e"}, {file = "identify-2.6.14.tar.gz", hash = "sha256:663494103b4f717cb26921c52f8751363dc89db64364cd836a9bf1535f53cd6a"}, @@ -681,6 +710,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -695,6 +725,8 @@ version = "8.5.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"flask\" and python_version < \"3.10\"" files = [ {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, @@ -704,12 +736,12 @@ files = [ zipp = ">=3.20" [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +test = ["flufl.flake8", "importlib-resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] [[package]] @@ -718,6 +750,7 @@ version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.8" +groups = ["tests"] files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -729,6 +762,7 @@ version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" +groups = ["dev"] files = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, @@ -743,6 +777,8 @@ version = "2.2.0" description = "Safely pass data to untrusted environments and back." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"flask\"" files = [ {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, @@ -754,6 +790,8 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"flask\"" files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -771,6 +809,7 @@ version = "0.9.2" description = "Check python packages from requirement.txt and report issues" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "liccheck-0.9.2-py2.py3-none-any.whl", hash = "sha256:15cbedd042515945fe9d58b62e0a5af2f2a7795def216f163bb35b3016a16637"}, {file = "liccheck-0.9.2.tar.gz", hash = "sha256:bdc2190f8e95af3c8f9c19edb784ba7d41ecb2bf9189422eae6112bf84c08cd5"}, @@ -786,6 +825,8 @@ version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"flask\"" files = [ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, @@ -855,6 +896,7 @@ version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, @@ -866,6 +908,7 @@ version = "5.2.0" description = "Rolling backport of unittest.mock for all Pythons" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "mock-5.2.0-py3-none-any.whl", hash = "sha256:7ba87f72ca0e915175596069dbbcc7c75af7b5e9b9bc107ad6349ede0819982f"}, {file = "mock-5.2.0.tar.gz", hash = "sha256:4e460e818629b4b173f32d08bf30d3af8123afbb8e04bb5707a1fd4799e503f0"}, @@ -882,6 +925,7 @@ version = "1.11.2" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" +groups = ["types"] files = [ {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, @@ -929,6 +973,7 @@ version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.8" +groups = ["format", "types"] files = [ {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, @@ -940,6 +985,7 @@ version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -951,6 +997,7 @@ version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["dev", "format", "tests"] files = [ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, @@ -962,6 +1009,7 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" +groups = ["format"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -973,6 +1021,7 @@ version = "0.14.1" description = "Check PEP-8 naming conventions, plugin for flake8" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pep8-naming-0.14.1.tar.gz", hash = "sha256:1ef228ae80875557eb6c1549deafed4dabbf3261cfcafa12f773fe0db9be8a36"}, {file = "pep8_naming-0.14.1-py3-none-any.whl", hash = "sha256:63f514fc777d715f935faf185dedd679ab99526a7f2f503abb61587877f7b1c5"}, @@ -987,6 +1036,7 @@ version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" +groups = ["dev", "format"] files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -1003,6 +1053,7 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["dev", "tests"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -1018,6 +1069,8 @@ version = "2.21.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version < \"3.9\"" files = [ {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, @@ -1036,6 +1089,8 @@ version = "3.6.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version >= \"3.9\"" files = [ {file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"}, {file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"}, @@ -1054,6 +1109,7 @@ version = "2.12.1" description = "Python style guide checker" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3"}, {file = "pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521"}, @@ -1065,6 +1121,8 @@ version = "2.23" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"}, {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"}, @@ -1076,6 +1134,7 @@ version = "3.2.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, @@ -1087,6 +1146,7 @@ version = "2.9.0" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, @@ -1107,6 +1167,7 @@ version = "1.8.0" description = "API to interact with the python pyproject.toml based projects" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228"}, {file = "pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496"}, @@ -1126,6 +1187,7 @@ version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" +groups = ["tests"] files = [ {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, @@ -1148,6 +1210,7 @@ version = "6.0.3" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, @@ -1217,48 +1280,41 @@ files = [ {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, ] -[[package]] -name = "requests" -version = "2.32.4" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -files = [ - {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, - {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset_normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - [[package]] name = "semantic-version" version = "2.10.0" description = "A library implementing the 'SemVer' scheme." optional = false python-versions = ">=2.7" +groups = ["dev"] files = [ {file = "semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177"}, {file = "semantic_version-2.10.0.tar.gz", hash = "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c"}, ] [package.extras] -dev = ["Django (>=1.11)", "check-manifest", "colorama (<=0.4.1)", "coverage", "flake8", "nose2", "readme-renderer (<25.0)", "tox", "wheel", "zest.releaser[recommended]"] +dev = ["Django (>=1.11)", "check-manifest", "colorama (<=0.4.1) ; python_version == \"3.4\"", "coverage", "flake8", "nose2", "readme-renderer (<25.0) ; python_version == \"3.4\"", "tox", "wheel", "zest.releaser[recommended]"] doc = ["Sphinx", "sphinx-rtd-theme"] +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + [[package]] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["dev"] files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -1270,6 +1326,7 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["dev", "format", "tests", "types"] files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -1304,6 +1361,7 @@ files = [ {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] +markers = {dev = "python_version < \"3.11\"", format = "python_version < \"3.11\"", tests = "python_full_version <= \"3.11.0a6\"", types = "python_version < \"3.11\""} [[package]] name = "tox" @@ -1311,6 +1369,7 @@ version = "4.25.0" description = "tox is a generic virtualenv management and test command line tool" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "tox-4.25.0-py3-none-any.whl", hash = "sha256:4dfdc7ba2cc6fdc6688dde1b21e7b46ff6c41795fb54586c91a3533317b5255c"}, {file = "tox-4.25.0.tar.gz", hash = "sha256:dd67f030317b80722cf52b246ff42aafd3ed27ddf331c415612d084304cf5e52"}, @@ -1332,26 +1391,13 @@ virtualenv = ">=20.29.1" [package.extras] test = ["devpi-process (>=1.0.2)", "pytest (>=8.3.4)", "pytest-mock (>=3.14)"] -[[package]] -name = "types-requests" -version = "2.32.0.20240914" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.8" -files = [ - {file = "types-requests-2.32.0.20240914.tar.gz", hash = "sha256:2850e178db3919d9bf809e434eef65ba49d0e7e33ac92d588f4a5e295fffd405"}, - {file = "types_requests-2.32.0.20240914-py3-none-any.whl", hash = "sha256:59c2f673eb55f32a99b2894faf6020e1a9f4a402ad0f192bfee0b64469054310"}, -] - -[package.dependencies] -urllib3 = ">=2" - [[package]] name = "types-setuptools" version = "75.1.0.20240917" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.8" +groups = ["types"] files = [ {file = "types-setuptools-75.1.0.20240917.tar.gz", hash = "sha256:12f12a165e7ed383f31def705e5c0fa1c26215dd466b0af34bd042f7d5331f55"}, {file = "types_setuptools-75.1.0.20240917-py3-none-any.whl", hash = "sha256:06f78307e68d1bbde6938072c57b81cf8a99bc84bd6dc7e4c5014730b097dc0c"}, @@ -1363,27 +1409,12 @@ version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main", "dev", "format", "tests", "types"] files = [ {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] - -[[package]] -name = "urllib3" -version = "2.2.3" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +markers = {main = "python_version < \"3.11\"", dev = "python_version < \"3.11\"", format = "python_version < \"3.11\"", tests = "python_version < \"3.11\""} [[package]] name = "virtualenv" @@ -1391,6 +1422,7 @@ version = "20.34.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "virtualenv-20.34.0-py3-none-any.whl", hash = "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026"}, {file = "virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a"}, @@ -1404,7 +1436,7 @@ typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\"" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "werkzeug" @@ -1412,6 +1444,8 @@ version = "3.0.6" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"flask\"" files = [ {file = "werkzeug-3.0.6-py3-none-any.whl", hash = "sha256:1bc0c2310d2fbb07b1dd1105eba2f7af72f322e1e455f2f93c993bee8c8a5f17"}, {file = "werkzeug-3.0.6.tar.gz", hash = "sha256:a8dd59d4de28ca70471a34cba79bed5f7ef2e036a76b3ab0835474246eb41f8d"}, @@ -1429,23 +1463,25 @@ version = "3.20.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"flask\" and python_version < \"3.10\"" files = [ {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [extras] flask = ["Flask"] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = ">=3.8.1,<4.0" -content-hash = "3ff83961673abf5e34bf736af959ea3b3e2dad184de7a3048a42a5b5c9e41580" +content-hash = "136f00d0a2be111c462cad9f44b9e4e2d39d15ac7c41c388e273199f89083884" diff --git a/pyproject.toml b/pyproject.toml index b422d1e14..f7dd694b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,18 +29,15 @@ packages = [{ include = "descope" }] [tool.poetry.extras] Flask = ["Flask"] - [tool.poetry.urls] "Bug Tracker" = "https://github.com/descope/python-sdk/issues" - [tool.poetry.dependencies] python = ">=3.8.1,<4.0" -requests = ">=2.27.0" pyjwt = { version = ">=2.4.0", extras = ["crypto"] } email-validator = [{ version = ">=2,<3", python = ">=3.8" }] -liccheck = "^0.9.1" Flask = ">=2" +httpx = "^0.27.2" [tool.poetry.group.dev.dependencies] mock = "5.2.0" @@ -64,7 +61,6 @@ black = [ [tool.poetry.group.types.dependencies] mypy = "1.11.2" -types-requests = "2.32.0.20240914" types-setuptools = "75.1.0.20240917" [tool.poetry.group.tests.dependencies] diff --git a/tests/management/test_access_key.py b/tests/management/test_access_key.py index 947a75600..ced57f793 100644 --- a/tests/management/test_access_key.py +++ b/tests/management/test_access_key.py @@ -6,6 +6,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -33,8 +34,8 @@ def test_create(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.access_key.create, @@ -42,9 +43,9 @@ def test_create(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"key": {"id": "ak1"}, "cleartext": "abc"}""" ) @@ -84,8 +85,8 @@ def test_create(self): "description": "this is my access key", "permittedIps": ["10.0.0.1", "192.168.1.0/24"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -98,8 +99,8 @@ def test_load(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.access_key.load, @@ -107,9 +108,9 @@ def test_load(self): ) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"key": {"id": "ak1"}}""") mock_get.return_value = network_resp resp = client.mgmt.access_key.load("key-id") @@ -123,8 +124,8 @@ def test_load(self): "x-descope-project-id": self.dummy_project_id, }, params={"id": "key-id"}, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -137,8 +138,8 @@ def test_search_all_users(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.access_key.search_all_access_keys, @@ -146,9 +147,9 @@ def test_search_all_users(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"keys": [{"id": "ak1"}, {"id": "ak2"}]}""" ) @@ -169,8 +170,8 @@ def test_search_all_users(self): json={ "tenantIds": ["t1, t2"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -183,8 +184,8 @@ def test_update(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.access_key.update, @@ -193,8 +194,8 @@ def test_update(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.access_key.update( "key-id", name="new-name", description=None @@ -213,8 +214,8 @@ def test_update(self): "name": "new-name", "description": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -227,8 +228,8 @@ def test_deactivate(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.access_key.deactivate, @@ -236,8 +237,8 @@ def test_deactivate(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.access_key.deactivate("ak1")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.access_key_deactivate_path}", @@ -250,8 +251,8 @@ def test_deactivate(self): json={ "id": "ak1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -264,8 +265,8 @@ def test_activate(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.access_key.activate, @@ -273,8 +274,8 @@ def test_activate(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.access_key.activate("ak1")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.access_key_activate_path}", @@ -287,8 +288,8 @@ def test_activate(self): json={ "id": "ak1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -301,8 +302,8 @@ def test_delete(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.access_key.delete, @@ -310,8 +311,8 @@ def test_delete(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.access_key.delete("ak1")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.access_key_delete_path}", @@ -324,7 +325,7 @@ def test_delete(self): json={ "id": "ak1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_audit.py b/tests/management/test_audit.py index dce1e02b4..8cae98209 100644 --- a/tests/management/test_audit.py +++ b/tests/management/test_audit.py @@ -6,6 +6,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -33,8 +34,8 @@ def test_search(self): ) # Test failed search - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.audit.search, @@ -42,9 +43,9 @@ def test_search(self): ) # Test success search - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "audits": [ { @@ -77,8 +78,8 @@ def test_search(self): }, params=None, json={"noTenants": False}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -91,16 +92,16 @@ def test_create_event(self): ) # Test failed search - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.audit.create_event, "a", "b", "c", "d" ) # Test success search - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = {} mock_post.return_value = network_resp client.mgmt.audit.create_event( @@ -127,7 +128,7 @@ def test_create_event(self): "type": "info", "data": {"some": "data"}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_authz.py b/tests/management/test_authz.py index 44112b802..5f405502b 100644 --- a/tests/management/test_authz.py +++ b/tests/management/test_authz.py @@ -4,6 +4,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -31,13 +32,13 @@ def test_save_schema(self): ) # Test failed save_schema - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.save_schema, {}, True) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.authz.save_schema({"name": "kuku"}, True)) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_schema_save}", @@ -48,8 +49,8 @@ def test_save_schema(self): }, params=None, json={"schema": {"name": "kuku"}, "upgrade": True}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -62,13 +63,13 @@ def test_delete_schema(self): ) # Test failed delete_schema - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.delete_schema) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.authz.delete_schema()) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_schema_delete}", @@ -79,8 +80,8 @@ def test_delete_schema(self): }, params=None, json=None, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -93,13 +94,13 @@ def test_load_schema(self): ) # Test failed load_schema - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.load_schema) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.authz.load_schema()) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_schema_load}", @@ -110,8 +111,8 @@ def test_load_schema(self): }, params=None, json=None, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -124,13 +125,13 @@ def test_save_namespace(self): ) # Test failed save_namespace - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.save_namespace, {}) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.authz.save_namespace({"name": "kuku"}, "old", "v1") ) @@ -147,8 +148,8 @@ def test_save_namespace(self): "oldName": "old", "schemaName": "v1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -161,13 +162,13 @@ def test_delete_namespace(self): ) # Test failed delete_namespace - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.delete_namespace, "a") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.authz.delete_namespace("a", "b")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_ns_delete}", @@ -178,8 +179,8 @@ def test_delete_namespace(self): }, params=None, json={"name": "a", "schemaName": "b"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -192,15 +193,15 @@ def test_save_relation_definition(self): ) # Test failed save_relation_definition - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.authz.save_relation_definition, {}, "a" ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.authz.save_relation_definition( {"name": "kuku"}, "a", "old", "v1" @@ -220,8 +221,8 @@ def test_save_relation_definition(self): "oldName": "old", "schemaName": "v1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -234,15 +235,15 @@ def test_delete_relation_definition(self): ) # Test failed delete_relation_definition - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.authz.delete_relation_definition, "a", "b" ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.authz.delete_relation_definition("a", "b", "c") ) @@ -255,8 +256,8 @@ def test_delete_relation_definition(self): }, params=None, json={"name": "a", "namespace": "b", "schemaName": "c"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -269,13 +270,13 @@ def test_create_relations(self): ) # Test failed create_relations - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.create_relations, []) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.authz.create_relations( [ @@ -306,8 +307,8 @@ def test_create_relations(self): } ] }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -320,13 +321,13 @@ def test_delete_relations(self): ) # Test failed delete_relations - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.delete_relations, []) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.authz.delete_relations( [ @@ -357,8 +358,8 @@ def test_delete_relations(self): } ] }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -371,15 +372,15 @@ def test_delete_relations_for_resources(self): ) # Test failed delete_relations_for_resources - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.authz.delete_relations_for_resources, [] ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.authz.delete_relations_for_resources(["r"])) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_re_delete_resources}", @@ -390,8 +391,8 @@ def test_delete_relations_for_resources(self): }, params=None, json={"resources": ["r"]}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -404,13 +405,13 @@ def test_has_relations(self): ) # Test failed has_relations - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.has_relations, []) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( client.mgmt.authz.has_relations( [ @@ -441,8 +442,8 @@ def test_has_relations(self): } ] }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -455,15 +456,15 @@ def test_who_can_access(self): ) # Test failed who_can_access - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.authz.who_can_access, "a", "b", "c" ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.authz.who_can_access("a", "b", "c")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_re_who}", @@ -474,8 +475,8 @@ def test_who_can_access(self): }, params=None, json={"resource": "a", "relationDefinition": "b", "namespace": "c"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -488,13 +489,13 @@ def test_resource_relations(self): ) # Test failed resource_relations - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.resource_relations, "a") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.authz.resource_relations("a")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_re_resource}", @@ -505,8 +506,8 @@ def test_resource_relations(self): }, params=None, json={"resource": "a"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -519,13 +520,13 @@ def test_targets_relations(self): ) # Test failed targets_relations - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.targets_relations, ["a"]) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.authz.targets_relations(["a"])) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_re_targets}", @@ -536,8 +537,8 @@ def test_targets_relations(self): }, params=None, json={"targets": ["a"]}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -550,15 +551,15 @@ def test_what_can_target_access(self): ) # Test failed what_can_target_access - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.authz.what_can_target_access, "a" ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.authz.what_can_target_access("a")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_re_target_all}", @@ -569,8 +570,8 @@ def test_what_can_target_access(self): }, params=None, json={"target": "a"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -583,8 +584,8 @@ def test_what_can_target_access_with_relation(self): ) # Test failed what_can_target_access_with_relation - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.authz.what_can_target_access_with_relation, @@ -594,8 +595,8 @@ def test_what_can_target_access_with_relation(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( client.mgmt.authz.what_can_target_access_with_relation("a", "b", "c") ) @@ -608,8 +609,8 @@ def test_what_can_target_access_with_relation(self): }, params=None, json={"target": "a", "relationDefinition": "b", "namespace": "c"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -622,13 +623,13 @@ def test_get_modified(self): ) # Test failed get_modified - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.authz.get_modified) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.authz.get_modified()) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.authz_get_modified}", @@ -639,7 +640,7 @@ def test_get_modified(self): }, params=None, json={"since": 0}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_fga.py b/tests/management/test_fga.py index c2f4ad2ed..a77f31192 100644 --- a/tests/management/test_fga.py +++ b/tests/management/test_fga.py @@ -4,6 +4,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -31,13 +32,13 @@ def test_save_schema(self): ) # Test failed save_schema - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.fga.save_schema, "") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.fga.save_schema("model AuthZ 1.0")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.fga_save_schema}", @@ -48,8 +49,8 @@ def test_save_schema(self): }, params=None, json={"dsl": "model AuthZ 1.0"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -62,13 +63,13 @@ def test_create_relations(self): ) # Test failed create_relations - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.fga.create_relations, []) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.fga.create_relations( [ @@ -101,8 +102,8 @@ def test_create_relations(self): } ] }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -115,13 +116,13 @@ def test_delete_relations(self): ) # Test failed delete_relations - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.fga.delete_relations, []) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.fga.delete_relations( [ @@ -154,8 +155,8 @@ def test_delete_relations(self): } ] }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -168,13 +169,13 @@ def test_check(self): ) # Test failed has_relations - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.fga.check, []) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( client.mgmt.fga.check( [ @@ -207,8 +208,8 @@ def test_check(self): } ] }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -225,8 +226,8 @@ def test_load_resources_details_success(self): {"resourceId": "r2", "resourceType": "type2", "displayName": "Name2"}, ] } - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True mock_post.return_value.json.return_value = response_body ids = [ {"resourceId": "r1", "resourceType": "type1"}, @@ -243,8 +244,8 @@ def test_load_resources_details_success(self): }, params=None, json={"resourceIdentifiers": ids}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -255,8 +256,8 @@ def test_load_resources_details_error(self): False, self.dummy_management_key, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False ids = [{"resourceId": "r1", "resourceType": "type1"}] self.assertRaises( AuthException, @@ -274,8 +275,8 @@ def test_save_resources_details_success(self): details = [ {"resourceId": "r1", "resourceType": "type1", "displayName": "Name1"} ] - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True client.mgmt.fga.save_resources_details(details) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.fga_resources_save}", @@ -286,8 +287,8 @@ def test_save_resources_details_success(self): }, params=None, json={"resourcesDetails": details}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -301,8 +302,8 @@ def test_save_resources_details_error(self): details = [ {"resourceId": "r1", "resourceType": "type1", "displayName": "Name1"} ] - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.fga.save_resources_details, @@ -320,8 +321,8 @@ def test_fga_cache_url_save_schema(self): fga_cache_url=fga_cache_url, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True client.mgmt.fga.save_schema("model AuthZ 1.0") mock_post.assert_called_with( f"{fga_cache_url}{MgmtV1.fga_save_schema}", @@ -332,8 +333,8 @@ def test_fga_cache_url_save_schema(self): }, params=None, json={"dsl": "model AuthZ 1.0"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -358,8 +359,8 @@ def test_fga_cache_url_create_relations(self): } ] - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True client.mgmt.fga.create_relations(relations) mock_post.assert_called_with( f"{fga_cache_url}{MgmtV1.fga_create_relations}", @@ -370,8 +371,8 @@ def test_fga_cache_url_create_relations(self): }, params=None, json={"tuples": relations}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -396,8 +397,8 @@ def test_fga_cache_url_delete_relations(self): } ] - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True client.mgmt.fga.delete_relations(relations) mock_post.assert_called_with( f"{fga_cache_url}{MgmtV1.fga_delete_relations}", @@ -408,8 +409,8 @@ def test_fga_cache_url_delete_relations(self): }, params=None, json={"tuples": relations}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -434,8 +435,8 @@ def test_fga_cache_url_check(self): } ] - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True mock_post.return_value.json.return_value = { "tuples": [ { @@ -454,8 +455,8 @@ def test_fga_cache_url_check(self): }, params=None, json={"tuples": relations}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(len(result), 1) @@ -472,8 +473,8 @@ def test_fga_without_cache_url_uses_default_base_url(self): # No fga_cache_url provided ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True client.mgmt.fga.save_schema("model AuthZ 1.0") # Should use default base URL mock_post.assert_called_with( @@ -485,7 +486,7 @@ def test_fga_without_cache_url_uses_default_base_url(self): }, params=None, json={"dsl": "model AuthZ 1.0"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_flow.py b/tests/management/test_flow.py index 4a527a5b1..7f585b5b0 100644 --- a/tests/management/test_flow.py +++ b/tests/management/test_flow.py @@ -4,6 +4,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -31,16 +32,16 @@ def test_list_flows(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.flow.list_flows, ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.flow.list_flows()) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.flow_list_path}", @@ -51,8 +52,8 @@ def test_list_flows(self): }, params=None, json=None, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -65,8 +66,8 @@ def test_delete_flows(self): ) # Test failed delete flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.flow.delete_flows, @@ -74,8 +75,8 @@ def test_delete_flows(self): ) # Test success delete flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.flow.delete_flows(["flow-1", "flow-2"])) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.flow_delete_path}", @@ -86,8 +87,8 @@ def test_delete_flows(self): }, params=None, json={"ids": ["flow-1", "flow-2"]}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -100,8 +101,8 @@ def test_export_flow(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.flow.export_flow, @@ -109,8 +110,8 @@ def test_export_flow(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.flow.export_flow("test")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.flow_export_path}", @@ -123,8 +124,8 @@ def test_export_flow(self): json={ "flowId": "test", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -137,8 +138,8 @@ def test_import_flow(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.flow.import_flow, @@ -148,8 +149,8 @@ def test_import_flow(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( client.mgmt.flow.import_flow("name", {"name": "test"}, [{"id": "test"}]) ) @@ -166,8 +167,8 @@ def test_import_flow(self): "flow": {"name": "test"}, "screens": [{"id": "test"}], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -180,13 +181,13 @@ def test_export_theme(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.flow.export_theme) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.flow.export_theme()) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.theme_export_path}", @@ -197,8 +198,8 @@ def test_export_theme(self): }, params=None, json={}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -211,15 +212,15 @@ def test_import_theme(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.flow.import_theme, {"id": "test"} ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.flow.import_theme({"id": "test"})) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.theme_import_path}", @@ -230,7 +231,7 @@ def test_import_theme(self): }, params=None, json={"theme": {"id": "test"}}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_group.py b/tests/management/test_group.py index f7d07a281..93a13ebf3 100644 --- a/tests/management/test_group.py +++ b/tests/management/test_group.py @@ -4,6 +4,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -31,8 +32,8 @@ def test_load_all_groups(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.group.load_all_groups, @@ -40,8 +41,8 @@ def test_load_all_groups(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.mgmt.group.load_all_groups("someTenantId")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.group_load_all_path}", @@ -54,8 +55,8 @@ def test_load_all_groups(self): json={ "tenantId": "someTenantId", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -68,8 +69,8 @@ def test_load_all_groups_for_members(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.group.load_all_groups_for_members, @@ -77,8 +78,8 @@ def test_load_all_groups_for_members(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( client.mgmt.group.load_all_groups_for_members( "someTenantId", ["one", "two"], ["three", "four"] @@ -97,8 +98,8 @@ def test_load_all_groups_for_members(self): "loginIds": ["three", "four"], "userIds": ["one", "two"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -111,8 +112,8 @@ def test_load_all_group_members(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.group.load_all_group_members, @@ -121,8 +122,8 @@ def test_load_all_group_members(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( client.mgmt.group.load_all_group_members("someTenantId", "someGroupId") ) @@ -138,7 +139,7 @@ def test_load_all_group_members(self): "tenantId": "someTenantId", "groupId": "someGroupId", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_jwt.py b/tests/management/test_jwt.py index 2cab70de8..536b9f5e2 100644 --- a/tests/management/test_jwt.py +++ b/tests/management/test_jwt.py @@ -5,8 +5,8 @@ from descope import AuthException, DescopeClient from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtLoginOptions, MgmtV1 - -from .. import common +from tests import common +from tests.testutils import SSLMatcher class TestUser(common.DescopeTest): @@ -33,8 +33,8 @@ def test_update_jwt(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.jwt.update_jwt, "jwt", {"k1": "v1"}, 0 ) @@ -44,9 +44,9 @@ def test_update_jwt(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"jwt": "response"}""") mock_post.return_value = network_resp resp = client.mgmt.jwt.update_jwt("test", {"k1": "v1"}, 40) @@ -64,8 +64,8 @@ def test_update_jwt(self): "customClaims": {"k1": "v1"}, "refreshDuration": 40, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -85,8 +85,8 @@ def test_update_jwt(self): "customClaims": {"k1": "v1"}, "refreshDuration": 0, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -100,8 +100,8 @@ def test_impersonate(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.jwt.impersonate, "imp1", "imp2", False ) @@ -115,9 +115,9 @@ def test_impersonate(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"jwt": "response"}""") mock_post.return_value = network_resp resp = client.mgmt.jwt.impersonate("imp1", "imp2", True) @@ -138,8 +138,8 @@ def test_impersonate(self): "selectedTenant": None, "refreshDuration": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -153,8 +153,8 @@ def test_stop_impersonation(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.jwt.stop_impersonation, @@ -162,9 +162,9 @@ def test_stop_impersonation(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"jwt": "response"}""") mock_post.return_value = network_resp resp = client.mgmt.jwt.stop_impersonation("jwtstr") @@ -183,8 +183,8 @@ def test_stop_impersonation(self): "selectedTenant": None, "refreshDuration": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -208,9 +208,9 @@ def test_sign_in(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"jwt": "response"}""") mock_post.return_value = network_resp client.mgmt.jwt.sign_in("loginId") @@ -231,8 +231,8 @@ def test_sign_in(self): "jwt": None, "refreshDuration": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -249,9 +249,9 @@ def test_sign_up(self): self.assertRaises(AuthException, client.mgmt.jwt.sign_up, "") # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"jwt": "response"}""") mock_post.return_value = network_resp client.mgmt.jwt.sign_up("loginId") @@ -282,8 +282,8 @@ def test_sign_up(self): "customClaims": None, "refreshDuration": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -300,9 +300,9 @@ def test_sign_up_or_in(self): self.assertRaises(AuthException, client.mgmt.jwt.sign_up_or_in, "") # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"jwt": "response"}""") mock_post.return_value = network_resp client.mgmt.jwt.sign_up_or_in("loginId") @@ -333,8 +333,8 @@ def test_sign_up_or_in(self): "customClaims": None, "refreshDuration": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -348,9 +348,9 @@ def test_anonymous(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"jwt": "response"}""") mock_post.return_value = network_resp client.mgmt.jwt.anonymous({"k1": "v1"}, "id") @@ -367,8 +367,8 @@ def test_anonymous(self): "selectedTenant": "id", "refreshDuration": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_outbound_application.py b/tests/management/test_outbound_application.py index 05a3874f1..4161c52a0 100644 --- a/tests/management/test_outbound_application.py +++ b/tests/management/test_outbound_application.py @@ -31,9 +31,9 @@ def test_create_application_success(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "app": { "id": "app123", @@ -70,9 +70,9 @@ def test_create_application_with_all_parameters_success(self): token_params = [URLParam("grant_type", "authorization_code")] prompts = [PromptType.LOGIN, PromptType.CONSENT] - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "app": { "id": "app123", @@ -118,8 +118,8 @@ def test_create_application_failure(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.create_application, @@ -134,9 +134,9 @@ def test_update_application_success(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "app": { "id": "app123", @@ -176,9 +176,9 @@ def test_update_application_with_all_parameters_success(self): token_params = [URLParam("grant_type", "authorization_code")] prompts = [PromptType.LOGIN, PromptType.CONSENT, PromptType.SELECT_ACCOUNT] - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "app": { "id": "app123", @@ -227,8 +227,8 @@ def test_update_application_failure(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.update_application, @@ -244,9 +244,9 @@ def test_delete_application_success(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_post.return_value = network_resp client.mgmt.outbound_application.delete_application("app123") @@ -258,8 +258,8 @@ def test_delete_application_failure(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.delete_application, @@ -274,9 +274,9 @@ def test_load_application_success(self): self.dummy_management_key, ) - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "app": { "id": "app123", @@ -303,8 +303,8 @@ def test_load_application_failure(self): self.dummy_management_key, ) - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.load_application, @@ -319,9 +319,9 @@ def test_load_all_applications_success(self): self.dummy_management_key, ) - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "apps": [ {"id": "app1", "name": "App 1", "description": "Description 1"}, @@ -346,8 +346,8 @@ def test_load_all_applications_failure(self): self.dummy_management_key, ) - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.load_all_applications, @@ -361,9 +361,9 @@ def test_fetch_token_by_scopes_success(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "token": { "token": "access-token", @@ -400,8 +400,8 @@ def test_fetch_token_by_scopes_failure(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.fetch_token_by_scopes, @@ -418,9 +418,9 @@ def test_fetch_token_success(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "token": { "token": "access-token", @@ -453,8 +453,8 @@ def test_fetch_token_failure(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.fetch_token, @@ -470,9 +470,9 @@ def test_fetch_tenant_token_by_scopes_success(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "token": { "token": "access-token", @@ -505,8 +505,8 @@ def test_fetch_tenant_token_by_scopes_failure(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.fetch_tenant_token_by_scopes, @@ -523,9 +523,9 @@ def test_fetch_tenant_token_success(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "token": { "token": "access-token", @@ -558,8 +558,8 @@ def test_fetch_tenant_token_failure(self): self.dummy_management_key, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application.fetch_tenant_token, @@ -807,9 +807,9 @@ def setUp(self) -> None: def test_fetch_token_by_scopes_success(self): client = DescopeClient(self.dummy_project_id, self.public_key_dict, False) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "token": { "token": "access-token", @@ -843,8 +843,8 @@ def test_fetch_token_by_scopes_failure(self): client = DescopeClient(self.dummy_project_id, self.public_key_dict, False) # Test failure of empty token - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application_by_token.fetch_token_by_scopes, @@ -855,8 +855,8 @@ def test_fetch_token_by_scopes_failure(self): ) # Test invalid response failure - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application_by_token.fetch_token_by_scopes, @@ -869,9 +869,9 @@ def test_fetch_token_by_scopes_failure(self): def test_fetch_token_success(self): client = DescopeClient(self.dummy_project_id, self.public_key_dict, False) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "token": { "token": "access-token", @@ -904,8 +904,8 @@ def test_fetch_token_failure(self): client = DescopeClient(self.dummy_project_id, self.public_key_dict, False) # Test failure of empty token - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertRaises( AuthException, client.mgmt.outbound_application_by_token.fetch_token, @@ -915,8 +915,8 @@ def test_fetch_token_failure(self): ) # Test invalid response failure - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application_by_token.fetch_token, @@ -928,9 +928,9 @@ def test_fetch_token_failure(self): def test_fetch_tenant_token_by_scopes_success(self): client = DescopeClient(self.dummy_project_id, self.public_key_dict, False) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "token": { "token": "access-token", @@ -965,8 +965,8 @@ def test_fetch_tenant_token_by_scopes_failure(self): client = DescopeClient(self.dummy_project_id, self.public_key_dict, False) # Test failure of empty token - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertRaises( AuthException, client.mgmt.outbound_application_by_token.fetch_tenant_token_by_scopes, @@ -977,8 +977,8 @@ def test_fetch_tenant_token_by_scopes_failure(self): ) # Test invalid response failure - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application_by_token.fetch_tenant_token_by_scopes, @@ -991,9 +991,9 @@ def test_fetch_tenant_token_by_scopes_failure(self): def test_fetch_tenant_token_success(self): client = DescopeClient(self.dummy_project_id, self.public_key_dict, False) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = { "token": { "token": "access-token", @@ -1022,8 +1022,8 @@ def test_fetch_tenant_token_failure(self): client = DescopeClient(self.dummy_project_id, self.public_key_dict, False) # Test failure of empty token - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertRaises( AuthException, client.mgmt.outbound_application_by_token.fetch_tenant_token, @@ -1033,8 +1033,8 @@ def test_fetch_tenant_token_failure(self): ) # Test invalid response failure - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.outbound_application_by_token.fetch_tenant_token, diff --git a/tests/management/test_permission.py b/tests/management/test_permission.py index b6a9caca0..aa7e1f93f 100644 --- a/tests/management/test_permission.py +++ b/tests/management/test_permission.py @@ -6,6 +6,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -33,8 +34,8 @@ def test_create(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.permission.create, @@ -42,8 +43,8 @@ def test_create(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.permission.create("P1", "Something")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.permission_create_path}", @@ -57,8 +58,8 @@ def test_create(self): "name": "P1", "description": "Something", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -71,8 +72,8 @@ def test_update(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.permission.update, @@ -81,8 +82,8 @@ def test_update(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.permission.update( "name", @@ -103,8 +104,8 @@ def test_update(self): "newName": "new-name", "description": "new-description", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -117,8 +118,8 @@ def test_delete(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.permission.delete, @@ -126,8 +127,8 @@ def test_delete(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.permission.delete("name")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.permission_delete_path}", @@ -140,8 +141,8 @@ def test_delete(self): json={ "name": "name", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -154,14 +155,14 @@ def test_load_all(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.permission.load_all) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"permissions": [{"name": "p1"}, {"name": "p2"}]}""" ) @@ -179,7 +180,7 @@ def test_load_all(self): "x-descope-project-id": self.dummy_project_id, }, params=None, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_project.py b/tests/management/test_project.py index 3217dcfec..2b3d15810 100644 --- a/tests/management/test_project.py +++ b/tests/management/test_project.py @@ -6,6 +6,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -33,8 +34,8 @@ def test_update_name(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.project.update_name, @@ -42,8 +43,8 @@ def test_update_name(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.project.update_name("new-name")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.project_update_name}", @@ -56,8 +57,8 @@ def test_update_name(self): json={ "name": "new-name", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -70,8 +71,8 @@ def test_update_tags(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.project.update_tags, @@ -79,8 +80,8 @@ def test_update_tags(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.project.update_tags(["tag1", "tag2"])) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.project_update_tags}", @@ -93,8 +94,8 @@ def test_update_tags(self): json={ "tags": ["tag1", "tag2"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -107,17 +108,17 @@ def test_list_projects(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.project.list_projects, ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True json_str = """ { "projects": [ @@ -145,8 +146,8 @@ def test_list_projects(self): }, params=None, json={}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -159,8 +160,8 @@ def test_clone(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.project.clone, @@ -170,9 +171,9 @@ def test_clone(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ { @@ -200,8 +201,8 @@ def test_clone(self): "environment": "production", "tags": ["apple", "banana", "cherry"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -214,17 +215,17 @@ def test_export_project(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.project.export_project, ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ { @@ -245,8 +246,8 @@ def test_export_project(self): }, params=None, json={}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -259,8 +260,8 @@ def test_import_project(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.project.import_project, @@ -270,9 +271,9 @@ def test_import_project(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_post.return_value = network_resp files = { "foo": "bar", @@ -291,7 +292,7 @@ def test_import_project(self): "foo": "bar", }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_role.py b/tests/management/test_role.py index 8bc15e176..bd040269b 100644 --- a/tests/management/test_role.py +++ b/tests/management/test_role.py @@ -6,6 +6,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -33,8 +34,8 @@ def test_create(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.role.create, @@ -42,8 +43,8 @@ def test_create(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.role.create("R1", "Something", ["P1"], "t1", True) ) @@ -62,8 +63,8 @@ def test_create(self): "tenantId": "t1", "default": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -76,8 +77,8 @@ def test_update(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.role.update, @@ -86,8 +87,8 @@ def test_update(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.role.update( "name", @@ -114,8 +115,8 @@ def test_update(self): "tenantId": "t1", "default": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -128,8 +129,8 @@ def test_delete(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.role.delete, @@ -137,8 +138,8 @@ def test_delete(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.role.delete("name")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.role_delete_path}", @@ -149,8 +150,8 @@ def test_delete(self): }, params=None, json={"name": "name", "tenantId": None}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -163,14 +164,14 @@ def test_load_all(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.role.load_all) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ { @@ -199,8 +200,8 @@ def test_load_all(self): "x-descope-project-id": self.dummy_project_id, }, params=None, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -213,8 +214,8 @@ def test_search(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.role.search, @@ -223,9 +224,9 @@ def test_search(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ { @@ -260,7 +261,7 @@ def test_search(self): "roleNameLike": "x", "permissionNames": ["p1", "p2"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_sso_application.py b/tests/management/test_sso_application.py index 8da82ba33..6fbedaa1f 100644 --- a/tests/management/test_sso_application.py +++ b/tests/management/test_sso_application.py @@ -12,6 +12,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -39,8 +40,8 @@ def test_create_oidc_application(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso_application.create_oidc_application, @@ -49,9 +50,9 @@ def test_create_oidc_application(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"id": "app1"}""") mock_post.return_value = network_resp resp = client.mgmt.sso_application.create_oidc_application( @@ -77,8 +78,8 @@ def test_create_oidc_application(self): "logo": None, "forceAuthentication": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -109,8 +110,8 @@ def test_create_saml_application(self): entity_id="", ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso_application.create_saml_application, @@ -121,9 +122,9 @@ def test_create_saml_application(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"id": "app1"}""") mock_post.return_value = network_resp resp = client.mgmt.sso_application.create_saml_application( @@ -188,8 +189,8 @@ def test_create_saml_application(self): "forceAuthentication": True, "logoutRedirectUrl": "http://dummy.com/logout", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -202,8 +203,8 @@ def test_update_oidc_application(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso_application.update_oidc_application, @@ -213,9 +214,9 @@ def test_update_oidc_application(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True self.assertIsNone( client.mgmt.sso_application.update_oidc_application( "app1", "name", "http://dummy.com" @@ -238,8 +239,8 @@ def test_update_oidc_application(self): "logo": None, "forceAuthentication": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -272,8 +273,8 @@ def test_update_saml_application(self): entity_id="", ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso_application.update_saml_application, @@ -285,9 +286,9 @@ def test_update_saml_application(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True self.assertIsNone( client.mgmt.sso_application.update_saml_application( id="id1", @@ -352,8 +353,8 @@ def test_update_saml_application(self): "forceAuthentication": False, "logoutRedirectUrl": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -366,8 +367,8 @@ def test_delete(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso_application.delete, @@ -375,8 +376,8 @@ def test_delete(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.sso_application.delete("app1")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.sso_application_delete_path}", @@ -389,8 +390,8 @@ def test_delete(self): json={ "id": "app1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -403,8 +404,8 @@ def test_load(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso_application.load, @@ -412,9 +413,9 @@ def test_load(self): ) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ {"id":"app1","name":"App1","description":"","enabled":true,"logo":"","appType":"saml","samlSettings":{"loginPageUrl":"http://dummy.com/login","idpCert":"cert","useMetadataInfo":true,"metadataUrl":"http://dummy.com/md","entityId":"","acsUrl":"","certificate":"","attributeMapping":[{"name":"email","type":"","value":"attrVal1"}],"groupsMapping":[{"name":"grp1","type":"","filterType":"roles","value":"","roles":[{"id":"myRoleId","name":"myRole"}]}],"idpMetadataUrl":"","idpEntityId":"","idpSsoUrl":"","acsAllowedCallbacks":[],"subjectNameIdType":"","subjectNameIdFormat":""},"oidcSettings":{"loginPageUrl":"","issuer":"","discoveryUrl":""}} @@ -453,8 +454,8 @@ def test_load(self): "x-descope-project-id": self.dummy_project_id, }, params={"id": "app1"}, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -467,14 +468,14 @@ def test_load_all(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.sso_application.load_all) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ { @@ -534,7 +535,7 @@ def test_load_all(self): "x-descope-project-id": self.dummy_project_id, }, params=None, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_sso_settings.py b/tests/management/test_sso_settings.py index 482e236ba..0c6cbc9b9 100644 --- a/tests/management/test_sso_settings.py +++ b/tests/management/test_sso_settings.py @@ -13,6 +13,7 @@ SSOSettings, ) +from tests.testutils import SSLMatcher from .. import common @@ -40,8 +41,8 @@ def test_delete_settings(self): ) # Test failed flows - with patch("requests.delete") as mock_delete: - mock_delete.return_value.ok = False + with patch("httpx.delete") as mock_delete: + mock_delete.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.delete_settings, @@ -49,9 +50,9 @@ def test_delete_settings(self): ) # Test success flow - with patch("requests.delete") as mock_delete: + with patch("httpx.delete") as mock_delete: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_delete.return_value = network_resp client.mgmt.sso.delete_settings("tenant-id") @@ -64,8 +65,8 @@ def test_delete_settings(self): "Authorization": f"Bearer {self.dummy_project_id}:{self.dummy_management_key}", "x-descope-project-id": self.dummy_project_id, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -78,8 +79,8 @@ def test_load_settings(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.load_settings, @@ -87,9 +88,9 @@ def test_load_settings(self): ) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"tenant": {"id": "T2AAAA", "name": "myTenantName", "selfProvisioningDomains": [], "customAttributes": {}, "authType": "saml", "domains": ["lulu", "kuku"]}, "saml": {"idpEntityId": "", "idpSSOUrl": "", "idpCertificate": "", "defaultSSORoles": ["aa", "bb"], "idpMetadataUrl": "https://dummy.com/metadata", "spEntityId": "", "spACSUrl": "", "spCertificate": "", "attributeMapping": {"name": "name", "email": "email", "username": "", "phoneNumber": "phone", "group": "", "givenName": "", "middleName": "", "familyName": "", "picture": "", "customAttributes": {}}, "groupsMapping": [], "redirectUrl": ""}, "oidc": {"name": "", "clientId": "", "clientSecret": "", "redirectUrl": "", "authUrl": "", "tokenUrl": "", "userDataUrl": "", "scope": [], "JWKsUrl": "", "userAttrMapping": {"loginId": "sub", "username": "", "name": "name", "email": "email", "phoneNumber": "phone_number", "verifiedEmail": "email_verified", "verifiedPhone": "phone_number_verified", "picture": "picture", "givenName": "given_name", "middleName": "middle_name", "familyName": "family_name"}, "manageProviderTokens": false, "callbackDomain": "", "prompt": [], "grantType": "authorization_code", "issuer": ""}}""" ) @@ -114,8 +115,8 @@ def test_load_settings(self): "x-descope-project-id": self.dummy_project_id, }, params={"tenantId": "T2AAAA"}, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -128,8 +129,8 @@ def test_configure_oidc_settings(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.configure_oidc_settings, @@ -142,8 +143,8 @@ def test_configure_oidc_settings(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.configure_oidc_settings( "tenant-id", @@ -214,8 +215,8 @@ def test_configure_oidc_settings(self): }, "domains": ["domain.com"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -228,8 +229,8 @@ def test_configure_saml_settings(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.configure_saml_settings, @@ -247,8 +248,8 @@ def test_configure_saml_settings(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.configure_saml_settings( "tenant-id", @@ -308,8 +309,8 @@ def test_configure_saml_settings(self): "redirectUrl": "https://redirect.com", "domains": ["domain.com"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -322,8 +323,8 @@ def test_configure_saml_settings_by_metadata(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.configure_saml_settings_by_metadata, @@ -334,8 +335,8 @@ def test_configure_saml_settings_by_metadata(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.configure_saml_settings_by_metadata( "tenant-id", @@ -391,8 +392,8 @@ def test_configure_saml_settings_by_metadata(self): "redirectUrl": "https://redirect.com", "domains": ["domain.com"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -409,8 +410,8 @@ def test_get_settings(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.get_settings, @@ -418,9 +419,9 @@ def test_get_settings(self): ) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"domains": ["lulu", "kuku"], "tenantId": "tenant-id"}""" ) @@ -436,8 +437,8 @@ def test_get_settings(self): "x-descope-project-id": self.dummy_project_id, }, params={"tenantId": "tenant-id"}, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -450,8 +451,8 @@ def test_configure(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.configure, @@ -464,8 +465,8 @@ def test_configure(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.configure( "tenant-id", @@ -492,14 +493,14 @@ def test_configure(self): "redirectURL": "https://redirect.com", "domains": ["domain.com"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Domain is optional - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.configure( "tenant-id", @@ -525,14 +526,14 @@ def test_configure(self): "redirectURL": "https://redirect.com", "domains": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Redirect is optional - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.configure( "tenant-id", @@ -559,8 +560,8 @@ def test_configure(self): "redirectURL": "", "domains": ["domain.com"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -573,8 +574,8 @@ def test_configure_via_metadata(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.configure_via_metadata, @@ -585,8 +586,8 @@ def test_configure_via_metadata(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.configure_via_metadata( "tenant-id", @@ -609,14 +610,14 @@ def test_configure_via_metadata(self): "redirectURL": "https://redirect.com", "domains": ["domain.com"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test partial arguments - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.configure_via_metadata( "tenant-id", @@ -637,8 +638,8 @@ def test_configure_via_metadata(self): "redirectURL": None, "domains": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -651,8 +652,8 @@ def test_mapping(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.sso.mapping, @@ -662,8 +663,8 @@ def test_mapping(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.sso.mapping( "tenant-id", @@ -694,7 +695,7 @@ def test_mapping(self): "customAttributes": None, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_tenant.py b/tests/management/test_tenant.py index 6a705cadd..74a35bf4b 100644 --- a/tests/management/test_tenant.py +++ b/tests/management/test_tenant.py @@ -6,6 +6,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS from descope.management.common import MgmtV1 +from tests.testutils import SSLMatcher from .. import common @@ -33,8 +34,8 @@ def test_create(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.tenant.create, @@ -42,9 +43,9 @@ def test_create(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"id": "t1"}""") mock_post.return_value = network_resp resp = client.mgmt.tenant.create("name", "t1", ["domain.com"]) @@ -64,15 +65,15 @@ def test_create(self): "enforceSSO": False, "disabled": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with custom attributes, enforce_sso, disabled - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"id": "t1"}""") mock_post.return_value = network_resp resp = client.mgmt.tenant.create( @@ -100,8 +101,8 @@ def test_create(self): "enforceSSO": True, "disabled": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -114,8 +115,8 @@ def test_update(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.tenant.update, @@ -124,8 +125,8 @@ def test_update(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.tenant.update( "t1", "new-name", ["domain.com"], enforce_sso=True, disabled=True @@ -146,14 +147,14 @@ def test_update(self): "enforceSSO": True, "disabled": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with custom attributes, enforce_sso, disabled - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone( client.mgmt.tenant.update( "t1", @@ -180,8 +181,8 @@ def test_update(self): "enforceSSO": True, "disabled": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -194,8 +195,8 @@ def test_delete(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.tenant.delete, @@ -203,8 +204,8 @@ def test_delete(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(client.mgmt.tenant.delete("t1", True)) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.tenant_delete_path}", @@ -215,8 +216,8 @@ def test_delete(self): }, params=None, json={"id": "t1", "cascade": True}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -229,8 +230,8 @@ def test_load(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, client.mgmt.tenant.load, @@ -238,9 +239,9 @@ def test_load(self): ) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ {"id": "t1", "name": "tenant1", "selfProvisioningDomains": ["domain1.com"], "createdTime": 172606520} @@ -258,8 +259,8 @@ def test_load(self): "x-descope-project-id": self.dummy_project_id, }, params={"id": "t1"}, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -272,14 +273,14 @@ def test_load_all(self): ) # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.tenant.load_all) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ { @@ -305,8 +306,8 @@ def test_load_all(self): "x-descope-project-id": self.dummy_project_id, }, params=None, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -319,14 +320,14 @@ def test_search_all(self): ) # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.mgmt.tenant.search_all) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ { @@ -361,8 +362,8 @@ def test_search_all(self): "tenantSelfProvisioningDomains": ["spd1"], "customAttributes": {"k1": "v1"}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/management/test_user.py b/tests/management/test_user.py index 33c0bb6bc..55e71af2e 100644 --- a/tests/management/test_user.py +++ b/tests/management/test_user.py @@ -14,6 +14,7 @@ UserPasswordPbkdf2, ) +from tests.testutils import SSLMatcher from .. import common @@ -40,8 +41,8 @@ def setUp(self) -> None: def test_create(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.create, @@ -49,9 +50,9 @@ def test_create(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.create( @@ -94,16 +95,16 @@ def test_create(self): "additionalLoginIds": ["id-1", "id-2"], "ssoAppIDs": ["app1", "app2"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_create_with_verified_parameters(self): # Test success flow with verified email and phone - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.create( @@ -148,15 +149,15 @@ def test_create_with_verified_parameters(self): "additionalLoginIds": None, "ssoAppIDs": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_create_test_user(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.create, @@ -164,9 +165,9 @@ def test_create_test_user(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.create_test_user( @@ -206,15 +207,15 @@ def test_create_test_user(self): "additionalLoginIds": None, "ssoAppIDs": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_invite(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.invite, @@ -222,9 +223,9 @@ def test_invite(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.invite( @@ -271,15 +272,15 @@ def test_invite(self): "ssoAppIDs": ["app1", "app2"], "templateId": "tid", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_invite_batch(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.invite_batch, @@ -287,9 +288,9 @@ def test_invite_batch(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"users": [{"id": "u1"}]}""") mock_post.return_value = network_resp user = UserObj( @@ -370,8 +371,8 @@ def test_invite_batch(self): }, params=None, json=expected_users, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -414,8 +415,8 @@ def test_invite_batch(self): }, params=None, json=expected_users, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -436,15 +437,15 @@ def test_invite_batch(self): }, params=None, json=expected_users, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_update(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.update, @@ -453,9 +454,9 @@ def test_update(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.update( @@ -489,14 +490,14 @@ def test_update(self): "additionalLoginIds": None, "ssoAppIDs": ["app1", "app2"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with verified flags - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.update( @@ -527,15 +528,15 @@ def test_update(self): "additionalLoginIds": None, "ssoAppIDs": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_patch(self): # Test failed flows - with patch("requests.patch") as mock_patch: - mock_patch.return_value.ok = False + with patch("httpx.patch") as mock_patch: + mock_patch.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.patch, @@ -544,9 +545,9 @@ def test_patch(self): ) # Test success flow with some params set - with patch("requests.patch") as mock_patch: + with patch("httpx.patch") as mock_patch: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_patch.return_value = network_resp resp = self.client.mgmt.user.patch( @@ -579,14 +580,14 @@ def test_patch(self): "customAttributes": {"ak": "av"}, "ssoAppIds": ["app1", "app2"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with other params - with patch("requests.patch") as mock_patch: + with patch("httpx.patch") as mock_patch: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_patch.return_value = network_resp resp = self.client.mgmt.user.patch( @@ -629,8 +630,8 @@ def test_patch(self): {"tenantId": "tenant2", "roleNames": ["role1", "role2"]}, ], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -646,9 +647,9 @@ def test_patch_with_status(self): valid_statuses = ["enabled", "disabled", "invited"] for status in valid_statuses: - with patch("requests.patch") as mock_patch: + with patch("httpx.patch") as mock_patch: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"user": {"id": "u1"}}""" ) @@ -670,15 +671,15 @@ def test_patch_with_status(self): "loginId": "id", "status": status, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test that status is not included when None - with patch("requests.patch") as mock_patch: + with patch("httpx.patch") as mock_patch: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_patch.return_value = network_resp @@ -715,9 +716,9 @@ def test_patch_batch(self): UserObj(login_id="user3", phone="+123456789", status="invited"), ] - with patch("requests.patch") as mock_patch: + with patch("httpx.patch") as mock_patch: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"patchedUsers": [{"id": "u1"}, {"id": "u2"}, {"id": "u3"}], "failedUsers": []}""" ) @@ -755,15 +756,15 @@ def test_patch_batch(self): }, ] }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test batch with mixed success/failure response - with patch("requests.patch") as mock_patch: + with patch("httpx.patch") as mock_patch: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"patchedUsers": [{"id": "u1"}], "failedUsers": [{"failure": "User not found", "user": {"loginId": "user2"}}]}""" ) @@ -778,8 +779,8 @@ def test_patch_batch(self): self.assertEqual(resp["failedUsers"][0]["failure"], "User not found") # Test failed batch operation - with patch("requests.patch") as mock_patch: - mock_patch.return_value.ok = False + with patch("httpx.patch") as mock_patch: + mock_patch.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.patch_batch, @@ -787,9 +788,9 @@ def test_patch_batch(self): ) # Test with test users flag - with patch("requests.patch") as mock_patch: + with patch("httpx.patch") as mock_patch: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"patchedUsers": [{"id": "u1"}], "failedUsers": []}""" ) @@ -805,8 +806,8 @@ def test_patch_batch(self): def test_delete(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.delete, @@ -814,8 +815,8 @@ def test_delete(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(self.client.mgmt.user.delete("u1")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.user_delete_path}", @@ -828,15 +829,15 @@ def test_delete(self): json={ "loginId": "u1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_delete_by_user_id(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.delete_by_user_id, @@ -844,8 +845,8 @@ def test_delete_by_user_id(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(self.client.mgmt.user.delete_by_user_id("u1")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.user_delete_path}", @@ -858,15 +859,15 @@ def test_delete_by_user_id(self): json={ "userId": "u1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_logout(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.logout_user, @@ -874,8 +875,8 @@ def test_logout(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(self.client.mgmt.user.logout_user("u1")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.user_logout_path}", @@ -888,15 +889,15 @@ def test_logout(self): json={ "loginId": "u1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_logout_by_user_id(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.logout_user_by_user_id, @@ -904,8 +905,8 @@ def test_logout_by_user_id(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNone(self.client.mgmt.user.logout_user_by_user_id("u1")) mock_post.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.user_logout_path}", @@ -918,23 +919,23 @@ def test_logout_by_user_id(self): json={ "userId": "u1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_delete_all_test_users(self): # Test failed flows - with patch("requests.delete") as mock_delete: - mock_delete.return_value.ok = False + with patch("httpx.delete") as mock_delete: + mock_delete.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.delete_all_test_users, ) # Test success flow - with patch("requests.delete") as mock_delete: - mock_delete.return_value.ok = True + with patch("httpx.delete") as mock_delete: + mock_delete.return_value.is_success = True self.assertIsNone(self.client.mgmt.user.delete_all_test_users()) mock_delete.assert_called_with( f"{common.DEFAULT_BASE_URL}{MgmtV1.user_delete_all_test_users_path}", @@ -944,15 +945,15 @@ def test_delete_all_test_users(self): "Authorization": f"Bearer {self.dummy_project_id}:{self.dummy_management_key}", "x-descope-project-id": self.dummy_project_id, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_load(self): # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.load, @@ -960,9 +961,9 @@ def test_load(self): ) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_get.return_value = network_resp resp = self.client.mgmt.user.load("valid-id") @@ -976,15 +977,15 @@ def test_load(self): "x-descope-project-id": self.dummy_project_id, }, params={"loginId": "valid-id"}, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_load_by_user_id(self): # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.load_by_user_id, @@ -992,9 +993,9 @@ def test_load_by_user_id(self): ) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_get.return_value = network_resp resp = self.client.mgmt.user.load_by_user_id("user-id") @@ -1008,15 +1009,15 @@ def test_load_by_user_id(self): "x-descope-project-id": self.dummy_project_id, }, params={"userId": "user-id"}, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_search_all(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.search_all, @@ -1024,8 +1025,8 @@ def test_search_all(self): ["r1", "r2"], ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertRaises( AuthException, self.client.mgmt.user.search_all, [], [], -1, 0 ) @@ -1035,9 +1036,9 @@ def test_search_all(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1071,15 +1072,15 @@ def test_search_all(self): "ssoAppIds": ["app1"], "loginIds": ["l1"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with text and sort - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1119,15 +1120,15 @@ def test_search_all(self): {"desc": False, "field": "bubu"}, ], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with custom attributes - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1165,15 +1166,15 @@ def test_search_all(self): "emails": ["a@b.com"], "phones": ["+111111"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with time parameters - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1211,15 +1212,15 @@ def test_search_all(self): "fromModifiedTime": 300, "toModifiedTime": 400, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with tenant_role_ids and tenant_role_names - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1258,15 +1259,15 @@ def test_search_all(self): "tenant2": {"values": ["admin", "user"], "and": False} }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_search_all_test_users(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.search_all_test_users, @@ -1274,8 +1275,8 @@ def test_search_all_test_users(self): ["r1", "r2"], ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertRaises( AuthException, self.client.mgmt.user.search_all_test_users, @@ -1295,9 +1296,9 @@ def test_search_all_test_users(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1330,15 +1331,15 @@ def test_search_all_test_users(self): "ssoAppIds": ["app1"], "loginIds": ["l1"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with text and sort - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1377,15 +1378,15 @@ def test_search_all_test_users(self): {"desc": False, "field": "bubu"}, ], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with custom attributes - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1422,15 +1423,15 @@ def test_search_all_test_users(self): "emails": ["a@b.com"], "phones": ["+111111"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with time parameters - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"users": [{"id": "u1"}]}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.search_all_test_users( @@ -1465,15 +1466,15 @@ def test_search_all_test_users(self): "fromModifiedTime": 300, "toModifiedTime": 400, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with tenant_role_ids and tenant_role_names - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"users": [{"id": "u1"}, {"id": "u2"}]}""" ) @@ -1512,15 +1513,15 @@ def test_search_all_test_users(self): "tenant2": {"values": ["admin", "user"], "and": False} }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_get_provider_token(self): # Test failed flows - with patch("requests.get") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.get") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.get_provider_token, @@ -1528,9 +1529,9 @@ def test_get_provider_token(self): "p1", ) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"provider": "p1", "providerUserId": "puid", "accessToken": "access123", "refreshToken": "refresh456", "expiration": "123123123", "scopes": ["s1", "s2"]}""" ) @@ -1557,15 +1558,15 @@ def test_get_provider_token(self): "withRefreshToken": True, "forceRefresh": True, }, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_activate(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.activate, @@ -1573,9 +1574,9 @@ def test_activate(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.activate("valid-id") @@ -1593,15 +1594,15 @@ def test_activate(self): "loginId": "valid-id", "status": "enabled", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_deactivate(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.deactivate, @@ -1609,9 +1610,9 @@ def test_deactivate(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.deactivate("valid-id") @@ -1629,15 +1630,15 @@ def test_deactivate(self): "loginId": "valid-id", "status": "disabled", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_update_login_id(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.update_login_id, @@ -1646,9 +1647,9 @@ def test_update_login_id(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "a@b.c"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.update_login_id("valid-id", "a@b.c") @@ -1666,15 +1667,15 @@ def test_update_login_id(self): "loginId": "valid-id", "newLoginId": "a@b.c", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_update_email(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.update_email, @@ -1683,9 +1684,9 @@ def test_update_email(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.update_email("valid-id", "a@b.c") @@ -1704,15 +1705,15 @@ def test_update_email(self): "email": "a@b.c", "verified": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_update_phone(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.update_phone, @@ -1721,9 +1722,9 @@ def test_update_phone(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.update_phone("valid-id", "+18005551234", True) @@ -1742,15 +1743,15 @@ def test_update_phone(self): "phone": "+18005551234", "verified": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_update_display_name(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.update_display_name, @@ -1759,9 +1760,9 @@ def test_update_display_name(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.update_display_name("valid-id", "foo") @@ -1779,15 +1780,15 @@ def test_update_display_name(self): "loginId": "valid-id", "displayName": "foo", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_update_picture(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.update_picture, @@ -1796,9 +1797,9 @@ def test_update_picture(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.update_picture("valid-id", "foo") @@ -1816,15 +1817,15 @@ def test_update_picture(self): "loginId": "valid-id", "picture": "foo", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_update_custom_attribute(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.update_custom_attribute, @@ -1834,9 +1835,9 @@ def test_update_custom_attribute(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.update_custom_attribute( @@ -1856,16 +1857,16 @@ def test_update_custom_attribute(self): "attributeKey": "foo", "attributeValue": "bar", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_set_roles(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.set_roles, @@ -1874,9 +1875,9 @@ def test_set_roles(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.set_roles("valid-id", ["foo", "bar"]) @@ -1894,15 +1895,15 @@ def test_set_roles(self): "loginId": "valid-id", "roleNames": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_add_roles(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.add_roles, @@ -1911,9 +1912,9 @@ def test_add_roles(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.add_roles("valid-id", ["foo", "bar"]) @@ -1931,15 +1932,15 @@ def test_add_roles(self): "loginId": "valid-id", "roleNames": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_remove_roles(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.remove_roles, @@ -1948,9 +1949,9 @@ def test_remove_roles(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.remove_roles("valid-id", ["foo", "bar"]) @@ -1968,15 +1969,15 @@ def test_remove_roles(self): "loginId": "valid-id", "roleNames": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_add_sso_apps(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.add_sso_apps, @@ -1985,9 +1986,9 @@ def test_add_sso_apps(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.add_sso_apps("valid-id", ["foo", "bar"]) @@ -2005,15 +2006,15 @@ def test_add_sso_apps(self): "loginId": "valid-id", "ssoAppIds": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_set_sso_apps(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.set_sso_apps, @@ -2022,9 +2023,9 @@ def test_set_sso_apps(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.set_sso_apps("valid-id", ["foo", "bar"]) @@ -2042,15 +2043,15 @@ def test_set_sso_apps(self): "loginId": "valid-id", "ssoAppIds": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_remove_sso_apps(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.remove_sso_apps, @@ -2059,9 +2060,9 @@ def test_remove_sso_apps(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.remove_sso_apps("valid-id", ["foo", "bar"]) @@ -2079,15 +2080,15 @@ def test_remove_sso_apps(self): "loginId": "valid-id", "ssoAppIds": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_add_tenant(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.add_tenant, @@ -2096,9 +2097,9 @@ def test_add_tenant(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.add_tenant("valid-id", "tid") @@ -2116,15 +2117,15 @@ def test_add_tenant(self): "loginId": "valid-id", "tenantId": "tid", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_remove_tenant(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.remove_tenant, @@ -2133,9 +2134,9 @@ def test_remove_tenant(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.remove_tenant("valid-id", "tid") @@ -2153,15 +2154,15 @@ def test_remove_tenant(self): "loginId": "valid-id", "tenantId": "tid", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_set_tenant_roles(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.set_tenant_roles, @@ -2171,9 +2172,9 @@ def test_set_tenant_roles(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.set_tenant_roles( @@ -2194,15 +2195,15 @@ def test_set_tenant_roles(self): "tenantId": "tid", "roleNames": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_add_tenant_roles(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.add_tenant_roles, @@ -2212,9 +2213,9 @@ def test_add_tenant_roles(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.add_tenant_roles( @@ -2235,15 +2236,15 @@ def test_add_tenant_roles(self): "tenantId": "tid", "roleNames": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_remove_tenant_roles(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.remove_tenant_roles, @@ -2253,9 +2254,9 @@ def test_remove_tenant_roles(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"user": {"id": "u1"}}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.remove_tenant_roles( @@ -2276,15 +2277,15 @@ def test_remove_tenant_roles(self): "tenantId": "tid", "roleNames": ["foo", "bar"], }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_generate_otp_for_test_user(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.generate_otp_for_test_user, @@ -2293,9 +2294,9 @@ def test_generate_otp_for_test_user(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"code": "123456", "loginId": "login-id"}""" ) @@ -2323,15 +2324,15 @@ def test_generate_otp_for_test_user(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_user_set_temporary_password(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.set_temporary_password, @@ -2340,9 +2341,9 @@ def test_user_set_temporary_password(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_post.return_value = network_resp self.client.mgmt.user.set_temporary_password( "login-id", @@ -2361,15 +2362,15 @@ def test_user_set_temporary_password(self): "password": "some-password", "setActive": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_user_set_active_password(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.set_active_password, @@ -2378,9 +2379,9 @@ def test_user_set_active_password(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_post.return_value = network_resp self.client.mgmt.user.set_active_password( "login-id", @@ -2399,15 +2400,15 @@ def test_user_set_active_password(self): "password": "some-password", "setActive": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_user_set_password(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.set_password, @@ -2416,9 +2417,9 @@ def test_user_set_password(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_post.return_value = network_resp self.client.mgmt.user.set_password( "login-id", @@ -2437,15 +2438,15 @@ def test_user_set_password(self): "password": "some-password", "setActive": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_user_expire_password(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.expire_password, @@ -2453,9 +2454,9 @@ def test_user_expire_password(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_post.return_value = network_resp self.client.mgmt.user.expire_password( "login-id", @@ -2471,15 +2472,15 @@ def test_user_expire_password(self): json={ "loginId": "login-id", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_user_remove_all_passkeys(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.remove_all_passkeys, @@ -2487,9 +2488,9 @@ def test_user_remove_all_passkeys(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_post.return_value = network_resp self.client.mgmt.user.remove_all_passkeys( "login-id", @@ -2505,15 +2506,15 @@ def test_user_remove_all_passkeys(self): json={ "loginId": "login-id", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_user_remove_totp_seed(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.remove_totp_seed, @@ -2521,9 +2522,9 @@ def test_user_remove_totp_seed(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_post.return_value = network_resp self.client.mgmt.user.remove_totp_seed( "login-id", @@ -2539,15 +2540,15 @@ def test_user_remove_totp_seed(self): json={ "loginId": "login-id", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_generate_magic_link_for_test_user(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.generate_magic_link_for_test_user, @@ -2557,9 +2558,9 @@ def test_generate_magic_link_for_test_user(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"link": "some-link", "loginId": "login-id"}""" ) @@ -2588,15 +2589,15 @@ def test_generate_magic_link_for_test_user(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_generate_enchanted_link_for_test_user(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.generate_enchanted_link_for_test_user, @@ -2605,9 +2606,9 @@ def test_generate_enchanted_link_for_test_user(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """{"link": "some-link", "loginId": "login-id", "pendingRef": "some-ref"}""" ) @@ -2636,23 +2637,23 @@ def test_generate_enchanted_link_for_test_user(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_generate_embedded_link(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.generate_embedded_link, "login-id" ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"token": "some-token"}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.generate_embedded_link( @@ -2671,16 +2672,16 @@ def test_generate_embedded_link(self): "customClaims": {"k1": "v1"}, "timeout": 0, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_generate_sign_up_embedded_link(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.generate_sign_up_embedded_link, @@ -2688,9 +2689,9 @@ def test_generate_sign_up_embedded_link(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads("""{"token": "some-token"}""") mock_post.return_value = network_resp resp = self.client.mgmt.user.generate_sign_up_embedded_link( @@ -2712,24 +2713,24 @@ def test_generate_sign_up_embedded_link(self): "loginOptions": {}, "timeout": 0, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_history(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, self.client.mgmt.user.history, ["user-id-1", "user-id-2"] ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads( """ [ @@ -2779,16 +2780,16 @@ def test_history(self): "x-descope-project-id": self.dummy_project_id, }, json=["user-id-1", "user-id-2"], - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_update_test_user(self): - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads('{"user": {"id": "u1"}}') mock_post.return_value = network_resp resp = self.client.mgmt.user.update( @@ -2819,15 +2820,15 @@ def test_update_test_user(self): "additionalLoginIds": None, "ssoAppIDs": None, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_patch_test_user(self): - with patch("requests.patch") as mock_patch: + with patch("httpx.patch") as mock_patch: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True network_resp.json.return_value = json.loads('{"user": {"id": "u1"}}') mock_patch.return_value = network_resp resp = self.client.mgmt.user.patch( @@ -2850,7 +2851,7 @@ def test_patch_test_user(self): "displayName": "test-user", "test": True, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/test_auth.py b/tests/test_auth.py index 7dba9635f..2ed8e5239 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -22,6 +22,7 @@ SESSION_TOKEN_NAME, EndpointsV1, ) +from tests.testutils import SSLMatcher from . import common @@ -112,18 +113,18 @@ def test_fetch_public_key(self): """ # Test failed flows - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises(AuthException, auth._fetch_public_keys) - with patch("requests.get") as mock_get: - mock_get.return_value.ok = True + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = True mock_get.return_value.text = "invalid json" self.assertRaises(AuthException, auth._fetch_public_keys) # test success flow - with patch("requests.get") as mock_get: - mock_get.return_value.ok = True + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = True mock_get.return_value.text = valid_keys_response self.assertIsNone(auth._fetch_public_keys()) @@ -354,8 +355,8 @@ def test_refresh_session(self): auth = Auth(self.dummy_project_id, self.public_key_dict) # Test fail flow - with patch("requests.post") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.post") as mock_request: + mock_request.return_value.is_success = False self.assertRaises( AuthException, auth.refresh_session, @@ -370,8 +371,8 @@ def test_validate_session_and_refresh_input(self): auth.validate_and_refresh_session(None, None) # Test validate_session with Ratelimit exception - with patch("requests.get") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.get") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = { "errorCode": "E130429", @@ -397,8 +398,8 @@ def test_validate_session_and_refresh_input(self): ) # Test refresh_session with Ratelimit exception - with patch("requests.get") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.get") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = { "errorCode": "E130429", @@ -428,8 +429,8 @@ def test_exchange_access_key(self): auth = Auth(self.dummy_project_id, self.public_key_dict) # Test fail flow - with patch("requests.post") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.post") as mock_request: + mock_request.return_value.is_success = False self.assertRaises( AuthException, auth.exchange_access_key, @@ -438,9 +439,9 @@ def test_exchange_access_key(self): # Test success flow valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0Mzc1OTYsImlhdCI6MTY1OTYzNzU5NiwiaXNzIjoiUDJDdHpVaGRxcElGMnlzOWdnN21zMDZVdnRDNCIsInN1YiI6IlUyQ3UwajBXUHczWU9pUElTSmI1Mkwwd1VWTWcifQ.WLnlHugvzZtrV9OzBB7SjpCLNRvKF3ImFpVyIN5orkrjO2iyAKg_Rb4XHk9sXGC1aW8puYzLbhE1Jv3kk2hDcKggfE8OaRNRm8byhGFZHnvPJwcP_Ya-aRmfAvCLcKOL" - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = {"sessionJwt": valid_jwt_token} my_mock_response.json.return_value = data mock_post.return_value = my_mock_response @@ -460,8 +461,8 @@ def test_exchange_access_key(self): }, params=None, json={"loginOptions": {"customClaims": {"k1": "v1"}}}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -557,8 +558,8 @@ def test_api_rate_limit_exception(self): auth = Auth(self.dummy_project_id, self.public_key_dict) # Test do_post - with patch("requests.post") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.post") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = { "errorCode": "E130429", @@ -583,8 +584,8 @@ def test_api_rate_limit_exception(self): ) # Test do_get - with patch("requests.get") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.get") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = { "errorCode": "E130429", @@ -595,7 +596,7 @@ def test_api_rate_limit_exception(self): API_RATE_LIMIT_RETRY_AFTER_HEADER: "10" } with self.assertRaises(RateLimitException) as cm: - auth.do_get(uri="http://test.com", params=False, allow_redirects=None) + auth.do_get(uri="http://test.com", params=False, follow_redirects=None) the_exception = cm.exception self.assertEqual(the_exception.status_code, "E130429") self.assertEqual(the_exception.error_type, ERROR_TYPE_API_RATE_LIMIT) @@ -609,8 +610,8 @@ def test_api_rate_limit_exception(self): ) # Test do_delete - with patch("requests.delete") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.delete") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = { "errorCode": "E130429", @@ -635,9 +636,9 @@ def test_api_rate_limit_exception(self): ) # Test do_delete with params and pswd - with patch("requests.delete") as mock_delete: + with patch("httpx.delete") as mock_delete: network_resp = mock.Mock() - network_resp.ok = True + network_resp.is_success = True mock_delete.return_value = network_resp auth.do_delete("/a/b", params={"key": "value"}, pswd="pswd") @@ -650,14 +651,14 @@ def test_api_rate_limit_exception(self): "Authorization": f"Bearer {self.dummy_project_id}:{'pswd'}", "x-descope-project-id": self.dummy_project_id, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test _fetch_public_keys rate limit - with patch("requests.get") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.get") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = { "errorCode": "E130429", @@ -685,8 +686,8 @@ def test_api_rate_limit_invalid_header(self): auth = Auth(self.dummy_project_id, self.public_key_dict) # Test do_post empty body - with patch("requests.post") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.post") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = { "errorCode": "E130429", @@ -714,8 +715,8 @@ def test_api_rate_limit_invalid_response_body(self): auth = Auth(self.dummy_project_id, self.public_key_dict) # Test do_post empty body - with patch("requests.post") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.post") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = "aaa" with self.assertRaises(RateLimitException) as cm: @@ -731,8 +732,8 @@ def test_api_rate_limit_empty_response_body(self): auth = Auth(self.dummy_project_id, self.public_key_dict) # Test do_post empty body - with patch("requests.post") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.post") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = "" with self.assertRaises(RateLimitException) as cm: @@ -748,8 +749,8 @@ def test_api_rate_limit_none_response_body(self): auth = Auth(self.dummy_project_id, self.public_key_dict) # Test do_post empty body - with patch("requests.post") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.post") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 429 mock_request.return_value.json.return_value = None with self.assertRaises(RateLimitException) as cm: @@ -763,13 +764,13 @@ def test_api_rate_limit_none_response_body(self): def test_raise_from_response(self): auth = Auth(self.dummy_project_id, self.public_key_dict) - with patch("requests.get") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.get") as mock_request: + mock_request.return_value.is_success = False mock_request.return_value.status_code = 400 mock_request.return_value.error_type = ERROR_TYPE_SERVER_ERROR mock_request.return_value.text = """{"errorCode":"E062108","errorDescription":"User not found","errorMessage":"Cannot find user"}""" with self.assertRaises(AuthException) as cm: - auth.do_get(uri="http://test.com", params=False, allow_redirects=None) + auth.do_get(uri="http://test.com", params=False, follow_redirects=None) the_exception = cm.exception self.assertEqual(the_exception.status_code, 400) self.assertEqual(the_exception.error_type, ERROR_TYPE_SERVER_ERROR) diff --git a/tests/test_descope_client.py b/tests/test_descope_client.py index 16f06695b..27c02c4f9 100644 --- a/tests/test_descope_client.py +++ b/tests/test_descope_client.py @@ -22,6 +22,7 @@ ) from . import common +from tests.testutils import SSLMatcher class TestDescopeClient(common.DescopeTest): @@ -104,13 +105,13 @@ def test_logout(self): self.assertRaises(AuthException, client.logout, None) # Test failed flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.logout, dummy_refresh_token) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.logout(dummy_refresh_token)) def test_logout_all(self): @@ -120,13 +121,13 @@ def test_logout_all(self): self.assertRaises(AuthException, client.logout_all, None) # Test failed flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, client.logout_all, dummy_refresh_token) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(client.logout_all(dummy_refresh_token)) def test_me(self): @@ -136,14 +137,14 @@ def test_me(self): self.assertRaises(AuthException, client.me, None) # Test failed flow - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises(AuthException, client.me, dummy_refresh_token) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = json.loads( """{"name": "Testy McTester", "email": "testy@tester.com"}""" ) @@ -159,8 +160,8 @@ def test_me(self): "Authorization": f"Bearer {self.dummy_project_id}", "x-descope-project-id": self.dummy_project_id, }, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -176,16 +177,16 @@ def test_my_tenants(self): ) # Test failed flow - with patch("requests.post") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.post") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, client.my_tenants, dummy_refresh_token, True ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = json.loads( """{"tenants": [{"id": "tenant_id", "name": "tenant_name"}]}""" ) @@ -204,8 +205,8 @@ def test_my_tenants(self): "x-descope-project-id": self.dummy_project_id, }, json={"dct": False, "ids": ["a"]}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -217,14 +218,14 @@ def test_history(self): self.assertRaises(AuthException, client.history, None) # Test failed flow - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises(AuthException, client.history, dummy_refresh_token) # Test success flow - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = json.loads( """ [ @@ -257,8 +258,8 @@ def test_history(self): "Authorization": f"Bearer {self.dummy_project_id}", "x-descope-project-id": self.dummy_project_id, }, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -368,12 +369,12 @@ def test_validate_session_valid_tokens(self): # Test case where key id cannot be found client2 = DescopeClient(self.dummy_project_id, None) - with patch("requests.get") as mock_request: + with patch("httpx.get") as mock_request: fake_key = deepcopy(self.public_key_dict) # overwrite the kid (so it will not be found) fake_key["kid"] = "dummy_kid" mock_request.return_value.text = json.dumps([fake_key]) - mock_request.return_value.ok = True + mock_request.return_value.is_success = True self.assertRaises( AuthException, client2.validate_and_refresh_session, @@ -383,9 +384,9 @@ def test_validate_session_valid_tokens(self): # Test case where we failed to load key client3 = DescopeClient(self.dummy_project_id, None) - with patch("requests.get") as mock_request: + with patch("httpx.get") as mock_request: mock_request.return_value.text = """[{"kid": "dummy_kid"}]""" - mock_request.return_value.ok = True + mock_request.return_value.is_success = True self.assertRaises( AuthException, client3.validate_and_refresh_session, @@ -396,9 +397,9 @@ def test_validate_session_valid_tokens(self): # Test case where header_alg != key[alg] self.public_key_dict["alg"] = "ES521" client4 = DescopeClient(self.dummy_project_id, self.public_key_dict) - with patch("requests.get") as mock_request: + with patch("httpx.get") as mock_request: mock_request.return_value.text = """[{"kid": "dummy_kid"}]""" - mock_request.return_value.ok = True + mock_request.return_value.is_success = True self.assertRaises( AuthException, client4.validate_and_refresh_session, @@ -418,9 +419,9 @@ def test_validate_session_valid_tokens(self): # expired_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3VDOXl2MlVHdEdJMW84NGdDWkViOXFFUVciLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEUyIsImV4cCI6MTY1OTY0NDI5OCwiaWF0IjoxNjU5NjQ0Mjk3LCJpc3MiOiJQMkN1Qzl5djJVR3RHSTFvODRnQ1pFYjlxRVFXIiwic3ViIjoiVTJDdUNQdUpnUFdIR0I1UDRHbWZidVBHaEdWbSJ9.wBuOnIQI_z3SXOszqsWCg8ilOPdE5ruWYHA3jkaeQ3uX9hWgCTd69paFajc-xdMYbqlIF7JHji7T9oVmkCUJvDNgRZRZO9boMFANPyXitLOK4aX3VZpMJBpFxdrWV3GE" valid_refresh_token = valid_jwt_token - with patch("requests.get") as mock_request: + with patch("httpx.get") as mock_request: mock_request.return_value.cookies = {SESSION_COOKIE_NAME: expired_jwt_token} - mock_request.return_value.ok = True + mock_request.return_value.is_success = True self.assertRaises( AuthException, @@ -472,17 +473,17 @@ def test_expired_token(self): ) # Test fail flow - with patch("requests.get") as mock_request: - mock_request.return_value.ok = False + with patch("httpx.get") as mock_request: + mock_request.return_value.is_success = False self.assertRaises( AuthException, client.validate_session, expired_jwt_token, ) - with patch("requests.get") as mock_request: + with patch("httpx.get") as mock_request: mock_request.return_value.cookies = {"aaa": "aaa"} - mock_request.return_value.ok = True + mock_request.return_value.is_success = True self.assertRaises( AuthException, client.validate_session, @@ -505,9 +506,9 @@ def test_expired_token(self): new_session_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3VDOXl2MlVHdEdJMW84NGdDWkViOXFFUVciLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEUyIsImV4cCI6MjQ5MzA2MTQxNSwiaWF0IjoxNjU5NjQzMDYxLCJpc3MiOiJQMkN1Qzl5djJVR3RHSTFvODRnQ1pFYjlxRVFXIiwic3ViIjoiVTJDdUNQdUpnUFdIR0I1UDRHbWZidVBHaEdWbSJ9.gMalOv1GhqYVsfITcOc7Jv_fibX1Iof6AFy2KCVmyHmU2KwATT6XYXsHjBFFLq262Pg-LS1IX9f_DV3ppzvb1pSY4ccsP6WDGd1vJpjp3wFBP9Sji6WXL0SCCJUFIyJR" valid_refresh_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3VDOXl2MlVHdEdJMW84NGdDWkViOXFFUVciLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0NDMwNjEsImlhdCI6MTY1OTY0MzA2MSwiaXNzIjoiUDJDdUM5eXYyVUd0R0kxbzg0Z0NaRWI5cUVRVyIsInN1YiI6IlUyQ3VDUHVKZ1BXSEdCNVA0R21mYnVQR2hHVm0ifQ.mRo9FihYMR3qnQT06Mj3CJ5X0uTCEcXASZqfLLUv0cPCLBtBqYTbuK-ZRDnV4e4N6zGCNX2a3jjpbyqbViOxICCNSxJsVb-sdsSujtEXwVMsTTLnpWmNsMbOUiKmoME0" expired_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3VDOXl2MlVHdEdJMW84NGdDWkViOXFFUVciLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEUyIsImV4cCI6MTY1OTY0NDI5OCwiaWF0IjoxNjU5NjQ0Mjk3LCJpc3MiOiJQMkN1Qzl5djJVR3RHSTFvODRnQ1pFYjlxRVFXIiwic3ViIjoiVTJDdUNQdUpnUFdIR0I1UDRHbWZidVBHaEdWbSJ9.wBuOnIQI_z3SXOszqsWCg8ilOPdE5ruWYHA3jkaeQ3uX9hWgCTd69paFajc-xdMYbqlIF7JHji7T9oVmkCUJvDNgRZRZO9boMFANPyXitLOK4aX3VZpMJBpFxdrWV3GE" - with patch("requests.post") as mock_request: + with patch("httpx.post") as mock_request: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"sessionJwt": new_session_token} mock_request.return_value = my_mock_response mock_request.return_value.cookies = {} @@ -539,9 +540,9 @@ def test_expired_token(self): new_refreshed_token = ( expired_jwt_token # the refreshed token should be invalid (or expired) ) - with patch("requests.get") as mock_request: + with patch("httpx.get") as mock_request: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"sessionJwt": new_refreshed_token} mock_request.return_value = my_mock_response mock_request.return_value.cookies = {} @@ -774,9 +775,9 @@ def test_exchange_access_key(self): ) dummy_access_key = "dummy access key" valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3VDOXl2MlVHdEdJMW84NGdDWkViOXFFUVciLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0NDMwNjEsImlhdCI6MTY1OTY0MzA2MSwiaXNzIjoiUDJDdUM5eXYyVUd0R0kxbzg0Z0NaRWI5cUVRVyIsInN1YiI6IlUyQ3VDUHVKZ1BXSEdCNVA0R21mYnVQR2hHVm0ifQ.mRo9FihYMR3qnQT06Mj3CJ5X0uTCEcXASZqfLLUv0cPCLBtBqYTbuK-ZRDnV4e4N6zGCNX2a3jjpbyqbViOxICCNSxJsVb-sdsSujtEXwVMsTTLnpWmNsMbOUiKmoME0" - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = {"sessionJwt": valid_jwt_token} my_mock_response.json.return_value = data mock_post.return_value = my_mock_response @@ -796,8 +797,8 @@ def test_exchange_access_key(self): }, params=None, json={"loginOptions": {"customClaims": {"k1": "v1"}}}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -843,10 +844,10 @@ def test_select_tenant(self): valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3VDOXl2MlVHdEdJMW84NGdDWkViOXFFUVciLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0NDMwNjEsImlhdCI6MTY1OTY0MzA2MSwiaXNzIjoiUDJDdUM5eXYyVUd0R0kxbzg0Z0NaRWI5cUVRVyIsInN1YiI6IlUyQ3VDUHVKZ1BXSEdCNVA0R21mYnVQR2hHVm0ifQ.mRo9FihYMR3qnQT06Mj3CJ5X0uTCEcXASZqfLLUv0cPCLBtBqYTbuK-ZRDnV4e4N6zGCNX2a3jjpbyqbViOxICCNSxJsVb-sdsSujtEXwVMsTTLnpWmNsMbOUiKmoME0" - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -865,8 +866,8 @@ def test_select_tenant(self): json={ "tenant": "t1", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -881,9 +882,9 @@ def test_auth_management_key_with_functions(self): auth_management_key=auth_mgmt_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response @@ -902,8 +903,8 @@ def test_auth_management_key_with_functions(self): "email": "test@example.com", }, params=None, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -914,9 +915,9 @@ def test_auth_management_key_with_functions(self): ): client_env = DescopeClient(self.dummy_project_id, self.public_key_dict) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response @@ -934,8 +935,8 @@ def test_auth_management_key_with_functions(self): "user": {"email": "test@example.com"}, "email": "test@example.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -951,9 +952,9 @@ def test_auth_management_key_with_functions(self): auth_management_key=direct_auth_mgmt_key, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response @@ -972,8 +973,8 @@ def test_auth_management_key_with_functions(self): "email": "test@example.com", }, params=None, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -987,9 +988,9 @@ def test_auth_management_key_with_refresh_token(self): # Test with refresh token function refresh_token = "test_refresh_token" - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "n***@example.com"} mock_post.return_value = my_mock_response @@ -1010,17 +1011,17 @@ def test_auth_management_key_with_refresh_token(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test without auth_management_key for comparison client_no_auth = DescopeClient(self.dummy_project_id, self.public_key_dict) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "n***@example.com"} mock_post.return_value = my_mock_response @@ -1041,8 +1042,8 @@ def test_auth_management_key_with_refresh_token(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), params=None, timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/test_enchantedlink.py b/tests/test_enchantedlink.py index d34a81c36..97eef1445 100644 --- a/tests/test_enchantedlink.py +++ b/tests/test_enchantedlink.py @@ -14,6 +14,7 @@ SignUpOptions, ) +from tests.testutils import SSLMatcher from . import common @@ -97,9 +98,9 @@ def test_compose_body(self): def test_sign_in(self): enchantedlink = EnchantedLink(Auth(self.dummy_project_id, self.public_key_dict)) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True # Test failed flows with self.assertRaises(AuthException): enchantedlink.sign_in("", "http://test.me") @@ -120,15 +121,15 @@ def test_sign_in(self): "URI": "http://test.me", "loginOptions": {}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res["pendingRef"], "aaaa") self.assertEqual(res["linkId"], "24") # Validate refresh token used while provided - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: refresh_token = "dummy refresh token" enchantedlink.sign_in( "dummy@dummy.com", @@ -153,13 +154,13 @@ def test_sign_in(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # With template options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: refresh_token = "dummy refresh token" enchantedlink.sign_in( "dummy@dummy.com", @@ -192,16 +193,16 @@ def test_sign_in(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_sign_in_with_login_options(self): enchantedlink = EnchantedLink(Auth(self.dummy_project_id, self.public_key_dict)) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = json.loads("""{"pendingRef": "aaaa", "linkId":"24"}""") my_mock_response.json.return_value = data mock_post.return_value = my_mock_response @@ -224,16 +225,16 @@ def test_sign_in_with_login_options(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_sign_up(self): enchantedlink = EnchantedLink(Auth(self.dummy_project_id, self.public_key_dict)) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True # Test failed flows self.assertRaises( @@ -266,14 +267,14 @@ def test_sign_up(self): "user": {"username": "user1", "email": "dummy@dummy.com"}, "email": "dummy@dummy.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res["pendingRef"], "aaaa") # Test user is None so using the login_id as default - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: data = json.loads("""{"pendingRef": "aaaa"}""") my_mock_response.json.return_value = data mock_post.return_value = my_mock_response @@ -296,14 +297,14 @@ def test_sign_up(self): "user": {"email": "dummy@dummy.com"}, "email": "dummy@dummy.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res["pendingRef"], "aaaa") # Test success flow with sign up options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: data = json.loads("""{"pendingRef": "aaaa"}""") my_mock_response.json.return_value = data mock_post.return_value = my_mock_response @@ -336,17 +337,17 @@ def test_sign_up(self): "revokeOtherSessions": True, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res["pendingRef"], "aaaa") def test_sign_up_or_in(self): enchantedlink = EnchantedLink(Auth(self.dummy_project_id, self.public_key_dict)) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = json.loads("""{"pendingRef": "aaaa"}""") my_mock_response.json.return_value = data mock_post.return_value = my_mock_response @@ -367,15 +368,15 @@ def test_sign_up_or_in(self): "URI": "http://test.me", "loginOptions": {}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with sign up options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = json.loads("""{"pendingRef": "aaaa"}""") my_mock_response.json.return_value = data mock_post.return_value = my_mock_response @@ -402,8 +403,8 @@ def test_sign_up_or_in(self): "templateOptions": {"bla": "blue"}, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -412,8 +413,8 @@ def test_verify(self): enchantedlink = EnchantedLink(Auth(self.dummy_project_id, self.public_key_dict)) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, enchantedlink.verify, @@ -422,9 +423,9 @@ def test_verify(self): # Test success flow valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0Mzc1OTYsImlhdCI6MTY1OTYzNzU5NiwiaXNzIjoiUDJDdHpVaGRxcElGMnlzOWdnN21zMDZVdnRDNCIsInN1YiI6IlUyQ3UwajBXUHczWU9pUElTSmI1Mkwwd1VWTWcifQ.WLnlHugvzZtrV9OzBB7SjpCLNRvKF3ImFpVyIN5orkrjO2iyAKg_Rb4XHk9sXGC1aW8puYzLbhE1Jv3kk2hDcKggfE8OaRNRm8byhGFZHnvPJwcP_Ya-aRmfAvCLcKOL" - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {} mock_post.return_value = my_mock_response mock_post.return_value.cookies = { @@ -437,9 +438,9 @@ def test_get_session(self): enchantedlink = EnchantedLink(Auth(self.dummy_project_id, self.public_key_dict)) valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0Mzc1OTYsImlhdCI6MTY1OTYzNzU5NiwiaXNzIjoiUDJDdHpVaGRxcElGMnlzOWdnN21zMDZVdnRDNCIsInN1YiI6IlUyQ3UwajBXUHczWU9pUElTSmI1Mkwwd1VWTWcifQ.WLnlHugvzZtrV9OzBB7SjpCLNRvKF3ImFpVyIN5orkrjO2iyAKg_Rb4XHk9sXGC1aW8puYzLbhE1Jv3kk2hDcKggfE8OaRNRm8byhGFZHnvPJwcP_Ya-aRmfAvCLcKOL" - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {} mock_post.return_value = my_mock_response mock_post.return_value.cookies = { @@ -450,9 +451,9 @@ def test_get_session(self): def test_update_user_email(self): enchantedlink = EnchantedLink(Auth(self.dummy_project_id, self.public_key_dict)) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True # Test failed flows self.assertRaises( AuthException, @@ -481,16 +482,16 @@ def test_update_user_email(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) # with template options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True data = json.loads("""{"pendingRef": "aaaa"}""") my_mock_response.json.return_value = data mock_post.return_value = my_mock_response @@ -515,8 +516,8 @@ def test_update_user_email(self): "onMergeUseExisting": False, "templateOptions": {"bla": "blue"}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) diff --git a/tests/test_magiclink.py b/tests/test_magiclink.py index c851b48cd..1b1401632 100644 --- a/tests/test_magiclink.py +++ b/tests/test_magiclink.py @@ -14,6 +14,7 @@ SignUpOptions, ) +from tests.testutils import SSLMatcher from . import common @@ -123,8 +124,8 @@ def test_sign_in(self): "http://test.me", ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, magiclink.sign_in, @@ -134,9 +135,9 @@ def test_sign_in(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response @@ -157,7 +158,7 @@ def test_sign_in(self): ) # Validate refresh token used while provided - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: refresh_token = "dummy refresh token" magiclink.sign_in( DeliveryMethod.EMAIL, @@ -183,13 +184,13 @@ def test_sign_in(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # With template options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: refresh_token = "dummy refresh token" magiclink.sign_in( DeliveryMethod.EMAIL, @@ -218,8 +219,8 @@ def test_sign_in(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -243,8 +244,8 @@ def test_sign_up(self): signup_user_details, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, magiclink.sign_up, @@ -255,9 +256,9 @@ def test_sign_up(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response resp = magiclink.sign_up( @@ -269,9 +270,9 @@ def test_sign_up(self): self.assertEqual("t***@example.com", resp) # Test success flow with sign up options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response resp = magiclink.sign_up( @@ -305,8 +306,8 @@ def test_sign_up(self): "templateId": "foo", }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) @@ -319,9 +320,9 @@ def test_sign_up(self): "email": "dummy@dummy.com", } - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -351,16 +352,16 @@ def test_sign_up(self): }, "email": "dummy@dummy.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) # Test user is None so using the login_id as default - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -385,8 +386,8 @@ def test_sign_up(self): "user": {"email": "dummy@dummy.com"}, "email": "dummy@dummy.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) @@ -396,8 +397,8 @@ def test_sign_up_or_in(self): # Test failed flows - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, magiclink.sign_up_or_in, @@ -407,9 +408,9 @@ def test_sign_up_or_in(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -420,9 +421,9 @@ def test_sign_up_or_in(self): ) # Test success flow with sign up options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -452,8 +453,8 @@ def test_sign_up_or_in(self): "templateId": "foo", }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) @@ -463,8 +464,8 @@ def test_verify(self): magiclink = MagicLink(Auth(self.dummy_project_id, self.public_key_dict)) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, magiclink.verify, @@ -473,9 +474,9 @@ def test_verify(self): # Test success flow valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0Mzc1OTYsImlhdCI6MTY1OTYzNzU5NiwiaXNzIjoiUDJDdHpVaGRxcElGMnlzOWdnN21zMDZVdnRDNCIsInN1YiI6IlUyQ3UwajBXUHczWU9pUElTSmI1Mkwwd1VWTWcifQ.WLnlHugvzZtrV9OzBB7SjpCLNRvKF3ImFpVyIN5orkrjO2iyAKg_Rb4XHk9sXGC1aW8puYzLbhE1Jv3kk2hDcKggfE8OaRNRm8byhGFZHnvPJwcP_Ya-aRmfAvCLcKOL" - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {} mock_post.return_value = my_mock_response mock_post.return_value.cookies = { @@ -492,13 +493,13 @@ def test_verify_with_get_keys_mock(self): # Test success flow valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0Mzc1OTYsImlhdCI6MTY1OTYzNzU5NiwiaXNzIjoiUDJDdHpVaGRxcElGMnlzOWdnN21zMDZVdnRDNCIsInN1YiI6IlUyQ3UwajBXUHczWU9pUElTSmI1Mkwwd1VWTWcifQ.WLnlHugvzZtrV9OzBB7SjpCLNRvKF3ImFpVyIN5orkrjO2iyAKg_Rb4XHk9sXGC1aW8puYzLbhE1Jv3kk2hDcKggfE8OaRNRm8byhGFZHnvPJwcP_Ya-aRmfAvCLcKOL" - with patch("requests.get") as mock_get: + with patch("httpx.get") as mock_get: mock_get.return_value.text = json.dumps({"keys": [self.public_key_dict]}) - mock_get.return_value.ok = True + mock_get.return_value.is_success = True - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {} mock_post.return_value = my_mock_response mock_post.return_value.cookies = { @@ -518,8 +519,8 @@ def test_update_user_email(self): "refresh_token1", ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, magiclink.update_user_email, @@ -529,9 +530,9 @@ def test_update_user_email(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -551,16 +552,16 @@ def test_update_user_email(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) # Test success flow with template options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -586,8 +587,8 @@ def test_update_user_email(self): "onMergeUseExisting": False, "templateOptions": {"bla": "blue"}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) @@ -604,8 +605,8 @@ def test_update_user_phone(self): "refresh_token1", ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, magiclink.update_user_phone, @@ -616,9 +617,9 @@ def test_update_user_phone(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedPhone": "*****1111"} mock_post.return_value = my_mock_response self.assertEqual( @@ -640,16 +641,16 @@ def test_update_user_phone(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) # Test success flow with template options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedPhone": "*****1111"} mock_post.return_value = my_mock_response self.assertEqual( @@ -676,8 +677,8 @@ def test_update_user_phone(self): "onMergeUseExisting": False, "templateOptions": {"bla": "blue"}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) diff --git a/tests/test_oauth.py b/tests/test_oauth.py index eed6bc468..c9138d939 100644 --- a/tests/test_oauth.py +++ b/tests/test_oauth.py @@ -9,6 +9,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS, EndpointsV1, LoginOptions from . import common +from tests.testutils import SSLMatcher class TestOAuth(common.DescopeTest): @@ -48,13 +49,13 @@ def test_oauth_start(self): # Test failed flows self.assertRaises(AuthException, oauth.start, "") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, oauth.start, "google") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(oauth.start("google")) self.assertRaises( @@ -65,8 +66,8 @@ def test_oauth_start(self): LoginOptions(mfa=True), ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True oauth.start("facebook") expected_uri = f"{common.DEFAULT_BASE_URL}{EndpointsV1.oauth_start_path}" mock_post.assert_called_with( @@ -78,8 +79,8 @@ def test_oauth_start(self): }, params={"provider": "facebook"}, json={}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -89,17 +90,17 @@ def test_oauth_start_with_login_options(self): # Test failed flows self.assertRaises(AuthException, oauth.start, "") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, oauth.start, "google") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(oauth.start("google")) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True lo = LoginOptions(stepup=True, custom_claims={"k1": "v1"}) oauth.start("facebook", login_options=lo, refresh_token="refresh") expected_uri = f"{common.DEFAULT_BASE_URL}{EndpointsV1.oauth_start_path}" @@ -112,8 +113,8 @@ def test_oauth_start_with_login_options(self): }, params={"provider": "facebook"}, json={"stepup": True, "customClaims": {"k1": "v1"}, "mfa": False}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -127,14 +128,14 @@ def test_exchange_token(self): self.assertRaises(AuthException, oauth.exchange_token, "") self.assertRaises(AuthException, oauth.exchange_token, None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, oauth.exchange_token, "c1") # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -151,8 +152,8 @@ def test_exchange_token(self): }, params=None, json={"code": "c1"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/test_otp.py b/tests/test_otp.py index 4e2713b99..3a50c1789 100644 --- a/tests/test_otp.py +++ b/tests/test_otp.py @@ -12,6 +12,7 @@ SignUpOptions, ) +from tests.testutils import SSLMatcher from . import common @@ -182,8 +183,8 @@ def test_sign_up(self): invalid_signup_user_details, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.otp.sign_up, @@ -193,9 +194,9 @@ def test_sign_up(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -213,9 +214,9 @@ def test_sign_up(self): "email": "dummy@dummy.com", } - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -242,15 +243,15 @@ def test_sign_up(self): }, "email": "dummy@dummy.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with sign up options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -284,15 +285,15 @@ def test_sign_up(self): "templateId": "foo", }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test user is None so using the login_id as default - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -312,8 +313,8 @@ def test_sign_up(self): "user": {"email": "dummy@dummy.com"}, "email": "dummy@dummy.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -330,8 +331,8 @@ def test_sign_in(self): self.assertRaises(AuthException, client.otp.sign_in, DeliveryMethod.EMAIL, "") self.assertRaises(AuthException, client.otp.sign_in, DeliveryMethod.EMAIL, None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.otp.sign_in, @@ -340,9 +341,9 @@ def test_sign_in(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -358,7 +359,7 @@ def test_sign_in(self): ) # Validate refresh token used while provided - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: refresh_token = "dummy refresh token" client.otp.sign_in( DeliveryMethod.EMAIL, @@ -382,13 +383,13 @@ def test_sign_in(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # With template options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: refresh_token = "dummy refresh token" client.otp.sign_in( DeliveryMethod.EMAIL, @@ -416,8 +417,8 @@ def test_sign_in(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -429,8 +430,8 @@ def test_sign_up_or_in(self): AuthException, client.otp.sign_up_or_in, DeliveryMethod.EMAIL, "" ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.otp.sign_up_or_in, @@ -439,9 +440,9 @@ def test_sign_up_or_in(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -450,9 +451,9 @@ def test_sign_up_or_in(self): ) # Test success flow with sign up options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -480,8 +481,8 @@ def test_sign_up_or_in(self): "templateId": "foo", }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) @@ -498,8 +499,8 @@ def test_verify_code(self): AuthException, client.otp.verify_code, DeliveryMethod.EMAIL, None, code ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.otp.verify_code, @@ -510,9 +511,9 @@ def test_verify_code(self): # Test success flow valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0Mzc1OTYsImlhdCI6MTY1OTYzNzU5NiwiaXNzIjoiUDJDdHpVaGRxcElGMnlzOWdnN21zMDZVdnRDNCIsInN1YiI6IlUyQ3UwajBXUHczWU9pUElTSmI1Mkwwd1VWTWcifQ.WLnlHugvzZtrV9OzBB7SjpCLNRvKF3ImFpVyIN5orkrjO2iyAKg_Rb4XHk9sXGC1aW8puYzLbhE1Jv3kk2hDcKggfE8OaRNRm8byhGFZHnvPJwcP_Ya-aRmfAvCLcKOL" - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {} mock_post.return_value = my_mock_response mock_post.return_value.cookies = { @@ -543,8 +544,8 @@ def test_update_user_email(self): "refresh_token1", ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.otp.update_user_email, @@ -554,9 +555,9 @@ def test_update_user_email(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -578,16 +579,16 @@ def test_update_user_email(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) # Test success flow with template options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedEmail": "t***@example.com"} mock_post.return_value = my_mock_response self.assertEqual( @@ -613,8 +614,8 @@ def test_update_user_email(self): "onMergeUseExisting": False, "templateOptions": {"bla": "blue"}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) @@ -648,8 +649,8 @@ def test_update_user_phone(self): "refresh_token1", ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, client.otp.update_user_phone, @@ -660,9 +661,9 @@ def test_update_user_phone(self): ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedPhone": "*****111"} mock_post.return_value = my_mock_response self.assertEqual( @@ -684,15 +685,15 @@ def test_update_user_phone(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedPhone": "*****111"} mock_post.return_value = my_mock_response self.assertEqual( @@ -714,15 +715,15 @@ def test_update_user_phone(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedPhone": "*****111"} mock_post.return_value = my_mock_response self.assertEqual( @@ -744,16 +745,16 @@ def test_update_user_phone(self): "addToLoginIDs": False, "onMergeUseExisting": False, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) # Test success flow with template options - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = {"maskedPhone": "*****111"} mock_post.return_value = my_mock_response self.assertEqual( @@ -780,8 +781,8 @@ def test_update_user_phone(self): "onMergeUseExisting": False, "templateOptions": {"bla": "blue"}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, params=None, ) diff --git a/tests/test_password.py b/tests/test_password.py index 51a97862b..d26600396 100644 --- a/tests/test_password.py +++ b/tests/test_password.py @@ -7,6 +7,7 @@ from descope.authmethod.password import Password # noqa: F401 from descope.common import DEFAULT_TIMEOUT_SECONDS, EndpointsV1 +from tests.testutils import SSLMatcher from . import common @@ -67,8 +68,8 @@ def test_sign_up(self): signup_user_details, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, password.sign_up, @@ -78,10 +79,10 @@ def test_sign_up(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -111,8 +112,8 @@ def test_sign_up(self): "email": "dummy@dummy.com", }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -148,8 +149,8 @@ def test_sign_in(self): None, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, password.sign_in, @@ -158,10 +159,10 @@ def test_sign_in(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -183,8 +184,8 @@ def test_sign_in(self): "loginId": "dummy@dummy.com", "password": "123456", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -204,8 +205,8 @@ def test_send_reset(self): None, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, password.send_reset, @@ -213,10 +214,10 @@ def test_send_reset(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"resetMethod": "magiclink", "maskedEmail": "du***@***my.com"}""" @@ -240,16 +241,16 @@ def test_send_reset(self): "loginId": "dummy@dummy.com", "redirectUrl": "https://redirect.here.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) # Test success flow with template options - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"resetMethod": "magiclink", "maskedEmail": "du***@***my.com"}""" @@ -278,8 +279,8 @@ def test_send_reset(self): "redirectUrl": "https://redirect.here.com", "templateOptions": {"bla": "blue"}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -335,8 +336,8 @@ def test_update(self): None, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, password.update, @@ -346,8 +347,8 @@ def test_update(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True valid_jwt_token = "eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkVGVuYW50cyI6eyIiOm51bGx9LCJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwNjc5MjA4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MjA5MDA4NzIwOCwiaWF0IjoxNjU4MDg3MjA4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQzU1dnl4dzBzUkw2RmRNNjhxUnNDRGRST1YifQ.cWP5up4R5xeIl2qoG2NtfLH3Q5nRJVKdz-FDoAXctOQW9g3ceZQi6rZQ-TPBaXMKw68bijN3bLJTqxWW5WHzqRUeopfuzTcMYmC0wP2XGJkrdF6A8D5QW6acSGqglFgu" self.assertIsNone( password.update("dummy@dummy.com", "123456", valid_jwt_token) @@ -364,8 +365,8 @@ def test_update(self): "loginId": "dummy@dummy.com", "newPassword": "123456", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -421,8 +422,8 @@ def test_replace(self): None, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, password.replace, @@ -432,10 +433,10 @@ def test_replace(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["test@company.com"], "name": "", "email": "test@company.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -460,26 +461,26 @@ def test_replace(self): "oldPassword": "123456", "newPassword": "1234567", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) def test_policy(self): password = Password(Auth(self.dummy_project_id, self.public_key_dict)) - with patch("requests.get") as mock_get: - mock_get.return_value.ok = False + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = False self.assertRaises( AuthException, password.get_policy, ) # Test success flow - with patch("requests.get") as mock_get: - mock_get.return_value.ok = True + with patch("httpx.get") as mock_get: + mock_get.return_value.is_success = True my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads("""{"minLength": 8, "lowercase": true}""") my_mock_response.json.return_value = data @@ -493,7 +494,7 @@ def test_policy(self): "x-descope-project-id": self.dummy_project_id, }, params=None, - allow_redirects=None, - verify=True, + follow_redirects=None, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/test_saml.py b/tests/test_saml.py index 804fb9a05..377d67484 100644 --- a/tests/test_saml.py +++ b/tests/test_saml.py @@ -9,6 +9,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS, EndpointsV1, LoginOptions from . import common +from tests.testutils import SSLMatcher class TestSAML(common.DescopeTest): @@ -40,17 +41,17 @@ def test_saml_start(self): self.assertRaises(AuthException, saml.start, "tenant1", "") self.assertRaises(AuthException, saml.start, "tenant1", None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, saml.start, "tenant1", "http://dummy.com") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(saml.start("tenant1", "http://dummy.com")) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True saml.start("tenant1", "http://dummy.com") expected_uri = ( f"{common.DEFAULT_BASE_URL}{EndpointsV1.auth_saml_start_path}" @@ -64,8 +65,8 @@ def test_saml_start(self): }, params={"tenant": "tenant1", "redirectURL": "http://dummy.com"}, json={}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertRaises( @@ -85,17 +86,17 @@ def test_saml_start_with_login_options(self): self.assertRaises(AuthException, saml.start, "tenant1", "") self.assertRaises(AuthException, saml.start, "tenant1", None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, saml.start, "tenant1", "http://dummy.com") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(saml.start("tenant1", "http://dummy.com")) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True lo = LoginOptions(stepup=True, custom_claims={"k1": "v1"}) saml.start("tenant1", "http://dummy.com", lo, "refresh") expected_uri = ( @@ -110,8 +111,8 @@ def test_saml_start_with_login_options(self): }, params={"tenant": "tenant1", "redirectURL": "http://dummy.com"}, json={"stepup": True, "customClaims": {"k1": "v1"}, "mfa": False}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -125,14 +126,14 @@ def test_exchange_token(self): self.assertRaises(AuthException, saml.exchange_token, "") self.assertRaises(AuthException, saml.exchange_token, None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, saml.exchange_token, "c1") # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -149,8 +150,8 @@ def test_exchange_token(self): }, params=None, json={"code": "c1"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/test_sso.py b/tests/test_sso.py index eb555fc3f..98a6cb46c 100644 --- a/tests/test_sso.py +++ b/tests/test_sso.py @@ -9,6 +9,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS, EndpointsV1, LoginOptions from . import common +from tests.testutils import SSLMatcher class TestSSO(common.DescopeTest): @@ -48,17 +49,17 @@ def test_sso_start(self): self.assertRaises(AuthException, sso.start, "", "http://dummy.com") self.assertRaises(AuthException, sso.start, None, "http://dummy.com") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, sso.start, "tenant1", "http://dummy.com") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(sso.start("tenant1", "http://dummy.com")) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True sso.start("tenant1", "http://dummy.com", sso_id="some-sso-id") expected_uri = f"{common.DEFAULT_BASE_URL}{EndpointsV1.auth_sso_start_path}" mock_post.assert_called_with( @@ -74,8 +75,8 @@ def test_sso_start(self): "ssoId": "some-sso-id", }, json={}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertRaises( @@ -93,17 +94,17 @@ def test_sso_start_with_login_options(self): self.assertRaises(AuthException, sso.start, "", "http://dummy.com") self.assertRaises(AuthException, sso.start, None, "http://dummy.com") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, sso.start, "tenant1", "http://dummy.com") # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(sso.start("tenant1", "http://dummy.com")) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True lo = LoginOptions(stepup=True, custom_claims={"k1": "v1"}) sso.start("tenant1", "http://dummy.com", lo, "refresh") expected_uri = f"{common.DEFAULT_BASE_URL}{EndpointsV1.auth_sso_start_path}" @@ -116,8 +117,8 @@ def test_sso_start_with_login_options(self): }, params={"tenant": "tenant1", "redirectURL": "http://dummy.com"}, json={"stepup": True, "customClaims": {"k1": "v1"}, "mfa": False}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -131,14 +132,14 @@ def test_exchange_token(self): self.assertRaises(AuthException, sso.exchange_token, "") self.assertRaises(AuthException, sso.exchange_token, None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises(AuthException, sso.exchange_token, "c1") # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -155,8 +156,8 @@ def test_exchange_token(self): }, params=None, json={"code": "c1"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) diff --git a/tests/test_totp.py b/tests/test_totp.py index 19f372965..b7771f653 100644 --- a/tests/test_totp.py +++ b/tests/test_totp.py @@ -7,6 +7,7 @@ from descope.authmethod.totp import TOTP # noqa: F401 from descope.common import DEFAULT_TIMEOUT_SECONDS, EndpointsV1, LoginOptions +from tests.testutils import SSLMatcher from . import common @@ -49,8 +50,8 @@ def test_sign_up(self): signup_user_details, ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, totp.sign_up, @@ -59,8 +60,8 @@ def test_sign_up(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(totp.sign_up("dummy@dummy.com", signup_user_details)) def test_sign_in(self): @@ -72,16 +73,16 @@ def test_sign_in(self): self.assertRaises(AuthException, totp.sign_in_code, "dummy@dummy.com", None) self.assertRaises(AuthException, totp.sign_in_code, "dummy@dummy.com", "") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, totp.sign_in_code, "dummy@dummy.com", "1234" ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -98,9 +99,9 @@ def test_sign_in(self): ) # Validate refresh token used while provided - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"jwts": ["eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpXVCJ9.eyJjb29raWVEb21haW4iOiIiLCJjb29raWVFeHBpcmF0aW9uIjoxNjYwMzg4MDc4LCJjb29raWVNYXhBZ2UiOjI1OTE5OTksImNvb2tpZU5hbWUiOiJEU1IiLCJjb29raWVQYXRoIjoiLyIsImV4cCI6MTY2MDIxNTI3OCwiaWF0IjoxNjU3Nzk2MDc4LCJpc3MiOiIyQnQ1V0xjY0xVZXkxRHA3dXRwdFpiM0Z4OUsiLCJzdWIiOiIyQnRFSGtnT3UwMmxtTXh6UElleGRNdFV3MU0ifQ.oAnvJ7MJvCyL_33oM7YCF12JlQ0m6HWRuteUVAdaswfnD4rHEBmPeuVHGljN6UvOP4_Cf0559o39UHVgm3Fwb-q7zlBbsu_nP1-PRl-F8NJjvBgC5RsAYabtJq7LlQmh"], "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -131,8 +132,8 @@ def test_sign_in(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) @@ -145,8 +146,8 @@ def test_update_user(self): self.assertRaises(AuthException, totp.update_user, "dummy@dummy.com", None) self.assertRaises(AuthException, totp.update_user, "dummy@dummy.com", "") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, totp.update_user, @@ -159,7 +160,7 @@ def test_update_user(self): """{ "provisioningURL": "http://dummy.com", "image": "imagedata", "key": "k01", "error": "" }""" ) my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = valid_response mock_post.return_value = my_mock_response res = totp.update_user("dummy@dummy.com", valid_jwt_token) @@ -173,8 +174,8 @@ def test_update_user(self): }, params=None, json={"loginId": "dummy@dummy.com"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res, valid_response) diff --git a/tests/test_webauthn.py b/tests/test_webauthn.py index 3a3a0bf02..79671d6ac 100644 --- a/tests/test_webauthn.py +++ b/tests/test_webauthn.py @@ -9,6 +9,7 @@ from descope.common import DEFAULT_TIMEOUT_SECONDS, EndpointsV1, LoginOptions from . import common +from tests.testutils import SSLMatcher class TestWebauthN(common.DescopeTest): @@ -88,8 +89,8 @@ def test_sign_up_start(self): ) self.assertRaises(AuthException, webauthn.sign_up_start, "id1", "") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, webauthn.sign_up_start, "id1", "https://example.com" ) @@ -98,13 +99,13 @@ def test_sign_up_start(self): valid_response = json.loads( """{"transactionId": "2COHI3LIixYhf6Q7EECYt20zyMi", "options": "{'publicKey':{'challenge':'5GOywA7BHL1QceQOfxHKDrasuN8SkbbgXmB5ImVZ+QU=','rp':{'name':'comp6','id':'localhost'},'user':{'name”:”dummy@dummy.com','displayName”:”dummy”,”id':'VTJDT0hJNWlWOHJaZ3VURkpKMzV3bjEydHRkTw=='},'pubKeyCredParams':[{'type':'public-key','alg':-7},{'type':'public-key','alg':-35},{'type':'public-key','alg':-36},{'type':'public-key','alg':-257},{'type':'public-key','alg':-258},{'type':'public-key','alg':-259},{'type':'public-key','alg':-37},{'type':'public-key','alg':-38},{'type':'public-key','alg':-39},{'type':'public-key','alg':-8}],'authenticatorSelection':{'userVerification':'preferred'},'timeout':60000,'attestation':'none'}}"}""" ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone(webauthn.sign_up_start("id1", "https://example.com")) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = valid_response mock_post.return_value = my_mock_response res = webauthn.sign_up_start("id1", "https://example.com") @@ -119,8 +120,8 @@ def test_sign_up_start(self): }, params=None, json={"user": {"loginId": "id1"}, "origin": "https://example.com"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res, valid_response) @@ -134,16 +135,16 @@ def test_sign_up_finish(self): self.assertRaises(AuthException, webauthn.sign_up_finish, "t01", "") self.assertRaises(AuthException, webauthn.sign_up_finish, "t01", None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, webauthn.sign_up_finish, "t01", "response01" ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"refreshJwt": "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0Mzc1OTYsImlhdCI6MTY1OTYzNzU5NiwiaXNzIjoiUDJDdHpVaGRxcElGMnlzOWdnN21zMDZVdnRDNCIsInN1YiI6IlUyQ3UwajBXUHczWU9pUElTSmI1Mkwwd1VWTWcifQ.WLnlHugvzZtrV9OzBB7SjpCLNRvKF3ImFpVyIN5orkrjO2iyAKg_Rb4XHk9sXGC1aW8puYzLbhE1Jv3kk2hDcKggfE8OaRNRm8byhGFZHnvPJwcP_Ya-aRmfAvCLcKOL", @@ -169,8 +170,8 @@ def test_sign_up_finish(self): }, params=None, json={"transactionId": "t01", "response": "response01"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertIsNotNone(webauthn.sign_up_finish("t01", "response01")) @@ -184,8 +185,8 @@ def test_sign_in_start(self): ) self.assertRaises(AuthException, webauthn.sign_in_start, "id", "") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, webauthn.sign_in_start, @@ -197,8 +198,8 @@ def test_sign_in_start(self): valid_response = json.loads( """{"transactionId": "2COHI3LIixYhf6Q7EECYt20zyMi", "options": "{'publicKey':{'challenge':'5GOywA7BHL1QceQOfxHKDrasuN8SkbbgXmB5ImVZ+QU=','rp':{'name':'comp6','id':'localhost'},'user':{'name”:”dummy@dummy.com','displayName”:”dummy”,”id':'VTJDT0hJNWlWOHJaZ3VURkpKMzV3bjEydHRkTw=='},'pubKeyCredParams':[{'type':'public-key','alg':-7},{'type':'public-key','alg':-35},{'type':'public-key','alg':-36},{'type':'public-key','alg':-257},{'type':'public-key','alg':-258},{'type':'public-key','alg':-259},{'type':'public-key','alg':-37},{'type':'public-key','alg':-38},{'type':'public-key','alg':-39},{'type':'public-key','alg':-8}],'authenticatorSelection':{'userVerification':'preferred'},'timeout':60000,'attestation':'none'}}"}""" ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( webauthn.sign_in_start("dummy@dummy.com", "https://example.com") ) @@ -210,9 +211,9 @@ def test_sign_in_start(self): LoginOptions(mfa=True), ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = valid_response mock_post.return_value = my_mock_response res = webauthn.sign_in_start("id1", "https://example.com") @@ -230,8 +231,8 @@ def test_sign_in_start(self): "origin": "https://example.com", "loginOptions": {}, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res, valid_response) @@ -245,8 +246,8 @@ def test_sign_in_start_with_login_options(self): ) self.assertRaises(AuthException, webauthn.sign_in_start, "id", "") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, webauthn.sign_in_start, @@ -258,15 +259,15 @@ def test_sign_in_start_with_login_options(self): valid_response = json.loads( """{"transactionId": "2COHI3LIixYhf6Q7EECYt20zyMi", "options": "{'publicKey':{'challenge':'5GOywA7BHL1QceQOfxHKDrasuN8SkbbgXmB5ImVZ+QU=','rp':{'name':'comp6','id':'localhost'},'user':{'name”:”dummy@dummy.com','displayName”:”dummy”,”id':'VTJDT0hJNWlWOHJaZ3VURkpKMzV3bjEydHRkTw=='},'pubKeyCredParams':[{'type':'public-key','alg':-7},{'type':'public-key','alg':-35},{'type':'public-key','alg':-36},{'type':'public-key','alg':-257},{'type':'public-key','alg':-258},{'type':'public-key','alg':-259},{'type':'public-key','alg':-37},{'type':'public-key','alg':-38},{'type':'public-key','alg':-39},{'type':'public-key','alg':-8}],'authenticatorSelection':{'userVerification':'preferred'},'timeout':60000,'attestation':'none'}}"}""" ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( webauthn.sign_in_start("dummy@dummy.com", "https://example.com") ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = valid_response mock_post.return_value = my_mock_response lo = LoginOptions(stepup=True, custom_claims={"k1": "v1"}) @@ -289,8 +290,8 @@ def test_sign_in_start_with_login_options(self): "mfa": False, }, }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res, valid_response) @@ -304,16 +305,16 @@ def test_sign_in_finish(self): self.assertRaises(AuthException, webauthn.sign_in_finish, "t01", "") self.assertRaises(AuthException, webauthn.sign_in_finish, "t01", None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, webauthn.sign_in_finish, "t01", "response01" ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( @@ -333,8 +334,8 @@ def test_sign_in_finish(self): }, params=None, json={"transactionId": "t01", "response": "response01"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertIsNotNone(webauthn.sign_up_finish("t01", "response01")) @@ -348,8 +349,8 @@ def test_sign_up_or_in_start(self): ) self.assertRaises(AuthException, webauthn.sign_up_or_in_start, "id", "") - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, webauthn.sign_up_or_in_start, @@ -361,15 +362,15 @@ def test_sign_up_or_in_start(self): valid_response = json.loads( """{"create": true, "transactionId": "2COHI3LIixYhf6Q7EECYt20zyMi", "options": "{'publicKey':{'challenge':'5GOywA7BHL1QceQOfxHKDrasuN8SkbbgXmB5ImVZ+QU=','rp':{'name':'comp6','id':'localhost'},'user':{'name”:”dummy@dummy.com','displayName”:”dummy”,”id':'VTJDT0hJNWlWOHJaZ3VURkpKMzV3bjEydHRkTw=='},'pubKeyCredParams':[{'type':'public-key','alg':-7},{'type':'public-key','alg':-35},{'type':'public-key','alg':-36},{'type':'public-key','alg':-257},{'type':'public-key','alg':-258},{'type':'public-key','alg':-259},{'type':'public-key','alg':-37},{'type':'public-key','alg':-38},{'type':'public-key','alg':-39},{'type':'public-key','alg':-8}],'authenticatorSelection':{'userVerification':'preferred'},'timeout':60000,'attestation':'none'}}"}""" ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( webauthn.sign_up_or_in_start("dummy@dummy.com", "https://example.com") ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = valid_response mock_post.return_value = my_mock_response res = webauthn.sign_up_or_in_start("id1", "https://example.com") @@ -386,8 +387,8 @@ def test_sign_up_or_in_start(self): "loginId": "id1", "origin": "https://example.com", }, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res, valid_response) @@ -418,8 +419,8 @@ def test_update_start(self): "https://example.com", ) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, webauthn.update_start, @@ -429,18 +430,18 @@ def test_update_start(self): ) # Test success flow - with patch("requests.post") as mock_post: - mock_post.return_value.ok = True + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = True self.assertIsNotNone( webauthn.update_start( "dummy@dummy.com", valid_jwt_token, "https://example.com" ) ) - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: valid_response = json.loads("{}") my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.json.return_value = valid_response mock_post.return_value = my_mock_response res = webauthn.update_start( @@ -456,8 +457,8 @@ def test_update_start(self): }, params=None, json={"loginId": "dummy@dummy.com", "origin": "https://example.com"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertEqual(res, valid_response) @@ -471,16 +472,16 @@ def test_update_finish(self): self.assertRaises(AuthException, webauthn.update_finish, "t01", "") self.assertRaises(AuthException, webauthn.update_finish, "t01", None) - with patch("requests.post") as mock_post: - mock_post.return_value.ok = False + with patch("httpx.post") as mock_post: + mock_post.return_value.is_success = False self.assertRaises( AuthException, webauthn.update_finish, "t01", "response01" ) # Test success flow - with patch("requests.post") as mock_post: + with patch("httpx.post") as mock_post: my_mock_response = mock.Mock() - my_mock_response.ok = True + my_mock_response.is_success = True my_mock_response.cookies = {} data = json.loads( """{"refreshJwt": "eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJKV1QifQ.eyJkcm4iOiJEU1IiLCJleHAiOjIyNjQ0Mzc1OTYsImlhdCI6MTY1OTYzNzU5NiwiaXNzIjoiUDJDdHpVaGRxcElGMnlzOWdnN21zMDZVdnRDNCIsInN1YiI6IlUyQ3UwajBXUHczWU9pUElTSmI1Mkwwd1VWTWcifQ.WLnlHugvzZtrV9OzBB7SjpCLNRvKF3ImFpVyIN5orkrjO2iyAKg_Rb4XHk9sXGC1aW8puYzLbhE1Jv3kk2hDcKggfE8OaRNRm8byhGFZHnvPJwcP_Ya-aRmfAvCLcKOL", "user": {"loginIds": ["guyp@descope.com"], "name": "", "email": "guyp@descope.com", "phone": "", "verifiedEmail": true, "verifiedPhone": false}, "firstSeen": false}""" @@ -498,8 +499,8 @@ def test_update_finish(self): }, params=None, json={"transactionId": "t01", "response": "response01"}, - allow_redirects=False, - verify=True, + follow_redirects=False, + verify=SSLMatcher(), timeout=DEFAULT_TIMEOUT_SECONDS, ) self.assertIsNotNone(webauthn.sign_up_finish("t01", "response01")) diff --git a/tests/testutils.py b/tests/testutils.py new file mode 100644 index 000000000..ecdd3d382 --- /dev/null +++ b/tests/testutils.py @@ -0,0 +1,6 @@ +from ssl import SSLContext + + +class SSLMatcher: + def __eq__(self, other): + return isinstance(other, SSLContext)