diff --git a/skcriteria/utils/bunch.py b/skcriteria/utils/bunch.py index 3e1da1a..f9aedd9 100644 --- a/skcriteria/utils/bunch.py +++ b/skcriteria/utils/bunch.py @@ -46,17 +46,14 @@ class Bunch(Mapping): >>> b.a = 3 >>> b['a'] 3 - >>> b.c = 6 - >>> b['c'] - 6 """ def __init__(self, name, data): if not isinstance(data, Mapping): raise TypeError("Data must be some kind of mapping") - self._name = str(name) - self._data = data + super().__setattr__("_name", str(name)) + super().__setattr__("_data", data) def __getitem__(self, k): """x.__getitem__(y) <==> x[y].""" @@ -69,6 +66,10 @@ def __getattr__(self, a): except KeyError: raise AttributeError(a) + def __setattr__(self, a, v): + """x.__setattr__(a, v) <==> x.a = v.""" + raise AttributeError(f"Bunch {self._name!r} is read-only") + def __copy__(self): """x.__copy__() <==> copy.copy(x).""" cls = type(self) @@ -87,7 +88,7 @@ def __deepcopy__(self, memo): memo[id(self)] = clone # now we copy the data - clone._data = copy.deepcopy(self._data, memo) + super(cls, clone).__setattr__("_data", copy.deepcopy(self._data, memo)) return clone diff --git a/tests/utils/test_bunch.py b/tests/utils/test_bunch.py index 9e97286..a5fa8cf 100644 --- a/tests/utils/test_bunch.py +++ b/tests/utils/test_bunch.py @@ -91,3 +91,9 @@ def test_Bunch_copy(): def test_Bunch_data_is_not_a_mapping(): with pytest.raises(TypeError, match="Data must be some kind of mapping"): bunch.Bunch("foo", None) + + +def test_Bunch_assign_fails(): + foo_bunch = bunch.Bunch("foo", {}) + with pytest.raises(AttributeError, match="Bunch 'foo' is read-only"): + foo_bunch.some_key = 1