]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
copy list for __iadd__
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 2 Dec 2021 02:39:59 +0000 (21:39 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 2 Dec 2021 19:58:02 +0000 (14:58 -0500)
Fixed issue where a list mapped with :func:`_orm.relationship` would go
into an endless loop if in-place added to itself, i.e. the ``+=`` operator
were used, as well as if ``.extend()`` were given the same list.

Fixes: #7389
Change-Id: Idd5118420f8bc684d1ee36b2b6d4c5812f36cc4c
(cherry picked from commit 9fc17513fe69a1fd26fc522f9862af3e0ebfd2c4)

doc/build/changelog/unreleased_14/7389.rst [new file with mode: 0644]
lib/sqlalchemy/orm/collections.py
test/orm/test_collection.py

diff --git a/doc/build/changelog/unreleased_14/7389.rst b/doc/build/changelog/unreleased_14/7389.rst
new file mode 100644 (file)
index 0000000..887193c
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: orm, bug
+    :tickets: 7389
+
+    Fixed issue where a list mapped with :func:`_orm.relationship` would go
+    into an endless loop if in-place added to itself, i.e. the ``+=`` operator
+    were used, as well as if ``.extend()`` were given the same list.
+
index ec4d00cb0b3173b13771caccdd2bfc1ac46b7991..351069f9a5d02f89755e55e1c293a20c000197c4 100644 (file)
@@ -1273,7 +1273,7 @@ def _list_decorators():
 
     def extend(fn):
         def extend(self, iterable):
-            for value in iterable:
+            for value in list(iterable):
                 self.append(value)
 
         _tidy(extend)
@@ -1283,7 +1283,7 @@ def _list_decorators():
         def __iadd__(self, iterable):
             # list.__iadd__ takes any iterable and seems to let TypeError
             # raise as-is instead of returning NotImplemented
-            for value in iterable:
+            for value in list(iterable):
                 self.append(value)
             return self
 
index 3473dcf50bfb879ee84cc337a0edc6aa90f038cb..c1ef16c6535dfaf9d2df3a0dc978a0b7fa29e36c 100644 (file)
@@ -2504,6 +2504,19 @@ class CustomCollectionsTest(fixtures.MappedTest):
         assert control == p.children
         assert control == list(p.children)
 
+        # test #7389
+        if hasattr(p.children, "__iadd__"):
+            control += control
+            p.children += p.children
+            assert control == list(p.children)
+
+        control[:] = [o]
+        p.children[:] = [o]
+        if hasattr(p.children, "extend"):
+            control.extend(control)
+            p.children.extend(p.children)
+            assert control == list(p.children)
+
     def test_custom(self):
         someothertable, sometable = (
             self.tables.someothertable,