osbot-utils 2.3.0__py3-none-any.whl → 2.5.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,5 +1,4 @@
1
1
  import uuid
2
-
3
2
  from osbot_utils.utils.Misc import is_guid
4
3
 
5
4
  GUID__NAMESPACE = uuid.UUID('2cfec064-537a-4ff7-8fdc-2fc9e2606f3d')
@@ -88,7 +88,7 @@ class Type_Safe:
88
88
  from osbot_utils.utils.Objects import convert_to_value_from_obj_annotation
89
89
  from osbot_utils.utils.Objects import value_type_matches_obj_annotation_for_attr
90
90
  from osbot_utils.utils.Objects import value_type_matches_obj_annotation_for_union_and_annotated
91
- from osbot_utils.type_safe.Type_Safe__Validator import Type_Safe__Validator
91
+ from osbot_utils.type_safe.validators.Type_Safe__Validator import Type_Safe__Validator
92
92
 
93
93
  annotations = all_annotations(self)
94
94
  if not annotations: # can't do type safety checks if the class does not have annotations
@@ -142,7 +142,7 @@ class Type_Safe:
142
142
  from enum import EnumMeta
143
143
  from osbot_utils.utils.Objects import obj_is_type_union_compatible
144
144
 
145
- IMMUTABLE_TYPES = (bool, int, float, complex, str, tuple, frozenset, bytes, NoneType, EnumMeta)
145
+ IMMUTABLE_TYPES = (bool, int, float, complex, str, tuple, frozenset, bytes, NoneType, EnumMeta, type)
146
146
 
147
147
 
148
148
  kwargs = {}
@@ -172,7 +172,15 @@ class Type_Safe:
172
172
  if var_value is not None: # allow None assignments on ctor since that is a valid use case
173
173
  if get_origin(var_type) is Annotated:
174
174
  continue
175
- if var_type and not isinstance(var_value, var_type): # check type
175
+ if get_origin(var_type) is type: # Special handling for Type[T]
176
+ if not isinstance(var_value, type):
177
+ exception_message = f"variable '{var_name}' is defined as Type[T] but has value '{var_value}' which is not a type"
178
+ raise ValueError(exception_message)
179
+ type_arg = get_args(var_type)[0]
180
+ if not issubclass(var_value, type_arg):
181
+ exception_message = f"variable '{var_name}' is defined as {var_type} but value {var_value} is not a subclass of {type_arg}"
182
+ raise ValueError(exception_message)
183
+ elif var_type and not isinstance(var_value, var_type): # check type
176
184
  exception_message = f"variable '{var_name}' is defined as type '{var_type}' but has value '{var_value}' of type '{type(var_value)}'"
177
185
  raise ValueError(exception_message)
178
186
  if var_type not in IMMUTABLE_TYPES and var_name.startswith('__') is False: # if var_type is not one of the IMMUTABLE_TYPES or is an __ internal
@@ -3,7 +3,7 @@ from enum import Enum
3
3
  from typing import get_args, get_origin, Union, List, Any # For type hinting utilities
4
4
 
5
5
 
6
- class Type_Safe_Method: # Class to handle method type safety validation
6
+ class Type_Safe__Method: # Class to handle method type safety validation
7
7
  def __init__(self, func): # Initialize with function
8
8
  self.func = func # Store original function
9
9
  self.sig = inspect.signature(func) # Get function signature
@@ -1,10 +1,10 @@
1
1
  import functools # For wrapping functions
2
- from osbot_utils.type_safe.Type_Safe_Method import Type_Safe_Method
2
+ from osbot_utils.type_safe.Type_Safe__Method import Type_Safe__Method
3
3
 
4
4
  def type_safe(func): # Main decorator function
5
5
  @functools.wraps(func) # Preserve function metadata
6
6
  def wrapper(*args, **kwargs): # Wrapper function
7
- type_checker = Type_Safe_Method(func) # Create type checker instance
7
+ type_checker = Type_Safe__Method(func) # Create type checker instance
8
8
  bound_args = type_checker.handle_type_safety(args, kwargs) # Validate type safety
9
9
  return func(**bound_args.arguments) # Call original function
10
10
 
@@ -1,5 +1,5 @@
1
1
  from typing import Any
2
- from osbot_utils.type_safe.Type_Safe__Validator import Type_Safe__Validator
2
+ from osbot_utils.type_safe.validators.Type_Safe__Validator import Type_Safe__Validator
3
3
 
4
4
 
5
5
  class Validator__Max(Type_Safe__Validator): # Validates that a numeric value is at most the specified maximum."""
@@ -1,5 +1,5 @@
1
1
  from typing import Any
2
- from osbot_utils.type_safe.Type_Safe__Validator import Type_Safe__Validator
2
+ from osbot_utils.type_safe.validators.Type_Safe__Validator import Type_Safe__Validator
3
3
 
4
4
  class Validator__Min(Type_Safe__Validator): # Validates that a value is at least the specified minimum. Works with any type that supports the < operator (numbers, strings, lists, etc.)
5
5
  min_value: Any
@@ -1,5 +1,5 @@
1
1
  from typing import Any
2
- from osbot_utils.type_safe.Type_Safe__Validator import Type_Safe__Validator
2
+ from osbot_utils.type_safe.validators.Type_Safe__Validator import Type_Safe__Validator
3
3
 
4
4
 
5
5
  class Validator__One_Of(Type_Safe__Validator): # Validates that a value is one of a set of allowed values."""
@@ -1,5 +1,5 @@
1
1
  from typing import Any
2
- from osbot_utils.type_safe.Type_Safe__Validator import Type_Safe__Validator
2
+ from osbot_utils.type_safe.validators.Type_Safe__Validator import Type_Safe__Validator
3
3
 
4
4
  class Validator__Regex(Type_Safe__Validator): # Validates that a string matches the specified regex pattern.
5
5
  pattern : str
@@ -25,7 +25,7 @@ if sys.version_info < (3, 8):
25
25
  else:
26
26
  return ()
27
27
  else:
28
- from typing import get_origin, get_args, List, Tuple, Dict
28
+ from typing import get_origin, get_args, List, Tuple, Dict, Type, _GenericAlias, ForwardRef
29
29
 
30
30
 
31
31
  def are_types_compatible_for_assigment(source_type, target_type):
@@ -128,6 +128,16 @@ def convert_to_value_from_obj_annotation(target, attr_name, value):
128
128
  if hasattr(obj_annotations,'get'):
129
129
  attribute_annotation = obj_annotations.get(attr_name)
130
130
  if attribute_annotation:
131
+ origin = get_origin(attribute_annotation) # Add handling for Type[T] annotations
132
+ if origin is type and isinstance(value, str):
133
+ try: # Convert string path to actual type
134
+ if len(value.rsplit('.', 1)) > 1:
135
+ module_name, class_name = value.rsplit('.', 1)
136
+ module = __import__(module_name, fromlist=[class_name])
137
+ return getattr(module, class_name)
138
+ except (ValueError, ImportError, AttributeError) as e:
139
+ raise ValueError(f"Could not convert '{value}' to type: {str(e)}")
140
+
131
141
  if attribute_annotation in TYPE_SAFE__CONVERT_VALUE__SUPPORTED_TYPES: # for now hard-coding this to just these types until we understand the side effects
132
142
  return attribute_annotation(value)
133
143
  return value
@@ -373,6 +383,8 @@ def obj_is_type_union_compatible(var_type, compatible_types):
373
383
  from typing import Union
374
384
 
375
385
  origin = get_origin(var_type)
386
+ if isinstance(var_type, _GenericAlias) and origin is type: # Add handling for Type[T]
387
+ return type in compatible_types # Allow if 'type' is in compatible types
376
388
  if origin is Union: # For Union types, including Optionals
377
389
  args = get_args(var_type) # Get the argument types
378
390
  for arg in args: # Iterate through each argument in the Union
@@ -454,8 +466,13 @@ def value_type_matches_obj_annotation_for_attr(target, attr_name, value):
454
466
  annotations = all_annotations(target)
455
467
  attr_type = annotations.get(attr_name)
456
468
  if attr_type:
457
- origin_attr_type = get_origin(attr_type) # to handle when type definition contains a generic
458
- if origin_attr_type is Annotated: # if the type is Annotated
469
+ origin_attr_type = get_origin(attr_type) # to handle when type definition contains a generic
470
+ if origin_attr_type is type: # Add handling for Type[T]
471
+ type_arg = get_args(attr_type)[0] # Get T from Type[T]
472
+ if isinstance(type_arg, (str, ForwardRef)): # Handle forward reference
473
+ type_arg = target.__class__ # If it's a forward reference, the target class should be the containing class
474
+ return isinstance(value, type) and issubclass(value, type_arg) # Check that value is a type and is subclass of type_arg
475
+ if origin_attr_type is Annotated: # if the type is Annotated
459
476
  args = get_args(attr_type)
460
477
  origin_attr_type = args[0]
461
478
 
