Apply black to cleanup code

This commit is contained in:
Griatch 2022-06-12 09:46:48 +02:00
parent 45ed27c7f1
commit a83f21ef2f
33 changed files with 256 additions and 194 deletions

View file

@ -450,9 +450,7 @@ class CmdSetHandler(object):
""" """
if "permanent" in kwargs: if "permanent" in kwargs:
logger.log_dep( logger.log_dep("obj.cmdset.add() kwarg 'permanent' has changed name to 'persistent'.")
"obj.cmdset.add() kwarg 'permanent' has changed name to 'persistent'."
)
persistent = kwargs["permanent"] if persistent is False else persistent persistent = kwargs["permanent"] if persistent is False else persistent
if not (isinstance(cmdset, str) or utils.inherits_from(cmdset, CmdSet)): if not (isinstance(cmdset, str) or utils.inherits_from(cmdset, CmdSet)):

View file

@ -2219,11 +2219,13 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
old_typeclass_path = obj.typeclass_path old_typeclass_path = obj.typeclass_path
if reset: if reset:
answer = yield("|yNote that this will reset the object back to its typeclass' default state, " answer = yield (
"removing any custom locks/perms/attributes etc that may have been added " "|yNote that this will reset the object back to its typeclass' default state, "
"by an explicit create_object call. Use `update` or type/force instead in order " "removing any custom locks/perms/attributes etc that may have been added "
"to keep such data. " "by an explicit create_object call. Use `update` or type/force instead in order "
"Continue [Y]/N?|n") "to keep such data. "
"Continue [Y]/N?|n"
)
if answer.upper() in ("N", "NO"): if answer.upper() in ("N", "NO"):
caller.msg("Aborted.") caller.msg("Aborted.")
return return
@ -3473,7 +3475,7 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
caller.msg("\n".join(msgs)) caller.msg("\n".join(msgs))
if "delete" not in self.switches: if "delete" not in self.switches:
if script and script.pk: if script and script.pk:
ScriptEvMore(caller, [script], session=self.session) ScriptEvMore(caller, [script], session=self.session)
else: else:
caller.msg("Script was deleted automatically.") caller.msg("Script was deleted automatically.")
else: else:

View file

@ -107,8 +107,7 @@ class TestGeneral(BaseEvenniaCommandTest):
def test_nick_list(self): def test_nick_list(self):
self.call(general.CmdNick(), "/list", "No nicks defined.") self.call(general.CmdNick(), "/list", "No nicks defined.")
self.call(general.CmdNick(), "test1 = Hello", self.call(general.CmdNick(), "test1 = Hello", "Inputline-nick 'test1' mapped to 'Hello'.")
"Inputline-nick 'test1' mapped to 'Hello'.")
self.call(general.CmdNick(), "/list", "Defined Nicks:") self.call(general.CmdNick(), "/list", "Defined Nicks:")
def test_get_and_drop(self): def test_get_and_drop(self):
@ -1295,7 +1294,8 @@ class TestBuilding(BaseEvenniaCommandTest):
"Obj2 = evennia.objects.objects.DefaultExit", "Obj2 = evennia.objects.objects.DefaultExit",
"Obj2 changed typeclass from evennia.objects.objects.DefaultObject " "Obj2 changed typeclass from evennia.objects.objects.DefaultObject "
"to evennia.objects.objects.DefaultExit.", "to evennia.objects.objects.DefaultExit.",
cmdstring="swap", inputs=["yes"], cmdstring="swap",
inputs=["yes"],
) )
self.call(building.CmdTypeclass(), "/list Obj", "Core typeclasses") self.call(building.CmdTypeclass(), "/list Obj", "Core typeclasses")
self.call( self.call(
@ -1332,7 +1332,7 @@ class TestBuilding(BaseEvenniaCommandTest):
"/reset/force Obj=evennia.objects.objects.DefaultObject", "/reset/force Obj=evennia.objects.objects.DefaultObject",
"Obj updated its existing typeclass (evennia.objects.objects.DefaultObject).\n" "Obj updated its existing typeclass (evennia.objects.objects.DefaultObject).\n"
"All object creation hooks were run. All old attributes where deleted before the swap.", "All object creation hooks were run. All old attributes where deleted before the swap.",
inputs=["yes"] inputs=["yes"],
) )
from evennia.prototypes.prototypes import homogenize_prototype from evennia.prototypes.prototypes import homogenize_prototype
@ -1359,7 +1359,7 @@ class TestBuilding(BaseEvenniaCommandTest):
"typeclasses.objects.Object.\nOnly the at_object_creation hook was run " "typeclasses.objects.Object.\nOnly the at_object_creation hook was run "
"(update mode). Attributes set before swap were not removed\n" "(update mode). Attributes set before swap were not removed\n"
"(use `swap` or `type/reset` to clear all). Prototype 'replaced_obj' was " "(use `swap` or `type/reset` to clear all). Prototype 'replaced_obj' was "
"successfully applied over the object type." "successfully applied over the object type.",
) )
assert self.obj1.db.desc == "protdesc" assert self.obj1.db.desc == "protdesc"

View file

@ -17,8 +17,10 @@ def get_component_class(component_name):
subclasses = Component.__subclasses__() subclasses = Component.__subclasses__()
component_class = next((sc for sc in subclasses if sc.name == component_name), None) component_class = next((sc for sc in subclasses if sc.name == component_name), None)
if component_class is None: if component_class is None:
message = f"Component named {component_name} has not been found. " \ message = (
f"Make sure it has been imported before being used." f"Component named {component_name} has not been found. "
f"Make sure it has been imported before being used."
)
raise Exception(message) raise Exception(message)
return component_class return component_class

View file

@ -13,6 +13,7 @@ class Component:
Each Component must supply the name, it is used as a slot name but also part of the attribute key. Each Component must supply the name, it is used as a slot name but also part of the attribute key.
""" """
name = "" name = ""
def __init__(self, host=None): def __init__(self, host=None):

View file

@ -26,7 +26,7 @@ class DBField(AttributeProperty):
db_fields = getattr(owner, "_db_fields", None) db_fields = getattr(owner, "_db_fields", None)
if db_fields is None: if db_fields is None:
db_fields = {} db_fields = {}
setattr(owner, '_db_fields', db_fields) setattr(owner, "_db_fields", db_fields)
db_fields[name] = self db_fields[name] = self
@ -50,7 +50,7 @@ class NDBField(NAttributeProperty):
ndb_fields = getattr(owner, "_ndb_fields", None) ndb_fields = getattr(owner, "_ndb_fields", None)
if ndb_fields is None: if ndb_fields is None:
ndb_fields = {} ndb_fields = {}
setattr(owner, '_ndb_fields', ndb_fields) setattr(owner, "_ndb_fields", ndb_fields)
ndb_fields[name] = self ndb_fields[name] = self
@ -64,6 +64,7 @@ class TagField:
Default value of a tag is added when the component is registered. Default value of a tag is added when the component is registered.
Tags are removed if the component itself is removed. Tags are removed if the component itself is removed.
""" """
def __init__(self, default=None, enforce_single=False): def __init__(self, default=None, enforce_single=False):
self._category_key = None self._category_key = None
self._default = default self._default = default
@ -78,7 +79,7 @@ class TagField:
tag_fields = getattr(owner, "_tag_fields", None) tag_fields = getattr(owner, "_tag_fields", None)
if tag_fields is None: if tag_fields is None:
tag_fields = {} tag_fields = {}
setattr(owner, '_tag_fields', tag_fields) setattr(owner, "_tag_fields", tag_fields)
tag_fields[name] = self tag_fields[name] = self
def __get__(self, instance, owner): def __get__(self, instance, owner):

View file

@ -16,6 +16,7 @@ class ComponentProperty:
Defaults can be overridden for this typeclass by passing kwargs Defaults can be overridden for this typeclass by passing kwargs
""" """
def __init__(self, component_name, **kwargs): def __init__(self, component_name, **kwargs):
""" """
Initializes the descriptor Initializes the descriptor
@ -49,6 +50,7 @@ class ComponentHandler:
It lets you add or remove components and will load components as needed. It lets you add or remove components and will load components as needed.
It stores the list of registered components on the host .db with component_names as key. It stores the list of registered components on the host .db with component_names as key.
""" """
def __init__(self, host): def __init__(self, host):
self.host = host self.host = host
self._loaded_components = {} self._loaded_components = {}
@ -124,7 +126,9 @@ class ComponentHandler:
self.host.signals.remove_object_listeners_and_responders(component) self.host.signals.remove_object_listeners_and_responders(component)
del self._loaded_components[component_name] del self._loaded_components[component_name]
else: else:
message = f"Cannot remove {component_name} from {self.host.name} as it is not registered." message = (
f"Cannot remove {component_name} from {self.host.name} as it is not registered."
)
raise ComponentIsNotRegistered(message) raise ComponentIsNotRegistered(message)
def remove_by_name(self, name): def remove_by_name(self, name):
@ -199,7 +203,9 @@ class ComponentHandler:
self._set_component(component_instance) self._set_component(component_instance)
self.host.signals.add_object_listeners_and_responders(component_instance) self.host.signals.add_object_listeners_and_responders(component_instance)
else: else:
message = f"Could not initialize runtime component {component_name} of {self.host.name}" message = (
f"Could not initialize runtime component {component_name} of {self.host.name}"
)
raise ComponentDoesNotExist(message) raise ComponentDoesNotExist(message)
def _set_component(self, component): def _set_component(self, component):

View file

@ -15,9 +15,11 @@ def as_listener(func=None, signal_name=None):
signal_name (str): The name of the signal to listen to, defaults to function name. signal_name (str): The name of the signal to listen to, defaults to function name.
""" """
if not func and signal_name: if not func and signal_name:
def wrapper(func): def wrapper(func):
func._listener_signal_name = signal_name func._listener_signal_name = signal_name
return func return func
return wrapper return wrapper
signal_name = func.__name__ signal_name = func.__name__
@ -35,9 +37,11 @@ def as_responder(func=None, signal_name=None):
signal_name (str): The name of the signal to respond to, defaults to function name. signal_name (str): The name of the signal to respond to, defaults to function name.
""" """
if not func and signal_name: if not func and signal_name:
def wrapper(func): def wrapper(func):
func._responder_signal_name = signal_name func._responder_signal_name = signal_name
return func return func
return wrapper return wrapper
signal_name = func.__name__ signal_name = func.__name__
@ -177,12 +181,12 @@ class SignalsHandler(object):
""" """
type_host = type(obj) type_host = type(obj)
for att_name, att_obj in type_host.__dict__.items(): for att_name, att_obj in type_host.__dict__.items():
listener_signal_name = getattr(att_obj, '_listener_signal_name', None) listener_signal_name = getattr(att_obj, "_listener_signal_name", None)
if listener_signal_name: if listener_signal_name:
callback = getattr(obj, att_name) callback = getattr(obj, att_name)
self.add_listener(signal_name=listener_signal_name, callback=callback) self.add_listener(signal_name=listener_signal_name, callback=callback)
responder_signal_name = getattr(att_obj, '_responder_signal_name', None) responder_signal_name = getattr(att_obj, "_responder_signal_name", None)
if responder_signal_name: if responder_signal_name:
callback = getattr(obj, att_name) callback = getattr(obj, att_name)
self.add_responder(signal_name=responder_signal_name, callback=callback) self.add_responder(signal_name=responder_signal_name, callback=callback)
@ -196,12 +200,12 @@ class SignalsHandler(object):
""" """
type_host = type(obj) type_host = type(obj)
for att_name, att_obj in type_host.__dict__.items(): for att_name, att_obj in type_host.__dict__.items():
listener_signal_name = getattr(att_obj, '_listener_signal_name', None) listener_signal_name = getattr(att_obj, "_listener_signal_name", None)
if listener_signal_name: if listener_signal_name:
callback = getattr(obj, att_name) callback = getattr(obj, att_name)
self.remove_listener(signal_name=listener_signal_name, callback=callback) self.remove_listener(signal_name=listener_signal_name, callback=callback)
responder_signal_name = getattr(att_obj, '_responder_signal_name', None) responder_signal_name = getattr(att_obj, "_responder_signal_name", None)
if responder_signal_name: if responder_signal_name:
callback = getattr(obj, att_name) callback = getattr(obj, att_name)
self.remove_responder(signal_name=responder_signal_name, callback=callback) self.remove_responder(signal_name=responder_signal_name, callback=callback)

View file

@ -56,7 +56,7 @@ class TestComponents(EvenniaTest):
def test_character_can_register_runtime_component(self): def test_character_can_register_runtime_component(self):
rct = RuntimeComponentTestC.create(self.char1) rct = RuntimeComponentTestC.create(self.char1)
self.char1.components.add(rct) self.char1.components.add(rct)
test_c = self.char1.components.get('test_c') test_c = self.char1.components.get("test_c")
assert test_c assert test_c
assert test_c.my_int == 6 assert test_c.my_int == 6
@ -110,7 +110,7 @@ class TestComponents(EvenniaTest):
assert handler.get("test_c") is rct assert handler.get("test_c") is rct
def test_can_access_component_regular_get(self): def test_can_access_component_regular_get(self):
assert self.char1.cmp.test_a is self.char1.components.get('test_a') assert self.char1.cmp.test_a is self.char1.components.get("test_a")
def test_returns_none_with_regular_get_when_no_attribute(self): def test_returns_none_with_regular_get_when_no_attribute(self):
assert self.char1.cmp.does_not_exist is None assert self.char1.cmp.does_not_exist is None
@ -127,7 +127,7 @@ class TestComponents(EvenniaTest):
def test_host_has_added_component_tags(self): def test_host_has_added_component_tags(self):
rct = RuntimeComponentTestC.create(self.char1) rct = RuntimeComponentTestC.create(self.char1)
self.char1.components.add(rct) self.char1.components.add(rct)
test_c = self.char1.components.get('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="test_c", category="components")
assert self.char1.tags.has(key="added_value", category="test_c::added_tag") assert self.char1.tags.has(key="added_value", category="test_c::added_tag")
@ -162,7 +162,7 @@ class TestComponents(EvenniaTest):
assert not self.char1.tags.has(key="added_value", category="test_c::added_tag") 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): def test_component_tags_only_hold_one_value_when_enforce_single(self):
test_b = self.char1.components.get('test_b') test_b = self.char1.components.get("test_b")
test_b.single_tag = "first_value" test_b.single_tag = "first_value"
test_b.single_tag = "second value" test_b.single_tag = "second value"
@ -171,7 +171,7 @@ class TestComponents(EvenniaTest):
assert not self.char1.tags.has(key="first_value", category="test_b::single_tag") 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): def test_component_tags_default_value_is_overridden_when_enforce_single(self):
test_b = self.char1.components.get('test_b') test_b = self.char1.components.get("test_b")
test_b.default_single_tag = "second value" test_b.default_single_tag = "second value"
assert self.char1.tags.has(key="second value", category="test_b::default_single_tag") assert self.char1.tags.has(key="second value", category="test_b::default_single_tag")
@ -179,12 +179,14 @@ class TestComponents(EvenniaTest):
assert not self.char1.tags.has(key="first_value", category="test_b::default_single_tag") 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): def test_component_tags_support_multiple_values_by_default(self):
test_b = self.char1.components.get('test_b') test_b = self.char1.components.get("test_b")
test_b.multiple_tags = "first value" test_b.multiple_tags = "first value"
test_b.multiple_tags = "second value" test_b.multiple_tags = "second value"
test_b.multiple_tags = "third 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 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="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="second value", category="test_b::multiple_tags")
assert self.char1.tags.has(key="third value", category="test_b::multiple_tags") assert self.char1.tags.has(key="third value", category="test_b::multiple_tags")
@ -193,11 +195,11 @@ class TestComponents(EvenniaTest):
class CharWithSignal(ComponentHolderMixin, DefaultCharacter): class CharWithSignal(ComponentHolderMixin, DefaultCharacter):
@signals.as_listener @signals.as_listener
def my_signal(self): def my_signal(self):
setattr(self, 'my_signal_is_called', True) setattr(self, "my_signal_is_called", True)
@signals.as_listener @signals.as_listener
def my_other_signal(self): def my_other_signal(self):
setattr(self, 'my_other_signal_is_called', True) setattr(self, "my_other_signal_is_called", True)
@signals.as_responder @signals.as_responder
def my_response(self): def my_response(self):
@ -213,11 +215,11 @@ class ComponentWithSignal(Component):
@signals.as_listener @signals.as_listener
def my_signal(self): def my_signal(self):
setattr(self, 'my_signal_is_called', True) setattr(self, "my_signal_is_called", True)
@signals.as_listener @signals.as_listener
def my_other_signal(self): def my_other_signal(self):
setattr(self, 'my_other_signal_is_called', True) setattr(self, "my_other_signal_is_called", True)
@signals.as_responder @signals.as_responder
def my_response(self): def my_response(self):
@ -236,14 +238,15 @@ class TestComponentSignals(BaseEvenniaTest):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.char1 = create.create_object( self.char1 = create.create_object(
CharWithSignal, key="Char", CharWithSignal,
key="Char",
) )
def test_host_can_register_as_listener(self): def test_host_can_register_as_listener(self):
self.char1.signals.trigger("my_signal") self.char1.signals.trigger("my_signal")
assert self.char1.my_signal_is_called assert self.char1.my_signal_is_called
assert not getattr(self.char1, 'my_other_signal_is_called', None) assert not getattr(self.char1, "my_other_signal_is_called", None)
def test_host_can_register_as_responder(self): def test_host_can_register_as_responder(self):
responses = self.char1.signals.query("my_response") responses = self.char1.signals.query("my_response")
@ -258,7 +261,7 @@ class TestComponentSignals(BaseEvenniaTest):
component = char.cmp.test_signal_a component = char.cmp.test_signal_a
assert component.my_signal_is_called assert component.my_signal_is_called
assert not getattr(component, 'my_other_signal_is_called', None) assert not getattr(component, "my_other_signal_is_called", None)
def test_component_can_register_as_responder(self): def test_component_can_register_as_responder(self):
char = self.char1 char = self.char1

