Skip to content

Commit 3fd1af8

Browse files
authored
Merge pull request #2929 from bagerard/infinite_loop_queryset_nocache_repr
Fix buggy rewinding during QuerySetNoCache.__repr__
2 parents 369c95c + 6a6a942 commit 3fd1af8

4 files changed

Lines changed: 36 additions & 4 deletions

File tree

‎docs/changelog.rst‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Changes in 1.0.0
4141
- Fixed stacklevel of many warnings (to point places emitting the warning more accurately)
4242
- Add support for collation/hint/comment to delete/update and aggregate #2842
4343
- BREAKING CHANGE: Remove LongField as it's equivalent to IntField since we drop support to Python2 long time ago (User should simply switch to IntField) #2309
44+
- BugFix - Prevent ``repr()`` from rewinding an actively iterated ``QuerySetNoCache`` #2870
4445
- Replace MongoEngine-created ``bson.SON`` objects with built-in dictionaries, SON providing no advantages since Python 3.7 as native dict preserved insertion order. #2898
4546
- BREAKING CHANGE: The obsolete ``slaves`` and ``is_slave`` connection options were silently ignored since 2014 and will now raise ``ConnectionFailure`` if provided #2920.
4647
- BugFix - Calling .clear on a ListField wasn't being marked as changed (and flushed to db upon .save()) #2858

‎mongoengine/queryset/queryset.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,5 @@ def __iter__(self):
186186
if queryset._iter:
187187
queryset = self.clone()
188188
queryset.rewind()
189+
queryset._iter = True
189190
return queryset

‎tests/fields/test_decimal128_field.py‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import json
2-
import random
32
from decimal import Decimal
43

54
import pytest
@@ -142,8 +141,8 @@ def test_storage(self):
142141

143142
def test_json(self):
144143
Decimal128Document.drop_collection()
145-
f = str(random.random())
146-
Decimal128Document(dec128_fld=f).save()
144+
value = "9.549665900909776e-05"
145+
Decimal128Document(dec128_fld=value).save()
147146
json_str = Decimal128Document.objects.to_json()
148147
array = json.loads(json_str)
149-
assert array[0]["dec128_fld"] == {"$numberDecimal": str(f)}
148+
assert array[0]["dec128_fld"] == {"$numberDecimal": "0.00009549665900909776"}

‎tests/queryset/test_queryset.py‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5590,6 +5590,37 @@ class Person(Document):
55905590
qs = Person.objects.no_cache()
55915591
assert repr(qs) == "[]"
55925592

5593+
def test_queryset_repr__not_iterated__lists_documents(self):
5594+
class Person(Document):
5595+
name = StringField()
5596+
5597+
def __repr__(self):
5598+
return f"<Person: {self.name}>"
5599+
5600+
Person.drop_collection()
5601+
Person.objects.insert([Person(name="a"), Person(name="b")])
5602+
5603+
querysets = (
5604+
Person.objects.order_by("name"),
5605+
Person.objects.order_by("name").no_cache(),
5606+
)
5607+
for queryset in querysets:
5608+
with self.subTest(queryset_type=type(queryset).__name__):
5609+
assert repr(queryset) == "[<Person: a>, <Person: b>]"
5610+
5611+
def test_no_cached_queryset_repr__during_iteration__reports_without_rewinding(self):
5612+
class Person(Document):
5613+
name = StringField()
5614+
5615+
Person.drop_collection()
5616+
Person.objects.insert([Person(name="a"), Person(name="b")])
5617+
qs = Person.objects.order_by("name").no_cache()
5618+
iterator = iter(qs)
5619+
5620+
assert next(iterator).name == "a"
5621+
assert repr(qs) == ".. queryset mid-iteration .."
5622+
assert next(iterator).name == "b"
5623+
55935624
def test_no_cached_on_a_cached_queryset_raise_error(self):
55945625
class Person(Document):
55955626
name = StringField()

0 commit comments

Comments
 (0)