]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add pep 584 to python immutabledict fallback
authorFederico Caselli <cfederico87@gmail.com>
Fri, 21 Oct 2022 19:11:23 +0000 (21:11 +0200)
committerFederico Caselli <cfederico87@gmail.com>
Sat, 22 Oct 2022 07:55:49 +0000 (09:55 +0200)
Fixes: #8695
Change-Id: Ie0412c3a7b2b1ba5bd5112f204318ff763cbb8f4

lib/sqlalchemy/cyextension/immutabledict.pyx
lib/sqlalchemy/util/_py_collections.py
test/base/test_utils.py

index 6ab25531129f3f31d19780ea72233d5c8fb4ccef..100287b380de32b391ff136420588b9974d6a029 100644 (file)
@@ -32,6 +32,7 @@ class ImmutableDictBase(dict):
     __delitem__ = __setitem__ = __setattr__ = _immutable
     clear = pop = popitem = setdefault = update = _immutable
 
+
 cdef class immutabledict(dict):
     def __repr__(self):
         return f"immutabledict({dict.__repr__(self)})"
@@ -118,7 +119,9 @@ cdef class immutabledict(dict):
         _immutable_fn(self)
 
     def __or__(self, other):
-        return immutabledict(super().__or__(other))
+        return immutabledict(dict.__or__(self, other))
 
     def __ror__(self, other):
-        return immutabledict(super().__ror__(other))
+        # NOTE: this is used only in cython 3.x;
+        # version 0.x will call __or__ with args inversed
+        return immutabledict(dict.__ror__(self, other))
index 488229abbe9c01a9a5d3195962625a47418eb44c..cd46893a44538a047f88f64e2d306b73b81f1ece 100644 (file)
@@ -27,6 +27,7 @@ from typing import TypeVar
 from typing import Union
 
 _T = TypeVar("_T", bound=Any)
+_S = TypeVar("_S", bound=Any)
 _KT = TypeVar("_KT", bound=Any)
 _VT = TypeVar("_VT", bound=Any)
 
@@ -129,8 +130,19 @@ class immutabledict(ImmutableDictBase[_KT, _VT]):
     def __repr__(self) -> str:
         return "immutabledict(%s)" % dict.__repr__(self)
 
+    # PEP 584
+    def __ior__(self, __value: Any) -> NoReturn:  # type: ignore
+        self._readonly()
 
-_S = TypeVar("_S", bound=Any)
+    def __or__(  # type: ignore[override]
+        self, __value: Mapping[_KT, _VT]
+    ) -> immutabledict[_KT, _VT]:
+        return immutabledict(super().__or__(__value))
+
+    def __ror__(  # type: ignore[override]
+        self, __value: Mapping[_KT, _VT]
+    ) -> immutabledict[_KT, _VT]:
+        return immutabledict(super().__ror__(__value))
 
 
 class OrderedSet(Set[_T]):
index 27945f23682ee9a10cb8d27a09e7c328bd04759b..0ef86545b53cb93bc011b4a69fd5a1f413e3c198 100644 (file)
@@ -343,6 +343,23 @@ class ImmutableDictTest(fixtures.TestBase):
         i2 = util.immutabledict({"a": 42, 42: "a"})
         eq_(str(i2), "immutabledict({'a': 42, 42: 'a'})")
 
+    @testing.requires.python39
+    def test_pep584(self):
+        i = util.immutabledict({"a": 2})
+        with expect_raises_message(TypeError, "object is immutable"):
+            i |= {"b": 42}
+        eq_(i, {"a": 2})
+
+        i2 = i | {"x": 3}
+        eq_(i, {"a": 2})
+        eq_(i2, {"a": 2, "x": 3})
+        is_true(isinstance(i2, util.immutabledict))
+
+        i2 = {"x": 3} | i2
+        eq_(i, {"a": 2})
+        eq_(i2, {"a": 2, "x": 3})
+        is_true(isinstance(i2, util.immutabledict))
+
 
 class ImmutableTest(fixtures.TestBase):
     @combinations(util.immutabledict({1: 2, 3: 4}), util.FacadeDict({2: 3}))