osbot_utils/version CHANGED
@@ -1 +1 @@
1
- v2.3.0
1
+ v2.5.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: osbot_utils
3
- Version: 2.3.0
3
+ Version: 2.5.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.3.0-blue)
26
+ ![Current Release](https://img.shields.io/badge/release-v2.5.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
 
@@ -36,7 +36,7 @@ osbot_utils/helpers/CFormat.py,sha256=QviXlx3cQF7Wq6bNQmvWPHknDDMQXg5bh5dsRncrg-
36
36
  osbot_utils/helpers/CPrint.py,sha256=ztKPNmT8BGxeyPXSQKRs63PqqbgxKDz_BiZmzFMup9g,1413
37
37
  osbot_utils/helpers/Dependency_Manager.py,sha256=79YRYnVfchewq8iSMJ5dzwW2D5u8chWcIqYE-G9YrSo,1337
38
38
  osbot_utils/helpers/Dict_To_Attr.py,sha256=NdhXl5mJH7-NaBk213amzc5Nfy3tJgW-N_uYIRE4hoc,208
39
- osbot_utils/helpers/Guid.py,sha256=fqiCYHrYff3yZ_Df-WJdXHl1RQtJHb4oCmDkJpcGN_k,828
39
+ osbot_utils/helpers/Guid.py,sha256=0Ay3TYYk2nPr-JRVRCMFxbr8OvoQomv5HjT7o5B7cos,827
40
40
  osbot_utils/helpers/Hashicorp_Secrets.py,sha256=e2fWWHK6bubpAm1sw5y8X5kh2Hk5d4JyZCnUovZip5A,4232
41
41
  osbot_utils/helpers/Local_Cache.py,sha256=0JZZX3fFImcwtbBvxAQl-EbBegSNJRhRMYF6ovTH6zY,3141
42
42
  osbot_utils/helpers/Local_Caches.py,sha256=aQmi1HSM0TH6WQPedG2fbz4KCCJ3DQTU9d18rB1jR0M,1885
@@ -277,19 +277,19 @@ 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=irrNiwWQHV4eP2dq9aKYDIETsG375U9U055YPZX1uQw,29658
281
- osbot_utils/type_safe/Type_Safe_Method.py,sha256=JLB7NkeuY4x_lIWJyvG1bDApCM_VyAQqrzQXhH7Z-8A,10969
280
+ osbot_utils/type_safe/Type_Safe.py,sha256=icn7r8mS1hkeo30uJ3NVJ7kms8P6MeHbA0ldz_MMXps,30430
282
281
  osbot_utils/type_safe/Type_Safe__Base.py,sha256=mL8GMaR9tsaUfwk8d-8zp2g-A8kNKiN6kroEFaNvMOk,5518
283
282
  osbot_utils/type_safe/Type_Safe__Dict.py,sha256=I_Ac0JH-ahmQrkADFVyiobTlH1JI31MKHaNszQW4PBo,2396
284
283
  osbot_utils/type_safe/Type_Safe__List.py,sha256=SzSIBkwSOAEpW_V2qh4-f0YHzmgB0T8PczBLbDgZGvg,1340
285
- osbot_utils/type_safe/Type_Safe__Validator.py,sha256=cJIPSBarjV716SZUOLvz7Mthjk-aUYKUQtRDtKUBmN4,779
284
+ osbot_utils/type_safe/Type_Safe__Method.py,sha256=wn05pjmdnjhXVFIUaxm6YfWJZGoTzs-IhJ534JKFiV0,10970
286
285
  osbot_utils/type_safe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
287
286
  osbot_utils/type_safe/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
288
- osbot_utils/type_safe/decorators/type_safe.py,sha256=yK1td-9WHFj2pe4dvBtw1cjYOE6z6-VnG5DCStGCO1c,1003
289
- osbot_utils/type_safe/validators/Validator__Max.py,sha256=ctsMADDqq9l9mxwedrOfI9Dg53nPxCsluB0cO8C6bT4,1264
290
- osbot_utils/type_safe/validators/Validator__Min.py,sha256=FfVoErZcibqYXvnH-Nl9c2pfPSKFH-CgAhUVBYsxVrc,1970
291
- osbot_utils/type_safe/validators/Validator__One_Of.py,sha256=RvEYjf2zT06LVucZeNhzFqTZOh-Bs-C9UNjXd_YLWa8,670
292
- osbot_utils/type_safe/validators/Validator__Regex.py,sha256=BZemPOU8XWc9bxk4jqPm_adnfhbOf6GD4-gatr_L0wo,997
287
+ osbot_utils/type_safe/decorators/type_safe.py,sha256=ERFfJuAIo5qLp03YEDu2zu5wxu65OhR7hOybwuTfLlc,1006
288
+ osbot_utils/type_safe/validators/Type_Safe__Validator.py,sha256=cJIPSBarjV716SZUOLvz7Mthjk-aUYKUQtRDtKUBmN4,779
289
+ osbot_utils/type_safe/validators/Validator__Max.py,sha256=pCvYF5Jb_cBgn1ArGhf6FNUB-NGCXPq3D36oYDCyAzg,1275
290
+ osbot_utils/type_safe/validators/Validator__Min.py,sha256=_-9MdAX2Jc2U0VzCHpEQLA8OVxuNe2y8uaJ6bQttimE,1981
291
+ osbot_utils/type_safe/validators/Validator__One_Of.py,sha256=YVdZv3Fw4vpJGXRSXFmTktFgzcLlUK7bkVSBV6Fxl-4,681
292
+ osbot_utils/type_safe/validators/Validator__Regex.py,sha256=oO_NKTcrcl7wjs5-HB-ovSV9S-3XOZjsa04rdUPsOMg,1008
293
293
  osbot_utils/type_safe/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
294
294
  osbot_utils/utils/Assert.py,sha256=u9XLgYn91QvNWZGyPi29SjPJSXRHlm9andIn3NJEVog,1745
295
295
  osbot_utils/utils/Call_Stack.py,sha256=awhWstC2mJCrOjNqNheTe2B7at-JFP6XG7VkMPpPNOE,6647
@@ -305,7 +305,7 @@ osbot_utils/utils/Json.py,sha256=0t7Hwefx8bg4JiZVr-xIbWP3BAk6_ZsnY7iV5pnRLDQ,713
305
305
  osbot_utils/utils/Json_Cache.py,sha256=mLPkkDZN-3ZVJiDvV1KBJXILtKkTZ4OepzOsDoBPhWg,2006
306
306
  osbot_utils/utils/Lists.py,sha256=tPz5x5s3sRO97WZ_nsxREBPC5cwaHrhgaYBhsrffTT8,5599
307
307
  osbot_utils/utils/Misc.py,sha256=H_xexJgiTxB3jDeDiW8efGQbO0Zuy8MM0iQ7qXC92JI,17363
308
- osbot_utils/utils/Objects.py,sha256=7QS_rBiLMLiD28be_br-7NrLfR7LtxFImjUGko8MqXM,21933
308
+ osbot_utils/utils/Objects.py,sha256=KN04fgKTlPtKr1d84ESDNlYMQikunyWJ3-I2VKZ8jjw,23661
309
309
  osbot_utils/utils/Png.py,sha256=V1juGp6wkpPigMJ8HcxrPDIP4bSwu51oNkLI8YqP76Y,1172
310
310
  osbot_utils/utils/Process.py,sha256=lr3CTiEkN3EiBx3ZmzYmTKlQoPdkgZBRjPulMxG-zdo,2357
311
311
  osbot_utils/utils/Python_Logger.py,sha256=M9Oi62LxfnRSlCN8GhaiwiBINvcSdGy39FCWjyDD-Xg,12792
@@ -317,8 +317,8 @@ osbot_utils/utils/Toml.py,sha256=Rxl8gx7mni5CvBAK-Ai02EKw-GwtJdd3yeHT2kMloik,166
317
317
  osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
318
318
  osbot_utils/utils/Zip.py,sha256=pR6sKliUY0KZXmqNzKY2frfW-YVQEVbLKiyqQX_lc-8,14052
319
319
  osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
320
- osbot_utils/version,sha256=B-GHcA-4RPUOEZ4BIL3emPJuZ5J9E1aQPTmIXKecyHE,7
321
- osbot_utils-2.3.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
322
- osbot_utils-2.3.0.dist-info/METADATA,sha256=_sYtNzPStrMRoLTa5C1PaRTfEzeeOV7SeccUXx9GAFo,1315
323
- osbot_utils-2.3.0.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
324
- osbot_utils-2.3.0.dist-info/RECORD,,
320
+ osbot_utils/version,sha256=ry5x0al4PtQq-0dv-mNU4Gk_sTAHYopdKOQmdWyn-ZE,7
321
+ osbot_utils-2.5.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
322
+ osbot_utils-2.5.0.dist-info/METADATA,sha256=Ow8znW_Olql05eKUGfwxkJDw5XMf0o_wwXjdS7J2In0,1315
323
+ osbot_utils-2.5.0.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
324
+ osbot_utils-2.5.0.dist-info/RECORD,,