[#1928] Helper functions and tests

This commit is contained in:
Aaron McMillin 2019-09-16 17:50:38 -04:00
parent ba9b41ed4b
commit f9bd07c3ed
2 changed files with 70 additions and 0 deletions

View file

@ -1603,6 +1603,8 @@ class CmdSetAttribute(ObjManipCommand):
key = "set"
locks = "cmd:perm(set) or perm(Builder)"
help_category = "Building"
nested_re = re.compile(r'\[.*?\]')
not_found = object()
def check_obj(self, obj):
"""
@ -1627,6 +1629,38 @@ class CmdSetAttribute(ObjManipCommand):
"""
return attr_name
def split_nested_attr(self, attr):
"""
Yields tuples of (possible attr name, nested keys on that attr).
For performance, this is biased to the deepest match, but allows compatability
with older attrs that might have been named with `[]`'s.
> list(split_nested_attr("nested['asdf'][0]"))
[
('nested', ['asdf', 0]),
("nested['asdf']", [0]),
("nested['asdf'][0]", []),
]
"""
parts = self.nested_re.findall(attr)
base_attr = ''
if parts:
base_attr = attr[:attr.find(parts[0])]
for index, part in enumerate(parts):
yield (base_attr, [p.strip('"\'[]') for p in parts[index:]])
base_attr += part
yield (attr, [])
def do_nested_lookup(self, value, *keys):
result = value
for key in keys:
try:
result = result.__getitem__(key)
except (IndexError, KeyError, TypeError):
return self.not_found
return result
def view_attr(self, obj, attr):
"""
Look up the value of an attribute and return a string displaying it.

View file

@ -535,6 +535,42 @@ class TestBuilding(CommandTest):
self.call(building.CmdWipe(), "Obj2/test2/test3", "Wiped attributes test2,test3 on Obj2.")
self.call(building.CmdWipe(), "Obj2", "Wiped all attributes on Obj2.")
def test_split_nested_attr(self):
split_nested_attr = building.CmdSetAttribute().split_nested_attr
test_cases = {
'test1': [('test1', [])],
'test2["dict"]': [('test2', ['dict']), ('test2["dict"]', [])],
# Quotes not actually required
'test3[dict]': [('test3', ['dict']), ('test3[dict]', [])],
# duplicate keys don't cause issues
'test4[0][0]': [('test4', ['0', '0']), ('test4[0]', ['0']), ('test4[0][0]', [])],
}
for attr, result in test_cases.items():
self.assertEqual(list(split_nested_attr(attr)), result)
def test_do_nested_lookup(self):
do_nested_lookup = building.CmdSetAttribute().do_nested_lookup
not_found = building.CmdSetAttribute.not_found
def do_test_single(value, key, result):
self.assertEqual(do_nested_lookup(value, key), result)
def do_test_multi(value, keys, result):
self.assertEqual(do_nested_lookup(value, *keys), result)
do_test_single([], 'test1', not_found)
do_test_single([1], 'test2', not_found)
do_test_single([], 0, not_found)
do_test_single([1], 2, not_found)
do_test_single([1], 0, 1)
do_test_single({}, 'test3', not_found)
do_test_single({}, 0, not_found)
do_test_single({'foo': 'bar'}, 'foo', 'bar')
do_test_multi({'one': [1, 2, 3]}, ('one', 0), 1)
do_test_multi([{}, {'two': 2}, 3], (1, 'two'), 2)
def test_name(self):
self.call(building.CmdName(), "", "Usage: ")
self.call(building.CmdName(), "Obj2=Obj3", "Object's name changed to 'Obj3'.")