View file

@ -328,4 +328,4 @@ class GametimeScript(DefaultScript):
callback() callback()
seconds = real_seconds_until(**self.db.gametime) seconds = real_seconds_until(**self.db.gametime)
self.start(interval=seconds,force_restart=True) self.start(interval=seconds, force_restart=True)

View file

@ -284,7 +284,7 @@ def parse_language(speaker, emote):
# the key is simply the running match in the emote # the key is simply the running match in the emote
key = f"##{imatch}" key = f"##{imatch}"
# replace say with ref markers in emote # replace say with ref markers in emote
emote = "{start}{{{key}}}{end}".format( start=emote[:istart], key=key, end=emote[iend:] ) emote = "{start}{{{key}}}{end}".format(start=emote[:istart], key=key, end=emote[iend:])
mapping[key] = (langname, saytext) mapping[key] = (langname, saytext)
if errors: if errors:
@ -339,18 +339,18 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False, case_
""" """
# build a list of candidates with all possible referrable names # build a list of candidates with all possible referrable names
# include 'me' keyword for self-ref # include 'me' keyword for self-ref
candidate_map = [(sender, 'me')] candidate_map = [(sender, "me")]
for obj in candidates: for obj in candidates:
# check if sender has any recogs for obj and add # check if sender has any recogs for obj and add
if hasattr(sender, "recog"): if hasattr(sender, "recog"):
if recog := sender.recog.get(obj): if recog := sender.recog.get(obj):
candidate_map.append((obj, recog)) candidate_map.append((obj, recog))
# check if obj has an sdesc and add # check if obj has an sdesc and add
if hasattr(obj, "sdesc"): if hasattr(obj, "sdesc"):
candidate_map.append((obj, obj.sdesc.get())) candidate_map.append((obj, obj.sdesc.get()))
# if no sdesc, include key plus aliases instead # if no sdesc, include key plus aliases instead
else: else:
candidate_map.extend( [(obj, obj.key)] + [(obj, alias) for alias in obj.aliases.all()] ) candidate_map.extend([(obj, obj.key)] + [(obj, alias) for alias in obj.aliases.all()])
# escape mapping syntax on the form {#id} if it exists already in emote, # escape mapping syntax on the form {#id} if it exists already in emote,
# if so it is replaced with just "id". # if so it is replaced with just "id".
@ -374,31 +374,40 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False, case_
match_index = marker_match.start() match_index = marker_match.start()
# split the emote string at the reference marker, to process everything after it # split the emote string at the reference marker, to process everything after it
head = string[:match_index] head = string[:match_index]
tail = string[match_index+1:] tail = string[match_index + 1 :]
if search_mode: if search_mode:
# match the candidates against the whole search string after the marker # match the candidates against the whole search string after the marker
rquery = "".join([r"\b(" + re.escape(word.strip(punctuation)) + r").*" for word in iter(tail.split())]) rquery = "".join(
matches = ((re.search(rquery, text, _RE_FLAGS), obj, text) for obj, text in candidate_map) [
r"\b(" + re.escape(word.strip(punctuation)) + r").*"
for word in iter(tail.split())
]
)
matches = (
(re.search(rquery, text, _RE_FLAGS), obj, text) for obj, text in candidate_map
)
# filter out any non-matching candidates # filter out any non-matching candidates
bestmatches = [(obj, match.group()) for match, obj, text in matches if match] bestmatches = [(obj, match.group()) for match, obj, text in matches if match]
else: else:
# to find the longest match, we start from the marker and lengthen the # to find the longest match, we start from the marker and lengthen the
# match query one word at a time. # match query one word at a time.
word_list = [] word_list = []
bestmatches = [] bestmatches = []
# preserve punctuation when splitting # preserve punctuation when splitting
tail = re.split('(\W)', tail) tail = re.split("(\W)", tail)
iend = 0 iend = 0
for i, item in enumerate(tail): for i, item in enumerate(tail):
# don't add non-word characters to the search query # don't add non-word characters to the search query
if not item.isalpha(): if not item.isalpha():
continue continue
word_list.append(item) word_list.append(item)
rquery = "".join([r"\b(" + re.escape(word) + r").*" for word in word_list]) rquery = "".join([r"\b(" + re.escape(word) + r").*" for word in word_list])
# match candidates against the current set of words # match candidates against the current set of words
matches = ((re.search(rquery, text, _RE_FLAGS), obj, text) for obj, text in candidate_map) matches = (
(re.search(rquery, text, _RE_FLAGS), obj, text) for obj, text in candidate_map
)
matches = [(obj, match.group()) for match, obj, text in matches if match] matches = [(obj, match.group()) for match, obj, text in matches if match]
if len(matches) == 0: if len(matches) == 0:
# no matches at this length, keep previous iteration as best # no matches at this length, keep previous iteration as best
@ -411,7 +420,7 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False, case_
# save search string # save search string
matched_text = "".join(tail[1:iend]) matched_text = "".join(tail[1:iend])
# recombine remainder of emote back into a string # recombine remainder of emote back into a string
tail = "".join(tail[iend+1:]) tail = "".join(tail[iend + 1 :])
nmatches = len(bestmatches) nmatches = len(bestmatches)
@ -549,18 +558,18 @@ def send_emote(sender, receivers, emote, anonymous_add="first", **kwargs):
if "anonymous_add" in kwargs: if "anonymous_add" in kwargs:
anonymous_add = kwargs.pop("anonymous_add") anonymous_add = kwargs.pop("anonymous_add")
# make sure to catch all possible self-refs # make sure to catch all possible self-refs
self_refs = [f"{skey}{ref}" for ref in ('t','^','v','~','')] self_refs = [f"{skey}{ref}" for ref in ("t", "^", "v", "~", "")]
if anonymous_add and not any(1 for tag in obj_mapping if tag in self_refs): if anonymous_add and not any(1 for tag in obj_mapping if tag in self_refs):
# no self-reference in the emote - add it # no self-reference in the emote - add it
if anonymous_add == "first": if anonymous_add == "first":
# add case flag for initial caps # add case flag for initial caps
skey += 't' skey += "t"
# don't put a space after the self-ref if it's a possessive emote # don't put a space after the self-ref if it's a possessive emote
femote = "{key}{emote}" if emote.startswith("'") else "{key} {emote}" femote = "{key}{emote}" if emote.startswith("'") else "{key} {emote}"
else: else:
# add it to the end # add it to the end
femote = "{emote} [{key}]" femote = "{emote} [{key}]"
emote = femote.format( key="{{"+ skey +"}}", emote=emote ) emote = femote.format(key="{{" + skey + "}}", emote=emote)
obj_mapping[skey] = sender obj_mapping[skey] = sender
# broadcast emote to everyone # broadcast emote to everyone
@ -663,7 +672,9 @@ class SdescHandler:
if len(cleaned_sdesc) > max_length: if len(cleaned_sdesc) > max_length:
raise SdescError( raise SdescError(
"Short desc can max be {} chars long (was {} chars).".format(max_length, len(cleaned_sdesc)) "Short desc can max be {} chars long (was {} chars).".format(
max_length, len(cleaned_sdesc)
)
) )
# store to attributes # store to attributes
@ -682,7 +693,6 @@ class SdescHandler:
return self.sdesc or self.obj.key return self.sdesc or self.obj.key
class RecogHandler: class RecogHandler:
""" """
This handler manages the recognition mapping This handler manages the recognition mapping
@ -758,7 +768,9 @@ class RecogHandler:
if len(cleaned_recog) > max_length: if len(cleaned_recog) > max_length:
raise RecogError( raise RecogError(
"Recog string cannot be longer than {} chars (was {} chars)".format(max_length, len(cleaned_recog)) "Recog string cannot be longer than {} chars (was {} chars)".format(
max_length, len(cleaned_recog)
)
) )
# mapping #dbref:obj # mapping #dbref:obj
@ -866,7 +878,7 @@ class CmdEmote(RPCommand): # replaces the main emote
emote = self.args emote = self.args
targets = self.caller.location.contents targets = self.caller.location.contents
if not emote.endswith((".", "?", "!", '"')): # If emote is not punctuated or speech, if not emote.endswith((".", "?", "!", '"')): # If emote is not punctuated or speech,
emote += "." # add a full-stop for good measure. emote += "." # add a full-stop for good measure.
send_emote(self.caller, targets, emote, anonymous_add="first") send_emote(self.caller, targets, emote, anonymous_add="first")
@ -1132,7 +1144,11 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
if forget_mode: if forget_mode:
# remove existing recog # remove existing recog
caller.recog.remove(obj) caller.recog.remove(obj)
caller.msg("You will now know them only as '{}'.".format( obj.get_display_name(caller, noid=True) )) caller.msg(
"You will now know them only as '{}'.".format(
obj.get_display_name(caller, noid=True)
)
)
else: else:
# set recog # set recog
sdesc = obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key sdesc = obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key
@ -1216,9 +1232,10 @@ class ContribRPObject(DefaultObject):
This class is meant as a mix-in or parent for objects in an This class is meant as a mix-in or parent for objects in an
rp-heavy game. It implements the base functionality for poses. rp-heavy game. It implements the base functionality for poses.
""" """
@lazy_property @lazy_property
def sdesc(self): def sdesc(self):
return SdescHandler(self) return SdescHandler(self)
def at_object_creation(self): def at_object_creation(self):
""" """
@ -1409,19 +1426,18 @@ class ContribRPObject(DefaultObject):
def get_posed_sdesc(self, sdesc, **kwargs): def get_posed_sdesc(self, sdesc, **kwargs):
""" """
Displays the object with its current pose string. Displays the object with its current pose string.
Returns: Returns:
pose (str): A string containing the object's sdesc and pose (str): A string containing the object's sdesc and
current or default pose. current or default pose.
""" """
# get the current pose, or default if no pose is set # get the current pose, or default if no pose is set
pose = self.db.pose or self.db.pose_default pose = self.db.pose or self.db.pose_default
# return formatted string, or sdesc as fallback # return formatted string, or sdesc as fallback
return f"{sdesc} {pose}" if pose else sdesc return f"{sdesc} {pose}" if pose else sdesc
def get_display_name(self, looker, **kwargs): def get_display_name(self, looker, **kwargs):
""" """
Displays the name of the object in a viewer-aware manner. Displays the name of the object in a viewer-aware manner.
@ -1448,8 +1464,8 @@ class ContribRPObject(DefaultObject):
is privileged to control said object. is privileged to control said object.
""" """
ref = kwargs.get("ref","~") ref = kwargs.get("ref", "~")
if looker == self: if looker == self:
# always show your own key # always show your own key
sdesc = self.key sdesc = self.key
@ -1460,13 +1476,12 @@ class ContribRPObject(DefaultObject):
except AttributeError: except AttributeError:
# use own sdesc as a fallback # use own sdesc as a fallback
sdesc = self.sdesc.get() sdesc = self.sdesc.get()
# add dbref is looker has control access and `noid` is not set
if self.access(looker, access_type="control") and not kwargs.get("noid",False):
sdesc = f"{sdesc}(#{self.id})"
return self.get_posed_sdesc(sdesc) if kwargs.get("pose", False) else sdesc
# add dbref is looker has control access and `noid` is not set
if self.access(looker, access_type="control") and not kwargs.get("noid", False):
sdesc = f"{sdesc}(#{self.id})"
return self.get_posed_sdesc(sdesc) if kwargs.get("pose", False) else sdesc
def return_appearance(self, looker): def return_appearance(self, looker):
""" """
@ -1475,7 +1490,7 @@ class ContribRPObject(DefaultObject):
Args: Args:
looker (Object): Object doing the looking. looker (Object): Object doing the looking.
Returns: Returns:
string (str): A string containing the name, appearance and contents string (str): A string containing the name, appearance and contents
of the object. of the object.
@ -1553,11 +1568,11 @@ class ContribRPCharacter(DefaultCharacter, ContribRPObject):
characters stand out from other objects. characters stand out from other objects.
""" """
ref = kwargs.get("ref","~") ref = kwargs.get("ref", "~")
if looker == self: if looker == self:
# process your key as recog since you recognize yourself # process your key as recog since you recognize yourself
sdesc = self.process_recog(self.key,self) sdesc = self.process_recog(self.key, self)
else: else:
try: try:
# get the sdesc looker should see, with formatting # get the sdesc looker should see, with formatting
@ -1567,12 +1582,11 @@ class ContribRPCharacter(DefaultCharacter, ContribRPObject):
sdesc = self.sdesc.get() sdesc = self.sdesc.get()
# add dbref is looker has control access and `noid` is not set # add dbref is looker has control access and `noid` is not set
if self.access(looker, access_type="control") and not kwargs.get("noid",False): if self.access(looker, access_type="control") and not kwargs.get("noid", False):
sdesc = f"{sdesc}(#{self.id})" sdesc = f"{sdesc}(#{self.id})"
return self.get_posed_sdesc(sdesc) if kwargs.get("pose", False) else sdesc return self.get_posed_sdesc(sdesc) if kwargs.get("pose", False) else sdesc
def at_object_creation(self): def at_object_creation(self):
""" """
Called at initial creation. Called at initial creation.
@ -1631,7 +1645,6 @@ class ContribRPCharacter(DefaultCharacter, ContribRPObject):
return sdesc return sdesc
def process_sdesc(self, sdesc, obj, **kwargs): def process_sdesc(self, sdesc, obj, **kwargs):
""" """
Allows to customize how your sdesc is displayed (primarily by Allows to customize how your sdesc is displayed (primarily by
@ -1713,7 +1726,4 @@ class ContribRPCharacter(DefaultCharacter, ContribRPObject):
the evennia.contrib.rpg.rplanguage module. the evennia.contrib.rpg.rplanguage module.
""" """
return "{label}|w{text}|n".format( return "{label}|w{text}|n".format(label=f"|W({language})" if language else "", text=text)
label=f"|W({language})" if language else "",
text=text
)

View file

@ -165,17 +165,19 @@ class TestRPSystem(BaseEvenniaTest):
) )
def test_get_sdesc(self): def test_get_sdesc(self):
looker = self.speaker # Sender looker = self.speaker # Sender
target = self.receiver1 # Receiver1 target = self.receiver1 # Receiver1
looker.sdesc.add(sdesc0) # A nice sender of emotes looker.sdesc.add(sdesc0) # A nice sender of emotes
target.sdesc.add(sdesc1) # The first receiver of emotes. target.sdesc.add(sdesc1) # The first receiver of emotes.
# sdesc with no processing # sdesc with no processing
self.assertEqual(looker.get_sdesc(target), "The first receiver of emotes.") self.assertEqual(looker.get_sdesc(target), "The first receiver of emotes.")
# sdesc with processing # sdesc with processing
self.assertEqual(looker.get_sdesc(target, process=True), "|bThe first receiver of emotes.|n") self.assertEqual(
looker.get_sdesc(target, process=True), "|bThe first receiver of emotes.|n"
looker.recog.add(target, recog01) # Mr Receiver )
looker.recog.add(target, recog01) # Mr Receiver
# recog with no processing # recog with no processing
self.assertEqual(looker.get_sdesc(target), "Mr Receiver") self.assertEqual(looker.get_sdesc(target), "Mr Receiver")
@ -233,7 +235,7 @@ class TestRPSystem(BaseEvenniaTest):
self.out1, self.out1,
"|bA nice sender of emotes|n looks at |mReceiver1|n. Then, " "|bA nice sender of emotes|n looks at |mReceiver1|n. Then, "
"|ba nice sender of emotes|n looks at |mReceiver1|n, |mReceiver1|n " "|ba nice sender of emotes|n looks at |mReceiver1|n, |mReceiver1|n "
"and |bAnother nice colliding sdesc-guy for tests|n twice." "and |bAnother nice colliding sdesc-guy for tests|n twice.",
) )
self.assertEqual( self.assertEqual(
self.out2, self.out2,

View file

@ -321,7 +321,6 @@ class TestTraitStatic(_TraitHandlerBase):
self.trait.mult = 0.75 self.trait.mult = 0.75
self.assertEqual(self._get_values(), (5, 1, 0.75, 4.5)) self.assertEqual(self._get_values(), (5, 1, 0.75, 4.5))
def test_delete(self): def test_delete(self):
"""Deleting resets to default.""" """Deleting resets to default."""
self.trait.mult = 2.0 self.trait.mult = 2.0
@ -362,7 +361,14 @@ class TestTraitCounter(_TraitHandlerBase):
def _get_values(self): def _get_values(self):
"""Get (base, mod, mult, value, min, max).""" """Get (base, mod, mult, value, min, max)."""
return (self.trait.base, self.trait.mod, self.trait.mult, self.trait.value, self.trait.min, self.trait.max) return (
self.trait.base,
self.trait.mod,
self.trait.mult,
self.trait.value,
self.trait.min,
self.trait.max,
)
def test_init(self): def test_init(self):
self.assertEqual( self.assertEqual(
@ -634,7 +640,14 @@ class TestTraitGauge(_TraitHandlerBase):
def _get_values(self): def _get_values(self):
"""Get (base, mod, mult, value, min, max).""" """Get (base, mod, mult, value, min, max)."""
return (self.trait.base, self.trait.mod, self.trait.mult, self.trait.value, self.trait.min, self.trait.max) return (
self.trait.base,
self.trait.mod,
self.trait.mult,
self.trait.value,
self.trait.min,
self.trait.max,
)
def test_init(self): def test_init(self):
self.assertEqual( self.assertEqual(

View file

@ -1148,7 +1148,7 @@ class Trait:
class StaticTrait(Trait): class StaticTrait(Trait):
""" """
Static Trait. This is a single value with a modifier, Static Trait. This is a single value with a modifier,
multiplier, and no concept of a 'current' value or min/max etc. multiplier, and no concept of a 'current' value or min/max etc.
value = (base + mod) * mult value = (base + mod) * mult
@ -1161,7 +1161,9 @@ class StaticTrait(Trait):
def __str__(self): def __str__(self):
status = "{value:11}".format(value=self.value) status = "{value:11}".format(value=self.value)
return "{name:12} {status} ({mod:+3}) (* {mult:.2f})".format(name=self.name, status=status, mod=self.mod, mult=self.mult) return "{name:12} {status} ({mod:+3}) (* {mult:.2f})".format(
name=self.name, status=status, mod=self.mod, mult=self.mult
)
# Helpers # Helpers
@property @property
@ -1189,7 +1191,7 @@ class StaticTrait(Trait):
def mult(self): def mult(self):
"""The trait's multiplier.""" """The trait's multiplier."""
return self._data["mult"] return self._data["mult"]
@mult.setter @mult.setter
def mult(self, amount): def mult(self, amount):
if type(amount) in (int, float): if type(amount) in (int, float):
@ -1322,16 +1324,16 @@ class CounterTrait(Trait):
now = time() now = time()
tdiff = now - self._data["last_update"] tdiff = now - self._data["last_update"]
current += rate * tdiff current += rate * tdiff
value = (current + self.mod) value = current + self.mod
# we must make sure so we don't overstep our bounds # we must make sure so we don't overstep our bounds
# even if .mod is included # even if .mod is included
if self._passed_ratetarget(value): if self._passed_ratetarget(value):
current = (self._data["ratetarget"] - self.mod) current = self._data["ratetarget"] - self.mod
self._stop_timer() self._stop_timer()
elif not self._within_boundaries(value): elif not self._within_boundaries(value):
current = (self._enforce_boundaries(value) - self.mod) current = self._enforce_boundaries(value) - self.mod
self._stop_timer() self._stop_timer()
else: else:
self._data["last_update"] = now self._data["last_update"] = now
@ -1378,7 +1380,7 @@ class CounterTrait(Trait):
@property @property
def mult(self): def mult(self):
return self._data["mult"] return self._data["mult"]
@mult.setter @mult.setter
def mult(self, amount): def mult(self, amount):
if type(amount) in (int, float): if type(amount) in (int, float):
@ -1571,7 +1573,9 @@ class GaugeTrait(CounterTrait):
def __str__(self): def __str__(self):
status = "{value:4} / {base:4}".format(value=self.value, base=self.base) status = "{value:4} / {base:4}".format(value=self.value, base=self.base)
return "{name:12} {status} ({mod:+3}) (* {mult:.2f})".format(name=self.name, status=status, mod=self.mod, mult=self.mult) return "{name:12} {status} ({mod:+3}) (* {mult:.2f})".format(
name=self.name, status=status, mod=self.mod, mult=self.mult
)
@property @property
def base(self): def base(self):
@ -1596,11 +1600,11 @@ class GaugeTrait(CounterTrait):
if value + self.base < self.min: if value + self.base < self.min:
value = self.min - self.base value = self.min - self.base
self._data["mod"] = value self._data["mod"] = value
@property @property
def mult(self): def mult(self):
return self._data["mult"] return self._data["mult"]
@mult.setter @mult.setter
def mult(self, amount): def mult(self, amount):
if type(amount) in (int, float): if type(amount) in (int, float):
@ -1621,7 +1625,7 @@ class GaugeTrait(CounterTrait):
if value is None: if value is None:
self._data["min"] = self.default_keys["min"] self._data["min"] = self.default_keys["min"]
elif type(value) in (int, float): elif type(value) in (int, float):
self._data["min"] = min(value, (self.base + self.mod) * self.mult) self._data["min"] = min(value, (self.base + self.mod) * self.mult)
@property @property
def max(self): def max(self):
@ -1644,7 +1648,7 @@ class GaugeTrait(CounterTrait):
def current(self): def current(self):
"""The `current` value of the gauge.""" """The `current` value of the gauge."""
return self._update_current( return self._update_current(
self._enforce_boundaries(self._data.get("current", (self.base + self.mod) * self.mult)) self._enforce_boundaries(self._data.get("current", (self.base + self.mod) * self.mult))
) )
@current.setter @current.setter
@ -1655,7 +1659,7 @@ class GaugeTrait(CounterTrait):
@current.deleter @current.deleter
def current(self): def current(self):
"Resets current back to 'full'" "Resets current back to 'full'"
self._data["current"] = (self.base + self.mod) * self.mult self._data["current"] = (self.base + self.mod) * self.mult
@property @property
def value(self): def value(self):

View file

@ -12,9 +12,13 @@ import re
# since we use them (e.g. as command names). # since we use them (e.g. as command names).
# Lunr's default ignore-word list is found here: # Lunr's default ignore-word list is found here:
# https://github.com/yeraydiazdiaz/lunr.py/blob/master/lunr/stop_word_filter.py # https://github.com/yeraydiazdiaz/lunr.py/blob/master/lunr/stop_word_filter.py
_LUNR_STOP_WORD_FILTER_EXCEPTIONS = ( _LUNR_STOP_WORD_FILTER_EXCEPTIONS = [
["about", "might", "get", "who", "say"] + settings.LUNR_STOP_WORD_FILTER_EXCEPTIONS "about",
) "might",
"get",
"who",
"say",
] + settings.LUNR_STOP_WORD_FILTER_EXCEPTIONS
_LUNR = None _LUNR = None

View file

@ -473,6 +473,7 @@ def tag(accessing_obj, accessed_obj, *args, **kwargs):
category = args[1] if len(args) > 1 else None category = args[1] if len(args) > 1 else None
return bool(accessing_obj.tags.get(tagkey, category=category)) return bool(accessing_obj.tags.get(tagkey, category=category))
def is_ooc(accessing_obj, accessed_obj, *args, **kwargs): def is_ooc(accessing_obj, accessed_obj, *args, **kwargs):
""" """
Usage: Usage:
@ -489,13 +490,14 @@ def is_ooc(accessing_obj, accessed_obj, *args, **kwargs):
session = accessed_obj.session session = accessed_obj.session
except AttributeError: except AttributeError:
session = account.sessions.get()[0] # note-this doesn't work well session = account.sessions.get()[0] # note-this doesn't work well
# for high multisession mode. We may need # for high multisession mode. We may need
# to change to sessiondb to resolve this # to change to sessiondb to resolve this
try: try:
return not account.get_puppet(session) return not account.get_puppet(session)
except TypeError: except TypeError:
return not session.get_puppet() return not session.get_puppet()
def objtag(accessing_obj, accessed_obj, *args, **kwargs): def objtag(accessing_obj, accessed_obj, *args, **kwargs):
""" """
Usage: Usage:

View file

@ -528,10 +528,10 @@ def search_prototype(
""" """
# This will load the prototypes the first time they are searched # This will load the prototypes the first time they are searched
loaded = getattr(load_module_prototypes, '_LOADED', False) loaded = getattr(load_module_prototypes, "_LOADED", False)
if not loaded: if not loaded:
load_module_prototypes() load_module_prototypes()
setattr(load_module_prototypes, '_LOADED', True) setattr(load_module_prototypes, "_LOADED", True)
# prototype keys are always in lowecase # prototype keys are always in lowecase
if key: if key:

View file

@ -2316,9 +2316,11 @@ def main():
if option in ("makemessages", "compilemessages"): if option in ("makemessages", "compilemessages"):
# some commands don't require the presence of a game directory to work # some commands don't require the presence of a game directory to work
need_gamedir = False need_gamedir = False
if CURRENT_DIR != EVENNIA_LIB: if CURRENT_DIR != EVENNIA_LIB:
print("You must stand in the evennia/evennia/ folder (where the 'locale/' " print(
"folder is located) to run this command.") "You must stand in the evennia/evennia/ folder (where the 'locale/' "
"folder is located) to run this command."
)
sys.exit() sys.exit()
if option in ("shell", "check", "makemigrations", "createsuperuser", "shell_plus"): if option in ("shell", "check", "makemigrations", "createsuperuser", "shell_plus"):

View file

@ -423,6 +423,7 @@ class Evennia:
logger.log_msg("Evennia Server successfully restarted in 'reset' mode.") logger.log_msg("Evennia Server successfully restarted in 'reset' mode.")
elif mode == "shutdown": elif mode == "shutdown":
from evennia.objects.models import ObjectDB from evennia.objects.models import ObjectDB
self.at_server_cold_start() self.at_server_cold_start()
# clear eventual lingering session storages # clear eventual lingering session storages
ObjectDB.objects.clear_all_sessids() ObjectDB.objects.clear_all_sessids()

View file

@ -197,7 +197,6 @@ class TestServer(TestCase):
class TestInitHooks(TestCase): class TestInitHooks(TestCase):
def setUp(self): def setUp(self):
from evennia.utils import create from evennia.utils import create

View file

@ -16,15 +16,18 @@ class EvenniaTestSuiteRunner(DiscoverRunner):
avoid running the large number of tests defined by Django avoid running the large number of tests defined by Django
""" """
def setup_test_environment(self, **kwargs): def setup_test_environment(self, **kwargs):
# the portal looping call starts before the unit-test suite so we # the portal looping call starts before the unit-test suite so we
# can't mock it - instead we stop it before starting the test - otherwise # can't mock it - instead we stop it before starting the test - otherwise
# we'd get unclean reactor errors across test boundaries. # we'd get unclean reactor errors across test boundaries.
from evennia.server.portal.portal import PORTAL from evennia.server.portal.portal import PORTAL
PORTAL.maintenance_task.stop() PORTAL.maintenance_task.stop()
# initialize evennia itself # initialize evennia itself
import evennia import evennia
evennia._init() evennia._init()
from django.conf import settings from django.conf import settings
@ -37,6 +40,7 @@ class EvenniaTestSuiteRunner(DiscoverRunner):
# remove testing flag after suite has run # remove testing flag after suite has run
from django.conf import settings from django.conf import settings
settings._TEST_ENVIRONMENT = False settings._TEST_ENVIRONMENT = False
super().teardown_test_environment(**kwargs) super().teardown_test_environment(**kwargs)

View file

@ -218,13 +218,15 @@ class AttributeProperty:
""" """
value = self._default value = self._default
try: try:
value = self.at_get(getattr(instance, self.attrhandler_name).get( value = self.at_get(
key=self._key, getattr(instance, self.attrhandler_name).get(
default=self._default, key=self._key,
category=self._category, default=self._default,
strattr=self._strattr, category=self._category,
raise_exception=self._autocreate, strattr=self._strattr,
)) raise_exception=self._autocreate,
)
)
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

View file

@ -96,6 +96,7 @@ class Tag(models.Model):
# Handlers making use of the Tags model # Handlers making use of the Tags model
# #
class TagProperty: class TagProperty:
""" """
Tag property descriptor. Allows for setting tags on an object as Django-like 'fields' Tag property descriptor. Allows for setting tags on an object as Django-like 'fields'
@ -112,6 +113,7 @@ class TagProperty:
mytag2 = TagProperty(category="tagcategory") mytag2 = TagProperty(category="tagcategory")
""" """
taghandler_name = "tags" taghandler_name = "tags"
def __init__(self, category=None, data=None): def __init__(self, category=None, data=None):
@ -134,10 +136,7 @@ class TagProperty:
""" """
try: try:
return getattr(instance, self.taghandler_name).get( return getattr(instance, self.taghandler_name).get(
key=self._key, key=self._key, category=self._category, return_list=False, raise_exception=True
category=self._category,
return_list=False,
raise_exception=True
) )
except AttributeError: except AttributeError:
self.__set__(instance, self._category) self.__set__(instance, self._category)
@ -150,9 +149,7 @@ class TagProperty:
self._category = category self._category = category
( (
getattr(instance, self.taghandler_name).add( getattr(instance, self.taghandler_name).add(
key=self._key, key=self._key, category=self._category, data=self._data
category=self._category,
data=self._data
) )
) )
@ -430,8 +427,15 @@ class TagHandler(object):
return ret[0] if len(ret) == 1 else ret return ret[0] if len(ret) == 1 else ret
def get(self, key=None, default=None, category=None, return_tagobj=False, return_list=False, def get(
raise_exception=False): self,
key=None,
default=None,
category=None,
return_tagobj=False,
return_list=False,
raise_exception=False,
):
""" """
Get the tag for the given key, category or combination of the two. Get the tag for the given key, category or combination of the two.
@ -613,6 +617,7 @@ class AliasProperty(TagProperty):
bob = AliasProperty() bob = AliasProperty()
""" """
taghandler_name = "aliases" taghandler_name = "aliases"
@ -636,6 +641,7 @@ class PermissionProperty(TagProperty):
myperm = PermissionProperty() myperm = PermissionProperty()
""" """
taghandler_name = "permissions" taghandler_name = "permissions"

View file

@ -145,7 +145,9 @@ class TestTypedObjectManager(BaseEvenniaTest):
def test_get_tag_with_any_including_nones(self): def test_get_tag_with_any_including_nones(self):
self.obj1.tags.add("tagA", "categoryA") self.obj1.tags.add("tagA", "categoryA")
self.assertEqual( self.assertEqual(
self._manager("get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB", None], match="any"), self._manager(
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB", None], match="any"
),
[self.obj1], [self.obj1],
) )

View file

@ -1255,12 +1255,12 @@ class EvMenu:
min_rows = 4 min_rows = 4
# split the items into columns # split the items into columns
split = max(min_rows, ceil(len(table)/ncols)) split = max(min_rows, ceil(len(table) / ncols))
max_end = len(table) max_end = len(table)
cols_list = [] cols_list = []
for icol in range(ncols): for icol in range(ncols):
start = icol*split start = icol * split
end = min(start+split,max_end) end = min(start + split, max_end)
cols_list.append(EvColumn(*table[start:end])) cols_list.append(EvColumn(*table[start:end]))
return str(EvTable(table=cols_list, border="none")) return str(EvTable(table=cols_list, border="none"))

View file

@ -410,7 +410,7 @@ class FuncParser:
single_quoted = -1 single_quoted = -1
elif single_quoted > 0: elif single_quoted > 0:
prefix = infuncstr[0:single_quoted] prefix = infuncstr[0:single_quoted]
infuncstr = prefix + infuncstr[single_quoted+1:] infuncstr = prefix + infuncstr[single_quoted + 1 :]
single_quoted = -1 single_quoted = -1
else: else:
infuncstr += char infuncstr += char
@ -427,7 +427,7 @@ class FuncParser:
double_quoted = -1 double_quoted = -1
elif double_quoted > 0: elif double_quoted > 0:
prefix = infuncstr[0:double_quoted] prefix = infuncstr[0:double_quoted]
infuncstr = prefix + infuncstr[double_quoted + 1:] infuncstr = prefix + infuncstr[double_quoted + 1 :]
double_quoted = -1 double_quoted = -1
else: else:
infuncstr += char infuncstr += char

View file

@ -67,7 +67,7 @@ class TimeScript(DefaultScript):
callback(*args, **kwargs) callback(*args, **kwargs)
seconds = real_seconds_until(**self.db.gametime) seconds = real_seconds_until(**self.db.gametime)
self.start(interval=seconds,force_restart=True) self.start(interval=seconds, force_restart=True)
# Access functions # Access functions

View file

@ -50,6 +50,7 @@ def _log(msg, logfunc, prefix="", **kwargs):
# log call functions (each has legacy aliases) # log call functions (each has legacy aliases)
def log_info(msg, **kwargs): def log_info(msg, **kwargs):
""" """
Logs any generic debugging/informative info that should appear in the log. Logs any generic debugging/informative info that should appear in the log.
@ -62,6 +63,7 @@ def log_info(msg, **kwargs):
""" """
_log(msg, log.info, **kwargs) _log(msg, log.info, **kwargs)
info = log_info info = log_info
log_infomsg = log_info log_infomsg = log_info
log_msg = log_info log_msg = log_info
@ -79,6 +81,7 @@ def log_warn(msg, **kwargs):
""" """
_log(msg, log.warn, **kwargs) _log(msg, log.warn, **kwargs)
warn = log_warn warn = log_warn
warning = log_warn warning = log_warn
log_warnmsg = log_warn log_warnmsg = log_warn
@ -120,6 +123,7 @@ def log_trace(msg=None, **kwargs):
if msg: if msg:
_log(msg, log.error, prefix="!!", **kwargs) _log(msg, log.error, prefix="!!", **kwargs)
log_tracemsg = log_trace log_tracemsg = log_trace
exception = log_trace exception = log_trace
critical = log_trace critical = log_trace
@ -156,6 +160,7 @@ def log_sec(msg, **kwargs):
""" """
_log(msg, log.info, prefix="SS", **kwargs) _log(msg, log.info, prefix="SS", **kwargs)
sec = log_sec sec = log_sec
security = log_sec security = log_sec
log_secmsg = log_sec log_secmsg = log_sec
@ -174,12 +179,12 @@ def log_server(msg, **kwargs):
_log(msg, log.info, prefix="Server", **kwargs) _log(msg, log.info, prefix="Server", **kwargs)
class GetLogObserver: class GetLogObserver:
""" """
Sets up how the system logs are formatted. Sets up how the system logs are formatted.
""" """
component_prefix = "" component_prefix = ""
event_levels = { event_levels = {
twisted_logger.LogLevel.debug: "??", twisted_logger.LogLevel.debug: "??",
@ -207,8 +212,7 @@ class GetLogObserver:
event["log_format"] = str(event.get("log_format", "")) event["log_format"] = str(event.get("log_format", ""))
component_prefix = self.component_prefix or "" component_prefix = self.component_prefix or ""
log_msg = twisted_logger.formatEventAsClassicLogText( log_msg = twisted_logger.formatEventAsClassicLogText(
event, event, formatTime=lambda e: twisted_logger.formatTime(e, _TIME_FORMAT)
formatTime=lambda e: twisted_logger.formatTime(e, _TIME_FORMAT)
) )
return f"{component_prefix}{log_msg}" return f"{component_prefix}{log_msg}"
@ -218,14 +222,15 @@ class GetLogObserver:
# Called by server/portal on startup # Called by server/portal on startup
class GetPortalLogObserver(GetLogObserver): class GetPortalLogObserver(GetLogObserver):
component_prefix = "|Portal| " component_prefix = "|Portal| "
class GetServerLogObserver(GetLogObserver): class GetServerLogObserver(GetLogObserver):
component_prefix = "" component_prefix = ""
# logging overrides # logging overrides
@ -352,6 +357,7 @@ class WeeklyLogFile(logfile.DailyLogFile):
self.lastDate = max(self.lastDate, self.toDate()) self.lastDate = max(self.lastDate, self.toDate())
self.size += len(data) self.size += len(data)
# Arbitrary file logger # Arbitrary file logger

View file

@ -96,7 +96,6 @@ DEFAULT_SETTING_RESETS = dict(
"evennia.game_template.server.conf.prototypefuncs", "evennia.game_template.server.conf.prototypefuncs",
], ],
BASE_GUEST_TYPECLASS="evennia.accounts.accounts.DefaultGuest", BASE_GUEST_TYPECLASS="evennia.accounts.accounts.DefaultGuest",
# a special setting boolean _TEST_ENVIRONMENT is set by the test runner # a special setting boolean _TEST_ENVIRONMENT is set by the test runner
# while the test suite is running. # while the test suite is running.
) )

View file

@ -119,14 +119,17 @@ class TestDbSerialize(TestCase):
class _InvalidContainer: class _InvalidContainer:
"""Container not saveable in Attribute (if obj is dbobj, it 'hides' it)""" """Container not saveable in Attribute (if obj is dbobj, it 'hides' it)"""
def __init__(self, obj): def __init__(self, obj):
self.hidden_obj = obj self.hidden_obj = obj
class _ValidContainer(_InvalidContainer): class _ValidContainer(_InvalidContainer):
"""Container possible to save in Attribute (handles hidden dbobj explicitly)""" """Container possible to save in Attribute (handles hidden dbobj explicitly)"""
def __serialize_dbobjs__(self): def __serialize_dbobjs__(self):
self.hidden_obj = dbserialize.dbserialize(self.hidden_obj) self.hidden_obj = dbserialize.dbserialize(self.hidden_obj)
def __deserialize_dbobjs__(self): def __deserialize_dbobjs__(self):
self.hidden_obj = dbserialize.dbunserialize(self.hidden_obj) self.hidden_obj = dbserialize.dbunserialize(self.hidden_obj)
@ -136,6 +139,7 @@ class DbObjWrappers(TestCase):
Test the `__serialize_dbobjs__` and `__deserialize_dbobjs__` methods. Test the `__serialize_dbobjs__` and `__deserialize_dbobjs__` methods.
""" """
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.dbobj1 = DefaultObject(db_key="Tester1") self.dbobj1 = DefaultObject(db_key="Tester1")
@ -148,7 +152,7 @@ class DbObjWrappers(TestCase):
self.dbobj1.db.testarg = _InvalidContainer(self.dbobj1) self.dbobj1.db.testarg = _InvalidContainer(self.dbobj1)
def test_consecutive_fetch(self): def test_consecutive_fetch(self):
con =_ValidContainer(self.dbobj2) con = _ValidContainer(self.dbobj2)
self.dbobj1.db.testarg = con self.dbobj1.db.testarg = con
attrobj = self.dbobj1.attributes.get("testarg", return_obj=True) attrobj = self.dbobj1.attributes.get("testarg", return_obj=True)
@ -157,7 +161,7 @@ class DbObjWrappers(TestCase):
self.assertEqual(attrobj.value.hidden_obj, self.dbobj2) self.assertEqual(attrobj.value.hidden_obj, self.dbobj2)
def test_dbobj_hidden_obj__success(self): def test_dbobj_hidden_obj__success(self):
con =_ValidContainer(self.dbobj2) con = _ValidContainer(self.dbobj2)
self.dbobj1.db.testarg = con self.dbobj1.db.testarg = con
# accessing the same data twice # accessing the same data twice

View file

@ -116,7 +116,7 @@ class TestFuncParser(TestCase):
("Test args2 $bar(foo, bar, too)", "Test args2 _test(foo, bar, too)"), ("Test args2 $bar(foo, bar, too)", "Test args2 _test(foo, bar, too)"),
(r"Test args3 $bar(foo, bar, ' too')", "Test args3 _test(foo, bar, too)"), (r"Test args3 $bar(foo, bar, ' too')", "Test args3 _test(foo, bar, too)"),
("Test args4 $foo('')", "Test args4 _test()"), ("Test args4 $foo('')", "Test args4 _test()"),
('Test args4 $foo("")', 'Test args4 _test()'), ('Test args4 $foo("")', "Test args4 _test()"),
("Test args5 $foo(\(\))", "Test args5 _test(())"), ("Test args5 $foo(\(\))", "Test args5 _test(())"),
("Test args6 $foo(\()", "Test args6 _test(()"), ("Test args6 $foo(\()", "Test args6 _test(()"),
("Test args7 $foo(())", "Test args7 _test(())"), ("Test args7 $foo(())", "Test args7 _test(())"),
@ -183,14 +183,20 @@ class TestFuncParser(TestCase):
("Test eval2 $eval((21 + 21) / 2)", "Test eval2 21.0"), ("Test eval2 $eval((21 + 21) / 2)", "Test eval2 21.0"),
("Test eval3 $eval(\"'21' + 'foo' + 'bar'\")", "Test eval3 21foobar"), ("Test eval3 $eval(\"'21' + 'foo' + 'bar'\")", "Test eval3 21foobar"),
(r"Test eval4 $eval(\'21\' + \'$repl()\' + \"''\" + str(10 // 2))", "Test eval4 21rr5"), (r"Test eval4 $eval(\'21\' + \'$repl()\' + \"''\" + str(10 // 2))", "Test eval4 21rr5"),
(r"Test eval5 $eval(\'21\' + \'\$repl()\' + \'\' + str(10 // 2))", "Test eval5 21$repl()5"), (
r"Test eval5 $eval(\'21\' + \'\$repl()\' + \'\' + str(10 // 2))",
"Test eval5 21$repl()5",
),
("Test eval6 $eval(\"'$repl(a)' + '$repl(b)'\")", "Test eval6 rarrbr"), ("Test eval6 $eval(\"'$repl(a)' + '$repl(b)'\")", "Test eval6 rarrbr"),
("Test type1 $typ([1,2,3,4])", "Test type1 <class 'list'>"), ("Test type1 $typ([1,2,3,4])", "Test type1 <class 'list'>"),
("Test type2 $typ((1,2,3,4))", "Test type2 <class 'tuple'>"), ("Test type2 $typ((1,2,3,4))", "Test type2 <class 'tuple'>"),
("Test type3 $typ({1,2,3,4})", "Test type3 <class 'set'>"), ("Test type3 $typ({1,2,3,4})", "Test type3 <class 'set'>"),
("Test type4 $typ({1:2,3:4})", "Test type4 <class 'dict'>"), ("Test type4 $typ({1:2,3:4})", "Test type4 <class 'dict'>"),
("Test type5 $typ(1), $typ(1.0)", "Test type5 <class 'int'>, <class 'float'>"), ("Test type5 $typ(1), $typ(1.0)", "Test type5 <class 'int'>, <class 'float'>"),
("Test type6 $typ(\"'1'\"), $typ('\"1.0\"')", "Test type6 <class 'str'>, <class 'str'>"), (
"Test type6 $typ(\"'1'\"), $typ('\"1.0\"')",
"Test type6 <class 'str'>, <class 'str'>",
),
("Test add1 $add(1, 2)", "Test add1 3"), ("Test add1 $add(1, 2)", "Test add1 3"),
("Test add2 $add([1,2,3,4], [5,6])", "Test add2 [1, 2, 3, 4, 5, 6]"), ("Test add2 $add([1,2,3,4], [5,6])", "Test add2 [1, 2, 3, 4, 5, 6]"),
("Test literal1 $sum($lit([1,2,3,4,5,6]))", "Test literal1 21"), ("Test literal1 $sum($lit([1,2,3,4,5,6]))", "Test literal1 21"),
@ -198,7 +204,6 @@ class TestFuncParser(TestCase):
("Test literal3 $typ($lit(1)aaa)", "Test literal3 <class 'str'>"), ("Test literal3 $typ($lit(1)aaa)", "Test literal3 <class 'str'>"),
("Test literal4 $typ(aaa$lit(1))", "Test literal4 <class 'str'>"), ("Test literal4 $typ(aaa$lit(1))", "Test literal4 <class 'str'>"),
("Test spider's thread", "Test spider's thread"), ("Test spider's thread", "Test spider's thread"),
] ]
) )
def test_parse(self, string, expected): def test_parse(self, string, expected):
@ -398,7 +403,7 @@ class TestDefaultCallables(TestCase):
("Some $rjust(Hello, width=30)", "Some Hello"), ("Some $rjust(Hello, width=30)", "Some Hello"),
("Some $cjust(Hello, 30)", "Some Hello "), ("Some $cjust(Hello, 30)", "Some Hello "),
("Some $eval(\"'-'*20\")Hello", "Some --------------------Hello"), ("Some $eval(\"'-'*20\")Hello", "Some --------------------Hello"),
("$crop(\"spider's silk\", 5)", "spide"), ('$crop("spider\'s silk", 5)', "spide"),
] ]
) )
def test_other_callables(self, string, expected): def test_other_callables(self, string, expected):
@ -468,13 +473,14 @@ class TestDefaultCallables(TestCase):
def test_escaped2(self): def test_escaped2(self):
raw_str = 'this should be $pad("""escaped,""" and """instead,""" cropped $crop(with a long,5) text., 80)' raw_str = 'this should be $pad("""escaped,""" and """instead,""" cropped $crop(with a long,5) text., 80)'
expected = 'this should be escaped, and instead, cropped with text. ' expected = "this should be escaped, and instead, cropped with text. "
result = self.parser.parse(raw_str) result = self.parser.parse(raw_str)
self.assertEqual( self.assertEqual(
result, result,
expected, expected,
) )
class TestCallableSearch(test_resources.BaseEvenniaTest): class TestCallableSearch(test_resources.BaseEvenniaTest):
""" """
Test the $search(query) callable Test the $search(query) callable

