Add Traits.traithandler back reference so custom Traits can find and read values of other traits on the handler. See #2801

This commit is contained in:
Griatch 2024-07-13 19:36:15 +02:00
parent d769a90b62
commit 7a7479955f
3 changed files with 30 additions and 15 deletions

View file

@ -6,6 +6,8 @@
bugs etc in-game (InspectorCaracal)
- [Feat][pull3586]: Add ANSI color support `|U`, `|I`, `|i`, `|s`, `|S` for
underline reset, italic/reset and strikethrough/reset (0xDEADFED5)
- Feat: Add `Trait.traithandler` back-reference so custom Traits from the Traits
contrib can find and reference other Traits. (Griatch)
- [Fix][pull3571]: Better visual display of partial multimatch search results
(InspectorCaracal)
- [Fix][pull3550]: Issue where rpsystem contrib search would do a global instead

View file

@ -9,10 +9,9 @@ Unit test module for Trait classes.
from copy import copy
from anything import Something
from mock import MagicMock, patch
from evennia.objects.objects import DefaultCharacter
from evennia.utils.test_resources import BaseEvenniaTestCase, EvenniaTest
from mock import MagicMock, patch
from . import traits
@ -156,6 +155,16 @@ class TraitHandlerTest(_TraitHandlerBase):
self.obj.attributes.get("traits", category="traits")["test1"]["value"], None
)
def test_related_traits(self):
"""Test traits related to each other via Trait.get_trait()"""
trait1 = self.traithandler.test1
trait2 = self.traithandler.test2
self.assertEqual(trait1.traithandler, self.traithandler)
self.assertEqual(trait1.get_trait("test1"), trait1)
self.assertEqual(trait1.get_trait("test2"), trait2)
class TestTrait(_TraitHandlerBase):
"""

View file

@ -456,15 +456,9 @@ from functools import total_ordering
from time import time
from django.conf import settings
from evennia.utils import logger
from evennia.utils.dbserialize import _SaverDict
from evennia.utils.utils import (
class_from_module,
inherits_from,
list_to_string,
percent,
)
from evennia.utils.utils import class_from_module, inherits_from, list_to_string, percent
# Available Trait classes.
# This way the user can easily supply their own. Each
@ -657,7 +651,9 @@ class TraitHandler:
if trait is None and trait_key in self.trait_data:
trait_type = self.trait_data[trait_key]["trait_type"]
trait_cls = self._get_trait_class(trait_type)
trait = self._cache[trait_key] = trait_cls(_GA(self, "trait_data")[trait_key])
trait = self._cache[trait_key] = trait_cls(
_GA(self, "trait_data")[trait_key], handler=self
)
return trait
def add(
@ -856,7 +852,7 @@ class Trait:
# and have them treated like data to store.
allow_extra_properties = True
def __init__(self, trait_data):
def __init__(self, trait_data, handler=None):
"""
This both initializes and validates the Trait on creation. It must
raise exception if validation fails. The TraitHandler will call this
@ -869,12 +865,15 @@ class Trait:
value in cls.data_default_values. Any extra kwargs will be made
available as extra properties on the Trait, assuming the class
variable `allow_extra_properties` is set.
handler (TraitHandler): The handler that this Trait is connected to.
This is for referencing other traits.
Raises:
TraitException: If input-validation failed.
"""
self._data = self.__class__.validate_input(self.__class__, trait_data)
self.traithandler = handler
if not isinstance(trait_data, _SaverDict):
logger.log_warn(
@ -955,6 +954,7 @@ class Trait:
"data_default",
"trait_type",
"allow_extra_properties",
"traithandler",
):
return _GA(self, key)
try:
@ -970,10 +970,9 @@ class Trait:
"""Set extra parameters as attributes.
Arbitrary attributes set on a Trait object will be
stored in the 'extra' key of the `_data` attribute.
stored as extra keys in the Trait's data.
This behavior is enabled by setting the instance
variable `_locked` to True.
This behavior is enabled by setting the instance variable `allow_extra_properties`.
"""
propobj = getattr(self.__class__, key, None)
@ -984,7 +983,7 @@ class Trait:
return
else:
# this is some other value
if key in ("_data",):
if key in ("_data", "traithandler"):
_SA(self, key, value)
return
if _GA(self, "allow_extra_properties"):
@ -1053,6 +1052,11 @@ class Trait:
"""Display name for the trait."""
return self._data["name"]
def get_trait(self, trait_key):
"""Get another Trait from the handler. Not used by default, but can be used
for custom traits that are affected by other traits on the same handler."""
return self.traithandler.get(trait_key)
key = name
# Numeric operations