From 7d553125baec3220dffbcbd5e31b2bda257f9b72 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 11 Aug 2024 12:09:48 +0200 Subject: [PATCH] Make `examine` command display `strattr` Attribute values correctly; Resolve #3590. Clean up some regex syntaxes for py3.13 compatibility --- CHANGELOG.md | 6 ++++- evennia/commands/default/building.py | 15 ++++++++--- evennia/commands/default/tests.py | 37 ++++++++++++++-------------- evennia/typeclasses/attributes.py | 3 ++- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa4243e8ec..ab94b2d08f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,12 @@ ## Main branch [Docs][issue3591]: Fix of NPC reaction tutorial code (Griatch) +[Docs][issue3590]: Make `examine` command properly show `strattr` type +Attribute values (Griatch) + +[issue3591]: https://github.com/evennia/evennia/issues/3591 +[issue3590]: https://github.com/evennia/evennia/issues/3590 -[issue3592]: https://github.com/evennia/evennia/issues/3591 ## Evennia 4.3.0 diff --git a/evennia/commands/default/building.py b/evennia/commands/default/building.py index 8cdf69c5f6..eb79385d60 100644 --- a/evennia/commands/default/building.py +++ b/evennia/commands/default/building.py @@ -5,11 +5,10 @@ Building and world design commands import re import typing +import evennia from django.conf import settings from django.core.paginator import Paginator from django.db.models import Max, Min, Q - -import evennia from evennia import InterruptCommand from evennia.commands.cmdhandler import generate_cmdset_providers, get_and_merge_cmdsets from evennia.locks.lockhandler import LockException @@ -2831,8 +2830,12 @@ class CmdExamine(ObjManipCommand): _FUNCPARSER = funcparser.FuncParser(settings.FUNCPARSER_OUTGOING_MESSAGES_MODULES) key, category, value = attr.db_key, attr.db_category, attr.value + valuetype = "" + if value is None and attr.strvalue is not None: + value = attr.strvalue + valuetype = " |B[strvalue]|n" typ = self._get_attribute_value_type(value) - typ = f" |B[type: {typ}]|n" if typ else "" + typ = f" |B[type:{typ}]|n{valuetype}" if typ else f"{valuetype}" value = utils.to_str(value) value = _FUNCPARSER.parse(ansi_raw(value), escape=True) return ( @@ -2846,8 +2849,12 @@ class CmdExamine(ObjManipCommand): _FUNCPARSER = funcparser.FuncParser(settings.FUNCPARSER_OUTGOING_MESSAGES_MODULES) key, category, value = attr.db_key, attr.db_category, attr.value + valuetype = "" + if value is None and attr.strvalue is not None: + value = attr.strvalue + valuetype = " |B[strvalue]|n" typ = self._get_attribute_value_type(value) - typ = f" |B[type: {typ}]|n" if typ else "" + typ = f" |B[type: {typ}]|n{valuetype}" if typ else f"{valuetype}" value = utils.to_str(value) value = _FUNCPARSER.parse(ansi_raw(value), escape=True) value = utils.crop(value) diff --git a/evennia/commands/default/tests.py b/evennia/commands/default/tests.py index f7fc7f1fd2..f7ffe45c7d 100644 --- a/evennia/commands/default/tests.py +++ b/evennia/commands/default/tests.py @@ -14,13 +14,10 @@ main test suite started with import datetime from unittest.mock import MagicMock, Mock, patch +import evennia from anything import Anything from django.conf import settings from django.test import override_settings -from parameterized import parameterized -from twisted.internet import task - -import evennia from evennia import ( DefaultCharacter, DefaultExit, @@ -32,14 +29,7 @@ from evennia import ( from evennia.commands import cmdparser from evennia.commands.cmdset import CmdSet from evennia.commands.command import Command, InterruptCommand -from evennia.commands.default import ( - account, - admin, - batchprocess, - building, - comms, - general, -) +from evennia.commands.default import account, admin, batchprocess, building, comms, general from evennia.commands.default import help as help_module from evennia.commands.default import syscommands, system, unloggedin from evennia.commands.default.cmdset_character import CharacterCmdSet @@ -48,6 +38,8 @@ from evennia.prototypes import prototypes as protlib from evennia.utils import create, gametime, utils from evennia.utils.test_resources import BaseEvenniaCommandTest # noqa from evennia.utils.test_resources import BaseEvenniaTest, EvenniaCommandTest +from parameterized import parameterized +from twisted.internet import task # ------------------------------------------------------------ # Command testing @@ -446,7 +438,7 @@ class TestCmdTasks(BaseEvenniaCommandTest): args = f"/pause {self.task.get_id()}" wanted_msg = "Pause task 1 with completion date" cmd_result = self.call(system.CmdTasks(), args, wanted_msg) - self.assertRegex(cmd_result, " \(func_test_cmd_tasks\) ") + self.assertRegex(cmd_result, r" \(func_test_cmd_tasks\) ") self.char1.execute_cmd("y") self.assertTrue(self.task.paused) self.task_handler.clock.advance(self.timedelay + 1) @@ -455,7 +447,7 @@ class TestCmdTasks(BaseEvenniaCommandTest): self.assertTrue(self.task.exists()) wanted_msg = "Unpause task 1 with completion date" cmd_result = self.call(system.CmdTasks(), args, wanted_msg) - self.assertRegex(cmd_result, " \(func_test_cmd_tasks\) ") + self.assertRegex(cmd_result, r" \(func_test_cmd_tasks\) ") self.char1.execute_cmd("y") # verify task continues after unpause self.task_handler.clock.advance(1) @@ -465,7 +457,7 @@ class TestCmdTasks(BaseEvenniaCommandTest): args = f"/do_task {self.task.get_id()}" wanted_msg = "Do_task task 1 with completion date" cmd_result = self.call(system.CmdTasks(), args, wanted_msg) - self.assertRegex(cmd_result, " \(func_test_cmd_tasks\) ") + self.assertRegex(cmd_result, r" \(func_test_cmd_tasks\) ") self.char1.execute_cmd("y") self.assertFalse(self.task.exists()) @@ -473,7 +465,7 @@ class TestCmdTasks(BaseEvenniaCommandTest): args = f"/remove {self.task.get_id()}" wanted_msg = "Remove task 1 with completion date" cmd_result = self.call(system.CmdTasks(), args, wanted_msg) - self.assertRegex(cmd_result, " \(func_test_cmd_tasks\) ") + self.assertRegex(cmd_result, r" \(func_test_cmd_tasks\) ") self.char1.execute_cmd("y") self.assertFalse(self.task.exists()) @@ -481,7 +473,7 @@ class TestCmdTasks(BaseEvenniaCommandTest): args = f"/call {self.task.get_id()}" wanted_msg = "Call task 1 with completion date" cmd_result = self.call(system.CmdTasks(), args, wanted_msg) - self.assertRegex(cmd_result, " \(func_test_cmd_tasks\) ") + self.assertRegex(cmd_result, r" \(func_test_cmd_tasks\) ") self.char1.execute_cmd("y") # make certain the task is still active self.assertTrue(self.task.active()) @@ -493,7 +485,7 @@ class TestCmdTasks(BaseEvenniaCommandTest): args = f"/cancel {self.task.get_id()}" wanted_msg = "Cancel task 1 with completion date" cmd_result = self.call(system.CmdTasks(), args, wanted_msg) - self.assertRegex(cmd_result, " \(func_test_cmd_tasks\) ") + self.assertRegex(cmd_result, r" \(func_test_cmd_tasks\) ") self.char1.execute_cmd("y") self.assertTrue(self.task.exists()) self.assertFalse(self.task.active()) @@ -797,7 +789,7 @@ class TestBuilding(BaseEvenniaCommandTest): self.call( building.CmdExamine(), "self/test2", - "Attribute Char/test2 [category=None]:\n\nthis is a \$random() value.", + "Attribute Char/test2 [category=None]:\n\nthis is a \\$random() value.", ) self.room1.scripts.add(self.script.__class__) @@ -805,6 +797,13 @@ class TestBuilding(BaseEvenniaCommandTest): self.account.scripts.add(self.script.__class__) self.call(building.CmdExamine(), "*TestAccount") + self.char1.attributes.add("strattr", "testval", strattr=True) + self.call( + building.CmdExamine(), + "self/strattr", + "Attribute Char/strattr [category=None] [strvalue]:\n\ntestval", + ) + def test_set_obj_alias(self): self.call(building.CmdSetObjAlias(), "Obj =", "Cleared aliases from Obj") self.call( diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index 03929dac43..174b9ab056 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -17,7 +17,6 @@ from copy import copy from django.conf import settings from django.db import models from django.utils.encoding import smart_str - from evennia.locks.lockhandler import LockHandler from evennia.utils.dbserialize import from_pickle, to_pickle from evennia.utils.idmapper.models import SharedMemoryModel @@ -142,6 +141,8 @@ class InMemoryAttribute(IAttribute): # Value and locks are special. We must call the wrappers. if key == "value": self.value = value + elif key == "strvalue": + self.db_strvalue = value elif key == "lock_storage": self.lock_storage = value else: