Skip to content

Commit a87b689

Browse files
authored
fix: handle non-string dict keys holding lists in keylists/keypaths (#583)
1 parent 1383959 commit a87b689

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

benedict/core/keylists.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ def _get_keylist_for_list(
2323
keylist = []
2424
for key, value in enumerate(ls):
2525
keys = list(parent_keys)
26-
keys[-1] += f"[{key}]"
26+
# Stringify the parent key before appending the index so non-string keys
27+
# (e.g. int/None/bool) holding a list don't raise a TypeError. String keys
28+
# are unaffected: f"{'a'}[0]" == "a[0]".
29+
keys[-1] = f"{keys[-1]}[{key}]"
2730
keylist += [keys]
2831
keylist += _get_keylist_for_value(value, keys, indexes)
2932
return keylist

tests/core/test_keylists.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,29 @@ def test_keylists_with_non_string_keys(self) -> None:
6060
for k in r:
6161
self.assertTrue(k in o)
6262

63+
def test_keylists_with_non_string_keys_and_lists_and_indexes_included(
64+
self,
65+
) -> None:
66+
# A non-string key (int/None/bool) holding a list used to raise
67+
# 'TypeError: unsupported operand type(s) for +=: 'int' and 'str''
68+
# while the same key holding a dict worked fine.
69+
i = {
70+
0: [1, 2],
71+
None: [3, 4],
72+
}
73+
o = _keylists(i, indexes=True)
74+
r = [
75+
[0],
76+
["0[0]"],
77+
["0[1]"],
78+
[None],
79+
["None[0]"],
80+
["None[1]"],
81+
]
82+
self.assertEqual(len(o), len(r))
83+
for k in r:
84+
self.assertTrue(k in o)
85+
6386
def test_keylists_with_lists_and_indexes_included(self) -> None:
6487
i = {
6588
"a": 1,

0 commit comments

Comments
 (0)