View file

@ -12,7 +12,9 @@ class TestText2Html(TestCase):
self.assertEqual("foo", parser.format_styles("foo")) self.assertEqual("foo", parser.format_styles("foo"))
self.assertEqual( self.assertEqual(
'<span class="color-001">red</span>foo', '<span class="color-001">red</span>foo',
parser.format_styles(ansi.ANSI_UNHILITE + ansi.ANSI_RED + "red" + ansi.ANSI_NORMAL + "foo"), parser.format_styles(
ansi.ANSI_UNHILITE + ansi.ANSI_RED + "red" + ansi.ANSI_NORMAL + "foo"
),
) )
self.assertEqual( self.assertEqual(
'<span class="bgcolor-001">red</span>foo', '<span class="bgcolor-001">red</span>foo',
@ -31,33 +33,15 @@ class TestText2Html(TestCase):
) )
self.assertEqual( self.assertEqual(
'a <span class="underline">red</span>foo', 'a <span class="underline">red</span>foo',
parser.format_styles( parser.format_styles("a " + ansi.ANSI_UNDERLINE + "red" + ansi.ANSI_NORMAL + "foo"),
"a "
+ ansi.ANSI_UNDERLINE
+ "red"
+ ansi.ANSI_NORMAL
+ "foo"
),
) )
self.assertEqual( self.assertEqual(
'a <span class="blink">red</span>foo', 'a <span class="blink">red</span>foo',
parser.format_styles( parser.format_styles("a " + ansi.ANSI_BLINK + "red" + ansi.ANSI_NORMAL + "foo"),
"a "
+ ansi.ANSI_BLINK
+ "red"
+ ansi.ANSI_NORMAL
+ "foo"
),
) )
self.assertEqual( self.assertEqual(
'a <span class="bgcolor-007 color-000">red</span>foo', 'a <span class="bgcolor-007 color-000">red</span>foo',
parser.format_styles( parser.format_styles("a " + ansi.ANSI_INVERSE + "red" + ansi.ANSI_NORMAL + "foo"),
"a "
+ ansi.ANSI_INVERSE
+ "red"
+ ansi.ANSI_NORMAL
+ "foo"
),
) )
def test_remove_bells(self): def test_remove_bells(self):
@ -65,13 +49,7 @@ class TestText2Html(TestCase):
self.assertEqual("foo", parser.remove_bells("foo")) self.assertEqual("foo", parser.remove_bells("foo"))
self.assertEqual( self.assertEqual(
"a red" + ansi.ANSI_NORMAL + "foo", "a red" + ansi.ANSI_NORMAL + "foo",
parser.remove_bells( parser.remove_bells("a " + ansi.ANSI_BEEP + "red" + ansi.ANSI_NORMAL + "foo"),
"a "
+ ansi.ANSI_BEEP
+ "red"
+ ansi.ANSI_NORMAL
+ "foo"
),
) )
def test_remove_backspaces(self): def test_remove_backspaces(self):
@ -160,20 +138,20 @@ class TestText2Html(TestCase):
self.assertEqual( self.assertEqual(
text2html.parse_html("|^|[CHello|n|u|rW|go|yr|bl|md|c!|[G!"), text2html.parse_html("|^|[CHello|n|u|rW|go|yr|bl|md|c!|[G!"),
'<span class="blink bgcolor-006">' '<span class="blink bgcolor-006">'
'Hello' "Hello"
'</span><span class="underline color-009">' '</span><span class="underline color-009">'
'W' "W"
'</span><span class="underline color-010">' '</span><span class="underline color-010">'
'o' "o"
'</span><span class="underline color-011">' '</span><span class="underline color-011">'
'r' "r"
'</span><span class="underline color-012">' '</span><span class="underline color-012">'
'l' "l"
'</span><span class="underline color-013">' '</span><span class="underline color-013">'
'd' "d"
'</span><span class="underline color-014">' '</span><span class="underline color-014">'
'!' "!"
'</span><span class="underline bgcolor-002 color-014">' '</span><span class="underline bgcolor-002 color-014">'
'!' "!"
'</span>', "</span>",
) )

View file

@ -2695,6 +2695,7 @@ def copy_word_case(base_word, new_word):
+ excess + excess
) )
def run_in_main_thread(function_or_method, *args, **kwargs): def run_in_main_thread(function_or_method, *args, **kwargs):
""" """
Force a callable to execute in the main Evennia thread. This is only relevant when Force a callable to execute in the main Evennia thread. This is only relevant when