mirror of
https://github.com/evennia/evennia.git
synced 2026-04-05 07:27:17 +02:00
Added some docstring, cleaned to avoid duplication, added relevant tests
This commit is contained in:
parent
6f6ceb231c
commit
79be6a4689
3 changed files with 85 additions and 23 deletions
|
|
@ -56,7 +56,13 @@ class NDBField(NAttributeProperty):
|
|||
|
||||
class TagField:
|
||||
"""
|
||||
Component Descriptor to add a tag to the host.
|
||||
Component Tags Descriptor.
|
||||
Allows you to set Tags related to a component on the class.
|
||||
The tags are set with a prefixed category, so it can support
|
||||
multiple tags or enforce a single one.
|
||||
|
||||
Default value of a tag is added when the component is registered.
|
||||
Tags are removed if the component itself is removed.
|
||||
"""
|
||||
def __init__(self, default=None, enforce_single=False):
|
||||
self._category_key = None
|
||||
|
|
@ -65,9 +71,8 @@ class TagField:
|
|||
|
||||
def __set_name__(self, owner, name):
|
||||
"""
|
||||
Called when descriptor is first assigned to the class. It is called with
|
||||
the name of the field.
|
||||
|
||||
Called when descriptor is first assigned to the class.
|
||||
It is called with the name of the field.
|
||||
"""
|
||||
self._category_key = f"{owner.name}__{name}"
|
||||
tag_fields = getattr(owner, "_tag_fields", None)
|
||||
|
|
@ -89,7 +94,7 @@ class TagField:
|
|||
tag_handler.clear(category=self._category_key)
|
||||
|
||||
tag_handler.add(
|
||||
key=self._key,
|
||||
key=value,
|
||||
category=self._category_key,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -64,12 +64,8 @@ class ComponentHandler:
|
|||
"""
|
||||
self._set_component(component)
|
||||
self.db_names.append(component.name)
|
||||
self.host.tags.add(component.name, category="components")
|
||||
self._add_component_tags(component)
|
||||
component.at_added(self.host)
|
||||
for tag_field_name in component.tag_field_names:
|
||||
default_tag = type(component).__dict__[tag_field_name]._default
|
||||
if default_tag:
|
||||
setattr(component, tag_field_name, default_tag)
|
||||
|
||||
def add_default(self, name):
|
||||
"""
|
||||
|
|
@ -89,8 +85,19 @@ class ComponentHandler:
|
|||
new_component = component.default_create(self.host)
|
||||
self._set_component(new_component)
|
||||
self.db_names.append(name)
|
||||
self.host.tags.add(name, category="components")
|
||||
self._add_component_tags(new_component)
|
||||
new_component.at_added(self.host)
|
||||
|
||||
def _add_component_tags(self, component):
|
||||
"""
|
||||
Private method that adds the Tags set on a Component via TagFields
|
||||
It will also add the name of the component so objects can be filtered
|
||||
by the components the implement.
|
||||
|
||||
Args:
|
||||
component (object): The component instance that is added.
|
||||
"""
|
||||
self.host.tags.add(component.name, category="components")
|
||||
for tag_field_name in component.tag_field_names:
|
||||
default_tag = type(component).__dict__[tag_field_name]._default
|
||||
if default_tag:
|
||||
|
|
@ -108,11 +115,9 @@ class ComponentHandler:
|
|||
"""
|
||||
component_name = component.name
|
||||
if component_name in self._loaded_components:
|
||||
self._remove_component_tags(component)
|
||||
component.at_removed(self.host)
|
||||
self.db_names.remove(component_name)
|
||||
self.host.tags.remove(component_name, category="components")
|
||||
for tag_field_name in component.tag_field_names:
|
||||
self.host.tags.remove()
|
||||
del self._loaded_components[component_name]
|
||||
else:
|
||||
message = f"Cannot remove {component_name} from {self.host.name} as it is not registered."
|
||||
|
|
@ -133,11 +138,24 @@ class ComponentHandler:
|
|||
message = f"Cannot remove {name} from {self.host.name} as it is not registered."
|
||||
raise ComponentIsNotRegistered(message)
|
||||
|
||||
self._remove_component_tags(instance)
|
||||
instance.at_removed(self.host)
|
||||
self.db_names.remove(name)
|
||||
self.host.tags.remove(name, category="components")
|
||||
|
||||
del self._loaded_components[name]
|
||||
|
||||
def _remove_component_tags(self, component):
|
||||
"""
|
||||
Private method that will remove the Tags set on a Component via TagFields
|
||||
It will also remove the component name tag.
|
||||
|
||||
Args:
|
||||
component (object): The component instance that is removed.
|
||||
"""
|
||||
self.host.tags.remove(component.name, category="components")
|
||||
for tag_field_name in component.tag_field_names:
|
||||
delattr(component, tag_field_name)
|
||||
|
||||
def get(self, name):
|
||||
"""
|
||||
Method to retrieve a cached Component instance by its name.
|
||||
|
|
@ -227,10 +245,6 @@ class ComponentHolderMixin(object):
|
|||
component = component_class.create(self, **values)
|
||||
component_names.append(component_name)
|
||||
self.components._loaded_components[component_name] = component
|
||||
for tag_field_name in component.tag_field_names:
|
||||
default_tag = type(component).__dict__[tag_field_name]._default
|
||||
if default_tag:
|
||||
setattr(component, tag_field_name, default_tag)
|
||||
|
||||
self.db.component_names = component_names
|
||||
|
||||
|
|
@ -239,8 +253,8 @@ class ComponentHolderMixin(object):
|
|||
Method that add component related tags that were set using ComponentProperty.
|
||||
"""
|
||||
super().basetype_posthook_setup()
|
||||
for component_name in self.db.component_names:
|
||||
self.tags.add(component_name, category="components")
|
||||
for component in self.components._loaded_components.values():
|
||||
self.components._add_component_tags(component)
|
||||
|
||||
@property
|
||||
def components(self) -> ComponentHandler:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from evennia.contrib.base_systems.components import Component, DBField
|
||||
from evennia.contrib.base_systems.components import Component, DBField, TagField
|
||||
from evennia.contrib.base_systems.components.holder import ComponentProperty, ComponentHolderMixin
|
||||
from evennia.objects.objects import DefaultCharacter
|
||||
from evennia.utils.test_resources import EvenniaTest
|
||||
|
|
@ -14,12 +14,17 @@ class ComponentTestB(Component):
|
|||
name = "test_b"
|
||||
my_int = DBField(default=1)
|
||||
my_list = DBField(default=[])
|
||||
default_tag = TagField(default="initial_value")
|
||||
single_tag = TagField(enforce_single=True)
|
||||
multiple_tags = TagField()
|
||||
default_single_tag = TagField(default="initial_value", enforce_single=True)
|
||||
|
||||
|
||||
class RuntimeComponentTestC(Component):
|
||||
name = "test_c"
|
||||
my_int = DBField(default=6)
|
||||
my_dict = DBField(default={})
|
||||
added_tag = TagField(default="added_value")
|
||||
|
||||
|
||||
class CharacterWithComponents(ComponentHolderMixin, DefaultCharacter):
|
||||
|
|
@ -111,7 +116,11 @@ class TestComponents(EvenniaTest):
|
|||
def test_host_has_class_component_tags(self):
|
||||
assert self.char1.tags.has(key="test_a", category="components")
|
||||
assert self.char1.tags.has(key="test_b", category="components")
|
||||
assert self.char1.tags.has(key="initial_value", category="test_b__default_tag")
|
||||
assert self.char1.test_b.default_tag == "initial_value"
|
||||
assert not self.char1.tags.has(key="test_c", category="components")
|
||||
assert not self.char1.tags.has(category="test_b__single_tag")
|
||||
assert not self.char1.tags.has(category="test_b__multiple_tags")
|
||||
|
||||
def test_host_has_added_component_tags(self):
|
||||
rct = RuntimeComponentTestC.create(self.char1)
|
||||
|
|
@ -119,12 +128,16 @@ class TestComponents(EvenniaTest):
|
|||
test_c = self.char1.components.get('test_c')
|
||||
|
||||
assert self.char1.tags.has(key="test_c", category="components")
|
||||
assert self.char1.tags.has(key="added_value", category="test_c__added_tag")
|
||||
assert test_c.added_tag == "added_value"
|
||||
|
||||
def test_host_has_added_default_component_tags(self):
|
||||
self.char1.components.add_default("test_c")
|
||||
test_c = self.char1.components.get("test_c")
|
||||
|
||||
assert self.char1.tags.has(key="test_c", category="components")
|
||||
assert self.char1.tags.has(key="added_value", category="test_c__added_tag")
|
||||
assert test_c.added_tag == "added_value"
|
||||
|
||||
def test_host_remove_component_tags(self):
|
||||
rct = RuntimeComponentTestC.create(self.char1)
|
||||
|
|
@ -134,6 +147,7 @@ class TestComponents(EvenniaTest):
|
|||
handler.remove(rct)
|
||||
|
||||
assert not self.char1.tags.has(key="test_c", category="components")
|
||||
assert not self.char1.tags.has(key="added_value", category="test_c__added_tag")
|
||||
|
||||
def test_host_remove_by_name_component_tags(self):
|
||||
rct = RuntimeComponentTestC.create(self.char1)
|
||||
|
|
@ -142,4 +156,33 @@ class TestComponents(EvenniaTest):
|
|||
assert self.char1.tags.has(key="test_c", category="components")
|
||||
handler.remove_by_name("test_c")
|
||||
|
||||
assert not self.char1.tags.has(key="test_c", category="components")
|
||||
assert not self.char1.tags.has(key="test_c", category="components")
|
||||
assert not self.char1.tags.has(key="added_value", category="test_c__added_tag")
|
||||
|
||||
def test_component_tags_only_hold_one_value_when_enforce_single(self):
|
||||
test_b = self.char1.components.get('test_b')
|
||||
test_b.single_tag = "first_value"
|
||||
test_b.single_tag = "second value"
|
||||
|
||||
assert self.char1.tags.has(key="second value", category="test_b__single_tag")
|
||||
assert test_b.single_tag == "second value"
|
||||
assert not self.char1.tags.has(key="first_value", category="test_b__single_tag")
|
||||
|
||||
def test_component_tags_default_value_is_overridden_when_enforce_single(self):
|
||||
test_b = self.char1.components.get('test_b')
|
||||
test_b.default_single_tag = "second value"
|
||||
|
||||
assert self.char1.tags.has(key="second value", category="test_b__default_single_tag")
|
||||
assert test_b.default_single_tag == "second value"
|
||||
assert not self.char1.tags.has(key="first_value", category="test_b__default_single_tag")
|
||||
|
||||
def test_component_tags_support_multiple_values_by_default(self):
|
||||
test_b = self.char1.components.get('test_b')
|
||||
test_b.multiple_tags = "first value"
|
||||
test_b.multiple_tags = "second value"
|
||||
test_b.multiple_tags = "third value"
|
||||
|
||||
assert all(val in test_b.multiple_tags for val in ("first value", "second value", "third value"))
|
||||
assert self.char1.tags.has(key="first value", category="test_b__multiple_tags")
|
||||
assert self.char1.tags.has(key="second value", category="test_b__multiple_tags")
|
||||
assert self.char1.tags.has(key="third value", category="test_b__multiple_tags")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue