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
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,4 @@ Suggestions and bug reporting:
- d00m514y3r
- Sébastien Weber (seb5g)
- Ward Loos (wrdls)
- x0Lazarus
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

Unreleased
----------

* Allow BoxList.extend to append its own contents once, like list.extend (thanks to x0Lazarus).

Version 7.4.1
-------------

Expand Down
2 changes: 2 additions & 0 deletions box/box_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ def append(self, p_object):
super().append(self._convert(p_object))

def extend(self, iterable):
if iterable is self:
iterable = list(self)
for item in iterable:
self.append(item)

Expand Down
36 changes: 36 additions & 0 deletions test/test_box_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,42 @@ def test_box_list(self):
assert isinstance(new_list[1], BoxList)
assert not isinstance(new_list.to_list(), BoxList)

@pytest.mark.parametrize("values", [[], [1], [1, 2], [{"SomeKey": 3}, [4]]])
def test_extend_self(self, values, monkeypatch):
data = BoxList(values, camel_killer_box=True)
expected = data.to_list() * 2
append = data.append
remaining = len(data)

def bounded_append(item):
nonlocal remaining
assert remaining > 0, "extend revisited an appended element"
remaining -= 1
append(item)

# Bound the regression test even if extend iterates its growing destination.
monkeypatch.setattr(data, "append", bounded_append)
assert data.extend(data) is None
assert remaining == 0
assert data.to_list() == expected
if values and isinstance(values[0], dict):
assert isinstance(data[2], Box)
assert data[2].some_key == 3
assert isinstance(data[3], BoxList)

def test_extend_generator_preserves_partial_progress(self):
data = BoxList([0])

def items():
yield {"value": 1}
raise ValueError("unfinished input")

with pytest.raises(ValueError, match="unfinished input"):
data.extend(items())
assert data[0] == 0
assert isinstance(data[1], Box)
assert data[1].value == 1

def test_frozen_list(self):
bl = BoxList([5, 4, 3], frozen_box=True)
with pytest.raises(BoxError):
Expand Down