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:
parent
d769a90b62
commit
7a7479955f
3 changed files with 30 additions and 15 deletions
|
|
@ -6,6 +6,8 @@
|
||||||
bugs etc in-game (InspectorCaracal)
|
bugs etc in-game (InspectorCaracal)
|
||||||
- [Feat][pull3586]: Add ANSI color support `|U`, `|I`, `|i`, `|s`, `|S` for
|
- [Feat][pull3586]: Add ANSI color support `|U`, `|I`, `|i`, `|s`, `|S` for
|
||||||
underline reset, italic/reset and strikethrough/reset (0xDEADFED5)
|
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
|
- [Fix][pull3571]: Better visual display of partial multimatch search results
|
||||||
(InspectorCaracal)
|
(InspectorCaracal)
|
||||||
- [Fix][pull3550]: Issue where rpsystem contrib search would do a global instead
|
- [Fix][pull3550]: Issue where rpsystem contrib search would do a global instead
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,9 @@ Unit test module for Trait classes.
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
from anything import Something
|
from anything import Something
|
||||||
from mock import MagicMock, patch
|
|
||||||
|
|
||||||
from evennia.objects.objects import DefaultCharacter
|
from evennia.objects.objects import DefaultCharacter
|
||||||
from evennia.utils.test_resources import BaseEvenniaTestCase, EvenniaTest
|
from evennia.utils.test_resources import BaseEvenniaTestCase, EvenniaTest
|
||||||
|
from mock import MagicMock, patch
|
||||||
|
|
||||||
from . import traits
|
from . import traits
|
||||||
|
|
||||||
|
|
@ -156,6 +155,16 @@ class TraitHandlerTest(_TraitHandlerBase):
|
||||||
self.obj.attributes.get("traits", category="traits")["test1"]["value"], None
|
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):
|
class TestTrait(_TraitHandlerBase):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -456,15 +456,9 @@ from functools import total_ordering
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from evennia.utils import logger
|
from evennia.utils import logger
|
||||||
from evennia.utils.dbserialize import _SaverDict
|
from evennia.utils.dbserialize import _SaverDict
|
||||||
from evennia.utils.utils import (
|
from evennia.utils.utils import class_from_module, inherits_from, list_to_string, percent
|
||||||
class_from_module,
|
|
||||||
inherits_from,
|
|
||||||
list_to_string,
|
|
||||||
percent,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Available Trait classes.
|
# Available Trait classes.
|
||||||
# This way the user can easily supply their own. Each
|
# 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:
|
if trait is None and trait_key in self.trait_data:
|
||||||
trait_type = self.trait_data[trait_key]["trait_type"]
|
trait_type = self.trait_data[trait_key]["trait_type"]
|
||||||
trait_cls = self._get_trait_class(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
|
return trait
|
||||||
|
|
||||||
def add(
|
def add(
|
||||||
|
|
@ -856,7 +852,7 @@ class Trait:
|
||||||
# and have them treated like data to store.
|
# and have them treated like data to store.
|
||||||
allow_extra_properties = True
|
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
|
This both initializes and validates the Trait on creation. It must
|
||||||
raise exception if validation fails. The TraitHandler will call this
|
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
|
value in cls.data_default_values. Any extra kwargs will be made
|
||||||
available as extra properties on the Trait, assuming the class
|
available as extra properties on the Trait, assuming the class
|
||||||
variable `allow_extra_properties` is set.
|
variable `allow_extra_properties` is set.
|
||||||
|
handler (TraitHandler): The handler that this Trait is connected to.
|
||||||
|
This is for referencing other traits.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
TraitException: If input-validation failed.
|
TraitException: If input-validation failed.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self._data = self.__class__.validate_input(self.__class__, trait_data)
|
self._data = self.__class__.validate_input(self.__class__, trait_data)
|
||||||
|
self.traithandler = handler
|
||||||
|
|
||||||
if not isinstance(trait_data, _SaverDict):
|
if not isinstance(trait_data, _SaverDict):
|
||||||
logger.log_warn(
|
logger.log_warn(
|
||||||
|
|
@ -955,6 +954,7 @@ class Trait:
|
||||||
"data_default",
|
"data_default",
|
||||||
"trait_type",
|
"trait_type",
|
||||||
"allow_extra_properties",
|
"allow_extra_properties",
|
||||||
|
"traithandler",
|
||||||
):
|
):
|
||||||
return _GA(self, key)
|
return _GA(self, key)
|
||||||
try:
|
try:
|
||||||
|
|
@ -970,10 +970,9 @@ class Trait:
|
||||||
"""Set extra parameters as attributes.
|
"""Set extra parameters as attributes.
|
||||||
|
|
||||||
Arbitrary attributes set on a Trait object will be
|
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
|
This behavior is enabled by setting the instance variable `allow_extra_properties`.
|
||||||
variable `_locked` to True.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
propobj = getattr(self.__class__, key, None)
|
propobj = getattr(self.__class__, key, None)
|
||||||
|
|
@ -984,7 +983,7 @@ class Trait:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# this is some other value
|
# this is some other value
|
||||||
if key in ("_data",):
|
if key in ("_data", "traithandler"):
|
||||||
_SA(self, key, value)
|
_SA(self, key, value)
|
||||||
return
|
return
|
||||||
if _GA(self, "allow_extra_properties"):
|
if _GA(self, "allow_extra_properties"):
|
||||||
|
|
@ -1053,6 +1052,11 @@ class Trait:
|
||||||
"""Display name for the trait."""
|
"""Display name for the trait."""
|
||||||
return self._data["name"]
|
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
|
key = name
|
||||||
|
|
||||||
# Numeric operations
|
# Numeric operations
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue