diff --git a/elasticsearch_dsl/utils.py b/elasticsearch_dsl/utils.py index 830cc4f7..021afc99 100644 --- a/elasticsearch_dsl/utils.py +++ b/elasticsearch_dsl/utils.py @@ -215,7 +215,11 @@ def __delitem__(self, key: str) -> None: del self._d_[key] def __setattr__(self, name: str, value: _ValT) -> None: - if name in self._d_ or not hasattr(self.__class__, name): + # the __orig__class__ attribute has to be treated as an exception, as + # is it added to an object when it is instantiated with type arguments + if ( + name in self._d_ or not hasattr(self.__class__, name) + ) and name != "__orig_class__": self._d_[name] = value else: # there is an attribute on the class (could be property, ..) - don't add it as field diff --git a/tests/test_utils.py b/tests/test_utils.py index 7c8bf232..fe417d2f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -45,12 +45,23 @@ class MyAttrDict(utils.AttrDict[str]): assert isinstance(l[:][0], MyAttrDict) +def test_attrlist_with_type_argument() -> None: + a = utils.AttrList[str](["a", "b"]) + assert list(a) == ["a", "b"] + + def test_attrdict_keys_items() -> None: a = utils.AttrDict({"a": {"b": 42, "c": 47}, "d": "e"}) assert list(a.keys()) == ["a", "d"] assert list(a.items()) == [("a", {"b": 42, "c": 47}), ("d", "e")] +def test_attrdict_with_type_argument() -> None: + a = utils.AttrDict[str]({"a": "b"}) + assert list(a.keys()) == ["a"] + assert list(a.items()) == [("a", "b")] + + def test_merge() -> None: a: utils.AttrDict[Any] = utils.AttrDict({"a": {"b": 42, "c": 47}}) b = {"a": {"b": 123, "d": -12}, "e": [1, 2, 3]}