ul-api-utils 7.10.5__py3-none-any.whl → 7.10.7__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.
- ul_api_utils/utils/instance_checks.py +16 -0
- ul_api_utils/utils/memory_db/__init__.py +0 -0
- ul_api_utils/utils/memory_db/__tests__/__init__.py +0 -0
- ul_api_utils/utils/memory_db/errors.py +8 -0
- ul_api_utils/utils/memory_db/repository.py +96 -0
- {ul_api_utils-7.10.5.dist-info → ul_api_utils-7.10.7.dist-info}/METADATA +1 -1
- {ul_api_utils-7.10.5.dist-info → ul_api_utils-7.10.7.dist-info}/RECORD +11 -6
- {ul_api_utils-7.10.5.dist-info → ul_api_utils-7.10.7.dist-info}/LICENSE +0 -0
- {ul_api_utils-7.10.5.dist-info → ul_api_utils-7.10.7.dist-info}/WHEEL +0 -0
- {ul_api_utils-7.10.5.dist-info → ul_api_utils-7.10.7.dist-info}/entry_points.txt +0 -0
- {ul_api_utils-7.10.5.dist-info → ul_api_utils-7.10.7.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def isinstance_namedtuple(obj: Any) -> bool:
|
|
5
|
+
namedtuple_unique_attributes = ('_asdict', '_fields')
|
|
6
|
+
is_tuple = isinstance(obj, tuple)
|
|
7
|
+
has_namedtuple_attributes = hasattr(obj, namedtuple_unique_attributes[0]) and hasattr(obj, namedtuple_unique_attributes[1])
|
|
8
|
+
return has_namedtuple_attributes and is_tuple
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def is_iterable(obj: Any) -> bool:
|
|
12
|
+
try:
|
|
13
|
+
iter(obj)
|
|
14
|
+
except TypeError:
|
|
15
|
+
return False
|
|
16
|
+
return True
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import decimal
|
|
2
|
+
import redis
|
|
3
|
+
import ormsgpack
|
|
4
|
+
import collections
|
|
5
|
+
|
|
6
|
+
from pydantic import ValidationError, parse_obj_as, BaseModel
|
|
7
|
+
from typing import Any, Type, overload, Iterator, KeysView, cast
|
|
8
|
+
|
|
9
|
+
from ul_api_utils.utils.instance_checks import isinstance_namedtuple
|
|
10
|
+
from ul_api_utils.utils.memory_db.errors import CompositeKeyError, UnsupportedParsingType
|
|
11
|
+
|
|
12
|
+
CompositeKeyT = tuple[str, Type[BaseModel]]
|
|
13
|
+
AnyKeyT = str | CompositeKeyT
|
|
14
|
+
AnyT = Any
|
|
15
|
+
RedisClientT = redis.StrictRedis | redis.Redis
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BaseMemoryDbRepository(collections.abc.MutableMapping[str, AnyT]):
|
|
19
|
+
def __init__(self, redis_client: RedisClientT) -> None:
|
|
20
|
+
self._db = redis_client
|
|
21
|
+
self._composite_key_max_length = 2
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def db(self) -> RedisClientT:
|
|
25
|
+
return self._db
|
|
26
|
+
|
|
27
|
+
def get(self, __key: str, *, parse_as_type: Type[BaseModel] | None = None, default: Any | None = None) -> AnyT | None: # type: ignore
|
|
28
|
+
try:
|
|
29
|
+
if parse_as_type is None:
|
|
30
|
+
return self[__key]
|
|
31
|
+
return self[__key, parse_as_type]
|
|
32
|
+
except KeyError:
|
|
33
|
+
return default
|
|
34
|
+
|
|
35
|
+
@overload
|
|
36
|
+
def __getitem__(self, key: str) -> AnyT:
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
@overload
|
|
40
|
+
def __getitem__(self, key: CompositeKeyT) -> AnyT:
|
|
41
|
+
...
|
|
42
|
+
|
|
43
|
+
def __getitem__(self, key: AnyKeyT) -> AnyT:
|
|
44
|
+
key_complex = isinstance(key, tuple)
|
|
45
|
+
|
|
46
|
+
if not key_complex:
|
|
47
|
+
single_key = cast(str, key)
|
|
48
|
+
return ormsgpack.unpackb(self._db[single_key])
|
|
49
|
+
|
|
50
|
+
composite_key = cast(CompositeKeyT, key)
|
|
51
|
+
|
|
52
|
+
if len(composite_key) > self._composite_key_max_length:
|
|
53
|
+
raise CompositeKeyError(f"Can't retrieve an item with {key=}. Composite key should have only two arguments.")
|
|
54
|
+
|
|
55
|
+
composite_key_name, _parse_as_type = composite_key
|
|
56
|
+
parsing_type_supported = issubclass(_parse_as_type, BaseModel) and _parse_as_type is not BaseModel
|
|
57
|
+
if not parsing_type_supported:
|
|
58
|
+
raise UnsupportedParsingType(f"Unsupported parsing type {_parse_as_type}.")
|
|
59
|
+
value = ormsgpack.unpackb(self._db[composite_key_name])
|
|
60
|
+
try:
|
|
61
|
+
if isinstance(value, list):
|
|
62
|
+
return parse_obj_as(list[_parse_as_type], value) # type: ignore
|
|
63
|
+
return parse_obj_as(_parse_as_type, value)
|
|
64
|
+
except ValidationError:
|
|
65
|
+
raise UnsupportedParsingType(f"Could not parse the value of key '{composite_key_name}' with type {_parse_as_type}") from None
|
|
66
|
+
|
|
67
|
+
def __setitem__(self, key: str, value: AnyT) -> None:
|
|
68
|
+
self._db[key] = ormsgpack.packb(value, option=ormsgpack.OPT_SERIALIZE_PYDANTIC, default=self._default_serializer)
|
|
69
|
+
|
|
70
|
+
def __delitem__(self, key: str) -> None:
|
|
71
|
+
del self._db[key]
|
|
72
|
+
|
|
73
|
+
def __iter__(self) -> Iterator[str]:
|
|
74
|
+
return iter(self.keys())
|
|
75
|
+
|
|
76
|
+
def __len__(self) -> int:
|
|
77
|
+
return len(self._db.keys())
|
|
78
|
+
|
|
79
|
+
def keys(self) -> KeysView[str]:
|
|
80
|
+
available_keys = [key.decode() for key in self._db.keys()]
|
|
81
|
+
return cast(KeysView[str], available_keys)
|
|
82
|
+
|
|
83
|
+
def clear(self) -> None:
|
|
84
|
+
self._db.flushdb()
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def _default_serializer(obj: Any) -> Any:
|
|
88
|
+
if isinstance_namedtuple(obj):
|
|
89
|
+
return obj._asdict()
|
|
90
|
+
if isinstance(obj, decimal.Decimal):
|
|
91
|
+
return str(obj)
|
|
92
|
+
if isinstance(obj, set):
|
|
93
|
+
return list(obj)
|
|
94
|
+
if isinstance(obj, frozenset):
|
|
95
|
+
return list(obj)
|
|
96
|
+
raise TypeError
|
|
@@ -108,6 +108,7 @@ ul_api_utils/utils/decode_base64.py,sha256=rqiD5Whzm2MPx-bk_4r4G4Pe4UUFyU_u-UAjZ
|
|
|
108
108
|
ul_api_utils/utils/deprecated.py,sha256=xR3ELgoDj7vJEY4CAYeEhdbtSJTfkukbjxcULtpMw58,866
|
|
109
109
|
ul_api_utils/utils/flags.py,sha256=AYN5nKWp4-uu6PSlPptL7ZiLqr3Pu-x5dffF6SBsqfg,957
|
|
110
110
|
ul_api_utils/utils/imports.py,sha256=i8PhoD0c_jnWTeXt_VxW_FihynwXSL_dHRT7jQiFyXE,376
|
|
111
|
+
ul_api_utils/utils/instance_checks.py,sha256=9punTfY5uabuJhmSGLfTgBqRderoFysCXBSI8rvbPco,467
|
|
111
112
|
ul_api_utils/utils/json_encoder.py,sha256=knpEW1c9XNdhgQg5gSeobEO2gPCasQB-0c8ig2Rc8Ho,4140
|
|
112
113
|
ul_api_utils/utils/load_modules.py,sha256=_CPmQuB6o_33FE6zFl_GyO5xS5gmjfNffB6k-cglKAA,685
|
|
113
114
|
ul_api_utils/utils/token_check.py,sha256=-Quuh8gOs9fNE1shYhdiMpQedafsLN7MB2ilSxG_F8E,489
|
|
@@ -135,15 +136,19 @@ ul_api_utils/utils/flask_swagger_generator/utils/security_type.py,sha256=AcWOQZB
|
|
|
135
136
|
ul_api_utils/utils/jinja/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
136
137
|
ul_api_utils/utils/jinja/t_url_for.py,sha256=PG9W4UbkWv2pLXNMQiCt22vp4sDi-Uz5w2u6DJ1fLkE,495
|
|
137
138
|
ul_api_utils/utils/jinja/to_pretty_json.py,sha256=wcc_EJ6yM4lipE0Vr6cgYOB-rBk7_j_Wa7bijjI_bCs,302
|
|
139
|
+
ul_api_utils/utils/memory_db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
140
|
+
ul_api_utils/utils/memory_db/errors.py,sha256=Bw1O1Y_WTCeCRNgb9iwrGT1fst6iHORhrNstwxiaUu8,267
|
|
141
|
+
ul_api_utils/utils/memory_db/repository.py,sha256=c_4BJuakhAtf0X3nlIKeWI4bsb1Wf2CK0xjKdY4_o-I,3395
|
|
142
|
+
ul_api_utils/utils/memory_db/__tests__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
138
143
|
ul_api_utils/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
139
144
|
ul_api_utils/validators/custom_fields.py,sha256=iqDnAvO-Bs13ZtLtccAG8SdJ8jWDlVcW6_ckChrTdXQ,4023
|
|
140
145
|
ul_api_utils/validators/validate_empty_object.py,sha256=3Ck_iwyJE_M5e7l6s1i88aqb73zIt06uaLrMG2PAb0A,299
|
|
141
146
|
ul_api_utils/validators/validate_uuid.py,sha256=EfvlRirv2EW0Z6w3s8E8rUa9GaI8qXZkBWhnPs8NFrA,257
|
|
142
147
|
ul_api_utils/validators/__tests__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
143
148
|
ul_api_utils/validators/__tests__/test_custom_fields.py,sha256=QLZ7DFta01Z7DOK9Z5Iq4uf_CmvDkVReis-GAl_QN48,1447
|
|
144
|
-
ul_api_utils-7.10.
|
|
145
|
-
ul_api_utils-7.10.
|
|
146
|
-
ul_api_utils-7.10.
|
|
147
|
-
ul_api_utils-7.10.
|
|
148
|
-
ul_api_utils-7.10.
|
|
149
|
-
ul_api_utils-7.10.
|
|
149
|
+
ul_api_utils-7.10.7.dist-info/LICENSE,sha256=6Qo8OdcqI8aGrswJKJYhST-bYqxVQBQ3ujKdTSdq-80,1062
|
|
150
|
+
ul_api_utils-7.10.7.dist-info/METADATA,sha256=2hbqUk-lZ-f5Z1ObSQ_Ax31kio0SvrLlqDzZaecK-C8,14715
|
|
151
|
+
ul_api_utils-7.10.7.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
152
|
+
ul_api_utils-7.10.7.dist-info/entry_points.txt,sha256=8tL3ySHWTyJMuV1hx1fHfN8zumDVOCOm63w3StphkXg,53
|
|
153
|
+
ul_api_utils-7.10.7.dist-info/top_level.txt,sha256=1XsW8iOSFaH4LOzDcnNyxHpHrbKU3fSn-aIAxe04jmw,21
|
|
154
|
+
ul_api_utils-7.10.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|