From 07ebb4a60b7cf8c5ae7b2d0311f196ad67485699 Mon Sep 17 00:00:00 2001 From: Alessandro Ogier Date: Wed, 27 Jul 2022 19:01:32 +0200 Subject: [PATCH] case sensitive set dict keys --- evennia/commands/default/building.py | 25 ++++++++++++++++++++- evennia/commands/default/tests.py | 33 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/evennia/commands/default/building.py b/evennia/commands/default/building.py index ccfe33f5b0..cc2e5d24bf 100644 --- a/evennia/commands/default/building.py +++ b/evennia/commands/default/building.py @@ -35,6 +35,8 @@ COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS) _FUNCPARSER = None _ATTRFUNCPARSER = None +_KEY_REGEX = re.compile(r"(?P.*?)(?P(\[.*\]\ *)+)?$") + # limit symbol import for API __all__ = ( "ObjManipCommand", @@ -126,7 +128,28 @@ class ObjManipCommand(COMMAND_DEFAULT_CLASS): aliases = [alias.strip() for alias in aliases.split(";") if alias.strip()] if "/" in objdef: objdef, attrs = [part.strip() for part in objdef.split("/", 1)] - attrs = [part.strip().lower() for part in attrs.split("/") if part.strip()] + _attrs = [] + + # Should an attribute key is specified, ie. we're working + # on a dict, what we want is to lowercase attribute name + # as usual but to preserve dict key case as one would + # expect: + # + # set box/MyAttr = {'FooBar': 1} + # Created attribute box/myattr [category:None] = {'FooBar': 1} + # set box/MyAttr['FooBar'] = 2 + # Modified attribute box/myattr [category:None] = {'FooBar': 2} + for match in ( + match + for part in map(str.strip, attrs.split("/")) + if part and (match := _KEY_REGEX.match(part.strip())) + ): + attr = match.group("attr").lower() + # reappend untouched key, if present + if match.group("key"): + attr += match.group("key") + _attrs.append(attr) + attrs = _attrs # store data obj_defs[iside].append({"name": objdef, "option": option, "aliases": aliases}) obj_attrs[iside].append({"name": objdef, "attrs": attrs}) diff --git a/evennia/commands/default/tests.py b/evennia/commands/default/tests.py index 32f4a882f5..3d677e978e 100644 --- a/evennia/commands/default/tests.py +++ b/evennia/commands/default/tests.py @@ -957,6 +957,39 @@ class TestBuilding(BaseEvenniaCommandTest): "{'one': 99, 'three': 3, '+': 42, '+1': 33}", ) + # dict - case sensitive keys + + self.call( + building.CmdSetAttribute(), + "Obj/test_case = {'FooBar': 1}", + "Created attribute Obj/test_case [category:None] = {'FooBar': 1}", + ) + self.call( + building.CmdSetAttribute(), + "Obj/test_case['FooBar'] = 2", + "Modified attribute Obj/test_case [category:None] = {'FooBar': 2}", + ) + self.call( + building.CmdSetAttribute(), + "Obj/test_case", + "Attribute Obj/test_case [category:None] = {'FooBar': 2}", + ) + self.call( + building.CmdSetAttribute(), + "Obj/test_case['FooBar'] = {'BarBaz': 1}", + "Modified attribute Obj/test_case [category:None] = {'FooBar': {'BarBaz': 1}}", + ) + self.call( + building.CmdSetAttribute(), + "Obj/test_case['FooBar']['BarBaz'] = 2", + "Modified attribute Obj/test_case [category:None] = {'FooBar': {'BarBaz': 2}}", + ) + self.call( + building.CmdSetAttribute(), + "Obj/test_case", + "Attribute Obj/test_case [category:None] = {'FooBar': {'BarBaz': 2}}", + ) + # tuple self.call( building.CmdSetAttribute(),