From 451c45d20b7bd85fdd8131784e8c666ba87ef8e1 Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 31 Aug 2020 19:38:57 +0200 Subject: [PATCH 1/6] Fix of unittest to account for mysql/psql variations --- evennia/commands/default/tests.py | 2 +- evennia/utils/tests/test_create_functions.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/evennia/commands/default/tests.py b/evennia/commands/default/tests.py index bbf1e5428c..3fef90e0d9 100644 --- a/evennia/commands/default/tests.py +++ b/evennia/commands/default/tests.py @@ -1146,7 +1146,7 @@ class TestBuilding(CommandTest): "= Obj", "To create a global script you need scripts/add .", ) - self.call(building.CmdScript(), "Obj = ", "dbref obj") + self.call(building.CmdScript(), "Obj ", "dbref ") self.call( building.CmdScript(), "/start Obj", "0 scripts started on Obj" diff --git a/evennia/utils/tests/test_create_functions.py b/evennia/utils/tests/test_create_functions.py index 392d62a9ee..c9ae5b2cb7 100644 --- a/evennia/utils/tests/test_create_functions.py +++ b/evennia/utils/tests/test_create_functions.py @@ -159,7 +159,7 @@ class TestCreateMessage(EvenniaTest): locks=locks, tags=tags, ) - self.assertEqual(msg.receivers, [self.char1, self.char2]) + self.assertEqual(set(msg.receivers), set([self.char1, self.char2])) self.assertTrue(all(lock in msg.locks.all() for lock in locks.split(";"))) self.assertEqual(msg.tags.all(), tags) From 2a392c290dd2b23400f37c9dc2ccc975d986d7fb Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 1 Sep 2020 19:10:07 +0200 Subject: [PATCH 2/6] Fix error in pluralization inflection. Resolves #2183. --- evennia/objects/objects.py | 13 +++++++------ evennia/utils/utils.py | 4 ++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 35ea3089e2..862f7cd832 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -339,22 +339,23 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): singular (str): The singular form to display. plural (str): The determined plural form of the key, including the count. """ + plural_category = "plural_key" key = kwargs.get("key", self.key) key = ansi.ANSIString(key) # this is needed to allow inflection of colored names try: - plural = _INFLECT.plural(key, 2) - plural = "%s %s" % (_INFLECT.number_to_words(count, threshold=12), plural) + plural = _INFLECT.plural(key, count) + plural = "{} {}".format(_INFLECT.number_to_words(count, threshold=12), plural) except IndexError: # this is raised by inflect if the input is not a proper noun plural = key singular = _INFLECT.an(key) - if not self.aliases.get(plural, category="plural_key"): + if not self.aliases.get(plural, category=plural_category): # we need to wipe any old plurals/an/a in case key changed in the interrim - self.aliases.clear(category="plural_key") - self.aliases.add(plural, category="plural_key") + self.aliases.clear(category=plural_category) + self.aliases.add(plural, category=plural_category) # save the singular form as an alias here too so we can display "an egg" and also # look at 'an egg'. - self.aliases.add(singular, category="plural_key") + self.aliases.add(singular, category=plural_category) return singular, plural def search( diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index 3127fc25a2..bd5d460b5b 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -1917,6 +1917,10 @@ def at_search_result(matches, caller, query="", quiet=False, **kwargs): for num, result in enumerate(matches): # we need to consider Commands, where .aliases is a list aliases = result.aliases.all() if hasattr(result.aliases, "all") else result.aliases + # remove any pluralization aliases + aliases = [alias for alias in aliases if + hasattr(alias, "category") + and alias.category not in ("plural_key", )] error += _MULTIMATCH_TEMPLATE.format( number=num + 1, name=result.get_display_name(caller) From 7fd29a9093620761d22250d8ba164b2e86a9415c Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 1 Sep 2020 20:35:16 +0200 Subject: [PATCH 3/6] Fix settings-reset functionality. Resolve #2187 --- evennia/server/evennia_launcher.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evennia/server/evennia_launcher.py b/evennia/server/evennia_launcher.py index 7a00f8e07d..50349651a1 100644 --- a/evennia/server/evennia_launcher.py +++ b/evennia/server/evennia_launcher.py @@ -1368,10 +1368,10 @@ def create_settings_file(init=True, secret_settings=False): if not init: # if not --init mode, settings file may already exist from before if os.path.exists(settings_path): - inp = eval(input("%s already exists. Do you want to reset it? y/[N]> " % settings_path)) + inp = input("%s already exists. Do you want to reset it? y/[N]> " % settings_path) if not inp.lower() == "y": print("Aborted.") - return + sys.exit() else: print("Reset the settings file.") From bf8d41562d2bde2b3f6022a1d3358052281bd049 Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 1 Sep 2020 20:40:48 +0200 Subject: [PATCH 4/6] Default to attrread as locktype for Attribute read access. Resolve #2185 --- evennia/typeclasses/attributes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index bc6b61dccf..16779ba4a8 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -186,7 +186,7 @@ class Attribute(SharedMemoryModel): def __repr__(self): return "%s(%s)" % (self.db_key, self.id) - def access(self, accessing_obj, access_type="read", default=False, **kwargs): + def access(self, accessing_obj, access_type="attrread", default=False, **kwargs): """ Determines if another object has permission to access. From 1e5c302e9bf238c97f2a597fb6652e7b124ea536 Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 1 Sep 2020 22:36:54 +0200 Subject: [PATCH 5/6] Use localtime for MudInfo channel output. Resolves #2182. --- evennia/accounts/accounts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evennia/accounts/accounts.py b/evennia/accounts/accounts.py index f9c97a90f7..fa76774e8e 100644 --- a/evennia/accounts/accounts.py +++ b/evennia/accounts/accounts.py @@ -1262,7 +1262,7 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase): ] except Exception: logger.log_trace() - now = timezone.now() + now = timezone.localtime() now = "%02i-%02i-%02i(%02i:%02i)" % (now.year, now.month, now.day, now.hour, now.minute) if _MUDINFO_CHANNEL: _MUDINFO_CHANNEL.tempmsg(f"[{_MUDINFO_CHANNEL.key}, {now}]: {message}") From 9040aafb0595268fd115416bf586a0f14b6a175e Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 1 Sep 2020 22:58:54 +0200 Subject: [PATCH 6/6] Make at_post_cmd() run after func() also for delayed commands. Resolve #2179 --- CHANGELOG.md | 2 ++ evennia/commands/cmdhandler.py | 31 +++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b889f0598..471aec0b1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,8 @@ without arguments starts a full interactive Python console. - Make `INLINEFUNC_STACK_MAXSIZE` default visible in `settings_default.py`. - Change how `ic` finds puppets; non-priveleged users will use `_playable_characters` list as candidates, Builders+ will use list, local search and only global search if no match found. +- Make `cmd.at_post_cmd()` always run after `cmd.func()`, even when the latter uses delays + with yield. ## Evennia 0.9 (2018-2019) diff --git a/evennia/commands/cmdhandler.py b/evennia/commands/cmdhandler.py index dd0f84e872..b22719ca35 100644 --- a/evennia/commands/cmdhandler.py +++ b/evennia/commands/cmdhandler.py @@ -206,7 +206,7 @@ def _progressive_cmd_run(cmd, generator, response=None): else: value = generator.send(response) except StopIteration: - pass + raise else: if isinstance(value, (int, float)): utils.delay(value, _progressive_cmd_run, cmd, generator) @@ -631,20 +631,31 @@ def cmdhandler( ret = cmd.func() if isinstance(ret, types.GeneratorType): # cmd.func() is a generator, execute progressively - _progressive_cmd_run(cmd, ret) + in_generator = True + try: + _progressive_cmd_run(cmd, ret) + except StopIteration: + # this means func() has run its course + in_generator = False yield None else: + in_generator = False ret = yield ret - # post-command hook - yield cmd.at_post_cmd() + if not in_generator: + # this will only run if we are out of the generator for this + # cmd, otherwise we would have at_post_cmd run before a delayed + # func() finished - if cmd.save_for_next: - # store a reference to this command, possibly - # accessible by the next command. - caller.ndb.last_cmd = yield copy(cmd) - else: - caller.ndb.last_cmd = None + # post-command hook + yield cmd.at_post_cmd() + + if cmd.save_for_next: + # store a reference to this command, possibly + # accessible by the next command. + caller.ndb.last_cmd = yield copy(cmd) + else: + caller.ndb.last_cmd = None # return result to the deferred returnValue(ret)