ul-api-utils 8.1.16__py3-none-any.whl → 8.1.18__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ul-api-utils might be problematic. Click here for more details.

@@ -16,8 +16,9 @@ from ul_api_utils.api_resource.api_resource_error_handling import WEB_EXCEPTION_
16
16
  ProcessingExceptionsParams, WEB_UNKNOWN_ERROR_PARAMS
17
17
  from ul_api_utils.api_resource.api_resource_fn_typing import ApiResourceFnTyping
18
18
  from ul_api_utils.api_resource.api_resource_type import ApiResourceType
19
- from ul_api_utils.api_resource.api_response import JsonApiResponse, HtmlApiResponse, FileApiResponse, JsonApiResponsePayload, EmptyJsonApiResponse, \
20
- RedirectApiResponse, ProxyJsonApiResponse, RootJsonApiResponse
19
+ from ul_api_utils.api_resource.api_response import JsonApiResponse, HtmlApiResponse, FileApiResponse, \
20
+ JsonApiResponsePayload, EmptyJsonApiResponse, \
21
+ RedirectApiResponse, ProxyJsonApiResponse, RootJsonApiResponse, RootJsonApiResponsePayload
21
22
  from ul_api_utils.conf import APPLICATION_ENV, APPLICATION_JWT_PUBLIC_KEY, APPLICATION_DEBUG
22
23
  from ul_api_utils.const import REQUEST_HEADER__X_FORWARDED_FOR, \
23
24
  RESPONSE_HEADER__WWW_AUTH, OOPS, REQUEST_HEADER__USER_AGENT
@@ -38,7 +39,7 @@ TPayload = TypeVar('TPayload')
38
39
 
39
40
 
40
41
  T = TypeVar('T')
41
- TResp = TypeVar('TResp', bound=JsonApiResponsePayload)
42
+ TResp = TypeVar('TResp', bound=Union[JsonApiResponsePayload, RootJsonApiResponsePayload[Any]])
42
43
 
43
44
 
44
45
  class ApiResource:
@@ -25,7 +25,7 @@ if TYPE_CHECKING:
25
25
  FN_SYSTEM_PROPS = {"api_resource", "query", "body", "return", "body_validation_error", "query_validation_error"}
26
26
 
27
27
 
28
- def _is_complex_type(annotation):
28
+ def _is_complex_type(annotation: Any) -> bool:
29
29
  origin = get_origin(annotation)
30
30
 
31
31
  # Optional[type_] is typing.Union
@@ -165,8 +165,7 @@ class ApiResourceFnTyping(NamedTuple):
165
165
  return kwargs, errors
166
166
  body = self._get_body()
167
167
  try:
168
- expected_typing: Type[BaseModel | List[BaseModel]] = List[self.body_typing] \
169
- if self.request_body_many else self.body_typing
168
+ expected_typing: Type[BaseModel | List[BaseModel]] = List[self.body_typing] if self.request_body_many else self.body_typing # type: ignore
170
169
  kwargs['body'] = TypeAdapter(expected_typing).validate_python(body)
171
170
  except ValidationError as ve:
172
171
  if self.has_body_validation_error:
@@ -168,7 +168,7 @@ class DictJsonApiResponsePayload(RootJsonApiResponsePayload[Dict[str, Any]]):
168
168
  pass
169
169
 
170
170
 
171
- TProxyPayload = TypeVar('TProxyPayload', bound=Union[JsonApiResponsePayload, List[JsonApiResponsePayload], None])
171
+ TProxyPayload = TypeVar('TProxyPayload', bound=Union[JsonApiResponsePayload, List[JsonApiResponsePayload], RootJsonApiResponsePayload[Any], List[RootJsonApiResponsePayload[Any]], None])
172
172
 
173
173
 
174
174
  class ProxyJsonApiResponse(Generic[TProxyPayload], EmptyJsonApiResponse):
@@ -7,7 +7,7 @@ from typing import Any, Optional, List, Generic, Type, TypeVar, Union, Dict, Nam
7
7
  import requests
8
8
  from pydantic import ValidationError
9
9
 
10
- from ul_api_utils.api_resource.api_response import JsonApiResponsePayload
10
+ from ul_api_utils.api_resource.api_response import JsonApiResponsePayload, RootJsonApiResponsePayload
11
11
  from ul_api_utils.api_resource.signature_check import set_model
