diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-12-01 21:39:59 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-12-02 14:57:42 -0500 |
commit | 9fc17513fe69a1fd26fc522f9862af3e0ebfd2c4 (patch) | |
tree | 81c787491ed06438e23cac74616c6cee9c824163 | |
parent | dff827df53cd3af8a641c74e5115707664eb6d79 (diff) | |
download | sqlalchemy-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.rst | 8 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/collections.py | 4 | ||||
-rw-r--r-- | test/orm/test_collection.py | 13 |
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, |