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.
@@ -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
@@ -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.7.0
1
+ v2.9.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: osbot_utils
3
- Version: 2.7.0
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
- ![Current Release](https://img.shields.io/badge/release-v2.7.0-blue)
26
+ ![Current Release](https://img.shields.io/badge/release-v2.9.0-blue)
27
27
  [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](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=NwniGTMB9La3Sbo08FkPn01ka9h70n8jTRcqtqSrmi4,30467
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=KN04fgKTlPtKr1d84ESDNlYMQikunyWJ3-I2VKZ8jjw,23661
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=EtyVXU03AffYJg9oYhRGCGg4FoQy8uTssAJDNu9cIQY,7
321
- osbot_utils-2.7.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
322
- osbot_utils-2.7.0.dist-info/METADATA,sha256=EwDB5K1xIrl97T8tWVAoGIdK8XOKdyQ4uqe9ZR_qI6Y,1315
323
- osbot_utils-2.7.0.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
324
- osbot_utils-2.7.0.dist-info/RECORD,,
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,,