Merge pull request #2802 from Tegiminis/develop

Make AttributeProperty getter/setter "object aware"
This commit is contained in:
Griatch 2022-07-11 11:38:40 +02:00 committed by GitHub
commit ae21036a34
2 changed files with 50 additions and 14 deletions

View file

@ -239,23 +239,32 @@ class SubAttributeProperty(AttributeProperty):
class SubTagProperty(TagProperty): class SubTagProperty(TagProperty):
pass 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): class TestObjectPropertiesClass(DefaultObject):
attr1 = AttributeProperty(default="attr1") attr1 = AttributeProperty(default="attr1")
attr2 = AttributeProperty(default="attr2", category="attrcategory") attr2 = AttributeProperty(default="attr2", category="attrcategory")
attr3 = AttributeProperty(default="attr3", autocreate=False) attr3 = AttributeProperty(default="attr3", autocreate=False)
attr4 = SubAttributeProperty(default="attr4") attr4 = SubAttributeProperty(default="attr4")
cusattr = CustomizedProperty(default=5)
tag1 = TagProperty() tag1 = TagProperty()
tag2 = TagProperty(category="tagcategory") tag2 = TagProperty(category="tagcategory")
tag3 = SubTagProperty() tag3 = SubTagProperty()
testalias = AliasProperty() testalias = AliasProperty()
testperm = PermissionProperty() testperm = PermissionProperty()
awaretest = 5
settest = 0
@property @property
def base_property(self): def base_property(self):
self.property_initialized = True self.property_initialized = True
class TestProperties(EvenniaTestCase): class TestProperties(EvenniaTestCase):
""" """
Test Properties. Test Properties.
@ -263,7 +272,7 @@ class TestProperties(EvenniaTestCase):
""" """
def setUp(self): def setUp(self):
self.obj = create.create_object(TestObjectPropertiesClass, key="testobj") self.obj: TestObjectPropertiesClass = create.create_object(TestObjectPropertiesClass, key="testobj")
def tearDown(self): def tearDown(self):
self.obj.delete() self.obj.delete()
@ -305,3 +314,30 @@ class TestProperties(EvenniaTestCase):
# Verify that regular properties do not get fetched in init_evennia_properties, # Verify that regular properties do not get fetched in init_evennia_properties,
# only Attribute or TagProperties. # only Attribute or TagProperties.
self.assertFalse(hasattr(obj, "property_initialized")) 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)

View file

@ -218,15 +218,13 @@ class AttributeProperty:
""" """
value = self._default value = self._default
try: try:
value = self.at_get( value = self.at_get(getattr(instance, self.attrhandler_name).get(
getattr(instance, self.attrhandler_name).get( key=self._key,
key=self._key, default=self._default,
default=self._default, category=self._category,
category=self._category, strattr=self._strattr,
strattr=self._strattr, raise_exception=self._autocreate,
raise_exception=self._autocreate, ), instance)
)
)
except AttributeError: except AttributeError:
if self._autocreate: if self._autocreate:
# attribute didn't exist and autocreate is set # attribute didn't exist and autocreate is set
@ -243,7 +241,7 @@ class AttributeProperty:
( (
getattr(instance, self.attrhandler_name).add( getattr(instance, self.attrhandler_name).add(
self._key, self._key,
self.at_set(value), self.at_set(value, instance),
category=self._category, category=self._category,
lockstring=self._lockstring, lockstring=self._lockstring,
strattr=self._strattr, strattr=self._strattr,
@ -259,13 +257,14 @@ class AttributeProperty:
""" """
getattr(instance, self.attrhandler_name).remove(key=self._key, category=self._category) 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 value to set is passed through the method. It can be used to customize/validate
the input in a custom child class. the input in a custom child class.
Args: Args:
value (any): The value about to the stored in this Attribute. value (any): The value about to the stored in this Attribute.
obj (object): Object the attribute is attached to
Returns: Returns:
any: The value to store. any: The value to store.
@ -276,13 +275,14 @@ class AttributeProperty:
""" """
return value 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 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. to react to the retrieval or modify the result in some way.
Args: Args:
value (any): Value returned from the Attribute. value (any): Value returned from the Attribute.
obj (object): Object the attribute is attached to
Returns: Returns:
any: The value to return to the caller. any: The value to return to the caller.