osbot-utils 2.7.0__py3-none-any.whl → 2.9.0__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.
- osbot_utils/type_safe/Type_Safe.py +12 -1
- osbot_utils/type_safe/methods/__init__.py +0 -0
- osbot_utils/type_safe/methods/type_safe_property.py +36 -0
- osbot_utils/utils/Objects.py +3 -0
- osbot_utils/version +1 -1
- {osbot_utils-2.7.0.dist-info → osbot_utils-2.9.0.dist-info}/METADATA +2 -2
- {osbot_utils-2.7.0.dist-info → osbot_utils-2.9.0.dist-info}/RECORD +9 -7
- {osbot_utils-2.7.0.dist-info → osbot_utils-2.9.0.dist-info}/LICENSE +0 -0
- {osbot_utils-2.7.0.dist-info → osbot_utils-2.9.0.dist-info}/WHEEL +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
# todo: find a way to add these documentations strings to a separate location so that
|
2
2
|
# the data is available in IDE's code complete
|
3
|
-
|
3
|
+
import inspect
|
4
4
|
import sys
|
5
5
|
import types
|
6
6
|
from osbot_utils.utils.Objects import default_value # todo: remove test mocking requirement for this to be here (instead of on the respective method)
|
@@ -157,6 +157,8 @@ class Type_Safe:
|
|
157
157
|
continue
|
158
158
|
if type(v) is functools._lru_cache_wrapper: # todo, find better way to handle edge cases like this one (which happens when the @cache decorator is used in a instance method that uses Kwargs_To_Self)
|
159
159
|
continue
|
160
|
+
if isinstance(v, property): # skip property descriptors since they should not be handled here
|
161
|
+
continue
|
160
162
|
if (k in kwargs) is False: # do not set the value is it has already been set
|
161
163
|
kwargs[k] = v
|
162
164
|
|
@@ -198,6 +200,15 @@ class Type_Safe:
|
|
198
200
|
import typing
|
199
201
|
from osbot_utils.type_safe.Type_Safe__List import Type_Safe__List
|
200
202
|
from osbot_utils.type_safe.Type_Safe__Dict import Type_Safe__Dict
|
203
|
+
if get_origin(var_type) is type: # Special handling for Type[T] # todo: reuse the get_origin value
|
204
|
+
type_args = get_args(var_type)
|
205
|
+
if type_args:
|
206
|
+
if isinstance(type_args[0], ForwardRef):
|
207
|
+
forward_name = type_args[0].__forward_arg__
|
208
|
+
for base_cls in inspect.getmro(cls):
|
209
|
+
if base_cls.__name__ == forward_name:
|
210
|
+
return cls # note: in this case we return the cls, and not the base_cls (which makes sense since this happens when the cls class uses base_cls as base, which has a ForwardRef to base_cls )
|
211
|
+
return type_args[0] # Return the actual type as the default value
|
201
212
|
|
202
213
|
if var_type is typing.Set: # todo: refactor the dict, set and list logic, since they are 90% the same
|
203
214
|
return set()
|
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
from typing import TypeVar, Type, Optional
|
2
|
+
|
3
|
+
T = TypeVar('T')
|
4
|
+
|
5
|
+
def type_safe_property(target_path: str, target_name: str, expected_type: Optional[Type[T]] = None) -> property: # Creates a type-safe property that delegates get/set operations to a nested data object
|
6
|
+
|
7
|
+
def getter(self) -> T:
|
8
|
+
target = self
|
9
|
+
for part in target_path.split('.'):
|
10
|
+
target = getattr(target, part)
|
11
|
+
|
12
|
+
value = getattr(target, target_name)
|
13
|
+
|
14
|
+
if expected_type and value is not None:
|
15
|
+
if not isinstance(value, expected_type):
|
16
|
+
raise TypeError(f"Property '{target_name}' returned value of type {type(value)}, expected {expected_type}")
|
17
|
+
return value
|
18
|
+
|
19
|
+
def setter(self, value: T) -> None:
|
20
|
+
if expected_type and value is not None:
|
21
|
+
if not isinstance(value, expected_type):
|
22
|
+
raise TypeError(f"Cannot set property '{target_name}' with value of type {type(value)}, expected {expected_type}")
|
23
|
+
|
24
|
+
target = self
|
25
|
+
for part in target_path.split('.'):
|
26
|
+
target = getattr(target, part)
|
27
|
+
if hasattr(target, target_name) is False:
|
28
|
+
raise AttributeError(f"Target path '{target_path}' does not have an attribute '{target_name}'")
|
29
|
+
setattr(target, target_name, value)
|
30
|
+
|
31
|
+
return property(getter, setter)
|
32
|
+
|
33
|
+
|
34
|
+
wire_as_property = type_safe_property
|
35
|
+
bind_as_property = type_safe_property
|
36
|
+
set_as_property = type_safe_property
|
osbot_utils/utils/Objects.py
CHANGED
@@ -469,9 +469,12 @@ def value_type_matches_obj_annotation_for_attr(target, attr_name, value):
|
|
469
469
|
origin_attr_type = get_origin(attr_type) # to handle when type definition contains a generic
|
470
470
|
if origin_attr_type is type: # Add handling for Type[T]
|
471
471
|
type_arg = get_args(attr_type)[0] # Get T from Type[T]
|
472
|
+
if type_arg == value:
|
473
|
+
return True
|
472
474
|
if isinstance(type_arg, (str, ForwardRef)): # Handle forward reference
|
473
475
|
type_arg = target.__class__ # If it's a forward reference, the target class should be the containing class
|
474
476
|
return isinstance(value, type) and issubclass(value, type_arg) # Check that value is a type and is subclass of type_arg
|
477
|
+
|
475
478
|
if origin_attr_type is Annotated: # if the type is Annotated
|
476
479
|
args = get_args(attr_type)
|
477
480
|
origin_attr_type = args[0]
|
osbot_utils/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
v2.
|
1
|
+
v2.9.0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: osbot_utils
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.9.0
|
4
4
|
Summary: OWASP Security Bot - Utils
|
5
5
|
Home-page: https://github.com/owasp-sbot/OSBot-Utils
|
6
6
|
License: MIT
|
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
|
|
23
23
|
|
24
24
|
Powerful Python util methods and classes that simplify common apis and tasks.
|
25
25
|
|
26
|
-

|
27
27
|
[](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
|
28
28
|
|
29
29
|
|
@@ -277,7 +277,7 @@ osbot_utils/testing/Temp_Zip_In_Memory.py,sha256=ibDIWt3K4CX558PbkLbX3InHyWYZcwQ
|
|
277
277
|
osbot_utils/testing/Unit_Test.py,sha256=MReR_wDGbbXFDPz7cmuGflcTxRB6TBnO9mYqRpSq8Pk,1304
|
278
278
|
osbot_utils/testing/Unzip_File.py,sha256=V5H97XO9rlvG5EYOSzAH4kTtAH1ohZ8R8ImvJh46ZNg,1177
|
279
279
|
osbot_utils/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
280
|
-
osbot_utils/type_safe/Type_Safe.py,sha256=
|
280
|
+
osbot_utils/type_safe/Type_Safe.py,sha256=RTi44N_p_gVO4-w6MwvRErv6z4DR-Vgv_X1JjfDV36M,31488
|
281
281
|
osbot_utils/type_safe/Type_Safe__Base.py,sha256=mL8GMaR9tsaUfwk8d-8zp2g-A8kNKiN6kroEFaNvMOk,5518
|
282
282
|
osbot_utils/type_safe/Type_Safe__Dict.py,sha256=I_Ac0JH-ahmQrkADFVyiobTlH1JI31MKHaNszQW4PBo,2396
|
283
283
|
osbot_utils/type_safe/Type_Safe__List.py,sha256=SzSIBkwSOAEpW_V2qh4-f0YHzmgB0T8PczBLbDgZGvg,1340
|
@@ -285,6 +285,8 @@ osbot_utils/type_safe/Type_Safe__Method.py,sha256=LOG2sqQyKBNNEiJxk_jngH6IWvpyVu
|
|
285
285
|
osbot_utils/type_safe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
286
286
|
osbot_utils/type_safe/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
287
287
|
osbot_utils/type_safe/decorators/type_safe.py,sha256=ERFfJuAIo5qLp03YEDu2zu5wxu65OhR7hOybwuTfLlc,1006
|
288
|
+
osbot_utils/type_safe/methods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
289
|
+
osbot_utils/type_safe/methods/type_safe_property.py,sha256=wl_wNPOZDWcNeb3JqRJLyYW0we-fZW6AylIil58VwyI,1432
|
288
290
|
osbot_utils/type_safe/validators/Type_Safe__Validator.py,sha256=cJIPSBarjV716SZUOLvz7Mthjk-aUYKUQtRDtKUBmN4,779
|
289
291
|
osbot_utils/type_safe/validators/Validator__Max.py,sha256=pCvYF5Jb_cBgn1ArGhf6FNUB-NGCXPq3D36oYDCyAzg,1275
|
290
292
|
osbot_utils/type_safe/validators/Validator__Min.py,sha256=_-9MdAX2Jc2U0VzCHpEQLA8OVxuNe2y8uaJ6bQttimE,1981
|
@@ -305,7 +307,7 @@ osbot_utils/utils/Json.py,sha256=0t7Hwefx8bg4JiZVr-xIbWP3BAk6_ZsnY7iV5pnRLDQ,713
|
|
305
307
|
osbot_utils/utils/Json_Cache.py,sha256=mLPkkDZN-3ZVJiDvV1KBJXILtKkTZ4OepzOsDoBPhWg,2006
|
306
308
|
osbot_utils/utils/Lists.py,sha256=tPz5x5s3sRO97WZ_nsxREBPC5cwaHrhgaYBhsrffTT8,5599
|
307
309
|
osbot_utils/utils/Misc.py,sha256=H_xexJgiTxB3jDeDiW8efGQbO0Zuy8MM0iQ7qXC92JI,17363
|
308
|
-
osbot_utils/utils/Objects.py,sha256=
|
310
|
+
osbot_utils/utils/Objects.py,sha256=3GHd0MzqXgE-_mTS58GIgmIUy2SY4lb6V99EtkgRUc0,23724
|
309
311
|
osbot_utils/utils/Png.py,sha256=V1juGp6wkpPigMJ8HcxrPDIP4bSwu51oNkLI8YqP76Y,1172
|
310
312
|
osbot_utils/utils/Process.py,sha256=lr3CTiEkN3EiBx3ZmzYmTKlQoPdkgZBRjPulMxG-zdo,2357
|
311
313
|
osbot_utils/utils/Python_Logger.py,sha256=M9Oi62LxfnRSlCN8GhaiwiBINvcSdGy39FCWjyDD-Xg,12792
|
@@ -317,8 +319,8 @@ osbot_utils/utils/Toml.py,sha256=Rxl8gx7mni5CvBAK-Ai02EKw-GwtJdd3yeHT2kMloik,166
|
|
317
319
|
osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
|
318
320
|
osbot_utils/utils/Zip.py,sha256=pR6sKliUY0KZXmqNzKY2frfW-YVQEVbLKiyqQX_lc-8,14052
|
319
321
|
osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
320
|
-
osbot_utils/version,sha256=
|
321
|
-
osbot_utils-2.
|
322
|
-
osbot_utils-2.
|
323
|
-
osbot_utils-2.
|
324
|
-
osbot_utils-2.
|
322
|
+
osbot_utils/version,sha256=351BylEWiITd1QlbdsxCEiDfpPqKeADndEHAIk3Q9AQ,7
|
323
|
+
osbot_utils-2.9.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
324
|
+
osbot_utils-2.9.0.dist-info/METADATA,sha256=-b-4-_Mt8tmi9TiODuka_8lw3eWnL74svEqP1kTLDMo,1315
|
325
|
+
osbot_utils-2.9.0.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
326
|
+
osbot_utils-2.9.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|