12
12
  from ul_api_utils.const import RESPONSE_PROP_DEBUG_STATS, RESPONSE_PROP_PAYLOAD, RESPONSE_PROP_OK, RESPONSE_PROP_ERRORS, RESPONSE_PROP_TOTAL, RESPONSE_PROP_COUNT, MIME__JSON, \
13
13
  RESPONSE_HEADER__CONTENT_TYPE
@@ -18,7 +18,7 @@ from ul_api_utils.utils.api_format import ApiFormat
18
18
  from ul_api_utils.internal_api.internal_api_error import InternalApiResponseErrorObj
19
19
  from ul_api_utils.utils.unwrap_typing import UnwrappedOptionalObjOrListOfObj
20
20
 
21
- TPyloadType = TypeVar('TPyloadType', bound=Union[JsonApiResponsePayload, List[JsonApiResponsePayload], None])
21
+ TPyloadType = TypeVar('TPyloadType', bound=Union[JsonApiResponsePayload, List[JsonApiResponsePayload], RootJsonApiResponsePayload[Any], List[RootJsonApiResponsePayload[Any]], None])
22
22
  TResp = TypeVar('TResp', bound='InternalApiResponse[Any]')
23
23
 
24
24
 
@@ -73,17 +73,17 @@ class InternalApiResponse(Generic[TPyloadType]):
73
73
 
74
74
  self._parsed_schema: Optional[InternalApiResponseSchema] = None
75
75
  self._parsed_json: Any = None
76
- self._parsed_payload: Union[None, JsonApiResponsePayload, List[JsonApiResponsePayload]] = None
76
+ self._parsed_payload: Union[None, JsonApiResponsePayload, List[JsonApiResponsePayload], RootJsonApiResponsePayload[Any], List[RootJsonApiResponsePayload[Any]]] = None
77
77
 
78
78
  self._status_checked = False
79
79
  self._info = info
80
80
 
81
81
  if payload_type is not None:
82
- self._payload_type = UnwrappedOptionalObjOrListOfObj.parse(payload_type, JsonApiResponsePayload)
82
+ self._payload_type = UnwrappedOptionalObjOrListOfObj.parse(payload_type, JsonApiResponsePayload) or UnwrappedOptionalObjOrListOfObj.parse(payload_type, RootJsonApiResponsePayload)
83
83
  if self._payload_type is None:
84
- tn = JsonApiResponsePayload.__name__
84
+ tn1, tn2 = JsonApiResponsePayload.__name__, RootJsonApiResponsePayload.__name__
85
85
  raise ValueError(
86
- f'payload_typing is invalid. must be Union[Type[{tn}], Optional[Type[{tn}]], List[Type[{tn}]], Optional[List[Type[{tn}]]]]. {payload_type} was given',
86
+ f'payload_typing is invalid. must be Union[Type[{tn1} | {tn2}], Optional[Type[{tn1} | {tn2}]], List[Type[{tn1} | {tn2}]], Optional[List[Type[{tn1} | {tn2}]]]]. {payload_type} was given',
87
87
  )
88
88
 
89
89
  def typed(self, payload_type: Type[TPyloadType]) -> 'InternalApiResponse[TPyloadType]':
@@ -2,7 +2,7 @@ import dataclasses
2
2
  import decimal
3
3
  import json
4
4
  from base64 import b64encode
5
- from datetime import date, datetime
5
+ from datetime import date, datetime, time
6
6
  from enum import Enum
7
7
  from json import JSONEncoder
8
8
  from typing import Dict, Any, Union, List, Optional, TYPE_CHECKING
@@ -62,6 +62,8 @@ class CustomJSONEncoder(JSONEncoder):
62
62
  return str(obj.isoformat())
63
63
  if isinstance(obj, date):
64
64
  return str(obj.isoformat())
65
+ if isinstance(obj, time):
66
+ return str(obj.isoformat())
65
67
  if isinstance(obj, UUID):
66
68
  return str(obj)
67
69
  if isinstance(obj, Enum):
@@ -2,6 +2,8 @@ from dataclasses import dataclass
2
2
  from types import NoneType
3
3
  from typing import NamedTuple, Type, Tuple, _GenericAlias, _UnionGenericAlias, Any, Union, Optional, TypeVar, Generic, Callable # type: ignore
4
4
 
5
+ from ul_api_utils.api_resource.api_response import RootJsonApiResponsePayload
6
+
5
7
 
6
8
  class TypingType(NamedTuple):
7
9
  value: Type[Any]
@@ -47,6 +49,7 @@ def unwrap_typing(t: Type[Any]) -> Union[TypingGeneric, TypingUnion, TypingType,
47
49
 
48
50
  T = TypeVar('T')
49
51
  TVal = TypeVar('TVal')
52
+ TValRoot = TypeVar('TValRoot', bound=RootJsonApiResponsePayload[Any])
50
53
 
51
54
 
52
55
  def default_constructor(value_type: Type[TVal], data: Any) -> TVal:
@@ -72,7 +75,7 @@ class UnwrappedOptionalObjOrListOfObj(Generic[TVal]):
72
75
  return constructor(self.value_type, payload) # type: ignore
73
76
 
74
77
  @staticmethod
75
- def parse(t: Type[Any], type_constraint: Optional[Type[TVal]]) -> 'Optional[UnwrappedOptionalObjOrListOfObj[TVal]]':
78
+ def parse(t: Type[Any], type_constraint: Optional[Type[TVal | TValRoot]]) -> 'Optional[UnwrappedOptionalObjOrListOfObj[TVal]]':
76
79
  unwrapped_t = unwrap_typing(t)
77
80
 
78
81
  many = False
@@ -59,8 +59,6 @@ class QueryParamsSeparatedList(Generic[QueryParamsSeparatedListValueType]):
59
59
  if cls._contains_type is None:
60
60
  raise TypeError("QueryParamsSeparatedList must be parameterized with a type, e.g., QueryParamsSeparatedList[int]")
61
61
 
62
- adapter = TypeAdapter(cls._contains_type)
63
-
64
62
  if not isinstance(query_param, list):
65
63
  query_param = [query_param]
66
64
 
@@ -72,7 +70,14 @@ class QueryParamsSeparatedList(Generic[QueryParamsSeparatedListValueType]):
72
70
 
73
71
  for idx, value in enumerate(splitted):
74
72
  try:
75
- validated_items.append(adapter.validate_python(value))
73
+ if cls._contains_type == Union[int, str]:
74
+ try:
75
+ validated_items.append(int(value))
76
+ except ValueError:
77
+ validated_items.append(value) # type: ignore
78
+ else:
79
+ adapter = TypeAdapter(cls._contains_type)
80
+ validated_items.append(adapter.validate_python(value))
76
81
  except ValidationError as e:
77
82
  for error in e.errors(include_url=False):
78
83
  error['loc'] = ('param', idx)
@@ -81,4 +86,4 @@ class QueryParamsSeparatedList(Generic[QueryParamsSeparatedListValueType]):
81
86
  if errors:
82
87
  raise ValidationError.from_exception_data("List validation error", errors)
83
88
 
84
- return validated_items
89
+ return validated_items # type: ignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ul-api-utils
3
- Version: 8.1.16
3
+ Version: 8.1.18
4
4
  Summary: Python api utils
5
5
  Author: Unic-lab
6
6
  Author-email:
@@ -26,12 +26,12 @@ ul_api_utils/sentry.py,sha256=UH_SwZCAoKH-Nw5B9CVQMoF-b1BJOp-ZTzwqUZ3Oq84,1801
26
26
  ul_api_utils/access/__init__.py,sha256=NUyRNvCVwfePrfdn5ATFVfHeSO3iq4-Syeup4IAZGzs,4526
27
27
  ul_api_utils/api_resource/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  ul_api_utils/api_resource/api_request.py,sha256=6Ag2trKIkenhYYPU2--hnfNJC5lLgBxVQ7jXj5D1eXM,3303
29
- ul_api_utils/api_resource/api_resource.py,sha256=j-E8KJiXWS1L0oVIerJZlbGpDL2ijlQrck4GrJPWPyE,17840
29
+ ul_api_utils/api_resource/api_resource.py,sha256=ERAGC4rrN_jmZ_dFhYZZ_Eczqdy5tQK7cfN7SY4sIfA,17914
30
30
  ul_api_utils/api_resource/api_resource_config.py,sha256=l9OYJy75UZLshOkEQDO5jlhXeb5H4HDPu-nLOjuoexw,769
31
31
  ul_api_utils/api_resource/api_resource_error_handling.py,sha256=E0SWpjFSIP-4SumbgzrHtFuFiGe9q38WsvLROt0YcPE,1168
32
- ul_api_utils/api_resource/api_resource_fn_typing.py,sha256=n5bux_azlV8aRtRQdoIP553tXWHCi7P-brKUAgj502E,18970
32
+ ul_api_utils/api_resource/api_resource_fn_typing.py,sha256=ogVJ8Y69DlL3CztpyfK_vI5CImdkJmfyJTtQm7JUi5Y,18981
33
33
  ul_api_utils/api_resource/api_resource_type.py,sha256=mgjSQI3swGpgpLI6y35LYtFrdN-kXyV5cQorwGW7h6g,462
34
- ul_api_utils/api_resource/api_response.py,sha256=bfnWo5GZUCzwJm8rDfzcpuYL4l63pBedJ0tTguP--qw,10069
34
+ ul_api_utils/api_resource/api_response.py,sha256=DYKqNI8xbXIMBCn-GmZx24Bsr7SBgKQDtGU2nbw3p6Q,10141
35
35
  ul_api_utils/api_resource/api_response_db.py,sha256=ucY6ANPlHZml7JAbvq-PL85z0bvERTjEJKvz-REPyok,888
36
36
  ul_api_utils/api_resource/api_response_payload_alias.py,sha256=FoD0LhQGZ2T8A5-VKRX5ADyzSgm7_dd3qxU2BgCVXkA,587
37
37
  ul_api_utils/api_resource/db_types.py,sha256=gF0oxisRkYLf7_2e7YEU-HJDxLy3dJCVaJsYQbOfG5k,433
@@ -60,7 +60,7 @@ ul_api_utils/internal_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
60
60
  ul_api_utils/internal_api/internal_api.py,sha256=gLlz4TYDgrmEF8S2XpNCKgAjLHsd21vs75kppHLoG6A,14067
61
61
  ul_api_utils/internal_api/internal_api_check_context.py,sha256=FJyYuyhp7AzvKSoyNrszw6vtUanSUKNNcDmlNH-UDI4,1709
62
62
  ul_api_utils/internal_api/internal_api_error.py,sha256=sdm3V2VLSfFVBmxaeo2Wy2wkhmxWTXGsCCR-u08ChMg,471
63
- ul_api_utils/internal_api/internal_api_response.py,sha256=rNAqY82ezupcRSnWY1YO2T5QhwfOFrak0dp23shgUxY,11583
63
+ ul_api_utils/internal_api/internal_api_response.py,sha256=TyS7iLbvTFb0oAcElK3fUAB5jNGQDtiJUrESn5BTTHM,11917
64
64
  ul_api_utils/internal_api/__tests__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  ul_api_utils/internal_api/__tests__/internal_api.py,sha256=X2iopeso6vryszeeA__lcqXQVtz3Nwt3ngH7M4OuN1U,1116
66
66
  ul_api_utils/internal_api/__tests__/internal_api_content_type.py,sha256=mfiYPkzKtfZKFpi4RSnWAoCd6mRijr6sFsa2TF-s5t8,749
@@ -111,11 +111,11 @@ ul_api_utils/utils/deprecated.py,sha256=xR3ELgoDj7vJEY4CAYeEhdbtSJTfkukbjxcULtpM
111
111
  ul_api_utils/utils/flags.py,sha256=AYN5nKWp4-uu6PSlPptL7ZiLqr3Pu-x5dffF6SBsqfg,957
112
112
  ul_api_utils/utils/imports.py,sha256=i8PhoD0c_jnWTeXt_VxW_FihynwXSL_dHRT7jQiFyXE,376
113
113
  ul_api_utils/utils/instance_checks.py,sha256=9punTfY5uabuJhmSGLfTgBqRderoFysCXBSI8rvbPco,467
114
- ul_api_utils/utils/json_encoder.py,sha256=ra43WhkAadIvVpUY3uik_Nzg0LVXUXTGYvx4Gx7fD_g,4578
114
+ ul_api_utils/utils/json_encoder.py,sha256=2uJuoZHNx0TpDLYdlVpch_Am1OXIG_gWHHvdPkfRV2c,4658
115
115
  ul_api_utils/utils/load_modules.py,sha256=_CPmQuB6o_33FE6zFl_GyO5xS5gmjfNffB6k-cglKAA,685
116
116
  ul_api_utils/utils/token_check.py,sha256=-Quuh8gOs9fNE1shYhdiMpQedafsLN7MB2ilSxG_F8E,489
117
117
  ul_api_utils/utils/token_check_through_request.py,sha256=OyyObu6Btk9br7auIYvWcMULhNznNSD5T0mWOwZX7Uk,663
118
- ul_api_utils/utils/unwrap_typing.py,sha256=19jyhkRcb89v1gzR62YDsMO9zxR2PU5bjYZm1is8Aoo,4189
118
+ ul_api_utils/utils/unwrap_typing.py,sha256=uObDLxYcRni6ieN9FuvWTa350HjSUIpgTb7FrIUzsVI,4349
119
119
  ul_api_utils/utils/uuid_converter.py,sha256=OZMuySkoALrQQOe312_BHVWN20Sz5frKuH9KYziAGsU,565
120
120
  ul_api_utils/utils/__tests__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
121
  ul_api_utils/utils/__tests__/api_path_version.py,sha256=n7VFVdwFqP_FS6PE3OUCS68oU3tG78xM4HxrKShLhNw,898
@@ -143,14 +143,14 @@ ul_api_utils/utils/memory_db/errors.py,sha256=Bw1O1Y_WTCeCRNgb9iwrGT1fst6iHORhrN
143
143
  ul_api_utils/utils/memory_db/repository.py,sha256=0AI0-VA4Md54BrAuZLX0Lg7rxyyGv54aWiiNUPycGSA,3760
144
144
  ul_api_utils/utils/memory_db/__tests__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
145
  ul_api_utils/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
- ul_api_utils/validators/custom_fields.py,sha256=LKmsn2R66BRPaDiZDqXmC7wCKxDK8OTD1Jk8fFj0_So,3778
146
+ ul_api_utils/validators/custom_fields.py,sha256=XAWXOp6RlbRcScSWO7ghPwlors2n_-yy0GELoS6O1M8,4082
147
147
  ul_api_utils/validators/validate_empty_object.py,sha256=3Ck_iwyJE_M5e7l6s1i88aqb73zIt06uaLrMG2PAb0A,299
148
148
  ul_api_utils/validators/validate_uuid.py,sha256=EfvlRirv2EW0Z6w3s8E8rUa9GaI8qXZkBWhnPs8NFrA,257
149
149
  ul_api_utils/validators/__tests__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
150
  ul_api_utils/validators/__tests__/test_custom_fields.py,sha256=20gLlnm1Ithsbbz3NIUXVAd92lW6YwVRSg_nETZhfaI,1442
151
- ul_api_utils-8.1.16.dist-info/LICENSE,sha256=6Qo8OdcqI8aGrswJKJYhST-bYqxVQBQ3ujKdTSdq-80,1062
152
- ul_api_utils-8.1.16.dist-info/METADATA,sha256=g3CCq5zlTMjyZp7D7BVWG7WyY6IY7M1KoSHNSnCkSHU,14748
153
- ul_api_utils-8.1.16.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
154
- ul_api_utils-8.1.16.dist-info/entry_points.txt,sha256=8tL3ySHWTyJMuV1hx1fHfN8zumDVOCOm63w3StphkXg,53
155
- ul_api_utils-8.1.16.dist-info/top_level.txt,sha256=1XsW8iOSFaH4LOzDcnNyxHpHrbKU3fSn-aIAxe04jmw,21
156
- ul_api_utils-8.1.16.dist-info/RECORD,,
151
+ ul_api_utils-8.1.18.dist-info/LICENSE,sha256=6Qo8OdcqI8aGrswJKJYhST-bYqxVQBQ3ujKdTSdq-80,1062
152
+ ul_api_utils-8.1.18.dist-info/METADATA,sha256=UlE7xz7c69sj9M6v4iTSv-s57s7o5sJSJRINnWauUHk,14748
153
+ ul_api_utils-8.1.18.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
154
+ ul_api_utils-8.1.18.dist-info/entry_points.txt,sha256=8tL3ySHWTyJMuV1hx1fHfN8zumDVOCOm63w3StphkXg,53
155
+ ul_api_utils-8.1.18.dist-info/top_level.txt,sha256=1XsW8iOSFaH4LOzDcnNyxHpHrbKU3fSn-aIAxe04jmw,21
156
+ ul_api_utils-8.1.18.dist-info/RECORD,,