From d70cecc93e87c1b3af55c00c6206b89230de7be6 Mon Sep 17 00:00:00 2001 From: Victor Silva Date: Mon, 17 Feb 2025 14:20:11 -0300 Subject: [PATCH 01/17] feat: adding sessions endpoints --- auth0/management/sessions.py | 84 ++++++++++++++++++++++++++ auth0/test/management/test_sessions.py | 45 ++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 auth0/management/sessions.py create mode 100644 auth0/test/management/test_sessions.py diff --git a/auth0/management/sessions.py b/auth0/management/sessions.py new file mode 100644 index 00000000..f626d83a --- /dev/null +++ b/auth0/management/sessions.py @@ -0,0 +1,84 @@ +from typing import Any + +from auth0.rest import RestClient +from auth0.rest import RestClientOptions +from auth0.types import TimeoutType + + +class Sessions: + """Auth0 users endpoints + + Args: + domain (str): Your Auth0 domain, e.g: 'username.auth0.com' + + token (str): Management API v2 Token + + telemetry (bool, optional): Enable or disable Telemetry + (defaults to True) + + timeout (float or tuple, optional): Change the requests + connect and read timeout. Pass a tuple to specify + both values separately or a float to set both to it. + (defaults to 5.0 for both) + + protocol (str, optional): Protocol to use when making requests. + (defaults to "https") + + rest_options (RestClientOptions): Pass an instance of + RestClientOptions to configure additional RestClient + options, such as rate-limit retries. + (defaults to None) + """ + + def __init__( + self, + domain: str, + token: str, + telemetry: bool = True, + timeout: TimeoutType = 5.0, + protocol: str = "https", + rest_options: RestClientOptions | None = None, + ) -> None: + self.domain = domain + self.protocol = protocol + self.client = RestClient(jwt=token, telemetry=telemetry, timeout=timeout, options=rest_options) + + def _url(self, id: str | None = None) -> str: + url = f"{self.protocol}://{self.domain}/api/v2/sessions" + if id is not None: + return f"{url}/{id}" + return url + + def get(self, id: str) -> dict[str, Any]: + """Get a session. + + Args: + id (str): The id of the session to retrieve. + + See: https://auth0.com/docs/api/management/v2#!/Sessions/get-session + """ + + return self.client.get(self._url(id)) + + def delete(self, id: str) -> None: + """Delete a session. + + Args: + id (str): The id of the session to delete. + + See: https://auth0.com/docs/api/management/v2#!/Sessions/delete-session + """ + + return self.client.delete(self._url(id)) + + def revoke(self, id: str) -> None: + """Revokes a session by ID and all associated refresh tokens.. + + Args: + id (str): The id of the session to revoke. + + See: https://auth0.com/docs/api/management/v2#!/Sessions/revoke-session + """ + + url = self._url(f"{id}/sessions") + return self.client.post(url) diff --git a/auth0/test/management/test_sessions.py b/auth0/test/management/test_sessions.py new file mode 100644 index 00000000..5144ebfa --- /dev/null +++ b/auth0/test/management/test_sessions.py @@ -0,0 +1,45 @@ +import unittest +from unittest import mock + +from ...management.users import Sessions + + +class TestUsers(unittest.TestCase): + def test_init_with_optionals(self): + t = Sessions(domain="domain", token="jwttoken", telemetry=False, timeout=(10, 2)) + self.assertEqual(t.client.options.timeout, (10, 2)) + telemetry_header = t.client.base_headers.get("Auth0-Client", None) + self.assertEqual(telemetry_header, None) + + @mock.patch("auth0.management.users.RestClient") + def test_get(self, mock_rc): + mock_instance = mock_rc.return_value + + u = Sessions(domain="domain", token="jwttoken") + u.get("user_id") + + mock_instance.get.assert_called_with( + "https://domain/api/v2/sessions/session_id" + ) + + @mock.patch("auth0.management.users.RestClient") + def test_delete(self, mock_rc): + mock_instance = mock_rc.return_value + + u = Sessions(domain="domain", token="jwttoken") + u.delete("session_id") + + mock_instance.delete.assert_called_with( + "https://domain/api/v2/sessions/session_id" + ) + + @mock.patch("auth0.management.users.RestClient") + def test_revoke(self, mock_rc): + mock_instance = mock_rc.return_value + + u = Sessions(domain="domain", token="jwttoken") + u.revoke("session_id") + + mock_instance.post.assert_called_with( + "https://domain/api/v2/sessions/session_id/sessions" + ) From eeee9b21b08bc7b0694332b9c4b0eac5311d3b10 Mon Sep 17 00:00:00 2001 From: Victor Silva Date: Mon, 17 Feb 2025 14:20:27 -0300 Subject: [PATCH 02/17] feat: add sessions in users and update doc --- README.md | 1 + auth0/management/__init__.py | 2 ++ auth0/management/users.py | 45 ++++++++++++++++++++++++-- auth0/test/management/test_sessions.py | 12 +++---- auth0/test/management/test_users.py | 24 +++++++++++++- 5 files changed, 75 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 215043ce..3bed7316 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ For more code samples on how to integrate the auth0-python SDK in your Python ap - Rules() ( `Auth0().rules` ) - SelfServiceProfiles() ( `Auth0().self_service_profiles` ) - Stats() ( `Auth0().stats` ) +- Sessions() ( `Auth0().sessions` ) - Tenants() ( `Auth0().tenants` ) - Tickets() ( `Auth0().tickets` ) - UserBlocks() (`Auth0().user_blocks` ) diff --git a/auth0/management/__init__.py b/auth0/management/__init__.py index 761446b6..b1a5fc76 100644 --- a/auth0/management/__init__.py +++ b/auth0/management/__init__.py @@ -24,6 +24,7 @@ from .rules import Rules from .rules_configs import RulesConfigs from .self_service_profiles import SelfServiceProfiles +from .sessions import Sessions from .stats import Stats from .tenants import Tenants from .tickets import Tickets @@ -64,6 +65,7 @@ "Rules", "SelfServiceProfiles", "Stats", + "Sessions", "Tenants", "Tickets", "UserBlocks", diff --git a/auth0/management/users.py b/auth0/management/users.py index 2fd9a46a..aa61ca37 100644 --- a/auth0/management/users.py +++ b/auth0/management/users.py @@ -348,7 +348,9 @@ def unlink_user_account(self, id: str, provider: str, user_id: str) -> Any: url = self._url(f"{id}/identities/{provider}/{user_id}") return self.client.delete(url) - def link_user_account(self, user_id: str, body: dict[str, Any]) -> list[dict[str, Any]]: + def link_user_account( + self, user_id: str, body: dict[str, Any] + ) -> list[dict[str, Any]]: """Link user accounts. Links the account specified in the body (secondary account) to the @@ -580,4 +582,43 @@ def delete_tokenset_by_id( """ url = self._url(f"{user_id}/federated-connections-tokensets/{tokenset_id}") - return self.client.delete(url) \ No newline at end of file + return self.client.delete(url) + + def delete_tokenset_by_id( + self, user_id: str, tokenset_id: str + ) -> Any: + """Deletes an tokenset by ID. + + Args: + user_id (str): The user_id to delete an authentication method by ID for. + tokenset_id (str): The tokenset_id to delete an tokenset by ID for. + + See: https://auth0.com/docs/api/management/v2#!/Users/delete_tokenset_by_id + """ + + url = self._url(f"{user_id}/federated-connections-tokensets/{tokenset_id}") + return self.client.delete(url) + + def get_sessions(self, user_id: str) -> dict[str, Any]: + """Get all sessions details for the given user. + + Args: + user_id (str): The user_id to get all sessions for the given user for. + + see: https://auth0.com/docs/api/management/v2#!/Users/get-sessions-for-user + """ + + url = self._url(f"{user_id}/sessions") + return self.client.get(url) + + def delete_sessions(self, user_id: str) -> dict[str, Any]: + """Delete all sessions for the given user. + + Args: + user_id (str): The user_id to delete all session for the given user for. + + See: https://auth0.com/docs/api/management/v2#!/Users/delete-sessions-for-user + """ + + url = self._url(f"{user_id}/sessions") + return self.client.delete(url) diff --git a/auth0/test/management/test_sessions.py b/auth0/test/management/test_sessions.py index 5144ebfa..5ecd0923 100644 --- a/auth0/test/management/test_sessions.py +++ b/auth0/test/management/test_sessions.py @@ -1,28 +1,28 @@ import unittest from unittest import mock -from ...management.users import Sessions +from ...management.sessions import Sessions -class TestUsers(unittest.TestCase): +class TestSessions(unittest.TestCase): def test_init_with_optionals(self): t = Sessions(domain="domain", token="jwttoken", telemetry=False, timeout=(10, 2)) self.assertEqual(t.client.options.timeout, (10, 2)) telemetry_header = t.client.base_headers.get("Auth0-Client", None) self.assertEqual(telemetry_header, None) - @mock.patch("auth0.management.users.RestClient") + @mock.patch("auth0.management.sessions.RestClient") def test_get(self, mock_rc): mock_instance = mock_rc.return_value u = Sessions(domain="domain", token="jwttoken") - u.get("user_id") + u.get("session_id") mock_instance.get.assert_called_with( "https://domain/api/v2/sessions/session_id" ) - @mock.patch("auth0.management.users.RestClient") + @mock.patch("auth0.management.sessions.RestClient") def test_delete(self, mock_rc): mock_instance = mock_rc.return_value @@ -33,7 +33,7 @@ def test_delete(self, mock_rc): "https://domain/api/v2/sessions/session_id" ) - @mock.patch("auth0.management.users.RestClient") + @mock.patch("auth0.management.sessions.RestClient") def test_revoke(self, mock_rc): mock_instance = mock_rc.return_value diff --git a/auth0/test/management/test_users.py b/auth0/test/management/test_users.py index 9cab65f6..b2fb4449 100644 --- a/auth0/test/management/test_users.py +++ b/auth0/test/management/test_users.py @@ -435,4 +435,26 @@ def test_delete_tokenset_by_id(self, mock_rc): mock_instance.delete.assert_called_with( "https://domain/api/v2/users/user_id/federated-connections-tokensets/tokenset_id" - ) \ No newline at end of file + ) + + @mock.patch("auth0.management.users.RestClient") + def test_get_sessions_by_user(self, mock_rc): + mock_instance = mock_rc.return_value + + u = Users(domain="domain", token="jwttoken") + u.get_sessions("user_id") + + mock_instance.get.assert_called_with( + "https://domain/api/v2/users/user_id/sessions" + ) + + @mock.patch("auth0.management.users.RestClient") + def test_delete_sessions_by_user(self, mock_rc): + mock_instance = mock_rc.return_value + + u = Users(domain="domain", token="jwttoken") + u.delete_sessions("user_id") + + mock_instance.delete.assert_called_with( + "https://domain/api/v2/users/user_id/sessions" + ) From 0a4b7a127969c9f085381d8637e44016948ae4c2 Mon Sep 17 00:00:00 2001 From: Victor Silva Date: Fri, 25 Jul 2025 23:38:52 -0300 Subject: [PATCH 03/17] chore(pre-commit): update flake8 to 7 --- .pre-commit-config.yaml | 2 +- auth0/management/users.py | 95 +++++------- poetry.lock | 318 +++++++++++++++++++------------------- requirements.txt | 80 +++++----- 4 files changed, 236 insertions(+), 259 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a598fec7..92028cd0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/pycqa/flake8 - rev: 5.0.4 + rev: 7.3.0 hooks: - id: flake8 diff --git a/auth0/management/users.py b/auth0/management/users.py index aa61ca37..6a29a92a 100644 --- a/auth0/management/users.py +++ b/auth0/management/users.py @@ -542,62 +542,45 @@ def delete_authentication_method_by_id( return self.client.delete(url) def list_tokensets( - self, id: str, page: int = 0, per_page: int = 25, include_totals: bool = True - ): - """List all the tokenset(s) associated to the user. - - Args: - id (str): The user's id. - - page (int, optional): The result's page number (zero based). By default, - retrieves the first page of results. - - per_page (int, optional): The amount of entries per page. By default, - retrieves 25 results per page. - - include_totals (bool, optional): True if the query summary is - to be included in the result, False otherwise. Defaults to True. - - See https://auth0.com/docs/api/management/v2#!/Users/get_tokensets - """ - - params = { - "per_page": per_page, - "page": page, - "include_totals": str(include_totals).lower(), - } - url = self._url(f"{id}/federated-connections-tokensets") - return self.client.get(url, params=params) - - def delete_tokenset_by_id( - self, user_id: str, tokenset_id: str - ) -> Any: - """Deletes an tokenset by ID. - - Args: - user_id (str): The user_id to delete an authentication method by ID for. - tokenset_id (str): The tokenset_id to delete an tokenset by ID for. - - See: https://auth0.com/docs/api/management/v2#!/Users/delete_tokenset_by_id - """ - - url = self._url(f"{user_id}/federated-connections-tokensets/{tokenset_id}") - return self.client.delete(url) - - def delete_tokenset_by_id( - self, user_id: str, tokenset_id: str - ) -> Any: - """Deletes an tokenset by ID. - - Args: - user_id (str): The user_id to delete an authentication method by ID for. - tokenset_id (str): The tokenset_id to delete an tokenset by ID for. - - See: https://auth0.com/docs/api/management/v2#!/Users/delete_tokenset_by_id - """ - - url = self._url(f"{user_id}/federated-connections-tokensets/{tokenset_id}") - return self.client.delete(url) + self, id: str, page: int = 0, per_page: int = 25, include_totals: bool = True + ): + """List all the tokenset(s) associated to the user. + + Args: + id (str): The user's id. + + page (int, optional): The result's page number (zero based). By default, + retrieves the first page of results. + + per_page (int, optional): The amount of entries per page. By default, + retrieves 25 results per page. + + include_totals (bool, optional): True if the query summary is + to be included in the result, False otherwise. Defaults to True. + + See https://auth0.com/docs/api/management/v2#!/Users/get_tokensets + """ + + params = { + "per_page": per_page, + "page": page, + "include_totals": str(include_totals).lower(), + } + url = self._url(f"{id}/federated-connections-tokensets") + return self.client.get(url, params=params) + + def delete_tokenset_by_id(self, user_id: str, tokenset_id: str) -> Any: + """Deletes an tokenset by ID. + + Args: + user_id (str): The user_id to delete an authentication method by ID for. + tokenset_id (str): The tokenset_id to delete an tokenset by ID for. + + See: https://auth0.com/docs/api/management/v2#!/Users/delete_tokenset_by_id + """ + + url = self._url(f"{user_id}/federated-connections-tokensets/{tokenset_id}") + return self.client.delete(url) def get_sessions(self, user_id: str) -> dict[str, Any]: """Get all sessions details for the given user. diff --git a/poetry.lock b/poetry.lock index dde7c710..b11c3c72 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,12 +1,12 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" version = "2.4.4" description = "Happy Eyeballs for asyncio" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, @@ -16,9 +16,9 @@ files = [ name = "aiohttp" version = "3.10.11" description = "Async http client/server framework (asyncio)" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"}, {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"}, @@ -129,9 +129,9 @@ speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] name = "aioresponses" version = "0.7.8" description = "Mock out requests made by ClientSession from aiohttp package" +category = "dev" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "aioresponses-0.7.8-py2.py3-none-any.whl", hash = "sha256:b73bd4400d978855e55004b23a3a84cb0f018183bcf066a85ad392800b5b9a94"}, {file = "aioresponses-0.7.8.tar.gz", hash = "sha256:b861cdfe5dc58f3b8afac7b0a6973d5d7b2cb608dd0f6253d16b8ee8eaf6df11"}, @@ -145,9 +145,9 @@ packaging = ">=22.0" name = "aiosignal" version = "1.3.1" description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] files = [ {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, @@ -158,14 +158,14 @@ frozenlist = ">=1.1.0" [[package]] name = "argcomplete" -version = "3.6.0" +version = "3.6.2" description = "Bash tab completion for argparse" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ - {file = "argcomplete-3.6.0-py3-none-any.whl", hash = "sha256:4e3e4e10beb20e06444dbac0ac8dda650cb6349caeefe980208d3c548708bedd"}, - {file = "argcomplete-3.6.0.tar.gz", hash = "sha256:2e4e42ec0ba2fff54b0d244d0b1623e86057673e57bafe72dda59c64bd5dee8b"}, + {file = "argcomplete-3.6.2-py3-none-any.whl", hash = "sha256:65b3133a29ad53fb42c48cf5114752c7ab66c1c38544fdf6460f450c09b42591"}, + {file = "argcomplete-3.6.2.tar.gz", hash = "sha256:d0519b1bc867f5f4f4713c41ad0aba73a4a5f007449716b16f385f2166dc6adf"}, ] [package.extras] @@ -175,10 +175,9 @@ test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] name = "async-timeout" version = "5.0.1" description = "Timeout context manager for asyncio programs" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] -markers = "python_version < \"3.11\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -188,9 +187,9 @@ files = [ name = "attrs" version = "25.3.0" description = "Classes Without Boilerplate" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, @@ -206,24 +205,23 @@ tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "certifi" -version = "2025.1.31" +version = "2025.7.14" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] +python-versions = ">=3.7" files = [ - {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, - {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, + {file = "certifi-2025.7.14-py3-none-any.whl", hash = "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2"}, + {file = "certifi-2025.7.14.tar.gz", hash = "sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995"}, ] [[package]] name = "cffi" version = "1.17.1" description = "Foreign Function Interface for Python calling C code." +category = "main" 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"}, @@ -299,113 +297,113 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.4.1" +version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] files = [ - {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, - {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, - {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}, + {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, + {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, ] [[package]] name = "click" version = "8.1.8" description = "Composable command line interface toolkit" +category = "dev" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, @@ -418,10 +416,9 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] -markers = "sys_platform == \"win32\" or platform_system == \"Windows\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -431,9 +428,9 @@ files = [ name = "coverage" version = "7.6.1" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] 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"}, @@ -519,9 +516,9 @@ toml = ["tomli"] name = "cryptography" version = "43.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" 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"}, @@ -567,17 +564,19 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "exceptiongroup" -version = "1.2.2" +version = "1.3.0" description = "Backport of PEP 654 (exception groups)" +category = "dev" optional = false python-versions = ">=3.7" -groups = ["dev"] -markers = "python_version < \"3.11\"" files = [ - {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, - {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, + {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, + {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + [package.extras] test = ["pytest (>=6)"] @@ -585,9 +584,9 @@ test = ["pytest (>=6)"] name = "frozenlist" version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, @@ -687,9 +686,9 @@ files = [ name = "idna" version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.6" -groups = ["main", "dev"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -702,9 +701,9 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 name = "iniconfig" version = "2.1.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -714,9 +713,9 @@ files = [ name = "mock" version = "5.2.0" description = "Rolling backport of unittest.mock for all Pythons" +category = "dev" 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"}, @@ -731,9 +730,9 @@ test = ["pytest", "pytest-cov"] name = "multidict" version = "6.1.0" description = "multidict implementation" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, @@ -834,23 +833,23 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} [[package]] name = "packaging" -version = "24.2" +version = "25.0" description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] [[package]] name = "pipx" version = "1.7.1" description = "Install and Run Python Applications in Isolated Environments" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pipx-1.7.1-py3-none-any.whl", hash = "sha256:3933c43bb344e649cb28e10d357e0967ce8572f1c19caf90cf39ae95c2a0afaf"}, {file = "pipx-1.7.1.tar.gz", hash = "sha256:762de134e16a462be92645166d225ecef446afaef534917f5f70008d63584360"}, @@ -868,9 +867,9 @@ userpath = ">=1.6,<1.9 || >1.9" name = "platformdirs" version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -885,9 +884,9 @@ type = ["mypy (>=1.11.2)"] name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -901,9 +900,9 @@ testing = ["pytest", "pytest-benchmark"] name = "propcache" version = "0.2.0" description = "Accelerated property cache" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, @@ -1009,10 +1008,9 @@ files = [ name = "pycparser" version = "2.22" description = "C parser in Python" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -1022,9 +1020,9 @@ files = [ name = "pyjwt" version = "2.9.0" description = "JSON Web Token implementation in Python" +category = "main" 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"}, @@ -1040,9 +1038,9 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] name = "pytest" version = "7.4.4" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, @@ -1063,9 +1061,9 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-aiohttp" version = "1.0.5" description = "Pytest plugin for aiohttp support" +category = "dev" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "pytest-aiohttp-1.0.5.tar.gz", hash = "sha256:880262bc5951e934463b15e3af8bb298f11f7d4d3ebac970aab425aff10a780a"}, {file = "pytest_aiohttp-1.0.5-py3-none-any.whl", hash = "sha256:63a5360fd2f34dda4ab8e6baee4c5f5be4cd186a403cabd498fced82ac9c561e"}, @@ -1083,9 +1081,9 @@ testing = ["coverage (==6.2)", "mypy (==0.931)"] name = "pytest-asyncio" version = "0.23.8" description = "Pytest support for asyncio" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, @@ -1102,9 +1100,9 @@ testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] name = "pytest-cov" version = "4.1.0" description = "Pytest plugin for measuring coverage." +category = "dev" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, @@ -1121,9 +1119,9 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pyyaml" version = "6.0.2" description = "YAML parser and emitter for Python" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1182,19 +1180,19 @@ files = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, + {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" +charset_normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" @@ -1206,9 +1204,9 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "responses" version = "0.24.1" description = "A utility library for mocking out the `requests` Python library." +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "responses-0.24.1-py3-none-any.whl", hash = "sha256:a2b43f4c08bfb9c9bd242568328c65a34b318741d3fab884ac843c5ceeb543f9"}, {file = "responses-0.24.1.tar.gz", hash = "sha256:b127c6ca3f8df0eb9cc82fd93109a3007a86acb24871834c47b77765152ecf8c"}, @@ -1226,10 +1224,9 @@ tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asy name = "tomli" version = "2.2.1" description = "A lil' TOML parser" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] -markers = "python_full_version <= \"3.11.0a6\"" 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"}, @@ -1267,24 +1264,23 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.2" +version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] -markers = "python_version < \"3.11\"" files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, + {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." +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, @@ -1300,9 +1296,9 @@ zstd = ["zstandard (>=0.18.0)"] name = "userpath" version = "1.9.2" description = "Cross-platform tool for adding locations to the user PATH" +category = "dev" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "userpath-1.9.2-py3-none-any.whl", hash = "sha256:2cbf01a23d655a1ff8fc166dfb78da1b641d1ceabf0fe5f970767d380b14e89d"}, {file = "userpath-1.9.2.tar.gz", hash = "sha256:6c52288dab069257cc831846d15d48133522455d4677ee69a9781f11dbefd815"}, @@ -1315,9 +1311,9 @@ click = "*" name = "yarl" version = "1.15.2" description = "Yet another URL library" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "yarl-1.15.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e4ee8b8639070ff246ad3649294336b06db37a94bdea0d09ea491603e0be73b8"}, {file = "yarl-1.15.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7cf963a357c5f00cb55b1955df8bbe68d2f2f65de065160a1c26b85a1e44172"}, @@ -1425,6 +1421,6 @@ multidict = ">=4.0" propcache = ">=0.2.0" [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = ">=3.8" content-hash = "7158be33f0b386869b46e49466a4fac7a8789003f5736530b807bcce311ab117" diff --git a/requirements.txt b/requirements.txt index af78d77e..7ae87cfc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,41 +1,39 @@ -aiohttp==3.8.6 ; python_version >= "3.7" and python_version < "4.0" -aioresponses==0.7.4 ; python_version >= "3.7" and python_version < "4.0" -aiosignal==1.3.2 ; python_version >= "3.7" and python_version < "4.0" -argcomplete==3.5.3 ; python_version >= "3.7" and python_version < "4.0" -async-timeout==4.0.3 ; python_version >= "3.7" and python_version < "4.0" -asynctest==0.13.0 ; python_version >= "3.7" and python_version < "3.8" -attrs==23.1.0 ; python_version >= "3.7" and python_version < "4.0" -certifi==2025.1.31 ; python_version >= "3.7" and python_version < "4.0" -cffi==1.17.1 ; python_version >= "3.7" and python_version < "4.0" -charset-normalizer==3.4.2 ; python_version >= "3.7" and python_version < "4.0" -click==8.1.8 ; python_version >= "3.7" and python_version < "4.0" -colorama==0.4.6 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32" or python_version >= "3.7" and python_version < "4.0" and platform_system == "Windows" -coverage[toml]==7.2.7 ; python_version >= "3.7" and python_version < "4.0" -cryptography==44.0.1 ; python_version >= "3.7" and python_version < "4.0" -exceptiongroup==1.1.3 ; python_version >= "3.7" and python_version < "3.11" -frozenlist==1.5.0 ; python_version >= "3.7" and python_version < "4.0" -idna==3.10 ; python_version >= "3.7" and python_version < "4.0" -importlib-metadata==6.7.0 ; python_version >= "3.7" and python_version < "3.8" -iniconfig==2.1.0 ; python_version >= "3.7" and python_version < "4.0" -mock==5.2.0 ; python_version >= "3.7" and python_version < "4.0" -multidict==6.0.4 ; python_version >= "3.7" and python_version < "4.0" -packaging==23.1 ; python_version >= "3.7" and python_version < "4.0" -pipx==1.2.0 ; python_version >= "3.7" and python_version < "4.0" -pluggy==1.2.0 ; python_version >= "3.7" and python_version < "4.0" -pycparser==2.21 ; python_version >= "3.7" and python_version < "4.0" -pyjwt==2.9.0 ; python_version >= "3.7" and python_version < "4.0" -pyopenssl==25.1.0 ; python_version >= "3.7" and python_version < "4.0" -pytest-aiohttp==1.0.5 ; python_version >= "3.7" and python_version < "4.0" -pytest-asyncio==0.23.8 ; python_version >= "3.7" and python_version < "4.0" -pytest-cov==4.1.0 ; python_version >= "3.7" and python_version < "4.0" -pytest==7.4.0 ; python_version >= "3.7" and python_version < "4.0" -pyyaml==6.0.2 ; python_version >= "3.7" and python_version < "4.0" -requests==2.32.4 ; python_version >= "3.7" and python_version < "4.0" -responses==0.23.3 ; python_version >= "3.7" and python_version < "4.0" -tomli==2.0.1 ; python_version >= "3.7" and python_full_version <= "3.11.0a6" -types-pyyaml==6.0.12.11 ; python_version >= "3.7" and python_version < "4.0" -typing-extensions==4.7.1 ; python_version >= "3.7" and python_version < "3.8" -urllib3==2.5.0 ; python_version >= "3.7" and python_version < "4.0" -userpath==1.9.2 ; python_version >= "3.7" and python_version < "4.0" -yarl==1.20.0 ; python_version >= "3.7" and python_version < "4.0" -zipp==3.19.1 ; python_version >= "3.7" and python_version < "3.8" +aiohappyeyeballs==2.4.4 ; python_version >= "3.8" +aiohttp==3.10.11 ; python_version >= "3.8" +aioresponses==0.7.8 ; python_version >= "3.8" +aiosignal==1.3.1 ; python_version >= "3.8" +argcomplete==3.6.2 ; python_version >= "3.8" +async-timeout==5.0.1 ; python_version < "3.11" and python_version >= "3.8" +attrs==25.3.0 ; python_version >= "3.8" +certifi==2025.7.14 ; python_version >= "3.8" +cffi==1.17.1 ; platform_python_implementation != "PyPy" and python_version >= "3.8" +charset-normalizer==3.4.2 ; python_version >= "3.8" +click==8.1.8 ; python_version >= "3.8" +colorama==0.4.6 ; python_version >= "3.8" and sys_platform == "win32" or python_version >= "3.8" and platform_system == "Windows" +coverage[toml]==7.6.1 ; python_version >= "3.8" +cryptography==43.0.3 ; python_version >= "3.8" +exceptiongroup==1.3.0 ; python_version < "3.11" and python_version >= "3.8" +frozenlist==1.5.0 ; python_version >= "3.8" +idna==3.10 ; python_version >= "3.8" +iniconfig==2.1.0 ; python_version >= "3.8" +mock==5.2.0 ; python_version >= "3.8" +multidict==6.1.0 ; python_version >= "3.8" +packaging==25.0 ; python_version >= "3.8" +pipx==1.7.1 ; python_version >= "3.8" +platformdirs==4.3.6 ; python_version >= "3.8" +pluggy==1.5.0 ; python_version >= "3.8" +propcache==0.2.0 ; python_version >= "3.8" +pycparser==2.22 ; platform_python_implementation != "PyPy" and python_version >= "3.8" +pyjwt==2.9.0 ; python_version >= "3.8" +pytest-aiohttp==1.0.5 ; python_version >= "3.8" +pytest-asyncio==0.23.8 ; python_version >= "3.8" +pytest-cov==4.1.0 ; python_version >= "3.8" +pytest==7.4.4 ; python_version >= "3.8" +pyyaml==6.0.2 ; python_version >= "3.8" +requests==2.32.4 ; python_version >= "3.8" +responses==0.24.1 ; python_version >= "3.8" +tomli==2.2.1 ; python_version >= "3.8" and python_full_version <= "3.11.0a6" +typing-extensions==4.13.2 ; python_version < "3.11" and python_version >= "3.8" +urllib3==2.2.3 ; python_version >= "3.8" +userpath==1.9.2 ; python_version >= "3.8" +yarl==1.15.2 ; python_version >= "3.8" From da1cf2bcc4b1046953262df901007b8a718cf86e Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Thu, 28 Aug 2025 16:04:29 +0100 Subject: [PATCH 04/17] Updates for CIBA with email --- auth0/authentication/back_channel_login.py | 9 +++++- auth0/authentication/get_token.py | 32 ++++++++++++------- .../authentication/test_back_channel_login.py | 25 +++++++++++++++ auth0/test/authentication/test_get_token.py | 31 ++++++++++++++++++ 4 files changed, 84 insertions(+), 13 deletions(-) diff --git a/auth0/authentication/back_channel_login.py b/auth0/authentication/back_channel_login.py index e275cde4..d7bba603 100644 --- a/auth0/authentication/back_channel_login.py +++ b/auth0/authentication/back_channel_login.py @@ -14,6 +14,7 @@ def back_channel_login( login_hint: str, scope: str, authorization_details: Optional[Union[str, List[Dict]]] = None, + requested_expiry: Optional[int] = None, **kwargs ) -> Any: """Send a Back-Channel Login. @@ -31,6 +32,9 @@ def back_channel_login( authorization_details (str, list of dict, optional): JSON string or a list of dictionaries representing Rich Authorization Requests (RAR) details to include in the CIBA request. + requested_expiry (int, optional): Number of seconds the authentication request is valid for. + Auth0 defaults to 30 seconds if not provided. + **kwargs: Other fields to send along with the request. Returns: @@ -50,7 +54,10 @@ def back_channel_login( data["authorization_details"] = authorization_details elif isinstance(authorization_details, list): data["authorization_details"] = json.dumps(authorization_details) - + + if requested_expiry is not None: + data["requested_expiry"] = str(requested_expiry) + data.update(kwargs) return self.authenticated_post( diff --git a/auth0/authentication/get_token.py b/auth0/authentication/get_token.py index 6d71c085..a7ab0dc8 100644 --- a/auth0/authentication/get_token.py +++ b/auth0/authentication/get_token.py @@ -266,7 +266,7 @@ def backchannel_login( use urn:openid:params:grant-type:ciba Returns: - access_token, id_token + access_token, id_token, refresh_token, token_type, expires_in, scope and authorization_details """ return self.authenticated_post( @@ -284,7 +284,8 @@ def access_token_for_connection( subject_token: str, requested_token_type: str, connection: str | None = None, - grant_type: str = "urn:auth0:params:oauth:grant-type:token-exchange:federated-connection-access-token" + grant_type: str = "urn:auth0:params:oauth:grant-type:token-exchange:federated-connection-access-token", + login_hint: str = None ) -> Any: """Calls /oauth/token endpoint with federated-connection-access-token grant type @@ -293,22 +294,29 @@ def access_token_for_connection( subject_token (str): String containing the value of subject_token_type. - requested_token_type (str): String containing the type of rquested token. + requested_token_type (str): String containing the type of requested token. connection (str, optional): Denotes the name of a social identity provider configured to your application + login_hint (str, optional): A hint to the OpenID Provider regarding the end-user for whom authentication is being requested + Returns: - access_token, scope, issued_token_type, token_type + access_token, scope, issued_token_type, token_type, expires_in """ + data = { + "client_id": self.client_id, + "grant_type": grant_type, + "subject_token_type": subject_token_type, + "subject_token": subject_token, + "requested_token_type": requested_token_type, + "connection": connection, + } + + if login_hint: + data["login_hint"] = login_hint + return self.authenticated_post( f"{self.protocol}://{self.domain}/oauth/token", - data={ - "client_id": self.client_id, - "grant_type": grant_type, - "subject_token_type": subject_token_type, - "subject_token": subject_token, - "requested_token_type": requested_token_type, - "connection": connection, - }, + data=data, ) \ No newline at end of file diff --git a/auth0/test/authentication/test_back_channel_login.py b/auth0/test/authentication/test_back_channel_login.py index 049477ac..bcc223ba 100644 --- a/auth0/test/authentication/test_back_channel_login.py +++ b/auth0/test/authentication/test_back_channel_login.py @@ -136,3 +136,28 @@ def test_with_authorization_details(self, mock_post): "Request data does not match expected data after JSON serialization." ) + @mock.patch("auth0.rest.RestClient.post") + def test_with_request_expiry(self, mock_post): + g = BackChannelLogin("my.domain.com", "cid", client_secret="clsec") + + g.back_channel_login( + binding_message="This is a binding message", + login_hint="{ \"format\": \"iss_sub\", \"iss\": \"https://my.domain.auth0.com/\", \"sub\": \"auth0|[USER ID]\" }", + scope="openid", + requested_expiry=100 + ) + + args, kwargs = mock_post.call_args + + self.assertEqual(args[0], "https://my.domain.com/bc-authorize") + self.assertEqual( + kwargs["data"], + { + "client_id": "cid", + "client_secret": "clsec", + "binding_message": "This is a binding message", + "login_hint": "{ \"format\": \"iss_sub\", \"iss\": \"https://my.domain.auth0.com/\", \"sub\": \"auth0|[USER ID]\" }", + "scope": "openid", + "requested_expiry": "100", + }, + ) diff --git a/auth0/test/authentication/test_get_token.py b/auth0/test/authentication/test_get_token.py index ac152dd4..9770e5e3 100644 --- a/auth0/test/authentication/test_get_token.py +++ b/auth0/test/authentication/test_get_token.py @@ -364,4 +364,35 @@ def test_connection_login(self, mock_post): "requested_token_type": "http://auth0.com/oauth/token-type/federated-connection-access-token", "connection": "google-oauth2" }, + ) + + @mock.patch("auth0.rest.RestClient.post") + def test_connection_loginwith_login_hint(self, mock_post): + g = GetToken("my.domain.com", "cid", client_secret="csec") + + g.access_token_for_connection( + subject_token_type="urn:ietf:params:oauth:token-type:refresh_token", + subject_token="refid", + requested_token_type="http://auth0.com/oauth/token-type/federated-connection-access-token", + connection="google-oauth2", + login_hint="john.doe@example.com" + ) + + args, kwargs = mock_post.call_args + + print(kwargs["data"]) + + self.assertEqual(args[0], "https://my.domain.com/oauth/token") + self.assertEqual( + kwargs["data"], + { + "grant_type": "urn:auth0:params:oauth:grant-type:token-exchange:federated-connection-access-token", + "client_id": "cid", + "client_secret": "csec", + "subject_token_type": "urn:ietf:params:oauth:token-type:refresh_token", + "subject_token": "refid", + "requested_token_type": "http://auth0.com/oauth/token-type/federated-connection-access-token", + "connection": "google-oauth2", + "login_hint": "john.doe@example.com" + }, ) \ No newline at end of file From 6adb025e5913d655f2c56788b1146e7ae17a67b6 Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Mon, 1 Sep 2025 10:15:21 +0100 Subject: [PATCH 05/17] Remove erroneous print --- auth0/test/authentication/test_get_token.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/auth0/test/authentication/test_get_token.py b/auth0/test/authentication/test_get_token.py index 9770e5e3..8cb3347c 100644 --- a/auth0/test/authentication/test_get_token.py +++ b/auth0/test/authentication/test_get_token.py @@ -380,8 +380,6 @@ def test_connection_loginwith_login_hint(self, mock_post): args, kwargs = mock_post.call_args - print(kwargs["data"]) - self.assertEqual(args[0], "https://my.domain.com/oauth/token") self.assertEqual( kwargs["data"], From f04ac1b6dc116d403b6b234daa9854e4074d79e2 Mon Sep 17 00:00:00 2001 From: Snehil Kishore Date: Thu, 11 Sep 2025 14:10:06 +0530 Subject: [PATCH 06/17] chore: fix workflow syntax errors and update dependencies (#724) - Bump Dependancy in `requirements.txt` and `pyproject.toml` - Update `poetry.lock` file - Remove `Semgrep` Workflow --- .github/workflows/codeql.yml | 2 +- .github/workflows/docs.yml | 6 +- .github/workflows/publish.yml | 4 +- .github/workflows/rl-scanner.yml | 5 +- .github/workflows/semgrep.yml | 40 ----- .github/workflows/snyk.yml | 2 +- .github/workflows/test.yml | 6 +- poetry.lock | 300 +++++++++++++++---------------- pyproject.toml | 4 +- requirements.txt | 80 +++++---- 10 files changed, 202 insertions(+), 247 deletions(-) delete mode 100644 .github/workflows/semgrep.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5f04aa4c..a107c4bd 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,7 +36,7 @@ jobs: run: exit 0 # Skip unnecessary test runs for dependabot and merge queues. Artifically flag as successful, as this is a required check for branch protection. - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Initialize CodeQL uses: github/codeql-action/init@v3 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 705dabdb..6f5ba53e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,13 +19,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Pages uses: actions/configure-pages@v5 - name: Configure Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.10" @@ -42,7 +42,7 @@ jobs: sphinx-build ./docs/source ./docs/build --keep-going -n -a -b html - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v4 with: path: "./docs/build" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4cb3d332..671b6efe 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 fetch-tags: true @@ -68,7 +68,7 @@ jobs: prerelease: ${{ steps.get_prerelease.outputs.prerelease }} - name: Configure Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.9" diff --git a/.github/workflows/rl-scanner.yml b/.github/workflows/rl-scanner.yml index a10b2419..b25561b6 100644 --- a/.github/workflows/rl-scanner.yml +++ b/.github/workflows/rl-scanner.yml @@ -31,14 +31,13 @@ jobs: scan-status: ${{ steps.rl-scan-conclusion.outcome }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 fetch-tags: true - name: Configure Python - uses: actions/setup-python@v5 - with: + uses: actions/setup-python@v6 python-version: ${{ inputs.python-version }} - name: Configure dependencies diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml deleted file mode 100644 index b0411b04..00000000 --- a/.github/workflows/semgrep.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Semgrep - -on: - merge_group: - pull_request: - types: - - opened - - synchronize - push: - branches: - - master - schedule: - - cron: "30 0 1,15 * *" - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} - -jobs: - run: - name: Check for Vulnerabilities - runs-on: ubuntu-latest - - container: - image: returntocorp/semgrep - - steps: - - if: github.actor == 'dependabot[bot]' || github.event_name == 'merge_group' - run: exit 0 # Skip unnecessary test runs for dependabot and merge queues. Artifically flag as successful, as this is a required check for branch protection. - - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.ref }} - - - run: semgrep ci - env: - SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml index 6dc486db..6bd8961c 100644 --- a/.github/workflows/snyk.yml +++ b/.github/workflows/snyk.yml @@ -31,7 +31,7 @@ jobs: - if: github.actor == 'dependabot[bot]' || github.event_name == 'merge_group' run: exit 0 # Skip unnecessary test runs for dependabot and merge queues. Artifically flag as successful, as this is a required check for branch protection. - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: ref: ${{ github.event.pull_request.head.sha || github.ref }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ed0f2e94..89f36e31 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,12 +42,12 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.event.pull_request.head.sha || github.ref }} - name: Configure Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "${{ matrix.python-version }}" @@ -80,6 +80,6 @@ jobs: - if: ${{ matrix.python-version == '3.10' }} name: Upload coverage - uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # pin@5.4.3 + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # pin@5.5.1 with: token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index b11c3c72..381bef4f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,12 +1,12 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" version = "2.4.4" description = "Happy Eyeballs for asyncio" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, @@ -16,9 +16,9 @@ files = [ name = "aiohttp" version = "3.10.11" description = "Async http client/server framework (asyncio)" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"}, {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"}, @@ -123,15 +123,15 @@ multidict = ">=4.5,<7.0" yarl = ">=1.12.0,<2.0" [package.extras] -speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] +speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.2.0) ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""] [[package]] name = "aioresponses" version = "0.7.8" description = "Mock out requests made by ClientSession from aiohttp package" -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "aioresponses-0.7.8-py2.py3-none-any.whl", hash = "sha256:b73bd4400d978855e55004b23a3a84cb0f018183bcf066a85ad392800b5b9a94"}, {file = "aioresponses-0.7.8.tar.gz", hash = "sha256:b861cdfe5dc58f3b8afac7b0a6973d5d7b2cb608dd0f6253d16b8ee8eaf6df11"}, @@ -145,9 +145,9 @@ packaging = ">=22.0" name = "aiosignal" version = "1.3.1" description = "aiosignal: a list of registered asynchronous callbacks" -category = "main" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, @@ -160,9 +160,9 @@ frozenlist = ">=1.1.0" name = "argcomplete" version = "3.6.2" description = "Bash tab completion for argparse" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "argcomplete-3.6.2-py3-none-any.whl", hash = "sha256:65b3133a29ad53fb42c48cf5114752c7ab66c1c38544fdf6460f450c09b42591"}, {file = "argcomplete-3.6.2.tar.gz", hash = "sha256:d0519b1bc867f5f4f4713c41ad0aba73a4a5f007449716b16f385f2166dc6adf"}, @@ -175,9 +175,10 @@ test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] name = "async-timeout" version = "5.0.1" description = "Timeout context manager for asyncio programs" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version < \"3.11\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -187,41 +188,42 @@ files = [ name = "attrs" version = "25.3.0" description = "Classes Without Boilerplate" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "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 = "certifi" -version = "2025.7.14" +version = "2025.8.3" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ - {file = "certifi-2025.7.14-py3-none-any.whl", hash = "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2"}, - {file = "certifi-2025.7.14.tar.gz", hash = "sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995"}, + {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, + {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, ] [[package]] name = "cffi" version = "1.17.1" description = "Foreign Function Interface for Python calling C code." -category = "main" 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"}, @@ -297,113 +299,100 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.4.2" +version = "3.4.3" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ - {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}, - {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, - {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, + {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" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, @@ -416,9 +405,10 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +markers = "sys_platform == \"win32\" or platform_system == \"Windows\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -428,9 +418,9 @@ files = [ name = "coverage" version = "7.6.1" description = "Code coverage measurement for Python" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] 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"}, @@ -510,15 +500,15 @@ 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" version = "43.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" 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"}, @@ -566,9 +556,10 @@ test-randomorder = ["pytest-randomly"] name = "exceptiongroup" version = "1.3.0" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] +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"}, @@ -584,9 +575,9 @@ test = ["pytest (>=6)"] name = "frozenlist" version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, @@ -686,9 +677,9 @@ files = [ name = "idna" version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -701,9 +692,9 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 name = "iniconfig" version = "2.1.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -713,9 +704,9 @@ files = [ name = "mock" version = "5.2.0" description = "Rolling backport of unittest.mock for all Pythons" -category = "dev" 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"}, @@ -730,9 +721,9 @@ test = ["pytest", "pytest-cov"] name = "multidict" version = "6.1.0" description = "multidict implementation" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, @@ -835,9 +826,9 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} name = "packaging" version = "25.0" description = "Core utilities for Python packages" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, @@ -847,9 +838,9 @@ files = [ name = "pipx" version = "1.7.1" description = "Install and Run Python Applications in Isolated Environments" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pipx-1.7.1-py3-none-any.whl", hash = "sha256:3933c43bb344e649cb28e10d357e0967ce8572f1c19caf90cf39ae95c2a0afaf"}, {file = "pipx-1.7.1.tar.gz", hash = "sha256:762de134e16a462be92645166d225ecef446afaef534917f5f70008d63584360"}, @@ -867,9 +858,9 @@ userpath = ">=1.6,<1.9 || >1.9" name = "platformdirs" version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -884,9 +875,9 @@ type = ["mypy (>=1.11.2)"] name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -900,9 +891,9 @@ testing = ["pytest", "pytest-benchmark"] name = "propcache" version = "0.2.0" description = "Accelerated property cache" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, @@ -1006,23 +997,24 @@ files = [ [[package]] name = "pycparser" -version = "2.22" +version = "2.23" description = "C parser in Python" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "platform_python_implementation != \"PyPy\"" files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, + {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"}, + {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"}, ] [[package]] name = "pyjwt" version = "2.9.0" description = "JSON Web Token implementation in Python" -category = "main" 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"}, @@ -1038,9 +1030,9 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] name = "pytest" version = "7.4.4" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, @@ -1061,9 +1053,9 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-aiohttp" version = "1.0.5" description = "Pytest plugin for aiohttp support" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-aiohttp-1.0.5.tar.gz", hash = "sha256:880262bc5951e934463b15e3af8bb298f11f7d4d3ebac970aab425aff10a780a"}, {file = "pytest_aiohttp-1.0.5-py3-none-any.whl", hash = "sha256:63a5360fd2f34dda4ab8e6baee4c5f5be4cd186a403cabd498fced82ac9c561e"}, @@ -1081,9 +1073,9 @@ testing = ["coverage (==6.2)", "mypy (==0.931)"] name = "pytest-asyncio" version = "0.23.8" description = "Pytest support for asyncio" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, @@ -1100,9 +1092,9 @@ testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] name = "pytest-cov" version = "4.1.0" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, @@ -1119,9 +1111,9 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pyyaml" version = "6.0.2" description = "YAML parser and emitter for Python" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1182,9 +1174,9 @@ files = [ name = "requests" version = "2.32.4" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, @@ -1202,14 +1194,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "responses" -version = "0.24.1" +version = "0.25.8" description = "A utility library for mocking out the `requests` Python library." -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "responses-0.24.1-py3-none-any.whl", hash = "sha256:a2b43f4c08bfb9c9bd242568328c65a34b318741d3fab884ac843c5ceeb543f9"}, - {file = "responses-0.24.1.tar.gz", hash = "sha256:b127c6ca3f8df0eb9cc82fd93109a3007a86acb24871834c47b77765152ecf8c"}, + {file = "responses-0.25.8-py3-none-any.whl", hash = "sha256:0c710af92def29c8352ceadff0c3fe340ace27cf5af1bbe46fb71275bcd2831c"}, + {file = "responses-0.25.8.tar.gz", hash = "sha256:9374d047a575c8f781b94454db5cab590b6029505f488d12899ddb10a4af1cf4"}, ] [package.dependencies] @@ -1218,15 +1210,16 @@ requests = ">=2.30.0,<3.0" urllib3 = ">=1.25.10,<3.0" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-PyYAML", "types-requests"] [[package]] name = "tomli" version = "2.2.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_full_version <= \"3.11.0a6\"" 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"}, @@ -1266,9 +1259,10 @@ files = [ name = "typing-extensions" version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version < \"3.11\"" 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"}, @@ -1278,16 +1272,16 @@ files = [ name = "urllib3" version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] 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)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -1296,9 +1290,9 @@ zstd = ["zstandard (>=0.18.0)"] name = "userpath" version = "1.9.2" description = "Cross-platform tool for adding locations to the user PATH" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "userpath-1.9.2-py3-none-any.whl", hash = "sha256:2cbf01a23d655a1ff8fc166dfb78da1b641d1ceabf0fe5f970767d380b14e89d"}, {file = "userpath-1.9.2.tar.gz", hash = "sha256:6c52288dab069257cc831846d15d48133522455d4677ee69a9781f11dbefd815"}, @@ -1311,9 +1305,9 @@ click = "*" name = "yarl" version = "1.15.2" description = "Yet another URL library" -category = "main" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "yarl-1.15.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e4ee8b8639070ff246ad3649294336b06db37a94bdea0d09ea491603e0be73b8"}, {file = "yarl-1.15.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7cf963a357c5f00cb55b1955df8bbe68d2f2f65de065160a1c26b85a1e44172"}, @@ -1421,6 +1415,6 @@ multidict = ">=4.0" propcache = ">=0.2.0" [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = ">=3.8" -content-hash = "7158be33f0b386869b46e49466a4fac7a8789003f5736530b807bcce311ab117" +content-hash = "f2b4849cb247bdefbbc9b155d28c5e1bcf9b4ca3c2c92defd30b21206018fa3f" diff --git a/pyproject.toml b/pyproject.toml index 235b31c0..83c499fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,11 +34,11 @@ requests = ">=2.32.3" urllib3 = ">=2.2.3" # requests has a weak dependency on urllib3 [tool.poetry.group.dev.dependencies] -aioresponses = "^0.7.4" +aioresponses = "^0.7.8" mock = "^5.1.0" pipx = "^1.7.1" pytest = "^7.4.0" pytest-aiohttp = "^1.0.4" pytest-asyncio = ">=0.21.1,<0.24.0" pytest-cov = "^4.1.0" -responses = ">=0.23.3,<0.25.0" +responses = ">=0.23.3,<0.26.0" diff --git a/requirements.txt b/requirements.txt index 7ae87cfc..f0f28bfe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,39 +1,41 @@ -aiohappyeyeballs==2.4.4 ; python_version >= "3.8" -aiohttp==3.10.11 ; python_version >= "3.8" -aioresponses==0.7.8 ; python_version >= "3.8" -aiosignal==1.3.1 ; python_version >= "3.8" -argcomplete==3.6.2 ; python_version >= "3.8" -async-timeout==5.0.1 ; python_version < "3.11" and python_version >= "3.8" -attrs==25.3.0 ; python_version >= "3.8" -certifi==2025.7.14 ; python_version >= "3.8" -cffi==1.17.1 ; platform_python_implementation != "PyPy" and python_version >= "3.8" -charset-normalizer==3.4.2 ; python_version >= "3.8" -click==8.1.8 ; python_version >= "3.8" -colorama==0.4.6 ; python_version >= "3.8" and sys_platform == "win32" or python_version >= "3.8" and platform_system == "Windows" -coverage[toml]==7.6.1 ; python_version >= "3.8" -cryptography==43.0.3 ; python_version >= "3.8" -exceptiongroup==1.3.0 ; python_version < "3.11" and python_version >= "3.8" -frozenlist==1.5.0 ; python_version >= "3.8" -idna==3.10 ; python_version >= "3.8" -iniconfig==2.1.0 ; python_version >= "3.8" -mock==5.2.0 ; python_version >= "3.8" -multidict==6.1.0 ; python_version >= "3.8" -packaging==25.0 ; python_version >= "3.8" -pipx==1.7.1 ; python_version >= "3.8" -platformdirs==4.3.6 ; python_version >= "3.8" -pluggy==1.5.0 ; python_version >= "3.8" -propcache==0.2.0 ; python_version >= "3.8" -pycparser==2.22 ; platform_python_implementation != "PyPy" and python_version >= "3.8" -pyjwt==2.9.0 ; python_version >= "3.8" -pytest-aiohttp==1.0.5 ; python_version >= "3.8" -pytest-asyncio==0.23.8 ; python_version >= "3.8" -pytest-cov==4.1.0 ; python_version >= "3.8" -pytest==7.4.4 ; python_version >= "3.8" -pyyaml==6.0.2 ; python_version >= "3.8" -requests==2.32.4 ; python_version >= "3.8" -responses==0.24.1 ; python_version >= "3.8" -tomli==2.2.1 ; python_version >= "3.8" and python_full_version <= "3.11.0a6" -typing-extensions==4.13.2 ; python_version < "3.11" and python_version >= "3.8" -urllib3==2.2.3 ; python_version >= "3.8" -userpath==1.9.2 ; python_version >= "3.8" -yarl==1.15.2 ; python_version >= "3.8" +aiohttp==3.8.6 ; python_version >= "3.7" and python_version < "4.0" +aioresponses==0.7.4 ; python_version >= "3.7" and python_version < "4.0" +aiosignal==1.4.0 ; python_version >= "3.7" and python_version < "4.0" +argcomplete==3.5.3 ; python_version >= "3.7" and python_version < "4.0" +async-timeout==4.0.3 ; python_version >= "3.7" and python_version < "4.0" +asynctest==0.13.0 ; python_version >= "3.7" and python_version < "3.8" +attrs==23.1.0 ; python_version >= "3.7" and python_version < "4.0" +certifi==2025.8.3 ; python_version >= "3.7" and python_version < "4.0" +cffi==1.17.1 ; python_version >= "3.7" and python_version < "4.0" +charset-normalizer==3.4.3 ; python_version >= "3.7" and python_version < "4.0" +click==8.1.8 ; python_version >= "3.7" and python_version < "4.0" +colorama==0.4.6 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32" or python_version >= "3.7" and python_version < "4.0" and platform_system == "Windows" +coverage[toml]==7.9.2 ; python_version >= "3.7" and python_version < "4.0" +cryptography==44.0.1 ; python_version >= "3.7" and python_version < "4.0" +exceptiongroup==1.3.0 ; python_version >= "3.7" and python_version < "3.11" +frozenlist==1.7.0 ; python_version >= "3.7" and python_version < "4.0" +idna==3.10 ; python_version >= "3.7" and python_version < "4.0" +importlib-metadata==6.7.0 ; python_version >= "3.7" and python_version < "3.8" +iniconfig==2.1.0 ; python_version >= "3.7" and python_version < "4.0" +mock==5.2.0 ; python_version >= "3.7" and python_version < "4.0" +multidict==6.0.4 ; python_version >= "3.7" and python_version < "4.0" +packaging==23.2 ; python_version >= "3.7" and python_version < "4.0" +pipx==1.2.0 ; python_version >= "3.7" and python_version < "4.0" +pluggy==1.6.0 ; python_version >= "3.7" and python_version < "4.0" +pycparser==2.23 ; python_version >= "3.7" and python_version < "4.0" +pyjwt==2.9.0 ; python_version >= "3.7" and python_version < "4.0" +pyopenssl==25.2.0 ; python_version >= "3.7" and python_version < "4.0" +pytest-aiohttp==1.0.5 ; python_version >= "3.7" and python_version < "4.0" +pytest-asyncio==0.23.8 ; python_version >= "3.7" and python_version < "4.0" +pytest-cov==4.1.0 ; python_version >= "3.7" and python_version < "4.0" +pytest==7.4.0 ; python_version >= "3.7" and python_version < "4.0" +pyyaml==6.0.2 ; python_version >= "3.7" and python_version < "4.0" +requests==2.32.4 ; python_version >= "3.7" and python_version < "4.0" +responses==0.23.3 ; python_version >= "3.7" and python_version < "4.0" +tomli==2.2.1 ; python_version >= "3.7" and python_full_version <= "3.11.0a6" +types-pyyaml==6.0.12.20250915 ; python_version >= "3.7" and python_version < "4.0" +typing-extensions==4.7.1 ; python_version >= "3.7" and python_version < "3.8" +urllib3==2.5.0 ; python_version >= "3.7" and python_version < "4.0" +userpath==1.9.2 ; python_version >= "3.7" and python_version < "4.0" +yarl==1.20.0 ; python_version >= "3.7" and python_version < "4.0" +zipp==3.19.1 ; python_version >= "3.7" and python_version < "3.8" From 6cf74ec1e08fe5f54039118620ff9a786f907f12 Mon Sep 17 00:00:00 2001 From: Snehil Kishore Date: Thu, 11 Sep 2025 14:24:24 +0530 Subject: [PATCH 07/17] Release 4.11.0 (#725) **Added** - feat: Support For Network ACL Endpoints [\#706](https://github.com/auth0/auth0-python/pull/706) ([kishore7snehil](https://github.com/kishore7snehil)) **Fixed** - chore: fix workflow syntax errors and update dependencies [\#724](https://github.com/auth0/auth0-python/pull/724) ([kishore7snehil](https://github.com/kishore7snehil)) --- .version | 2 +- CHANGELOG.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.version b/.version index 1910ba9d..91f3b438 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -4.10.0 \ No newline at end of file +4.11.0 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 76b3118a..e6cf6465 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## [4.11.0](https://github.com/auth0/auth0-python/tree/4.11.0) (2025-09-11) +[Full Changelog](https://github.com/auth0/auth0-python/compare/4.10.0...4.11.0) + +**Added** +- feat: Support For Network ACL Endpoints [\#706](https://github.com/auth0/auth0-python/pull/706) ([kishore7snehil](https://github.com/kishore7snehil)) + +**Fixed** +- chore: fix workflow syntax errors and update dependencies [\#724](https://github.com/auth0/auth0-python/pull/724) ([kishore7snehil](https://github.com/kishore7snehil)) + ## [4.10.0](https://github.com/auth0/auth0-python/tree/4.10.0) (2025-06-05) [Full Changelog](https://github.com/auth0/auth0-python/compare/4.9.0...4.10.0) From 1e09057b37d2e86aae69d8e6927868b43caf5d40 Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Fri, 12 Sep 2025 15:07:32 +0100 Subject: [PATCH 08/17] Add headers to Auth0Error --- auth0/exceptions.py | 2 ++ auth0/rest.py | 2 ++ auth0/test/authentication/test_get_token.py | 24 +++++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/auth0/exceptions.py b/auth0/exceptions.py index 8515be04..533e9321 100644 --- a/auth0/exceptions.py +++ b/auth0/exceptions.py @@ -10,11 +10,13 @@ def __init__( error_code: str, message: str, content: Any | None = None, + headers: Any | None = None, ) -> None: self.status_code = status_code self.error_code = error_code self.message = message self.content = content + self.headers = headers def __str__(self) -> str: return f"{self.status_code}: {self.message}" diff --git a/auth0/rest.py b/auth0/rest.py index 196ad7ac..74d897ce 100644 --- a/auth0/rest.py +++ b/auth0/rest.py @@ -296,12 +296,14 @@ def content(self) -> Any: error_code=self._error_code(), message=self._error_message(), content=self._content, + headers=self._headers ) raise Auth0Error( status_code=self._status_code, error_code=self._error_code(), message=self._error_message(), + headers=self._headers ) else: return self._content diff --git a/auth0/test/authentication/test_get_token.py b/auth0/test/authentication/test_get_token.py index 8cb3347c..85e403f8 100644 --- a/auth0/test/authentication/test_get_token.py +++ b/auth0/test/authentication/test_get_token.py @@ -1,4 +1,5 @@ import unittest +import requests from fnmatch import fnmatch from unittest import mock from unittest.mock import ANY @@ -335,7 +336,26 @@ def test_backchannel_login(self, mock_post): "grant_type": "urn:openid:params:grant-type:ciba", }, ) - + + @mock.patch("auth0.rest.RestClient.post") + def test_backchannel_login_headers_on_failure(self, mock_post): + response = requests.Response() + response.status_code = 400 + response.headers = {"Retry-After": 100} + response._content = b'{"error":"slow_down"}' + mock_post.side_effect = requests.exceptions.HTTPError(response=response) + + g = GetToken("my.domain.com", "cid", client_secret="csec") + + try: + g.backchannel_login( + auth_req_id="reqid", + grant_type="urn:openid:params:grant-type:ciba", + ) + except requests.exceptions.HTTPError as e: + self.assertEqual(e.response.headers["Retry-After"], 100) + self.assertEqual(e.response.status_code, 400) + @mock.patch("auth0.rest.RestClient.post") def test_connection_login(self, mock_post): g = GetToken("my.domain.com", "cid", client_secret="csec") @@ -367,7 +387,7 @@ def test_connection_login(self, mock_post): ) @mock.patch("auth0.rest.RestClient.post") - def test_connection_loginwith_login_hint(self, mock_post): + def test_connection_login_with_login_hint(self, mock_post): g = GetToken("my.domain.com", "cid", client_secret="csec") g.access_token_for_connection( From 47238d91e09ce40e8781f3d22dad51f43c435af6 Mon Sep 17 00:00:00 2001 From: Snehil Kishore Date: Thu, 11 Sep 2025 14:43:06 +0530 Subject: [PATCH 09/17] fix: add missing indentation for Python configuration step --- .github/workflows/rl-scanner.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rl-scanner.yml b/.github/workflows/rl-scanner.yml index b25561b6..14514656 100644 --- a/.github/workflows/rl-scanner.yml +++ b/.github/workflows/rl-scanner.yml @@ -38,6 +38,7 @@ jobs: - name: Configure Python uses: actions/setup-python@v6 + with: python-version: ${{ inputs.python-version }} - name: Configure dependencies @@ -79,4 +80,4 @@ jobs: PRODSEC_TOOLS_ARN: ${{ secrets.PRODSEC_TOOLS_ARN }} - name: Output scan result - run: echo "scan-status=${{ steps.rl-scan-conclusion.outcome }}" >> $GITHUB_ENV + run: echo "scan-status=${{ steps.rl-scan-conclusion.outcome }}" >> $GITHUB_ENV \ No newline at end of file From bfd7587993c741c426c9922f7f8b33e9b2c65d96 Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Mon, 15 Sep 2025 10:25:24 +0100 Subject: [PATCH 10/17] Updates per PR feedback --- auth0/authentication/back_channel_login.py | 4 +- .../authentication/test_back_channel_login.py | 47 +++++++++++++++++++ auth0/test/authentication/test_get_token.py | 16 +++---- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/auth0/authentication/back_channel_login.py b/auth0/authentication/back_channel_login.py index d7bba603..d1885f79 100644 --- a/auth0/authentication/back_channel_login.py +++ b/auth0/authentication/back_channel_login.py @@ -33,7 +33,7 @@ def back_channel_login( Rich Authorization Requests (RAR) details to include in the CIBA request. requested_expiry (int, optional): Number of seconds the authentication request is valid for. - Auth0 defaults to 30 seconds if not provided. + Auth0 defaults to 300 seconds (5 mins) if not provided. **kwargs: Other fields to send along with the request. @@ -56,6 +56,8 @@ def back_channel_login( data["authorization_details"] = json.dumps(authorization_details) if requested_expiry is not None: + if not isinstance(requested_expiry, int) or requested_expiry <= 0: + raise ValueError("requested_expiry must be a positive integer") data["requested_expiry"] = str(requested_expiry) data.update(kwargs) diff --git a/auth0/test/authentication/test_back_channel_login.py b/auth0/test/authentication/test_back_channel_login.py index bcc223ba..2b8705a2 100644 --- a/auth0/test/authentication/test_back_channel_login.py +++ b/auth0/test/authentication/test_back_channel_login.py @@ -33,6 +33,23 @@ def test_ciba(self, mock_post): }, ) + @mock.patch("requests.request") + def test_server_error(self, mock_requests_request): + response = requests.Response() + response.status_code = 400 + response._content = b'{"error":"foo"}' + mock_requests_request.return_value = response + + g = BackChannelLogin("my.domain.com", "cid", client_secret="clsec") + with self.assertRaises(Auth0Error) as context: + g.back_channel_login( + binding_message="msg", + login_hint="hint", + scope="openid" + ) + self.assertEqual(context.exception.status_code, 400) + self.assertEqual(context.exception.message, 'foo') + @mock.patch("auth0.rest.RestClient.post") def test_should_require_binding_message(self, mock_post): g = BackChannelLogin("my.domain.com", "cid", client_secret="clsec") @@ -161,3 +178,33 @@ def test_with_request_expiry(self, mock_post): "requested_expiry": "100", }, ) + + def test_requested_expiry_negative_raises(self): + g = BackChannelLogin("my.domain.com", "cid", client_secret="clsec") + with self.assertRaises(ValueError): + g.back_channel_login( + binding_message="msg", + login_hint="hint", + scope="openid", + requested_expiry=-10 + ) + + def test_requested_expiry_zero_raises(self): + g = BackChannelLogin("my.domain.com", "cid", client_secret="clsec") + with self.assertRaises(ValueError): + g.back_channel_login( + binding_message="msg", + login_hint="hint", + scope="openid", + requested_expiry=0 + ) + + def test_requested_non_int_raises(self): + g = BackChannelLogin("my.domain.com", "cid", client_secret="clsec") + with self.assertRaises(ValueError): + g.back_channel_login( + binding_message="msg", + login_hint="hint", + scope="openid", + requested_expiry="string_instead_of_int" + ) diff --git a/auth0/test/authentication/test_get_token.py b/auth0/test/authentication/test_get_token.py index 85e403f8..bc6721f1 100644 --- a/auth0/test/authentication/test_get_token.py +++ b/auth0/test/authentication/test_get_token.py @@ -6,6 +6,7 @@ from cryptography.hazmat.primitives import asymmetric, serialization +from ... import Auth0Error from ...authentication.get_token import GetToken @@ -337,24 +338,23 @@ def test_backchannel_login(self, mock_post): }, ) - @mock.patch("auth0.rest.RestClient.post") - def test_backchannel_login_headers_on_failure(self, mock_post): + @mock.patch("requests.request") + def test_backchannel_login_headers_on_failure(self, mock_requests_request): response = requests.Response() response.status_code = 400 - response.headers = {"Retry-After": 100} + response.headers = {"Retry-After": "100"} response._content = b'{"error":"slow_down"}' - mock_post.side_effect = requests.exceptions.HTTPError(response=response) + mock_requests_request.return_value = response g = GetToken("my.domain.com", "cid", client_secret="csec") - try: + with self.assertRaises(Auth0Error) as context: g.backchannel_login( auth_req_id="reqid", grant_type="urn:openid:params:grant-type:ciba", ) - except requests.exceptions.HTTPError as e: - self.assertEqual(e.response.headers["Retry-After"], 100) - self.assertEqual(e.response.status_code, 400) + self.assertEqual(context.exception.headers["Retry-After"], "100") + self.assertEqual(context.exception.status_code, 400) @mock.patch("auth0.rest.RestClient.post") def test_connection_login(self, mock_post): From a95935c2591d9726c04b01c5ecd6b98a466f9a46 Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Mon, 15 Sep 2025 13:09:05 +0100 Subject: [PATCH 11/17] Release 4.12.0 --- .version | 2 +- CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.version b/.version index 91f3b438..bcd250ed 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -4.11.0 \ No newline at end of file +4.12.0 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e6cf6465..07b8007e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## [4.12.0](https://github.com/auth0/auth0-python/tree/4.12.0) (2025-09-15) +[Full Changelog](https://github.com/auth0/auth0-python/compare/4.11.0...4.12.0) + +**Added** +- Updates for CIBA with email [\#720](https://github.com/auth0/auth0-python/pull/720) ([adamjmcgrath](https://github.com/adamjmcgrath)) + ## [4.11.0](https://github.com/auth0/auth0-python/tree/4.11.0) (2025-09-11) [Full Changelog](https://github.com/auth0/auth0-python/compare/4.10.0...4.11.0) From fdf71f2b2ea10fd7b717870d642c27d44a452adc Mon Sep 17 00:00:00 2001 From: Patrick Malouin Date: Wed, 17 Sep 2025 14:46:01 -0400 Subject: [PATCH 12/17] fix(backchannel): expose headers on `slow_down` errors (HTTP 429s) --- auth0/exceptions.py | 4 ++-- auth0/rest.py | 1 + auth0/test/authentication/test_base.py | 6 ++++++ auth0/test/authentication/test_get_token.py | 10 +++++----- auth0/test/management/test_rest.py | 6 ++++++ 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/auth0/exceptions.py b/auth0/exceptions.py index 533e9321..03801e68 100644 --- a/auth0/exceptions.py +++ b/auth0/exceptions.py @@ -23,8 +23,8 @@ def __str__(self) -> str: class RateLimitError(Auth0Error): - def __init__(self, error_code: str, message: str, reset_at: int) -> None: - super().__init__(status_code=429, error_code=error_code, message=message) + def __init__(self, error_code: str, message: str, reset_at: int, headers: Any | None = None) -> None: + super().__init__(status_code=429, error_code=error_code, message=message, headers=headers) self.reset_at = reset_at diff --git a/auth0/rest.py b/auth0/rest.py index 74d897ce..a2d9bd9a 100644 --- a/auth0/rest.py +++ b/auth0/rest.py @@ -289,6 +289,7 @@ def content(self) -> Any: error_code=self._error_code(), message=self._error_message(), reset_at=reset_at, + headers=self._headers, ) if self._error_code() == "mfa_required": raise Auth0Error( diff --git a/auth0/test/authentication/test_base.py b/auth0/test/authentication/test_base.py index eed9d040..a4f52d83 100644 --- a/auth0/test/authentication/test_base.py +++ b/auth0/test/authentication/test_base.py @@ -158,6 +158,10 @@ def test_post_rate_limit_error(self, mock_request): self.assertEqual(context.exception.message, "desc") self.assertIsInstance(context.exception, RateLimitError) self.assertEqual(context.exception.reset_at, 9) + self.assertIsNotNone(context.exception.headers) + self.assertEqual(context.exception.headers["x-ratelimit-limit"], "3") + self.assertEqual(context.exception.headers["x-ratelimit-remaining"], "6") + self.assertEqual(context.exception.headers["x-ratelimit-reset"], "9") @mock.patch("requests.request") def test_post_rate_limit_error_without_headers(self, mock_request): @@ -177,6 +181,8 @@ def test_post_rate_limit_error_without_headers(self, mock_request): self.assertEqual(context.exception.message, "desc") self.assertIsInstance(context.exception, RateLimitError) self.assertEqual(context.exception.reset_at, -1) + self.assertIsNotNone(context.exception.headers) + self.assertEqual(context.exception.headers, {}) @mock.patch("requests.request") def test_post_error_with_code_property(self, mock_request): diff --git a/auth0/test/authentication/test_get_token.py b/auth0/test/authentication/test_get_token.py index bc6721f1..7c98d341 100644 --- a/auth0/test/authentication/test_get_token.py +++ b/auth0/test/authentication/test_get_token.py @@ -6,7 +6,7 @@ from cryptography.hazmat.primitives import asymmetric, serialization -from ... import Auth0Error +from ...exceptions import RateLimitError from ...authentication.get_token import GetToken @@ -339,22 +339,22 @@ def test_backchannel_login(self, mock_post): ) @mock.patch("requests.request") - def test_backchannel_login_headers_on_failure(self, mock_requests_request): + def test_backchannel_login_headers_on_slow_down(self, mock_requests_request): response = requests.Response() - response.status_code = 400 + response.status_code = 429 response.headers = {"Retry-After": "100"} response._content = b'{"error":"slow_down"}' mock_requests_request.return_value = response g = GetToken("my.domain.com", "cid", client_secret="csec") - with self.assertRaises(Auth0Error) as context: + with self.assertRaises(RateLimitError) as context: g.backchannel_login( auth_req_id="reqid", grant_type="urn:openid:params:grant-type:ciba", ) self.assertEqual(context.exception.headers["Retry-After"], "100") - self.assertEqual(context.exception.status_code, 400) + self.assertEqual(context.exception.status_code, 429) @mock.patch("auth0.rest.RestClient.post") def test_connection_login(self, mock_post): diff --git a/auth0/test/management/test_rest.py b/auth0/test/management/test_rest.py index 7113c446..6288daf9 100644 --- a/auth0/test/management/test_rest.py +++ b/auth0/test/management/test_rest.py @@ -278,6 +278,10 @@ def test_get_rate_limit_error(self, mock_request): self.assertEqual(context.exception.message, "message") self.assertIsInstance(context.exception, RateLimitError) self.assertEqual(context.exception.reset_at, 9) + self.assertIsNotNone(context.exception.headers) + self.assertEqual(context.exception.headers["x-ratelimit-limit"], "3") + self.assertEqual(context.exception.headers["x-ratelimit-remaining"], "6") + self.assertEqual(context.exception.headers["x-ratelimit-reset"], "9") self.assertEqual(rc._metrics["retries"], 0) @@ -300,6 +304,8 @@ def test_get_rate_limit_error_without_headers(self, mock_request): self.assertEqual(context.exception.message, "message") self.assertIsInstance(context.exception, RateLimitError) self.assertEqual(context.exception.reset_at, -1) + self.assertIsNotNone(context.exception.headers) + self.assertEqual(context.exception.headers, {}) self.assertEqual(rc._metrics["retries"], 1) From ddbf0b552ed46213575486640d63c1a2d479c859 Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Wed, 17 Sep 2025 20:22:08 +0100 Subject: [PATCH 13/17] Release 4.13.0 (#745) **Added** - fix(backchannel): expose headers on `slow_down` errors (HTTP 429s) [\#744](https://github.com/auth0/auth0-python/pull/744) ([pmalouin](https://github.com/pmalouin)) --- .version | 2 +- CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.version b/.version index bcd250ed..01b73abe 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -4.12.0 \ No newline at end of file +4.13.0 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 07b8007e..2cd01db7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## [4.13.0](https://github.com/auth0/auth0-python/tree/4.13.0) (2025-09-17) +[Full Changelog](https://github.com/auth0/auth0-python/compare/4.12.0...4.13.0) + +**Added** +- fix(backchannel): expose headers on `slow_down` errors (HTTP 429s) [\#744](https://github.com/auth0/auth0-python/pull/744) ([pmalouin](https://github.com/pmalouin)) + ## [4.12.0](https://github.com/auth0/auth0-python/tree/4.12.0) (2025-09-15) [Full Changelog](https://github.com/auth0/auth0-python/compare/4.11.0...4.12.0) From d803e7fed3aaa9afacecdd0156942bf7a61bb535 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 19:39:03 +0530 Subject: [PATCH 14/17] chore(deps): bump snyk/actions from 0.4.0 to 1.0.0 (#750) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [snyk/actions](https://github.com/snyk/actions) from 0.4.0 to 1.0.0.
Release notes

Sourced from snyk/actions's releases.

v1.0.0

What's Changed

The GitHub Action should be considered ready for use in production pipelines. To formally signal this status we are releasing a v1.0.0

Full Changelog: https://github.com/snyk/actions/compare/v0...v1.0.0

v0.5.0

What's Changed

... (truncated)

Commits
  • 9adf32b chore(ci): adjust to build release based on current branch (#202)
  • ce71ff9 feat: release stable v1.0.0 (#201)
  • de2dda6 chore(ci): pin action to immutable sha (#199)
  • 6f87086 chore(ci): generate GitHub releases based on commits (#198)
  • e222141 fix: update upload-sarif documentations (#196)
  • 42be729 chore: add security.md [PRODSEC-5886] (#197)
  • 10a13eb fix: synchronizing Github actions templates (#195)
  • 7d78c83 chore: fixing wrong github warning markdown
  • 2f3c869 docs: add contributing and support sections (#194)
  • ae57bdf fix: synchronize actions with the snyk-images repository (#193)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=snyk/actions&package-manager=github_actions&previous-version=0.4.0&new-version=1.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Snehil Kishore --- .github/workflows/snyk.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml index 6bd8961c..3bfb147e 100644 --- a/.github/workflows/snyk.yml +++ b/.github/workflows/snyk.yml @@ -35,6 +35,6 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha || github.ref }} - - uses: snyk/actions/python@b98d498629f1c368650224d6d212bf7dfa89e4bf # pin@0.4.0 + - uses: snyk/actions/python@9adf32b1121593767fc3c057af55b55db032dc04 # pin@1.0.0 env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} \ No newline at end of file From b59349dc9a56ad4c15cfcb1056858e5909f0ebaa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 19:40:10 +0530 Subject: [PATCH 15/17] chore(deps): bump github/codeql-action from 3 to 4 (#751) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
Release notes

Sourced from github/codeql-action's releases.

v3.30.7

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

3.30.7 - 06 Oct 2025

No user facing changes.

See the full CHANGELOG.md for more information.

v3.30.6

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

3.30.6 - 02 Oct 2025

  • Update default CodeQL bundle version to 2.23.2. #3168

See the full CHANGELOG.md for more information.

v3.30.5

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

3.30.5 - 26 Sep 2025

  • We fixed a bug that was introduced in 3.30.4 with upload-sarif which resulted in files without a .sarif extension not getting uploaded. #3160

See the full CHANGELOG.md for more information.

v3.30.4

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

3.30.4 - 25 Sep 2025

  • We have improved the CodeQL Action's ability to validate that the workflow it is used in does not use different versions of the CodeQL Action for different workflow steps. Mixing different versions of the CodeQL Action in the same workflow is unsupported and can lead to unpredictable results. A warning will now be emitted from the codeql-action/init step if different versions of the CodeQL Action are detected in the workflow file. Additionally, an error will now be thrown by the other CodeQL Action steps if they load a configuration file that was generated by a different version of the codeql-action/init step. #3099 and #3100
  • We added support for reducing the size of dependency caches for Java analyses, which will reduce cache usage and speed up workflows. This will be enabled automatically at a later time. #3107
  • You can now run the latest CodeQL nightly bundle by passing tools: nightly to the init action. In general, the nightly bundle is unstable and we only recommend running it when directed by GitHub staff. #3130
  • Update default CodeQL bundle version to 2.23.1. #3118

See the full CHANGELOG.md for more information.

v3.30.3

CodeQL Action Changelog

... (truncated)

Changelog

Sourced from github/codeql-action's changelog.

3.29.4 - 23 Jul 2025

No user facing changes.

3.29.3 - 21 Jul 2025

No user facing changes.

3.29.2 - 30 Jun 2025

  • Experimental: When the quality-queries input for the init action is provided with an argument, separate .quality.sarif files are produced and uploaded for each language with the results of the specified queries. Do not use this in production as it is part of an internal experiment and subject to change at any time. #2935

3.29.1 - 27 Jun 2025

  • Fix bug in PR analysis where user-provided include query filter fails to exclude non-included queries. #2938
  • Update default CodeQL bundle version to 2.22.1. #2950

3.29.0 - 11 Jun 2025

  • Update default CodeQL bundle version to 2.22.0. #2925
  • Bump minimum CodeQL bundle version to 2.16.6. #2912

3.28.21 - 28 July 2025

No user facing changes.

3.28.20 - 21 July 2025

3.28.19 - 03 Jun 2025

  • The CodeQL Action no longer includes its own copy of the extractor for the actions language, which is currently in public preview. The actions extractor has been included in the CodeQL CLI since v2.20.6. If your workflow has enabled the actions language and you have pinned your tools: property to a specific version of the CodeQL CLI earlier than v2.20.6, you will need to update to at least CodeQL v2.20.6 or disable actions analysis.
  • Update default CodeQL bundle version to 2.21.4. #2910

3.28.18 - 16 May 2025

  • Update default CodeQL bundle version to 2.21.3. #2893
  • Skip validating SARIF produced by CodeQL for improved performance. #2894
  • The number of threads and amount of RAM used by CodeQL can now be set via the CODEQL_THREADS and CODEQL_RAM runner environment variables. If set, these environment variables override the threads and ram inputs respectively. #2891

3.28.17 - 02 May 2025

  • Update default CodeQL bundle version to 2.21.2. #2872

3.28.16 - 23 Apr 2025

... (truncated)

Commits
  • aac66ec Remove update-proxy-release workflow
  • 91a63dc Remove undefined values from results of unsafeEntriesInvariant
  • d25fa60 ESLint: Disable no-unused-vars for parameters starting with _
  • 3adb1ff Reorder supported tags in descending order
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Snehil Kishore --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a107c4bd..b8d64fc9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,15 +39,15 @@ jobs: uses: actions/checkout@v5 - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@v4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: "/language:${{ matrix.language }}" From 729c67679035970981015f2b3d99f270b3c97ac2 Mon Sep 17 00:00:00 2001 From: Snehil Kishore Date: Thu, 9 Oct 2025 20:17:16 +0530 Subject: [PATCH 16/17] feat: add Claude Code PR Review workflow (#752) ## Changes - Added new GitHub Actions workflow configuration for Claude Code PR Review --- .github/workflows/claude-code-review.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/claude-code-review.yml diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 00000000..d2183bca --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,18 @@ +name: Claude Code PR Review + +on: + issue_comment: + types: [ created ] + pull_request_review_comment: + types: [ created ] + pull_request_review: + types: [ submitted ] + +jobs: + claude-review: + permissions: + contents: write + issues: write + pull-requests: write + id-token: write + uses: auth0/auth0-ai-pr-analyzer-gh-action/.github/workflows/claude-code-review.yml@main \ No newline at end of file From da856f3b2d4b08469a6b193096b9c129ee136ca6 Mon Sep 17 00:00:00 2001 From: arpit-jain_atko Date: Thu, 16 Oct 2025 16:14:08 +0530 Subject: [PATCH 17/17] feat: Add Ask DeepWiki badge --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3bed7316..9dcd6f1e 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ![Release](https://img.shields.io/pypi/v/auth0-python) [![Codecov](https://img.shields.io/codecov/c/github/auth0/auth0-python)](https://codecov.io/gh/auth0/auth0-python) +[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/auth0/auth0-python) ![Downloads](https://img.shields.io/pypi/dw/auth0-python) [![License](https://img.shields.io/:license-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT) [![CircleCI](https://img.shields.io/circleci/build/github/auth0/auth0-python)](https://circleci.com/gh/auth0/auth0-python) @@ -187,4 +188,4 @@ Please do not report security vulnerabilities on the public GitHub issue tracker

Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout Why Auth0?

-This project is licensed under the MIT license. See the LICENSE file for more info.

+This project is licensed under the MIT license. See the LICENSE file for more info.

\ No newline at end of file