osbot-utils 2.64.0__py3-none-any.whl → 2.65.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__Method.py +23 -12
- osbot_utils/type_safe/decorators/type_safe.py +12 -4
- osbot_utils/version +1 -1
- {osbot_utils-2.64.0.dist-info → osbot_utils-2.65.0.dist-info}/METADATA +2 -2
- {osbot_utils-2.64.0.dist-info → osbot_utils-2.65.0.dist-info}/RECORD +7 -7
- {osbot_utils-2.64.0.dist-info → osbot_utils-2.65.0.dist-info}/LICENSE +0 -0
- {osbot_utils-2.64.0.dist-info → osbot_utils-2.65.0.dist-info}/WHEEL +0 -0
@@ -10,12 +10,13 @@ class Type_Safe__Method:
|
|
10
10
|
self.func = func # Store original function
|
11
11
|
self.sig = inspect.signature(func) # Get function signature
|
12
12
|
self.annotations = func.__annotations__ # Get function annotations
|
13
|
+
self.params = list(self.sig.parameters.keys())
|
13
14
|
|
14
15
|
def check_for_any_use(self):
|
15
16
|
for param_name, type_hint in self.annotations.items():
|
16
17
|
if type_hint is any: # Detect incorrect usage of lowercase any
|
17
18
|
raise ValueError(f"Parameter '{param_name}' uses lowercase 'any' instead of 'Any' from typing module. "
|
18
|
-
|
19
|
+
f"Please use 'from typing import Any' and annotate as '{param_name}: Any'")
|
19
20
|
|
20
21
|
def handle_type_safety(self, args: tuple, kwargs: dict): # Main method to handle type safety
|
21
22
|
self.check_for_any_use()
|
@@ -80,10 +81,6 @@ class Type_Safe__Method:
|
|
80
81
|
self.validate_union_type(param_name, param_value, expected_type) # Validate union
|
81
82
|
return # Exit early
|
82
83
|
|
83
|
-
# if self.try_basic_type_conversion(param_value, expected_type, param_name, # Try basic type conversion
|
84
|
-
# bound_args): # Pass bound args
|
85
|
-
# return # Exit if conversion successful
|
86
|
-
|
87
84
|
self.validate_direct_type(param_name, param_value, expected_type) # Direct type validation
|
88
85
|
|
89
86
|
def is_optional_type(self, type_hint: Any) -> bool: # Check if type is Optional
|
@@ -108,9 +105,13 @@ class Type_Safe__Method:
|
|
108
105
|
if not isinstance(param_value, list): # Check if value is a list
|
109
106
|
raise ValueError(f"Parameter '{param_name}' expected a list but got {type(param_value)}") # Raise error if not list
|
110
107
|
|
111
|
-
item_type = get_args(expected_type)[0]
|
112
|
-
|
113
|
-
|
108
|
+
item_type = get_args(expected_type)[0] # Get list item type
|
109
|
+
if get_origin(item_type) is not None: # Handle the case when item_type is a subscripted type (which is not supported at the moment)
|
110
|
+
raise NotImplementedError(f"Validation for list items with subscripted type"
|
111
|
+
f" '{item_type}' is not yet supported "
|
112
|
+
f"in parameter '{param_name}'.") # todo: add support for checking for subscripted types
|
113
|
+
for i, item in enumerate(param_value): # Check each list item
|
114
|
+
if not isinstance(item, item_type): # Validate item type
|
114
115
|
raise ValueError(f"List item at index {i} expected type {item_type}, but got {type(item)}") # Raise error for invalid item
|
115
116
|
|
116
117
|
def validate_type_parameter(self, param_name: str, param_value: Any, expected_type: Any): # Validate a Type[T] parameter
|
@@ -163,6 +164,7 @@ class Type_Safe__Method:
|
|
163
164
|
is_optional = self.is_optional_type(expected_type) # Check if type is optional
|
164
165
|
has_default = self.has_default_value(param_name) # Check if has default value
|
165
166
|
self.validate_none_value(param_name, is_optional, has_default) # Validate None value
|
167
|
+
return True
|
166
168
|
|
167
169
|
origin = get_origin(expected_type)
|
168
170
|
|
@@ -174,11 +176,20 @@ class Type_Safe__Method:
|
|
174
176
|
if not isinstance(param_value, dict):
|
175
177
|
raise ValueError(f"Parameter '{param_name}' expected dict but got {type(param_value)}")
|
176
178
|
key_type, value_type = get_args(expected_type)
|
179
|
+
if value_type is Any: # if value type is Any, we don't need to do any checks since they will all match
|
180
|
+
return True
|
177
181
|
for k, v in param_value.items():
|
178
|
-
if
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
+
if get_origin(key_type) is None:
|
183
|
+
if not isinstance(k, key_type):
|
184
|
+
raise ValueError(f"Dict key '{k}' expected type {key_type}, but got {type(k)}")
|
185
|
+
else:
|
186
|
+
raise NotImplementedError(f"Validation for subscripted key type '{key_type}' not yet supported in parameter '{param_name}'")
|
187
|
+
|
188
|
+
if get_origin(value_type) is None:
|
189
|
+
if not isinstance(v, value_type):
|
190
|
+
raise ValueError(f"Dict value for key '{k}' expected type {value_type}, but got {type(v)}")
|
191
|
+
elif value_type is not Any:
|
192
|
+
raise NotImplementedError(f"Validation for subscripted value type '{value_type}' not yet supported in parameter '{param_name}'")
|
182
193
|
return True
|
183
194
|
base_type = origin
|
184
195
|
else:
|
@@ -1,12 +1,20 @@
|
|
1
1
|
import functools # For wrapping functions
|
2
2
|
from osbot_utils.type_safe.Type_Safe__Method import Type_Safe__Method
|
3
3
|
|
4
|
-
def type_safe(func):
|
4
|
+
def type_safe(func): # Main decorator function
|
5
|
+
type_checker = Type_Safe__Method(func) # Create type checker instance
|
6
|
+
|
7
|
+
has_only_self = len(type_checker.params) == 1 and type_checker.params[0] == 'self' # Check if method has only 'self' parameter or no parameters
|
8
|
+
has_no_params = len(type_checker.params) == 0
|
9
|
+
direct_execution = has_no_params or has_only_self # these are major performance optimisation where this @type_safe had an overhead of 250x (even on methods with no params) to now having an over head of ~5x
|
10
|
+
|
5
11
|
@functools.wraps(func) # Preserve function metadata
|
6
12
|
def wrapper(*args, **kwargs): # Wrapper function
|
7
|
-
|
8
|
-
|
9
|
-
|
13
|
+
if direct_execution:
|
14
|
+
return func(*args, **kwargs)
|
15
|
+
else:
|
16
|
+
bound_args = type_checker.handle_type_safety(args, kwargs) # Validate type safety
|
17
|
+
return func(**bound_args.arguments) # Call original function
|
10
18
|
|
11
19
|
return wrapper # Return wrapped function
|
12
20
|
|
osbot_utils/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
v2.
|
1
|
+
v2.65.0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: osbot_utils
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.65.0
|
4
4
|
Summary: OWASP Security Bot - Utils
|
5
5
|
License: MIT
|
6
6
|
Author: Dinis Cruz
|
@@ -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
|
|
@@ -374,13 +374,13 @@ osbot_utils/type_safe/Type_Safe.py,sha256=LOWRGOGpnRU2iTRLP47vUoyalK0vjFrWlnaghB
|
|
374
374
|
osbot_utils/type_safe/Type_Safe__Base.py,sha256=UTMipTL6mXoetAEUCI5hs8RqXp4NDYOvoAiYoFOt5jg,8807
|
375
375
|
osbot_utils/type_safe/Type_Safe__Dict.py,sha256=QB200L5eNWT3FnUv8sm5kncj1wXJsJ9uRycNFl9xb6Y,3077
|
376
376
|
osbot_utils/type_safe/Type_Safe__List.py,sha256=y_lp7Ai0HfQCqC8Bxn0g6_M9MP5lPOXy5Dhkuj2fJvQ,1891
|
377
|
-
osbot_utils/type_safe/Type_Safe__Method.py,sha256=
|
377
|
+
osbot_utils/type_safe/Type_Safe__Method.py,sha256=cvFYoR42SPU4qQPG45CCHQw7i-sq7R6gHECcsncGGL4,16653
|
378
378
|
osbot_utils/type_safe/Type_Safe__Primitive.py,sha256=CJ4LP2W5i9utSSzuiiJrwqvwdMv1DeQ6dIZICtYfLTY,3635
|
379
379
|
osbot_utils/type_safe/Type_Safe__Set.py,sha256=j12fc8cbd9-s_a13ysaz723rNEW4Dt6hObCd0S-AjIg,1432
|
380
380
|
osbot_utils/type_safe/Type_Safe__Tuple.py,sha256=Kx7C4YfHybRbMmVMcmV6yFLi4T48pb592vEZfjjyLxo,1710
|
381
381
|
osbot_utils/type_safe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
382
382
|
osbot_utils/type_safe/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
383
|
-
osbot_utils/type_safe/decorators/type_safe.py,sha256=
|
383
|
+
osbot_utils/type_safe/decorators/type_safe.py,sha256=pghmcxZp-L3E3yQMSPOyC-inVO1KU1aql_naEqWLt-8,1507
|
384
384
|
osbot_utils/type_safe/methods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
385
385
|
osbot_utils/type_safe/methods/type_safe_property.py,sha256=DcJkOIs6swJtkglsZVKLyFSczCGSJISOVwAmvjCOQvo,1425
|
386
386
|
osbot_utils/type_safe/shared/Type_Safe__Annotations.py,sha256=nmVqCbhk4kUYrw_mdYqugxQlv4gM3NUUH89FYTHUg-c,1133
|
@@ -432,8 +432,8 @@ osbot_utils/utils/Toml.py,sha256=Rxl8gx7mni5CvBAK-Ai02EKw-GwtJdd3yeHT2kMloik,166
|
|
432
432
|
osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
|
433
433
|
osbot_utils/utils/Zip.py,sha256=pR6sKliUY0KZXmqNzKY2frfW-YVQEVbLKiyqQX_lc-8,14052
|
434
434
|
osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
435
|
-
osbot_utils/version,sha256=
|
436
|
-
osbot_utils-2.
|
437
|
-
osbot_utils-2.
|
438
|
-
osbot_utils-2.
|
439
|
-
osbot_utils-2.
|
435
|
+
osbot_utils/version,sha256=oCkmaExem5YihngZUO4qUVW6DPLlhdxUDeJF0raydEg,8
|
436
|
+
osbot_utils-2.65.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
437
|
+
osbot_utils-2.65.0.dist-info/METADATA,sha256=kWWFHflY8D1c-M9vqnraZaziAIrgTpG9r8teABngWrY,1329
|
438
|
+
osbot_utils-2.65.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
439
|
+
osbot_utils-2.65.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|