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)
- Vitaliy Voloshin (vitalivo)
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

Unreleased
----------

* Prevent frozen BoxList mutation through clear, in-place addition, and in-place multiplication.

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

Expand Down
12 changes: 11 additions & 1 deletion box/box_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __init__(self, iterable: Iterable | None = None, box_class: type[box.Box] =
def frozen(*args, **kwargs):
raise BoxError("BoxList is frozen")

for method in ["append", "extend", "insert", "pop", "remove", "reverse", "sort"]:
for method in ["append", "clear", "extend", "insert", "pop", "remove", "reverse", "sort"]:
self.__setattr__(method, frozen)

def __getitem__(self, item):
Expand Down Expand Up @@ -113,6 +113,16 @@ def __setitem__(self, key, value):
return super().__getitem__(pos).__setitem__(children, value)
super().__setitem__(key, value)

def __iadd__(self, value):
if self.box_options.get("frozen_box"):
raise BoxError("BoxList is frozen")
return super().__iadd__(value)

def __imul__(self, value):
if self.box_options.get("frozen_box"):
raise BoxError("BoxList is frozen")
return super().__imul__(value)

def _is_intact_type(self, obj):
if self.box_options.get("box_intact_types") and isinstance(obj, self.box_options["box_intact_types"]):
return True
Expand Down
25 changes: 25 additions & 0 deletions test/test_box_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Test files gathered from json.org and yaml.org

import json
import operator
import os
import shutil
import sys
Expand Down Expand Up @@ -274,3 +275,27 @@ def test_circular_references(self):
circular_list.append(circular_list)
circular_box = BoxList(circular_list)
assert circular_box[0] == circular_box


@pytest.mark.parametrize(
"mutate, expected",
[
(lambda value: value.clear(), []),
(lambda value: operator.iadd(value, [3]), [1, 2, 3]),
(lambda value: operator.imul(value, 2), [1, 2, 1, 2]),
(lambda value: operator.imul(value, 0), []),
],
)
def test_frozen_list_inplace_mutations(mutate, expected):
frozen = BoxList([1, 2], frozen_box=True)
original_hash = hash(frozen)
with pytest.raises(BoxError, match="BoxList is frozen"):
mutate(frozen)
assert frozen == [1, 2]
assert hash(frozen) == original_hash

mutable = BoxList([1, 2])
alias = mutable
mutate(mutable)
assert mutable is alias
assert mutable == expected