summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-12-01 21:39:59 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2021-12-02 14:57:42 -0500
commit9fc17513fe69a1fd26fc522f9862af3e0ebfd2c4 (patch)
tree81c787491ed06438e23cac74616c6cee9c824163
parentdff827df53cd3af8a641c74e5115707664eb6d79 (diff)
downloadsqlalchemy-9fc17513fe69a1fd26fc522f9862af3e0ebfd2c4.tar.gz
copy list for __iadd__
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
-rw-r--r--doc/build/changelog/unreleased_14/7389.rst8
-rw-r--r--lib/sqlalchemy/orm/collections.py4
-rw-r--r--test/orm/test_collection.py13
3 files changed, 23 insertions, 2 deletions
diff --git a/doc/build/changelog/unreleased_14/7389.rst b/doc/build/changelog/unreleased_14/7389.rst
new file mode 100644
index 000000000..887193c28
--- /dev/null
+++ b/doc/build/changelog/unreleased_14/7389.rst
@@ -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.
+
diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py
index ccb88866e..d71c84268 100644
--- a/lib/sqlalchemy/orm/collections.py
+++ b/lib/sqlalchemy/orm/collections.py
@@ -1252,7 +1252,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)
@@ -1262,7 +1262,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
diff --git a/test/orm/test_collection.py b/test/orm/test_collection.py
index 9babe6366..806d98a69 100644
--- a/test/orm/test_collection.py
+++ b/test/orm/test_collection.py
@@ -2500,6 +2500,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,