From 2dda47f9c4d8ad2546271c07d0bf8c65a7b99568 Mon Sep 17 00:00:00 2001 From: evilchili Date: Sun, 31 Dec 2023 09:55:09 -0800 Subject: [PATCH] fix dependency ordering bug in basic properties containing template strings --- dnd_item/types.py | 12 ++++++------ tests/test_types.py | 30 ++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/dnd_item/types.py b/dnd_item/types.py index 6e6d7cc..fff3828 100644 --- a/dnd_item/types.py +++ b/dnd_item/types.py @@ -30,7 +30,7 @@ class AttributeMap(Mapping): AttributeMap is a data class that is also a mapping, converting a dict into an object with attributes. Example: - >>> amap = AttributeDict(attributes={'foo': True, 'bar': False}) + >>> amap = AttributeMap(attributes={'foo': True, 'bar': False}) >>> amap.foo True >>> amap.bar @@ -40,7 +40,7 @@ class AttributeMap(Mapping): recursively transform dictionary members sinto AttributeMaps: >>> nested_dict = {'foo': {'bar': {'baz': True}, 'boz': False}} - >>> amap = AttributeDict.from_dict(nested_dict) + >>> amap = AttributeMap.from_dict(nested_dict) >>> amap.foo.bar.baz True >>> amap.foo.boz @@ -48,14 +48,14 @@ class AttributeMap(Mapping): The dictionary can be accessed directly via 'attributes': - >>> amap = AttributeDict(attributes={'foo': True, 'bar': False}) + >>> amap = AttributeMap(attributes={'foo': True, 'bar': False}) >>> list(amap.attributes.keys()): >>>['foo', 'bar'] Because AttributeMap is a mapping, you can use it anywhere you would use a regular mapping, like a dict: - >>> amap = AttributeDict(attributes={'foo': True, 'bar': False}) + >>> amap = AttributeMap(attributes={'foo': True, 'bar': False}) >>> 'foo' in amap True >>> "{foo}, {bar}".format(**amap) @@ -97,7 +97,7 @@ class Item(AttributeMap): """ Item is the base class for items, weapons, and spells, and is intended to be subclassed to define those things. Item extends AttributeMap to provide - some helper methods, including the name and description properties.o + some helper methods, including the name and description properties. Creating Items @@ -234,7 +234,7 @@ class Item(AttributeMap): return obj # step through the supplied attributes and format each member. - for k, v in attrs.items(): + for k, v in sorted(attrs.items(), key=lambda i: '{' in f"{i[0]}{i[1]}"): if type(v) is dict: attributes[k] = AttributeMap.from_dict(_format(v)) else: diff --git a/tests/test_types.py b/tests/test_types.py index fffdac3..4466a77 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -1,11 +1,25 @@ from dnd_item import types -def test_item_attributes(): - item = types.Item.from_dict( - foo='bar', - baz={ - 'qaz': True - } - ) - assert item.baz.qaz is True +def test_Item_attributes(): + assert types.Item.from_dict(dict( + name='{length}ft. Pole', + weight='7lbs.', + value=5, + length=10 + )).name == '10ft. Pole' + + +def test_item_nested_attributes(): + assert types.Item.from_dict(dict( + name='{length}ft. Pole', + length=10, + properties=dict( + engraved=dict( + description='"Property of {info.owner}!"' + ), + ), + info=dict( + owner='Jules Ultardottir', + ) + )).description == 'Engraved. "Property of Jules Ultardottir!"'