From 8a75c90b76b3d6b3822726b295b639f9370c0dc4 Mon Sep 17 00:00:00 2001 From: Roman Matveev Date: Wed, 18 Dec 2024 14:01:52 +0400 Subject: [PATCH 1/2] little refactor --- pyproject.toml | 29 ++++++++++++++++++++++- src/ssoready/core/http_client.py | 5 ++-- src/ssoready/core/jsonable_encoder.py | 4 +++- src/ssoready/saml/client.py | 34 +++++++++++++++------------ 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 77b34e0..0e17e30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,34 @@ +[project] +name = "ssoready" +version = "1.1.0" +description = "Python client library for SSOReady" +readme = "README.md" +authors = [] +keywords = [] +license = "MIT" +classifiers = [ + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Operating System :: OS Independent", + "Operating System :: POSIX", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Topic :: Software Development :: Libraries :: Python Modules", + "Typing :: Typed", + "License :: OSI Approved :: MIT License" +] + [tool.poetry] name = "ssoready" version = "1.1.0" -description = "" +description = "Python client library for SSOReady" readme = "README.md" authors = [] keywords = [] diff --git a/src/ssoready/core/http_client.py b/src/ssoready/core/http_client.py index 4e6877d..a6eb2b0 100644 --- a/src/ssoready/core/http_client.py +++ b/src/ssoready/core/http_client.py @@ -91,6 +91,7 @@ def __init__(self, *, httpx_client: httpx.Client): def request( self, *args: typing.Any, max_retries: int = 0, retries: int = 0, **kwargs: typing.Any ) -> httpx.Response: + """Here retries is just a counter of times the request has been retried which stores in request.""" response = self.httpx_client.request(*args, **kwargs) if _should_retry(response=response): if max_retries > retries: @@ -100,7 +101,7 @@ def request( @wraps(httpx.Client.stream) @contextmanager - def stream(self, *args: typing.Any, max_retries: int = 0, retries: int = 0, **kwargs: typing.Any) -> typing.Any: + def stream(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: with self.httpx_client.stream(*args, **kwargs) as stream: yield stream @@ -124,7 +125,7 @@ async def request( @wraps(httpx.AsyncClient.stream) @asynccontextmanager async def stream( - self, *args: typing.Any, max_retries: int = 0, retries: int = 0, **kwargs: typing.Any + self, *args: typing.Any, **kwargs: typing.Any ) -> typing.Any: async with self.httpx_client.stream(*args, **kwargs) as stream: yield stream diff --git a/src/ssoready/core/jsonable_encoder.py b/src/ssoready/core/jsonable_encoder.py index 7f48273..d96beb5 100644 --- a/src/ssoready/core/jsonable_encoder.py +++ b/src/ssoready/core/jsonable_encoder.py @@ -8,13 +8,14 @@ https://github.com/tiangolo/fastapi/blob/master/fastapi/encoders.py """ +from _typeshed import DataclassInstance import dataclasses import datetime as dt from collections import defaultdict from enum import Enum from pathlib import PurePath from types import GeneratorType -from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union, cast from .datetime_utils import serialize_datetime from .pydantic_utilities import pydantic_v1 @@ -53,6 +54,7 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] obj_dict = obj_dict["__root__"] return jsonable_encoder(obj_dict, custom_encoder=encoder) if dataclasses.is_dataclass(obj): + obj = cast(DataclassInstance, obj) obj_dict = dataclasses.asdict(obj) return jsonable_encoder(obj_dict, custom_encoder=custom_encoder) if isinstance(obj, Enum): diff --git a/src/ssoready/saml/client.py b/src/ssoready/saml/client.py index 0950f14..3d60f4b 100644 --- a/src/ssoready/saml/client.py +++ b/src/ssoready/saml/client.py @@ -4,6 +4,8 @@ import urllib.parse from json.decoder import JSONDecodeError +from ssoready.core.http_client import AsyncHttpClient, HttpClient + from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.jsonable_encoder import jsonable_encoder @@ -20,7 +22,7 @@ class SamlClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._client_wrapper: SyncClientWrapper = client_wrapper def redeem_saml_access_code( self, *, saml_access_code: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None @@ -52,8 +54,8 @@ def redeem_saml_access_code( _request: typing.Dict[str, typing.Any] = {} if saml_access_code is not OMIT: _request["samlAccessCode"] = saml_access_code - _response = self._client_wrapper.httpx_client.request( - method="POST", + _response = HttpClient.request( + self._client_wrapper.httpx_client, url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/saml/redeem"), params=encode_query( jsonable_encoder( @@ -78,10 +80,10 @@ def redeem_saml_access_code( if request_options is not None and request_options.get("timeout_in_seconds") is not None else self._client_wrapper.get_timeout(), retries=0, - max_retries=request_options.get("max_retries") if request_options is not None else 0, # type: ignore + max_retries=request_options.get("max_retries", 0) if request_options is not None else 0, ) if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(RedeemSamlAccessCodeResponse, _response.json()) # type: ignore + return pydantic_v1.parse_obj_as(RedeemSamlAccessCodeResponse, _response.json()) try: _response_json = _response.json() except JSONDecodeError: @@ -136,8 +138,8 @@ def get_saml_redirect_url( _request["organizationExternalId"] = organization_external_id if state is not OMIT: _request["state"] = state - _response = self._client_wrapper.httpx_client.request( - method="POST", + _response = HttpClient.request( + self._client_wrapper.httpx_client, url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/saml/redirect"), params=encode_query( jsonable_encoder( @@ -162,10 +164,10 @@ def get_saml_redirect_url( if request_options is not None and request_options.get("timeout_in_seconds") is not None else self._client_wrapper.get_timeout(), retries=0, - max_retries=request_options.get("max_retries") if request_options is not None else 0, # type: ignore + max_retries=request_options.get("max_retries", 0) if request_options is not None else 0, ) if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(GetSamlRedirectUrlResponse, _response.json()) # type: ignore + return pydantic_v1.parse_obj_as(GetSamlRedirectUrlResponse, _response.json()) try: _response_json = _response.json() except JSONDecodeError: @@ -175,7 +177,7 @@ def get_saml_redirect_url( class AsyncSamlClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._client_wrapper: AsyncClientWrapper = client_wrapper async def redeem_saml_access_code( self, *, saml_access_code: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None @@ -207,7 +209,8 @@ async def redeem_saml_access_code( _request: typing.Dict[str, typing.Any] = {} if saml_access_code is not OMIT: _request["samlAccessCode"] = saml_access_code - _response = await self._client_wrapper.httpx_client.request( + _response = await AsyncHttpClient.request( + self._client_wrapper.httpx_client, method="POST", url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/saml/redeem"), params=encode_query( @@ -233,10 +236,10 @@ async def redeem_saml_access_code( if request_options is not None and request_options.get("timeout_in_seconds") is not None else self._client_wrapper.get_timeout(), retries=0, - max_retries=request_options.get("max_retries") if request_options is not None else 0, # type: ignore + max_retries=request_options.get("max_retries", 0) if request_options is not None else 0, ) if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(RedeemSamlAccessCodeResponse, _response.json()) # type: ignore + return pydantic_v1.parse_obj_as(RedeemSamlAccessCodeResponse, _response.json()) try: _response_json = _response.json() except JSONDecodeError: @@ -291,7 +294,8 @@ async def get_saml_redirect_url( _request["organizationExternalId"] = organization_external_id if state is not OMIT: _request["state"] = state - _response = await self._client_wrapper.httpx_client.request( + _response = await AsyncHttpClient.request( + self._client_wrapper.httpx_client, method="POST", url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/saml/redirect"), params=encode_query( @@ -317,7 +321,7 @@ async def get_saml_redirect_url( if request_options is not None and request_options.get("timeout_in_seconds") is not None else self._client_wrapper.get_timeout(), retries=0, - max_retries=request_options.get("max_retries") if request_options is not None else 0, # type: ignore + max_retries=request_options.get("max_retries", 0) if request_options is not None else 0, ) if 200 <= _response.status_code < 300: return pydantic_v1.parse_obj_as(GetSamlRedirectUrlResponse, _response.json()) # type: ignore From 32d3a11c6f5d4980739586d53adda6b334493b70 Mon Sep 17 00:00:00 2001 From: Roman Matveev Date: Wed, 18 Dec 2024 14:03:58 +0400 Subject: [PATCH 2/2] fix --- src/ssoready/core/http_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ssoready/core/http_client.py b/src/ssoready/core/http_client.py index a6eb2b0..264c1cb 100644 --- a/src/ssoready/core/http_client.py +++ b/src/ssoready/core/http_client.py @@ -91,7 +91,7 @@ def __init__(self, *, httpx_client: httpx.Client): def request( self, *args: typing.Any, max_retries: int = 0, retries: int = 0, **kwargs: typing.Any ) -> httpx.Response: - """Here retries is just a counter of times the request has been retried which stores in request.""" + """Here retries is just a counter of times the request has been retried which is stored in request.""" response = self.httpx_client.request(*args, **kwargs) if _should_retry(response=response): if max_retries > retries: