Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions box/box_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,15 @@ def __setitem__(self, key, value):
return super().__setitem__(pos, value)
children = key[len(list_pos.group()) :].lstrip(".")
if self.box_options.get("default_box"):
# Only replace the element at ``pos`` with a fresh container when it is
# not already the right one; otherwise a second dotted write into an
# existing element (e.g. ``a[0].y`` after ``a[0].x``) would discard the
# data already stored there. Mirrors the guard in Box.__setitem__.
current = super().__getitem__(pos)
if children[0] == "[":
super().__setitem__(pos, box.BoxList(**self.box_options))
else:
if not isinstance(current, box.BoxList):
super().__setitem__(pos, box.BoxList(**self.box_options))
elif not isinstance(current, box.Box):
super().__setitem__(pos, self.box_options.get("box_class")(**self.box_options))
return super().__getitem__(pos).__setitem__(children, value)
super().__setitem__(key, value)
Expand Down
18 changes: 18 additions & 0 deletions test/test_box_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,24 @@ def test_box_list_default_dots(self):
box_3["a.b[0]"] = 42
assert box_3.a.b[0] == 42

# A second dotted write into an existing list element must not discard
# the keys already written there (regression).
box_4 = Box(default_box=True, box_dots=True)
box_4["a[0].x"] = 1
box_4["a[0].y"] = 2
assert box_4.a[0].to_dict() == {"x": 1, "y": 2}

box_5 = Box(default_box=True, box_dots=True)
box_5["a[0][0].x"] = 1
box_5["a[0][1].y"] = 2
assert box_5.a[0].to_list() == [{"x": 1}, {"y": 2}]

# A scalar already at the position is still overwritten.
box_6 = Box(default_box=True, box_dots=True)
box_6["a[0]"] = 5
box_6["a[0].x"] = 1
assert box_6.a[0].to_dict() == {"x": 1}

def test_box_config_propagate(self):
structure = Box(a=[Box(default_box=False)], default_box=True, box_inherent_settings=True)
assert structure._box_config["default_box"] is True
Expand Down