From 9b1e2752892e67117456de74251c6188c7744246 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sun, 12 Jan 2025 00:13:28 +0000 Subject: [PATCH 1/5] Update release badge and version file --- README.md | 2 +- osbot_utils/version | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 81946302..f0299ade 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Powerful Python util methods and classes that simplify common apis and tasks. -![Current Release](https://img.shields.io/badge/release-v2.10.0-blue) +![Current Release](https://img.shields.io/badge/release-v2.10.1-blue) [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils) diff --git a/osbot_utils/version b/osbot_utils/version index 80de12c5..c0151c8a 100644 --- a/osbot_utils/version +++ b/osbot_utils/version @@ -1 +1 @@ -v2.10.0 +v2.10.1 diff --git a/pyproject.toml b/pyproject.toml index 8456ad80..b6553c2b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "osbot_utils" -version = "v2.10.0" +version = "v2.10.1" description = "OWASP Security Bot - Utils" authors = ["Dinis Cruz "] license = "MIT" From 7d13fc22a7ee41adc46b6d968d620f4cd6ee9800 Mon Sep 17 00:00:00 2001 From: Dinis Cruz Date: Sun, 12 Jan 2025 01:20:47 +0000 Subject: [PATCH 2/5] removed Type_Safe 'auto feature' of trying to find get_ and set_ methods (this is better done outside of this class) --- osbot_utils/type_safe/Type_Safe.py | 34 ++++----- tests/unit/type_safe/test_Type_Safe.py | 99 +++++++++++++------------- 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/osbot_utils/type_safe/Type_Safe.py b/osbot_utils/type_safe/Type_Safe.py index c29209e3..203a3fa5 100644 --- a/osbot_utils/type_safe/Type_Safe.py +++ b/osbot_utils/type_safe/Type_Safe.py @@ -65,23 +65,23 @@ def __init__(self, **kwargs): def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): pass - def __getattr__(self, name): # Called when an attribute is not found through normal attribute access - if name.startswith(("set_", "get_")): # Check if the requested attribute is a getter or setter method - prefix = name[:4] # Extract "set_" or "get_" from the method name - attr_name = name[4:] # Get the actual attribute name by removing the prefix - - if hasattr(self, attr_name): # Verify that the target attribute actually exists on the object - if prefix == "set_": # Handle setter method creation - def setter(value): # Create a dynamic setter function that takes a value parameter - setattr(self, attr_name, value) # Set the attribute value using type-safe setattr from Type_Safe - return self # Return self for method chaining - return setter # Return the setter function - else: # get_ # Handle getter method creation - def getter(): # Create a dynamic getter function with no parameters - return getattr(self, attr_name) # Return the attribute value using Python's built-in getattr - return getter # Return the getter function - - raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") # Raise error if attribute is not a valid getter/setter + # def __getattr__(self, name): # Called when an attribute is not found through normal attribute access + # if name.startswith(("set_", "get_")): # Check if the requested attribute is a getter or setter method + # prefix = name[:4] # Extract "set_" or "get_" from the method name + # attr_name = name[4:] # Get the actual attribute name by removing the prefix + # + # if hasattr(self, attr_name): # Verify that the target attribute actually exists on the object + # if prefix == "set_": # Handle setter method creation + # def setter(value): # Create a dynamic setter function that takes a value parameter + # setattr(self, attr_name, value) # Set the attribute value using type-safe setattr from Type_Safe + # return self # Return self for method chaining + # return setter # Return the setter function + # else: # get_ # Handle getter method creation + # def getter(): # Create a dynamic getter function with no parameters + # return getattr(self, attr_name) # Return the attribute value using Python's built-in getattr + # return getter # Return the getter function + # + # raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") # Raise error if attribute is not a valid getter/setter def __setattr__(self, name, value): from osbot_utils.utils.Objects import convert_dict_to_value_from_obj_annotation diff --git a/tests/unit/type_safe/test_Type_Safe.py b/tests/unit/type_safe/test_Type_Safe.py index e7e25e12..bec4711c 100644 --- a/tests/unit/type_safe/test_Type_Safe.py +++ b/tests/unit/type_safe/test_Type_Safe.py @@ -616,55 +616,56 @@ class Target_Class(Base_Class): merged_class.an_int= 456 # confirm that change in merged_class assert base_class.an_int == 456 # impacts base_class - def test___supports_automatic_getters_and_setters_for_attributes(self): - class An_Class(Type_Safe): - an_str : str - an_int : int - an_list : list - _private : str # Test private attribute behavior - - an_class = An_Class() - - # Test basic getter/setter functionality - assert an_class.set_an_str('abc') == an_class - assert an_class.get_an_str() == 'abc' - assert an_class.json() == {'an_int': 0, 'an_list': [], 'an_str': 'abc', '_private': ''} - - # Test method chaining - assert an_class.set_an_int(123).set_an_str('def').get_an_str() == 'def' - assert an_class.get_an_int() == 123 - - # Test list attribute - test_list = [1, 2, 3] - assert an_class.set_an_list(test_list) == an_class - assert an_class.get_an_list() == test_list - - # Test None assignments - with pytest.raises(ValueError, match="Can't set None, to a variable that is already set. Invalid type for attribute 'an_str'. Expected '' but got ''"): - assert an_class.set_an_str(None) == an_class - assert an_class.get_an_str() == 'def' # confirm value has not been changed - - # Test private attribute access - assert an_class.set__private("secret") == an_class - assert an_class.get__private() == "secret" - - # Test error cases - with pytest.raises(AttributeError, match="'An_Class' object has no attribute 'set_an_aaa'"): - an_class.set_an_aaa() - with pytest.raises(AttributeError, match="'An_Class' object has no attribute 'get_an_aaa'"): - an_class.get_an_aaa() - with pytest.raises(AttributeError, match="'An_Class' object has no attribute 'aaaaaaaaaa'"): - an_class.aaaaaaaaaa() - with pytest.raises(ValueError, match="Invalid type for attribute 'an_str'. Expected '' but got '"): - an_class.set_an_str(123) - with pytest.raises(ValueError, match="Invalid type for attribute 'an_int'. Expected '' but got '"): - an_class.set_an_int('abc') - - # Test edge cases - with pytest.raises(AttributeError): - an_class.get_() # Empty attribute name - with pytest.raises(AttributeError): - an_class.set_() # Empty attribute name + # not supported anymore (it was a good idea, but this is better done with set_as_property) + # def test___supports_automatic_getters_and_setters_for_attributes(self): + # class An_Class(Type_Safe): + # an_str : str + # an_int : int + # an_list : list + # _private : str # Test private attribute behavior + # + # an_class = An_Class() + # + # # Test basic getter/setter functionality + # assert an_class.set_an_str('abc') == an_class + # assert an_class.get_an_str() == 'abc' + # assert an_class.json() == {'an_int': 0, 'an_list': [], 'an_str': 'abc', '_private': ''} + # + # # Test method chaining + # assert an_class.set_an_int(123).set_an_str('def').get_an_str() == 'def' + # assert an_class.get_an_int() == 123 + # + # # Test list attribute + # test_list = [1, 2, 3] + # assert an_class.set_an_list(test_list) == an_class + # assert an_class.get_an_list() == test_list + # + # # Test None assignments + # with pytest.raises(ValueError, match="Can't set None, to a variable that is already set. Invalid type for attribute 'an_str'. Expected '' but got ''"): + # assert an_class.set_an_str(None) == an_class + # assert an_class.get_an_str() == 'def' # confirm value has not been changed + # + # # Test private attribute access + # assert an_class.set__private("secret") == an_class + # assert an_class.get__private() == "secret" + # + # # Test error cases + # with pytest.raises(AttributeError, match="'An_Class' object has no attribute 'set_an_aaa'"): + # an_class.set_an_aaa() + # with pytest.raises(AttributeError, match="'An_Class' object has no attribute 'get_an_aaa'"): + # an_class.get_an_aaa() + # with pytest.raises(AttributeError, match="'An_Class' object has no attribute 'aaaaaaaaaa'"): + # an_class.aaaaaaaaaa() + # with pytest.raises(ValueError, match="Invalid type for attribute 'an_str'. Expected '' but got '"): + # an_class.set_an_str(123) + # with pytest.raises(ValueError, match="Invalid type for attribute 'an_int'. Expected '' but got '"): + # an_class.set_an_int('abc') + # + # # Test edge cases + # with pytest.raises(AttributeError): + # an_class.get_() # Empty attribute name + # with pytest.raises(AttributeError): + # an_class.set_() # Empty attribute name def test__type_assignments_and_validation(self): # Test simple type assignment with 'type' annotation class Simple_Type(Type_Safe): From 031f7995bb0100f58aa0a8236ba5e250cd9ac25b Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sun, 12 Jan 2025 01:21:41 +0000 Subject: [PATCH 3/5] Update release badge and version file --- README.md | 2 +- osbot_utils/version | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f0299ade..5bac2370 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Powerful Python util methods and classes that simplify common apis and tasks. -![Current Release](https://img.shields.io/badge/release-v2.10.1-blue) +![Current Release](https://img.shields.io/badge/release-v2.10.2-blue) [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils) diff --git a/osbot_utils/version b/osbot_utils/version index c0151c8a..1e8349cd 100644 --- a/osbot_utils/version +++ b/osbot_utils/version @@ -1 +1 @@ -v2.10.1 +v2.10.2 diff --git a/pyproject.toml b/pyproject.toml index b6553c2b..a6c3d3fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "osbot_utils" -version = "v2.10.1" +version = "v2.10.2" description = "OWASP Security Bot - Utils" authors = ["Dinis Cruz "] license = "MIT" From 90069f9acdc090728fbb7c0fe4760b985fd63819 Mon Sep 17 00:00:00 2001 From: Dinis Cruz Date: Sun, 12 Jan 2025 02:47:50 +0000 Subject: [PATCH 4/5] minor fix --- osbot_utils/type_safe/methods/type_safe_property.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osbot_utils/type_safe/methods/type_safe_property.py b/osbot_utils/type_safe/methods/type_safe_property.py index 44a3a117..7a4a8809 100644 --- a/osbot_utils/type_safe/methods/type_safe_property.py +++ b/osbot_utils/type_safe/methods/type_safe_property.py @@ -2,7 +2,7 @@ T = TypeVar('T') -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 +def type_safe_property(target_path: str, target_name: str, expected_type: Optional[Type[T]] = None) -> T: # Creates a type-safe property that delegates get/set operations to a nested data object def getter(self) -> T: target = self From d9a987ce1d4d45c3455601c4f5c82de6858596c1 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sun, 12 Jan 2025 02:48:41 +0000 Subject: [PATCH 5/5] Update release badge and version file --- README.md | 2 +- osbot_utils/version | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5bac2370..74ae7b15 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Powerful Python util methods and classes that simplify common apis and tasks. -![Current Release](https://img.shields.io/badge/release-v2.10.2-blue) +![Current Release](https://img.shields.io/badge/release-v2.10.3-blue) [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils) diff --git a/osbot_utils/version b/osbot_utils/version index 1e8349cd..28793914 100644 --- a/osbot_utils/version +++ b/osbot_utils/version @@ -1 +1 @@ -v2.10.2 +v2.10.3 diff --git a/pyproject.toml b/pyproject.toml index a6c3d3fd..111f47f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "osbot_utils" -version = "v2.10.2" +version = "v2.10.3" description = "OWASP Security Bot - Utils" authors = ["Dinis Cruz "] license = "MIT"