diff --git a/evennia/commands/cmdsethandler.py b/evennia/commands/cmdsethandler.py index 1930aa3bce..d6338eac75 100644 --- a/evennia/commands/cmdsethandler.py +++ b/evennia/commands/cmdsethandler.py @@ -450,9 +450,7 @@ class CmdSetHandler(object): """ if "permanent" in kwargs: - logger.log_dep( - "obj.cmdset.add() kwarg 'permanent' has changed name to 'persistent'." - ) + logger.log_dep("obj.cmdset.add() kwarg 'permanent' has changed name to 'persistent'.") persistent = kwargs["permanent"] if persistent is False else persistent if not (isinstance(cmdset, str) or utils.inherits_from(cmdset, CmdSet)): diff --git a/evennia/commands/default/building.py b/evennia/commands/default/building.py index e8d3b6a5b6..582c6434e4 100644 --- a/evennia/commands/default/building.py +++ b/evennia/commands/default/building.py @@ -2219,11 +2219,13 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS): old_typeclass_path = obj.typeclass_path if reset: - answer = yield("|yNote that this will reset the object back to its typeclass' default state, " - "removing any custom locks/perms/attributes etc that may have been added " - "by an explicit create_object call. Use `update` or type/force instead in order " - "to keep such data. " - "Continue [Y]/N?|n") + answer = yield ( + "|yNote that this will reset the object back to its typeclass' default state, " + "removing any custom locks/perms/attributes etc that may have been added " + "by an explicit create_object call. Use `update` or type/force instead in order " + "to keep such data. " + "Continue [Y]/N?|n" + ) if answer.upper() in ("N", "NO"): caller.msg("Aborted.") return @@ -3473,7 +3475,7 @@ class CmdScripts(COMMAND_DEFAULT_CLASS): caller.msg("\n".join(msgs)) if "delete" not in self.switches: if script and script.pk: - ScriptEvMore(caller, [script], session=self.session) + ScriptEvMore(caller, [script], session=self.session) else: caller.msg("Script was deleted automatically.") else: diff --git a/evennia/commands/default/tests.py b/evennia/commands/default/tests.py index cfcc622689..32f4a882f5 100644 --- a/evennia/commands/default/tests.py +++ b/evennia/commands/default/tests.py @@ -107,8 +107,7 @@ class TestGeneral(BaseEvenniaCommandTest): def test_nick_list(self): self.call(general.CmdNick(), "/list", "No nicks defined.") - self.call(general.CmdNick(), "test1 = Hello", - "Inputline-nick 'test1' mapped to 'Hello'.") + self.call(general.CmdNick(), "test1 = Hello", "Inputline-nick 'test1' mapped to 'Hello'.") self.call(general.CmdNick(), "/list", "Defined Nicks:") def test_get_and_drop(self): @@ -1295,7 +1294,8 @@ class TestBuilding(BaseEvenniaCommandTest): "Obj2 = evennia.objects.objects.DefaultExit", "Obj2 changed typeclass from evennia.objects.objects.DefaultObject " "to evennia.objects.objects.DefaultExit.", - cmdstring="swap", inputs=["yes"], + cmdstring="swap", + inputs=["yes"], ) self.call(building.CmdTypeclass(), "/list Obj", "Core typeclasses") self.call( @@ -1332,7 +1332,7 @@ class TestBuilding(BaseEvenniaCommandTest): "/reset/force Obj=evennia.objects.objects.DefaultObject", "Obj updated its existing typeclass (evennia.objects.objects.DefaultObject).\n" "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 @@ -1359,7 +1359,7 @@ class TestBuilding(BaseEvenniaCommandTest): "typeclasses.objects.Object.\nOnly the at_object_creation hook was run " "(update mode). Attributes set before swap were not removed\n" "(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" diff --git a/evennia/contrib/base_systems/components/__init__.py b/evennia/contrib/base_systems/components/__init__.py index 1aa94a1df1..21bb6bf936 100644 --- a/evennia/contrib/base_systems/components/__init__.py +++ b/evennia/contrib/base_systems/components/__init__.py @@ -17,8 +17,10 @@ def get_component_class(component_name): subclasses = Component.__subclasses__() component_class = next((sc for sc in subclasses if sc.name == component_name), None) if component_class is None: - message = f"Component named {component_name} has not been found. " \ - f"Make sure it has been imported before being used." + message = ( + f"Component named {component_name} has not been found. " + f"Make sure it has been imported before being used." + ) raise Exception(message) return component_class diff --git a/evennia/contrib/base_systems/components/component.py b/evennia/contrib/base_systems/components/component.py index 4b1697da38..4be5b86d15 100644 --- a/evennia/contrib/base_systems/components/component.py +++ b/evennia/contrib/base_systems/components/component.py @@ -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. """ + name = "" def __init__(self, host=None): diff --git a/evennia/contrib/base_systems/components/dbfield.py b/evennia/contrib/base_systems/components/dbfield.py index 9adbf8197f..fc3a104ffb 100644 --- a/evennia/contrib/base_systems/components/dbfield.py +++ b/evennia/contrib/base_systems/components/dbfield.py @@ -26,7 +26,7 @@ class DBField(AttributeProperty): db_fields = getattr(owner, "_db_fields", None) if db_fields is None: db_fields = {} - setattr(owner, '_db_fields', db_fields) + setattr(owner, "_db_fields", db_fields) db_fields[name] = self @@ -50,7 +50,7 @@ class NDBField(NAttributeProperty): ndb_fields = getattr(owner, "_ndb_fields", None) if ndb_fields is None: ndb_fields = {} - setattr(owner, '_ndb_fields', ndb_fields) + setattr(owner, "_ndb_fields", ndb_fields) ndb_fields[name] = self @@ -64,6 +64,7 @@ class TagField: 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 self._default = default @@ -78,7 +79,7 @@ class TagField: tag_fields = getattr(owner, "_tag_fields", None) if tag_fields is None: tag_fields = {} - setattr(owner, '_tag_fields', tag_fields) + setattr(owner, "_tag_fields", tag_fields) tag_fields[name] = self def __get__(self, instance, owner): diff --git a/evennia/contrib/base_systems/components/holder.py b/evennia/contrib/base_systems/components/holder.py index d5112083cd..91d4330f58 100644 --- a/evennia/contrib/base_systems/components/holder.py +++ b/evennia/contrib/base_systems/components/holder.py @@ -16,6 +16,7 @@ class ComponentProperty: Defaults can be overridden for this typeclass by passing kwargs """ + def __init__(self, component_name, **kwargs): """ Initializes the descriptor @@ -49,6 +50,7 @@ class ComponentHandler: 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. """ + def __init__(self, host): self.host = host self._loaded_components = {} @@ -124,7 +126,9 @@ class ComponentHandler: self.host.signals.remove_object_listeners_and_responders(component) del self._loaded_components[component_name] 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) def remove_by_name(self, name): @@ -199,7 +203,9 @@ class ComponentHandler: self._set_component(component_instance) self.host.signals.add_object_listeners_and_responders(component_instance) 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) def _set_component(self, component): diff --git a/evennia/contrib/base_systems/components/signals.py b/evennia/contrib/base_systems/components/signals.py index 23ace839dd..eff5137c64 100644 --- a/evennia/contrib/base_systems/components/signals.py +++ b/evennia/contrib/base_systems/components/signals.py @@ -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. """ if not func and signal_name: + def wrapper(func): func._listener_signal_name = signal_name return func + return wrapper 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. """ if not func and signal_name: + def wrapper(func): func._responder_signal_name = signal_name return func + return wrapper signal_name = func.__name__ @@ -177,12 +181,12 @@ class SignalsHandler(object): """ type_host = type(obj) 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: callback = getattr(obj, att_name) 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: callback = getattr(obj, att_name) self.add_responder(signal_name=responder_signal_name, callback=callback) @@ -196,12 +200,12 @@ class SignalsHandler(object): """ type_host = type(obj) 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: callback = getattr(obj, att_name) 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: callback = getattr(obj, att_name) self.remove_responder(signal_name=responder_signal_name, callback=callback) diff --git a/evennia/contrib/base_systems/components/tests.py b/evennia/contrib/base_systems/components/tests.py index 413b964c18..6251575af6 100644 --- a/evennia/contrib/base_systems/components/tests.py +++ b/evennia/contrib/base_systems/components/tests.py @@ -56,7 +56,7 @@ class TestComponents(EvenniaTest): def test_character_can_register_runtime_component(self): rct = RuntimeComponentTestC.create(self.char1) 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.my_int == 6 @@ -110,7 +110,7 @@ class TestComponents(EvenniaTest): assert handler.get("test_c") is rct 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): assert self.char1.cmp.does_not_exist is None @@ -127,7 +127,7 @@ class TestComponents(EvenniaTest): def test_host_has_added_component_tags(self): rct = RuntimeComponentTestC.create(self.char1) 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="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") 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 = "second value" @@ -171,7 +171,7 @@ class TestComponents(EvenniaTest): 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 = 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") @@ -179,12 +179,14 @@ class TestComponents(EvenniaTest): 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 = 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 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") @@ -193,11 +195,11 @@ class TestComponents(EvenniaTest): class CharWithSignal(ComponentHolderMixin, DefaultCharacter): @signals.as_listener def my_signal(self): - setattr(self, 'my_signal_is_called', True) + setattr(self, "my_signal_is_called", True) @signals.as_listener def my_other_signal(self): - setattr(self, 'my_other_signal_is_called', True) + setattr(self, "my_other_signal_is_called", True) @signals.as_responder def my_response(self): @@ -213,11 +215,11 @@ class ComponentWithSignal(Component): @signals.as_listener def my_signal(self): - setattr(self, 'my_signal_is_called', True) + setattr(self, "my_signal_is_called", True) @signals.as_listener def my_other_signal(self): - setattr(self, 'my_other_signal_is_called', True) + setattr(self, "my_other_signal_is_called", True) @signals.as_responder def my_response(self): @@ -236,14 +238,15 @@ class TestComponentSignals(BaseEvenniaTest): def setUp(self): super().setUp() self.char1 = create.create_object( - CharWithSignal, key="Char", + CharWithSignal, + key="Char", ) def test_host_can_register_as_listener(self): self.char1.signals.trigger("my_signal") 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): responses = self.char1.signals.query("my_response") @@ -258,7 +261,7 @@ class TestComponentSignals(BaseEvenniaTest): component = char.cmp.test_signal_a 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): char = self.char1 diff --git a/evennia/contrib/base_systems/custom_gametime/custom_gametime.py b/evennia/contrib/base_systems/custom_gametime/custom_gametime.py index 33588deca9..eac9020b8a 100644 --- a/evennia/contrib/base_systems/custom_gametime/custom_gametime.py +++ b/evennia/contrib/base_systems/custom_gametime/custom_gametime.py @@ -328,4 +328,4 @@ class GametimeScript(DefaultScript): callback() seconds = real_seconds_until(**self.db.gametime) - self.start(interval=seconds,force_restart=True) + self.start(interval=seconds, force_restart=True) diff --git a/evennia/contrib/rpg/rpsystem/rpsystem.py b/evennia/contrib/rpg/rpsystem/rpsystem.py index c191d72d93..69f29280c6 100644 --- a/evennia/contrib/rpg/rpsystem/rpsystem.py +++ b/evennia/contrib/rpg/rpsystem/rpsystem.py @@ -284,7 +284,7 @@ def parse_language(speaker, emote): # the key is simply the running match in the emote key = f"##{imatch}" # 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) 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 # include 'me' keyword for self-ref - candidate_map = [(sender, 'me')] + candidate_map = [(sender, "me")] for obj in candidates: # check if sender has any recogs for obj and add if hasattr(sender, "recog"): if recog := sender.recog.get(obj): - candidate_map.append((obj, recog)) + candidate_map.append((obj, recog)) # check if obj has an sdesc and add if hasattr(obj, "sdesc"): candidate_map.append((obj, obj.sdesc.get())) # if no sdesc, include key plus aliases instead 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, # 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() # split the emote string at the reference marker, to process everything after it head = string[:match_index] - tail = string[match_index+1:] - + tail = string[match_index + 1 :] + if search_mode: # 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())]) - matches = ((re.search(rquery, text, _RE_FLAGS), obj, text) for obj, text in candidate_map) + rquery = "".join( + [ + 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 bestmatches = [(obj, match.group()) for match, obj, text in matches if match] 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. word_list = [] bestmatches = [] # preserve punctuation when splitting - tail = re.split('(\W)', tail) + tail = re.split("(\W)", tail) iend = 0 for i, item in enumerate(tail): # don't add non-word characters to the search query if not item.isalpha(): - continue + continue word_list.append(item) rquery = "".join([r"\b(" + re.escape(word) + r").*" for word in word_list]) # 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] if len(matches) == 0: # 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 matched_text = "".join(tail[1:iend]) # recombine remainder of emote back into a string - tail = "".join(tail[iend+1:]) + tail = "".join(tail[iend + 1 :]) nmatches = len(bestmatches) @@ -549,18 +558,18 @@ def send_emote(sender, receivers, emote, anonymous_add="first", **kwargs): if "anonymous_add" in kwargs: anonymous_add = kwargs.pop("anonymous_add") # 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): # no self-reference in the emote - add it if anonymous_add == "first": # 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 femote = "{key}{emote}" if emote.startswith("'") else "{key} {emote}" else: # add it to the end femote = "{emote} [{key}]" - emote = femote.format( key="{{"+ skey +"}}", emote=emote ) + emote = femote.format(key="{{" + skey + "}}", emote=emote) obj_mapping[skey] = sender # broadcast emote to everyone @@ -663,7 +672,9 @@ class SdescHandler: if len(cleaned_sdesc) > max_length: 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 @@ -682,7 +693,6 @@ class SdescHandler: return self.sdesc or self.obj.key - class RecogHandler: """ This handler manages the recognition mapping @@ -758,7 +768,9 @@ class RecogHandler: if len(cleaned_recog) > max_length: 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 @@ -866,7 +878,7 @@ class CmdEmote(RPCommand): # replaces the main emote emote = self.args targets = self.caller.location.contents 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") @@ -1132,7 +1144,11 @@ class CmdRecog(RPCommand): # assign personal alias to object in room if forget_mode: # remove existing recog 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: # set recog 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 rp-heavy game. It implements the base functionality for poses. """ + @lazy_property def sdesc(self): - return SdescHandler(self) + return SdescHandler(self) def at_object_creation(self): """ @@ -1409,19 +1426,18 @@ class ContribRPObject(DefaultObject): def get_posed_sdesc(self, sdesc, **kwargs): """ Displays the object with its current pose string. - + Returns: pose (str): A string containing the object's sdesc and current or default pose. """ - + # get the current pose, or default if no pose is set pose = self.db.pose or self.db.pose_default - + # return formatted string, or sdesc as fallback return f"{sdesc} {pose}" if pose else sdesc - def get_display_name(self, looker, **kwargs): """ Displays the name of the object in a viewer-aware manner. @@ -1448,8 +1464,8 @@ class ContribRPObject(DefaultObject): is privileged to control said object. """ - ref = kwargs.get("ref","~") - + ref = kwargs.get("ref", "~") + if looker == self: # always show your own key sdesc = self.key @@ -1460,13 +1476,12 @@ class ContribRPObject(DefaultObject): except AttributeError: # use own sdesc as a fallback 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): """ @@ -1475,7 +1490,7 @@ class ContribRPObject(DefaultObject): Args: looker (Object): Object doing the looking. - + Returns: string (str): A string containing the name, appearance and contents of the object. @@ -1553,11 +1568,11 @@ class ContribRPCharacter(DefaultCharacter, ContribRPObject): characters stand out from other objects. """ - ref = kwargs.get("ref","~") - + ref = kwargs.get("ref", "~") + if looker == self: # process your key as recog since you recognize yourself - sdesc = self.process_recog(self.key,self) + sdesc = self.process_recog(self.key, self) else: try: # get the sdesc looker should see, with formatting @@ -1567,12 +1582,11 @@ class ContribRPCharacter(DefaultCharacter, ContribRPObject): 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): + 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 at_object_creation(self): """ Called at initial creation. @@ -1631,7 +1645,6 @@ class ContribRPCharacter(DefaultCharacter, ContribRPObject): return sdesc - def process_sdesc(self, sdesc, obj, **kwargs): """ Allows to customize how your sdesc is displayed (primarily by @@ -1713,7 +1726,4 @@ class ContribRPCharacter(DefaultCharacter, ContribRPObject): the evennia.contrib.rpg.rplanguage module. """ - return "{label}|w{text}|n".format( - label=f"|W({language})" if language else "", - text=text - ) + return "{label}|w{text}|n".format(label=f"|W({language})" if language else "", text=text) diff --git a/evennia/contrib/rpg/rpsystem/tests.py b/evennia/contrib/rpg/rpsystem/tests.py index f0d040d6f7..bd2ea32896 100644 --- a/evennia/contrib/rpg/rpsystem/tests.py +++ b/evennia/contrib/rpg/rpsystem/tests.py @@ -165,17 +165,19 @@ class TestRPSystem(BaseEvenniaTest): ) def test_get_sdesc(self): - looker = self.speaker # Sender - target = self.receiver1 # Receiver1 - looker.sdesc.add(sdesc0) # A nice sender of emotes - target.sdesc.add(sdesc1) # The first receiver of emotes. + looker = self.speaker # Sender + target = self.receiver1 # Receiver1 + looker.sdesc.add(sdesc0) # A nice sender of emotes + target.sdesc.add(sdesc1) # The first receiver of emotes. # sdesc with no processing self.assertEqual(looker.get_sdesc(target), "The first receiver of emotes.") # sdesc with processing - self.assertEqual(looker.get_sdesc(target, process=True), "|bThe first receiver of emotes.|n") - - looker.recog.add(target, recog01) # Mr Receiver + self.assertEqual( + looker.get_sdesc(target, process=True), "|bThe first receiver of emotes.|n" + ) + + looker.recog.add(target, recog01) # Mr Receiver # recog with no processing self.assertEqual(looker.get_sdesc(target), "Mr Receiver") @@ -233,7 +235,7 @@ class TestRPSystem(BaseEvenniaTest): self.out1, "|bA nice sender of emotes|n looks at |mReceiver1|n. Then, " "|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.out2, diff --git a/evennia/contrib/rpg/traits/tests.py b/evennia/contrib/rpg/traits/tests.py index a6bc405357..612fd8840d 100644 --- a/evennia/contrib/rpg/traits/tests.py +++ b/evennia/contrib/rpg/traits/tests.py @@ -321,7 +321,6 @@ class TestTraitStatic(_TraitHandlerBase): self.trait.mult = 0.75 self.assertEqual(self._get_values(), (5, 1, 0.75, 4.5)) - def test_delete(self): """Deleting resets to default.""" self.trait.mult = 2.0 @@ -362,7 +361,14 @@ class TestTraitCounter(_TraitHandlerBase): def _get_values(self): """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): self.assertEqual( @@ -634,7 +640,14 @@ class TestTraitGauge(_TraitHandlerBase): def _get_values(self): """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): self.assertEqual( diff --git a/evennia/contrib/rpg/traits/traits.py b/evennia/contrib/rpg/traits/traits.py index 303fe89bf7..cd759fa8c0 100644 --- a/evennia/contrib/rpg/traits/traits.py +++ b/evennia/contrib/rpg/traits/traits.py @@ -1148,7 +1148,7 @@ class 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. value = (base + mod) * mult @@ -1161,7 +1161,9 @@ class StaticTrait(Trait): def __str__(self): 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 @property @@ -1189,7 +1191,7 @@ class StaticTrait(Trait): def mult(self): """The trait's multiplier.""" return self._data["mult"] - + @mult.setter def mult(self, amount): if type(amount) in (int, float): @@ -1322,16 +1324,16 @@ class CounterTrait(Trait): now = time() tdiff = now - self._data["last_update"] current += rate * tdiff - value = (current + self.mod) + value = current + self.mod # we must make sure so we don't overstep our bounds # even if .mod is included if self._passed_ratetarget(value): - current = (self._data["ratetarget"] - self.mod) + current = self._data["ratetarget"] - self.mod self._stop_timer() elif not self._within_boundaries(value): - current = (self._enforce_boundaries(value) - self.mod) + current = self._enforce_boundaries(value) - self.mod self._stop_timer() else: self._data["last_update"] = now @@ -1378,7 +1380,7 @@ class CounterTrait(Trait): @property def mult(self): return self._data["mult"] - + @mult.setter def mult(self, amount): if type(amount) in (int, float): @@ -1571,7 +1573,9 @@ class GaugeTrait(CounterTrait): def __str__(self): 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 def base(self): @@ -1596,11 +1600,11 @@ class GaugeTrait(CounterTrait): if value + self.base < self.min: value = self.min - self.base self._data["mod"] = value - + @property def mult(self): return self._data["mult"] - + @mult.setter def mult(self, amount): if type(amount) in (int, float): @@ -1621,7 +1625,7 @@ class GaugeTrait(CounterTrait): if value is None: self._data["min"] = self.default_keys["min"] 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 def max(self): @@ -1644,7 +1648,7 @@ class GaugeTrait(CounterTrait): def current(self): """The `current` value of the gauge.""" 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 @@ -1655,7 +1659,7 @@ class GaugeTrait(CounterTrait): @current.deleter def current(self): "Resets current back to 'full'" - self._data["current"] = (self.base + self.mod) * self.mult + self._data["current"] = (self.base + self.mod) * self.mult @property def value(self): diff --git a/evennia/help/utils.py b/evennia/help/utils.py index 981aea1fd0..85a254ac9e 100644 --- a/evennia/help/utils.py +++ b/evennia/help/utils.py @@ -12,9 +12,13 @@ import re # since we use them (e.g. as command names). # Lunr's default ignore-word list is found here: # https://github.com/yeraydiazdiaz/lunr.py/blob/master/lunr/stop_word_filter.py -_LUNR_STOP_WORD_FILTER_EXCEPTIONS = ( - ["about", "might", "get", "who", "say"] + settings.LUNR_STOP_WORD_FILTER_EXCEPTIONS -) +_LUNR_STOP_WORD_FILTER_EXCEPTIONS = [ + "about", + "might", + "get", + "who", + "say", +] + settings.LUNR_STOP_WORD_FILTER_EXCEPTIONS _LUNR = None diff --git a/evennia/locks/lockfuncs.py b/evennia/locks/lockfuncs.py index 8f2cdb70a8..b3d3de0a5e 100644 --- a/evennia/locks/lockfuncs.py +++ b/evennia/locks/lockfuncs.py @@ -473,6 +473,7 @@ def tag(accessing_obj, accessed_obj, *args, **kwargs): category = args[1] if len(args) > 1 else None return bool(accessing_obj.tags.get(tagkey, category=category)) + def is_ooc(accessing_obj, accessed_obj, *args, **kwargs): """ Usage: @@ -489,13 +490,14 @@ def is_ooc(accessing_obj, accessed_obj, *args, **kwargs): session = accessed_obj.session except AttributeError: session = account.sessions.get()[0] # note-this doesn't work well - # for high multisession mode. We may need - # to change to sessiondb to resolve this + # for high multisession mode. We may need + # to change to sessiondb to resolve this try: return not account.get_puppet(session) except TypeError: return not session.get_puppet() + def objtag(accessing_obj, accessed_obj, *args, **kwargs): """ Usage: diff --git a/evennia/prototypes/prototypes.py b/evennia/prototypes/prototypes.py index f9b6c564d3..8c002c6145 100644 --- a/evennia/prototypes/prototypes.py +++ b/evennia/prototypes/prototypes.py @@ -528,10 +528,10 @@ def search_prototype( """ # 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: load_module_prototypes() - setattr(load_module_prototypes, '_LOADED', True) + setattr(load_module_prototypes, "_LOADED", True) # prototype keys are always in lowecase if key: diff --git a/evennia/server/evennia_launcher.py b/evennia/server/evennia_launcher.py index 846e674ad0..110e4d218a 100644 --- a/evennia/server/evennia_launcher.py +++ b/evennia/server/evennia_launcher.py @@ -2316,9 +2316,11 @@ def main(): if option in ("makemessages", "compilemessages"): # some commands don't require the presence of a game directory to work need_gamedir = False - if CURRENT_DIR != EVENNIA_LIB: - print("You must stand in the evennia/evennia/ folder (where the 'locale/' " - "folder is located) to run this command.") + if CURRENT_DIR != EVENNIA_LIB: + print( + "You must stand in the evennia/evennia/ folder (where the 'locale/' " + "folder is located) to run this command." + ) sys.exit() if option in ("shell", "check", "makemigrations", "createsuperuser", "shell_plus"): diff --git a/evennia/server/server.py b/evennia/server/server.py index 4f653ffad5..4739d43ff3 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -423,6 +423,7 @@ class Evennia: logger.log_msg("Evennia Server successfully restarted in 'reset' mode.") elif mode == "shutdown": from evennia.objects.models import ObjectDB + self.at_server_cold_start() # clear eventual lingering session storages ObjectDB.objects.clear_all_sessids() diff --git a/evennia/server/tests/test_server.py b/evennia/server/tests/test_server.py index d0c79064a0..a5bf8a825a 100644 --- a/evennia/server/tests/test_server.py +++ b/evennia/server/tests/test_server.py @@ -197,7 +197,6 @@ class TestServer(TestCase): class TestInitHooks(TestCase): - def setUp(self): from evennia.utils import create diff --git a/evennia/server/tests/testrunner.py b/evennia/server/tests/testrunner.py index 9199164c58..69bd632461 100644 --- a/evennia/server/tests/testrunner.py +++ b/evennia/server/tests/testrunner.py @@ -16,15 +16,18 @@ class EvenniaTestSuiteRunner(DiscoverRunner): avoid running the large number of tests defined by Django """ + def setup_test_environment(self, **kwargs): # 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 # we'd get unclean reactor errors across test boundaries. from evennia.server.portal.portal import PORTAL + PORTAL.maintenance_task.stop() # initialize evennia itself import evennia + evennia._init() from django.conf import settings @@ -37,6 +40,7 @@ class EvenniaTestSuiteRunner(DiscoverRunner): # remove testing flag after suite has run from django.conf import settings + settings._TEST_ENVIRONMENT = False super().teardown_test_environment(**kwargs) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index 7c5a537c19..9830befa7f 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -218,13 +218,15 @@ class AttributeProperty: """ value = self._default try: - value = self.at_get(getattr(instance, self.attrhandler_name).get( - key=self._key, - default=self._default, - category=self._category, - strattr=self._strattr, - raise_exception=self._autocreate, - )) + value = self.at_get( + getattr(instance, self.attrhandler_name).get( + key=self._key, + default=self._default, + category=self._category, + strattr=self._strattr, + raise_exception=self._autocreate, + ) + ) except AttributeError: if self._autocreate: # attribute didn't exist and autocreate is set diff --git a/evennia/typeclasses/tags.py b/evennia/typeclasses/tags.py index 7e0926156b..2803c8de26 100644 --- a/evennia/typeclasses/tags.py +++ b/evennia/typeclasses/tags.py @@ -96,6 +96,7 @@ class Tag(models.Model): # Handlers making use of the Tags model # + class TagProperty: """ Tag property descriptor. Allows for setting tags on an object as Django-like 'fields' @@ -112,6 +113,7 @@ class TagProperty: mytag2 = TagProperty(category="tagcategory") """ + taghandler_name = "tags" def __init__(self, category=None, data=None): @@ -134,10 +136,7 @@ class TagProperty: """ try: return getattr(instance, self.taghandler_name).get( - key=self._key, - category=self._category, - return_list=False, - raise_exception=True + key=self._key, category=self._category, return_list=False, raise_exception=True ) except AttributeError: self.__set__(instance, self._category) @@ -150,9 +149,7 @@ class TagProperty: self._category = category ( getattr(instance, self.taghandler_name).add( - key=self._key, - category=self._category, - data=self._data + key=self._key, category=self._category, data=self._data ) ) @@ -430,8 +427,15 @@ class TagHandler(object): return ret[0] if len(ret) == 1 else ret - def get(self, key=None, default=None, category=None, return_tagobj=False, return_list=False, - raise_exception=False): + def get( + 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. @@ -613,6 +617,7 @@ class AliasProperty(TagProperty): bob = AliasProperty() """ + taghandler_name = "aliases" @@ -636,6 +641,7 @@ class PermissionProperty(TagProperty): myperm = PermissionProperty() """ + taghandler_name = "permissions" diff --git a/evennia/typeclasses/tests.py b/evennia/typeclasses/tests.py index 90c4945898..d97e7c3b5e 100644 --- a/evennia/typeclasses/tests.py +++ b/evennia/typeclasses/tests.py @@ -145,7 +145,9 @@ class TestTypedObjectManager(BaseEvenniaTest): def test_get_tag_with_any_including_nones(self): self.obj1.tags.add("tagA", "categoryA") 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], ) diff --git a/evennia/utils/evmenu.py b/evennia/utils/evmenu.py index 4dae1b700d..060d47c140 100644 --- a/evennia/utils/evmenu.py +++ b/evennia/utils/evmenu.py @@ -1255,12 +1255,12 @@ class EvMenu: min_rows = 4 # 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) cols_list = [] for icol in range(ncols): - start = icol*split - end = min(start+split,max_end) + start = icol * split + end = min(start + split, max_end) cols_list.append(EvColumn(*table[start:end])) return str(EvTable(table=cols_list, border="none")) diff --git a/evennia/utils/funcparser.py b/evennia/utils/funcparser.py index 54fc64b0c8..7186ff47b0 100644 --- a/evennia/utils/funcparser.py +++ b/evennia/utils/funcparser.py @@ -410,7 +410,7 @@ class FuncParser: single_quoted = -1 elif single_quoted > 0: prefix = infuncstr[0:single_quoted] - infuncstr = prefix + infuncstr[single_quoted+1:] + infuncstr = prefix + infuncstr[single_quoted + 1 :] single_quoted = -1 else: infuncstr += char @@ -427,7 +427,7 @@ class FuncParser: double_quoted = -1 elif double_quoted > 0: prefix = infuncstr[0:double_quoted] - infuncstr = prefix + infuncstr[double_quoted + 1:] + infuncstr = prefix + infuncstr[double_quoted + 1 :] double_quoted = -1 else: infuncstr += char diff --git a/evennia/utils/gametime.py b/evennia/utils/gametime.py index ab14c77847..9b915b368b 100644 --- a/evennia/utils/gametime.py +++ b/evennia/utils/gametime.py @@ -67,7 +67,7 @@ class TimeScript(DefaultScript): callback(*args, **kwargs) seconds = real_seconds_until(**self.db.gametime) - self.start(interval=seconds,force_restart=True) + self.start(interval=seconds, force_restart=True) # Access functions diff --git a/evennia/utils/logger.py b/evennia/utils/logger.py index ea0728a501..98bc5a499d 100644 --- a/evennia/utils/logger.py +++ b/evennia/utils/logger.py @@ -50,6 +50,7 @@ def _log(msg, logfunc, prefix="", **kwargs): # log call functions (each has legacy aliases) + def log_info(msg, **kwargs): """ 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) + info = log_info log_infomsg = log_info log_msg = log_info @@ -79,6 +81,7 @@ def log_warn(msg, **kwargs): """ _log(msg, log.warn, **kwargs) + warn = log_warn warning = log_warn log_warnmsg = log_warn @@ -120,6 +123,7 @@ def log_trace(msg=None, **kwargs): if msg: _log(msg, log.error, prefix="!!", **kwargs) + log_tracemsg = log_trace exception = log_trace critical = log_trace @@ -156,6 +160,7 @@ def log_sec(msg, **kwargs): """ _log(msg, log.info, prefix="SS", **kwargs) + sec = log_sec security = log_sec log_secmsg = log_sec @@ -174,12 +179,12 @@ def log_server(msg, **kwargs): _log(msg, log.info, prefix="Server", **kwargs) - class GetLogObserver: """ Sets up how the system logs are formatted. """ + component_prefix = "" event_levels = { twisted_logger.LogLevel.debug: "??", @@ -207,8 +212,7 @@ class GetLogObserver: event["log_format"] = str(event.get("log_format", "")) component_prefix = self.component_prefix or "" log_msg = twisted_logger.formatEventAsClassicLogText( - event, - formatTime=lambda e: twisted_logger.formatTime(e, _TIME_FORMAT) + event, formatTime=lambda e: twisted_logger.formatTime(e, _TIME_FORMAT) ) return f"{component_prefix}{log_msg}" @@ -218,14 +222,15 @@ class GetLogObserver: # Called by server/portal on startup + class GetPortalLogObserver(GetLogObserver): component_prefix = "|Portal| " + class GetServerLogObserver(GetLogObserver): component_prefix = "" - # logging overrides @@ -352,6 +357,7 @@ class WeeklyLogFile(logfile.DailyLogFile): self.lastDate = max(self.lastDate, self.toDate()) self.size += len(data) + # Arbitrary file logger diff --git a/evennia/utils/test_resources.py b/evennia/utils/test_resources.py index 65b62ea633..53d054de37 100644 --- a/evennia/utils/test_resources.py +++ b/evennia/utils/test_resources.py @@ -96,7 +96,6 @@ DEFAULT_SETTING_RESETS = dict( "evennia.game_template.server.conf.prototypefuncs", ], BASE_GUEST_TYPECLASS="evennia.accounts.accounts.DefaultGuest", - # a special setting boolean _TEST_ENVIRONMENT is set by the test runner # while the test suite is running. ) diff --git a/evennia/utils/tests/test_dbserialize.py b/evennia/utils/tests/test_dbserialize.py index 5cd5ffceda..d4fd101ef0 100644 --- a/evennia/utils/tests/test_dbserialize.py +++ b/evennia/utils/tests/test_dbserialize.py @@ -119,14 +119,17 @@ class TestDbSerialize(TestCase): class _InvalidContainer: """Container not saveable in Attribute (if obj is dbobj, it 'hides' it)""" + def __init__(self, obj): self.hidden_obj = obj class _ValidContainer(_InvalidContainer): """Container possible to save in Attribute (handles hidden dbobj explicitly)""" + def __serialize_dbobjs__(self): self.hidden_obj = dbserialize.dbserialize(self.hidden_obj) + def __deserialize_dbobjs__(self): self.hidden_obj = dbserialize.dbunserialize(self.hidden_obj) @@ -136,6 +139,7 @@ class DbObjWrappers(TestCase): Test the `__serialize_dbobjs__` and `__deserialize_dbobjs__` methods. """ + def setUp(self): super().setUp() self.dbobj1 = DefaultObject(db_key="Tester1") @@ -148,7 +152,7 @@ class DbObjWrappers(TestCase): self.dbobj1.db.testarg = _InvalidContainer(self.dbobj1) def test_consecutive_fetch(self): - con =_ValidContainer(self.dbobj2) + con = _ValidContainer(self.dbobj2) self.dbobj1.db.testarg = con attrobj = self.dbobj1.attributes.get("testarg", return_obj=True) @@ -157,7 +161,7 @@ class DbObjWrappers(TestCase): self.assertEqual(attrobj.value.hidden_obj, self.dbobj2) def test_dbobj_hidden_obj__success(self): - con =_ValidContainer(self.dbobj2) + con = _ValidContainer(self.dbobj2) self.dbobj1.db.testarg = con # accessing the same data twice diff --git a/evennia/utils/tests/test_funcparser.py b/evennia/utils/tests/test_funcparser.py index 3f6e6eb2f9..1296f7899b 100644 --- a/evennia/utils/tests/test_funcparser.py +++ b/evennia/utils/tests/test_funcparser.py @@ -116,7 +116,7 @@ class TestFuncParser(TestCase): ("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)"), ("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 args6 $foo(\()", "Test args6 _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 eval3 $eval(\"'21' + 'foo' + 'bar'\")", "Test eval3 21foobar"), (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 type1 $typ([1,2,3,4])", "Test type1 "), ("Test type2 $typ((1,2,3,4))", "Test type2 "), ("Test type3 $typ({1,2,3,4})", "Test type3 "), ("Test type4 $typ({1:2,3:4})", "Test type4 "), ("Test type5 $typ(1), $typ(1.0)", "Test type5 , "), - ("Test type6 $typ(\"'1'\"), $typ('\"1.0\"')", "Test type6 , "), + ( + "Test type6 $typ(\"'1'\"), $typ('\"1.0\"')", + "Test type6 , ", + ), ("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 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 "), ("Test literal4 $typ(aaa$lit(1))", "Test literal4 "), ("Test spider's thread", "Test spider's thread"), - ] ) def test_parse(self, string, expected): @@ -398,7 +403,7 @@ class TestDefaultCallables(TestCase): ("Some $rjust(Hello, width=30)", "Some Hello"), ("Some $cjust(Hello, 30)", "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): @@ -468,13 +473,14 @@ class TestDefaultCallables(TestCase): def test_escaped2(self): 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) self.assertEqual( result, expected, ) + class TestCallableSearch(test_resources.BaseEvenniaTest): """ Test the $search(query) callable diff --git a/evennia/utils/tests/test_text2html.py b/evennia/utils/tests/test_text2html.py index 361ab086cf..cb99ab8bd7 100644 --- a/evennia/utils/tests/test_text2html.py +++ b/evennia/utils/tests/test_text2html.py @@ -12,7 +12,9 @@ class TestText2Html(TestCase): self.assertEqual("foo", parser.format_styles("foo")) self.assertEqual( 'redfoo', - 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( 'redfoo', @@ -31,33 +33,15 @@ class TestText2Html(TestCase): ) self.assertEqual( 'a redfoo', - parser.format_styles( - "a " - + ansi.ANSI_UNDERLINE - + "red" - + ansi.ANSI_NORMAL - + "foo" - ), + parser.format_styles("a " + ansi.ANSI_UNDERLINE + "red" + ansi.ANSI_NORMAL + "foo"), ) self.assertEqual( 'a redfoo', - parser.format_styles( - "a " - + ansi.ANSI_BLINK - + "red" - + ansi.ANSI_NORMAL - + "foo" - ), + parser.format_styles("a " + ansi.ANSI_BLINK + "red" + ansi.ANSI_NORMAL + "foo"), ) self.assertEqual( 'a redfoo', - parser.format_styles( - "a " - + ansi.ANSI_INVERSE - + "red" - + ansi.ANSI_NORMAL - + "foo" - ), + parser.format_styles("a " + ansi.ANSI_INVERSE + "red" + ansi.ANSI_NORMAL + "foo"), ) def test_remove_bells(self): @@ -65,13 +49,7 @@ class TestText2Html(TestCase): self.assertEqual("foo", parser.remove_bells("foo")) self.assertEqual( "a red" + ansi.ANSI_NORMAL + "foo", - parser.remove_bells( - "a " - + ansi.ANSI_BEEP - + "red" - + ansi.ANSI_NORMAL - + "foo" - ), + parser.remove_bells("a " + ansi.ANSI_BEEP + "red" + ansi.ANSI_NORMAL + "foo"), ) def test_remove_backspaces(self): @@ -160,20 +138,20 @@ class TestText2Html(TestCase): self.assertEqual( text2html.parse_html("|^|[CHello|n|u|rW|go|yr|bl|md|c!|[G!"), '' - 'Hello' + "Hello" '' - 'W' + "W" '' - 'o' + "o" '' - 'r' + "r" '' - 'l' + "l" '' - 'd' + "d" '' - '!' + "!" '' - '!' - '', + "!" + "", ) diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index d603a93bd2..10f8073e31 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -2695,6 +2695,7 @@ def copy_word_case(base_word, new_word): + excess ) + 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