osbot-utils 2.2.0__py3-none-any.whl → 2.4.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/helpers/Guid.py +0 -1
- osbot_utils/type_safe/Type_Safe.py +10 -2
- osbot_utils/type_safe/Type_Safe_Method.py +12 -4
- osbot_utils/type_safe/decorators/__init__.py +0 -0
- osbot_utils/utils/Objects.py +18 -3
- osbot_utils/version +1 -1
- {osbot_utils-2.2.0.dist-info → osbot_utils-2.4.0.dist-info}/METADATA +2 -2
- {osbot_utils-2.2.0.dist-info → osbot_utils-2.4.0.dist-info}/RECORD +11 -10
- /osbot_utils/{decorators/methods → type_safe/decorators}/type_safe.py +0 -0
- {osbot_utils-2.2.0.dist-info → osbot_utils-2.4.0.dist-info}/LICENSE +0 -0
- {osbot_utils-2.2.0.dist-info → osbot_utils-2.4.0.dist-info}/WHEEL +0 -0
osbot_utils/helpers/Guid.py
CHANGED
@@ -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
|
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
|
@@ -1,15 +1,22 @@
|
|
1
1
|
import inspect # For function introspection
|
2
2
|
from enum import Enum
|
3
|
-
from typing import get_args, get_origin,
|
3
|
+
from typing import get_args, get_origin, Union, List, Any # For type hinting utilities
|
4
4
|
|
5
5
|
|
6
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
|
10
|
-
self.annotations = func.__annotations__ # Get
|
10
|
+
self.annotations = func.__annotations__ # Get function annotations
|
11
|
+
|
12
|
+
def check_for_any_use(self):
|
13
|
+
for param_name, type_hint in self.annotations.items():
|
14
|
+
if type_hint is any: # Detect incorrect usage of lowercase any
|
15
|
+
raise ValueError(f"Parameter '{param_name}' uses lowercase 'any' instead of 'Any' from typing module. "
|
16
|
+
f"Please use 'from typing import Any' and annotate as '{param_name}: Any'")
|
11
17
|
|
12
18
|
def handle_type_safety(self, args: tuple, kwargs: dict): # Main method to handle type safety
|
19
|
+
self.check_for_any_use()
|
13
20
|
bound_args = self.bind_args(args, kwargs) # Bind arguments to parameters
|
14
21
|
for param_name, param_value in bound_args.arguments.items(): # Iterate through arguments
|
15
22
|
if param_name != 'self': # Skip self parameter
|
@@ -107,5 +114,6 @@ class Type_Safe_Method:
|
|
107
114
|
|
108
115
|
def validate_direct_type(self, param_name: str, # Validate direct type match
|
109
116
|
param_value: Any, expected_type: Any): # Type parameters
|
110
|
-
if
|
111
|
-
|
117
|
+
if expected_type is not Any:
|
118
|
+
if not isinstance(param_value, expected_type): # Check type match
|
119
|
+
raise ValueError(f"Parameter '{param_name}' expected type {expected_type}, but got {type(param_value)}") # Raise error if no match
|
File without changes
|
osbot_utils/utils/Objects.py
CHANGED
@@ -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
|
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,11 @@ 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)
|
458
|
-
if origin_attr_type is
|
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
|
+
return isinstance(value, type) and issubclass(value, type_arg) # Check that value is a type and is subclass of type_arg
|
473
|
+
if origin_attr_type is Annotated: # if the type is Annotated
|
459
474
|
args = get_args(attr_type)
|
460
475
|
origin_attr_type = args[0]
|
461
476
|
|
osbot_utils/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
v2.
|
1
|
+
v2.4.0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: osbot_utils
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.4.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
|
|
@@ -29,7 +29,6 @@ osbot_utils/decorators/methods/function_type_check.py,sha256=o8Je6k-tXd3UmbgVL0g
|
|
29
29
|
osbot_utils/decorators/methods/obj_as_context.py,sha256=59JgxUvEruh_4ROoWHXK22Jv8C4_E5mSxb4aG3JbL50,104
|
30
30
|
osbot_utils/decorators/methods/remove_return_value.py,sha256=EerRwBFDJ3ICKA0BrNzelRECb3n2NUMoFzcn0rQyCUY,1162
|
31
31
|
osbot_utils/decorators/methods/required_fields.py,sha256=PZd9LKd4qBeqxgP9FgTtLNNJ0coZx99hFJyNEKmF1K0,783
|
32
|
-
osbot_utils/decorators/methods/type_safe.py,sha256=yK1td-9WHFj2pe4dvBtw1cjYOE6z6-VnG5DCStGCO1c,1003
|
33
32
|
osbot_utils/fluent/Fluent_Dict.py,sha256=nZ2z91s39sU2a-TLYpBirRoWgDXHrs0tQ9Bi_ZdKeW0,481
|
34
33
|
osbot_utils/fluent/Fluent_List.py,sha256=PfDDC9sm16CFnNQ8gkhCEsmKcZp8iyQ0YBpSHvYssG8,1089
|
35
34
|
osbot_utils/fluent/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
@@ -37,7 +36,7 @@ osbot_utils/helpers/CFormat.py,sha256=QviXlx3cQF7Wq6bNQmvWPHknDDMQXg5bh5dsRncrg-
|
|
37
36
|
osbot_utils/helpers/CPrint.py,sha256=ztKPNmT8BGxeyPXSQKRs63PqqbgxKDz_BiZmzFMup9g,1413
|
38
37
|
osbot_utils/helpers/Dependency_Manager.py,sha256=79YRYnVfchewq8iSMJ5dzwW2D5u8chWcIqYE-G9YrSo,1337
|
39
38
|
osbot_utils/helpers/Dict_To_Attr.py,sha256=NdhXl5mJH7-NaBk213amzc5Nfy3tJgW-N_uYIRE4hoc,208
|
40
|
-
osbot_utils/helpers/Guid.py,sha256=
|
39
|
+
osbot_utils/helpers/Guid.py,sha256=0Ay3TYYk2nPr-JRVRCMFxbr8OvoQomv5HjT7o5B7cos,827
|
41
40
|
osbot_utils/helpers/Hashicorp_Secrets.py,sha256=e2fWWHK6bubpAm1sw5y8X5kh2Hk5d4JyZCnUovZip5A,4232
|
42
41
|
osbot_utils/helpers/Local_Cache.py,sha256=0JZZX3fFImcwtbBvxAQl-EbBegSNJRhRMYF6ovTH6zY,3141
|
43
42
|
osbot_utils/helpers/Local_Caches.py,sha256=aQmi1HSM0TH6WQPedG2fbz4KCCJ3DQTU9d18rB1jR0M,1885
|
@@ -278,13 +277,15 @@ osbot_utils/testing/Temp_Zip_In_Memory.py,sha256=ibDIWt3K4CX558PbkLbX3InHyWYZcwQ
|
|
278
277
|
osbot_utils/testing/Unit_Test.py,sha256=MReR_wDGbbXFDPz7cmuGflcTxRB6TBnO9mYqRpSq8Pk,1304
|
279
278
|
osbot_utils/testing/Unzip_File.py,sha256=V5H97XO9rlvG5EYOSzAH4kTtAH1ohZ8R8ImvJh46ZNg,1177
|
280
279
|
osbot_utils/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
281
|
-
osbot_utils/type_safe/Type_Safe.py,sha256=
|
282
|
-
osbot_utils/type_safe/Type_Safe_Method.py,sha256=
|
280
|
+
osbot_utils/type_safe/Type_Safe.py,sha256=asybUt2JqDP34b7s6clCcurJpaJg_4oOI4Qt10PQ2bM,30419
|
281
|
+
osbot_utils/type_safe/Type_Safe_Method.py,sha256=JLB7NkeuY4x_lIWJyvG1bDApCM_VyAQqrzQXhH7Z-8A,10969
|
283
282
|
osbot_utils/type_safe/Type_Safe__Base.py,sha256=mL8GMaR9tsaUfwk8d-8zp2g-A8kNKiN6kroEFaNvMOk,5518
|
284
283
|
osbot_utils/type_safe/Type_Safe__Dict.py,sha256=I_Ac0JH-ahmQrkADFVyiobTlH1JI31MKHaNszQW4PBo,2396
|
285
284
|
osbot_utils/type_safe/Type_Safe__List.py,sha256=SzSIBkwSOAEpW_V2qh4-f0YHzmgB0T8PczBLbDgZGvg,1340
|
286
285
|
osbot_utils/type_safe/Type_Safe__Validator.py,sha256=cJIPSBarjV716SZUOLvz7Mthjk-aUYKUQtRDtKUBmN4,779
|
287
286
|
osbot_utils/type_safe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
287
|
+
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
|
288
289
|
osbot_utils/type_safe/validators/Validator__Max.py,sha256=ctsMADDqq9l9mxwedrOfI9Dg53nPxCsluB0cO8C6bT4,1264
|
289
290
|
osbot_utils/type_safe/validators/Validator__Min.py,sha256=FfVoErZcibqYXvnH-Nl9c2pfPSKFH-CgAhUVBYsxVrc,1970
|
290
291
|
osbot_utils/type_safe/validators/Validator__One_Of.py,sha256=RvEYjf2zT06LVucZeNhzFqTZOh-Bs-C9UNjXd_YLWa8,670
|
@@ -304,7 +305,7 @@ osbot_utils/utils/Json.py,sha256=0t7Hwefx8bg4JiZVr-xIbWP3BAk6_ZsnY7iV5pnRLDQ,713
|
|
304
305
|
osbot_utils/utils/Json_Cache.py,sha256=mLPkkDZN-3ZVJiDvV1KBJXILtKkTZ4OepzOsDoBPhWg,2006
|
305
306
|
osbot_utils/utils/Lists.py,sha256=tPz5x5s3sRO97WZ_nsxREBPC5cwaHrhgaYBhsrffTT8,5599
|
306
307
|
osbot_utils/utils/Misc.py,sha256=H_xexJgiTxB3jDeDiW8efGQbO0Zuy8MM0iQ7qXC92JI,17363
|
307
|
-
osbot_utils/utils/Objects.py,sha256=
|
308
|
+
osbot_utils/utils/Objects.py,sha256=F3H0ux-IjfyMIA1ou-xc0Ra1Z7oON3fuYRH_qaGsQ4Y,23375
|
308
309
|
osbot_utils/utils/Png.py,sha256=V1juGp6wkpPigMJ8HcxrPDIP4bSwu51oNkLI8YqP76Y,1172
|
309
310
|
osbot_utils/utils/Process.py,sha256=lr3CTiEkN3EiBx3ZmzYmTKlQoPdkgZBRjPulMxG-zdo,2357
|
310
311
|
osbot_utils/utils/Python_Logger.py,sha256=M9Oi62LxfnRSlCN8GhaiwiBINvcSdGy39FCWjyDD-Xg,12792
|
@@ -316,8 +317,8 @@ osbot_utils/utils/Toml.py,sha256=Rxl8gx7mni5CvBAK-Ai02EKw-GwtJdd3yeHT2kMloik,166
|
|
316
317
|
osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
|
317
318
|
osbot_utils/utils/Zip.py,sha256=pR6sKliUY0KZXmqNzKY2frfW-YVQEVbLKiyqQX_lc-8,14052
|
318
319
|
osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
319
|
-
osbot_utils/version,sha256=
|
320
|
-
osbot_utils-2.
|
321
|
-
osbot_utils-2.
|
322
|
-
osbot_utils-2.
|
323
|
-
osbot_utils-2.
|
320
|
+
osbot_utils/version,sha256=p1zoKgZOpZRdZ0kkLKwgWGFUdRL6IoXVo1tPBL0f9tY,7
|
321
|
+
osbot_utils-2.4.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
322
|
+
osbot_utils-2.4.0.dist-info/METADATA,sha256=M41QEpJLyE3h5hjXubqfqshQ7-wn0ioHXjgt7AKFuOU,1315
|
323
|
+
osbot_utils-2.4.0.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
324
|
+
osbot_utils-2.4.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|