From 14c35fdbe026b8ea484bbe53ed08df3d81da97ec Mon Sep 17 00:00:00 2001 From: Tegiminis Date: Sun, 10 Jul 2022 02:32:05 -0700 Subject: [PATCH 1/6] makes attributeproperty "object-aware" --- evennia/typeclasses/attributes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index 7c5a537c19..1165c59ebf 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -224,7 +224,7 @@ class AttributeProperty: category=self._category, strattr=self._strattr, raise_exception=self._autocreate, - )) + ), instance) except AttributeError: if self._autocreate: # attribute didn't exist and autocreate is set @@ -274,7 +274,7 @@ class AttributeProperty: """ return value - def at_get(self, value): + def at_get(self, value, obj): """ The value returned from the Attribute is passed through this method. It can be used to react to the retrieval or modify the result in some way. From 1075e5652ca56ae28cd15810763bad9266ea5aeb Mon Sep 17 00:00:00 2001 From: Tegiminis Date: Sun, 10 Jul 2022 03:20:16 -0700 Subject: [PATCH 2/6] makes attributeproperties object-aware, part 2 --- evennia/typeclasses/attributes.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index 9917b351b8..2e801b5bce 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -218,7 +218,6 @@ class AttributeProperty: """ value = self._default try: -<<<<<<< HEAD value = self.at_get(getattr(instance, self.attrhandler_name).get( key=self._key, default=self._default, @@ -226,17 +225,6 @@ class AttributeProperty: strattr=self._strattr, raise_exception=self._autocreate, ), instance) -======= - value = self.at_get( - getattr(instance, self.attrhandler_name).get( - key=self._key, - default=self._default, - category=self._category, - strattr=self._strattr, - raise_exception=self._autocreate, - ) - ) ->>>>>>> ce3992f999a164881462d8f878d71a47a8f946cc except AttributeError: if self._autocreate: # attribute didn't exist and autocreate is set @@ -253,7 +241,7 @@ class AttributeProperty: ( getattr(instance, self.attrhandler_name).add( self._key, - self.at_set(value), + self.at_set(value, instance), category=self._category, lockstring=self._lockstring, strattr=self._strattr, @@ -269,7 +257,7 @@ class AttributeProperty: """ getattr(instance, self.attrhandler_name).remove(key=self._key, category=self._category) - def at_set(self, value): + def at_set(self, value, obj): """ The value to set is passed through the method. It can be used to customize/validate the input in a custom child class. From 95d7cde7efd7bfa1a221d81a73af2f17edb41eb3 Mon Sep 17 00:00:00 2001 From: Tegiminis Date: Sun, 10 Jul 2022 03:25:56 -0700 Subject: [PATCH 3/6] docstring fix --- evennia/typeclasses/attributes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index 2e801b5bce..b8c68bb7ac 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -264,6 +264,7 @@ class AttributeProperty: Args: value (any): The value about to the stored in this Attribute. + obj (object): Object the attribute is attached to Returns: any: The value to store. @@ -281,6 +282,7 @@ class AttributeProperty: Args: value (any): Value returned from the Attribute. + obj (object): Object the attribute is attached to Returns: any: The value to return to the caller. From dfcc5fb5c0fa9d57aaedb20b6f56de6b4f36de67 Mon Sep 17 00:00:00 2001 From: Tegiminis Date: Sun, 10 Jul 2022 03:48:54 -0700 Subject: [PATCH 4/6] remove unused argument --- evennia/typeclasses/attributes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index b8c68bb7ac..f714753b99 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -211,7 +211,7 @@ class AttributeProperty: """ self._key = name - def __get__(self, instance, owner): + def __get__(self, instance): """ Called when the attrkey is retrieved from the instance. From e27751a9269497e535abae37b3373cdb9ddb0842 Mon Sep 17 00:00:00 2001 From: Tegiminis Date: Sun, 10 Jul 2022 03:55:52 -0700 Subject: [PATCH 5/6] Revert "remove unused argument" This reverts commit dfcc5fb5c0fa9d57aaedb20b6f56de6b4f36de67. --- evennia/typeclasses/attributes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index f714753b99..b8c68bb7ac 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -211,7 +211,7 @@ class AttributeProperty: """ self._key = name - def __get__(self, instance): + def __get__(self, instance, owner): """ Called when the attrkey is retrieved from the instance. From 8377871e9f36a14ade35081a5b9afe7d01fc9f04 Mon Sep 17 00:00:00 2001 From: Tegiminis Date: Mon, 11 Jul 2022 02:16:25 -0700 Subject: [PATCH 6/6] unit tests for customized attributeproperty getter/setter --- evennia/objects/tests.py | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/evennia/objects/tests.py b/evennia/objects/tests.py index a718d9b01b..b447eed09f 100644 --- a/evennia/objects/tests.py +++ b/evennia/objects/tests.py @@ -239,23 +239,32 @@ class SubAttributeProperty(AttributeProperty): class SubTagProperty(TagProperty): pass +class CustomizedProperty(AttributeProperty): + def at_set(self, value, obj): + obj.settest = value + return value + + def at_get(self, value, obj): + return value + obj.awaretest class TestObjectPropertiesClass(DefaultObject): attr1 = AttributeProperty(default="attr1") attr2 = AttributeProperty(default="attr2", category="attrcategory") attr3 = AttributeProperty(default="attr3", autocreate=False) attr4 = SubAttributeProperty(default="attr4") + cusattr = CustomizedProperty(default=5) tag1 = TagProperty() tag2 = TagProperty(category="tagcategory") tag3 = SubTagProperty() testalias = AliasProperty() testperm = PermissionProperty() + awaretest = 5 + settest = 0 @property def base_property(self): self.property_initialized = True - class TestProperties(EvenniaTestCase): """ Test Properties. @@ -263,7 +272,7 @@ class TestProperties(EvenniaTestCase): """ def setUp(self): - self.obj = create.create_object(TestObjectPropertiesClass, key="testobj") + self.obj: TestObjectPropertiesClass = create.create_object(TestObjectPropertiesClass, key="testobj") def tearDown(self): self.obj.delete() @@ -305,3 +314,30 @@ class TestProperties(EvenniaTestCase): # Verify that regular properties do not get fetched in init_evennia_properties, # only Attribute or TagProperties. self.assertFalse(hasattr(obj, "property_initialized")) + + def test_object_awareness(self): + '''Test the "object-awareness" of customized AttributeProperty getter/setters''' + obj = self.obj + + # attribute properties receive on obj ref in the getter/setter that can customize return + self.assertEqual(obj.cusattr, 10) + self.assertEqual(obj.settest, 5) + obj.awaretest = 10 + self.assertEqual(obj.cusattr, 15) + obj.cusattr = 10 + self.assertEqual(obj.cusattr, 20) + self.assertEqual(obj.settest, 10) + + # attribute value mutates if you do += or similar (combined get-set) + obj.cusattr += 10 + self.assertEqual(obj.attributes.get("cusattr"), 30) + self.assertEqual(obj.settest, 30) + self.assertEqual(obj.cusattr, 40) + obj.awaretest = 0 + obj.cusattr += 20 + self.assertEqual(obj.attributes.get("cusattr"), 50) + self.assertEqual(obj.settest, 50) + self.assertEqual(obj.cusattr, 50) + del obj.cusattr + self.assertEqual(obj.cusattr, 5) + self.assertEqual(obj.settest, 5)