From 8fb7d30456d664b336d602db2085af1f6433ab35 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Wed, 17 Jul 2024 14:52:08 -0400 Subject: [PATCH] [5.1.x] Fixed #35603 -- Prevented F.__contains__() from hanging. Regression in 94b6f101f7dc363a8e71593570b17527dbb9f77f. Backport of 6b3f55446fdc62bd277903fd188a1781e4d92d29 from main. --- django/db/models/expressions.py | 5 +++++ tests/expressions/tests.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 4ee22420d9..7779173f3c 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -884,6 +884,11 @@ class F(Combinable): def __getitem__(self, subscript): return Sliced(self, subscript) + def __contains__(self, other): + # Disable old-style iteration protocol inherited from implementing + # __getitem__() to prevent this method from hanging. + raise TypeError(f"argument of type '{self.__class__.__name__}' is not iterable") + def resolve_expression( self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False ): diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py index 3538900092..64103f14db 100644 --- a/tests/expressions/tests.py +++ b/tests/expressions/tests.py @@ -1302,6 +1302,11 @@ class FTests(SimpleTestCase): self.assertNotEqual(f, value) self.assertNotEqual(value, f) + def test_contains(self): + msg = "argument of type 'F' is not iterable" + with self.assertRaisesMessage(TypeError, msg): + "" in F("name") + class ExpressionsTests(TestCase): def test_F_reuse(self):