Fixes __repr__ modifying the cursor

Fixes MongoEngine/mongoengine#30
This commit is contained in:
Ross Lawley 2012-06-22 16:22:27 +01:00
parent 6d90ce250a
commit 056c604dc3
3 changed files with 54 additions and 22 deletions

View File

@ -2,6 +2,11 @@
Changelog Changelog
========= =========
Changes in 0.6.X
================
- Fixes __repr__ modifying the cursor
Changes in 0.6.12 Changes in 0.6.12
================= =================
- Fixes scalar lookups for primary_key - Fixes scalar lookups for primary_key

View File

@ -341,6 +341,7 @@ class QuerySet(object):
self._timeout = True self._timeout = True
self._class_check = True self._class_check = True
self._slave_okay = False self._slave_okay = False
self._iter = False
self._scalar = [] self._scalar = []
# If inheritance is allowed, only return instances and instances of # If inheritance is allowed, only return instances and instances of
@ -953,6 +954,7 @@ class QuerySet(object):
def next(self): def next(self):
"""Wrap the result in a :class:`~mongoengine.Document` object. """Wrap the result in a :class:`~mongoengine.Document` object.
""" """
self._iter = True
try: try:
if self._limit == 0: if self._limit == 0:
raise StopIteration raise StopIteration
@ -969,6 +971,7 @@ class QuerySet(object):
.. versionadded:: 0.3 .. versionadded:: 0.3
""" """
self._iter = False
self._cursor.rewind() self._cursor.rewind()
def count(self): def count(self):
@ -1808,21 +1811,24 @@ class QuerySet(object):
return data return data
def __repr__(self): def __repr__(self):
limit = REPR_OUTPUT_SIZE + 1 """Provides the string representation of the QuerySet
start = (0 if self._skip is None else self._skip)
if self._limit is None: .. versionchanged:: 0.6.13 Now doesnt modify the cursor
stop = start + limit """
if self._limit is not None:
if self._limit - start > limit: if self._iter:
stop = start + limit return '.. queryset mid-iteration ..'
else:
stop = self._limit data = []
try: for i in xrange(REPR_OUTPUT_SIZE + 1):
data = list(self[start:stop]) try:
except pymongo.errors.InvalidOperation: data.append(self.next())
return ".. queryset mid-iteration .." except StopIteration:
break
if len(data) > REPR_OUTPUT_SIZE: if len(data) > REPR_OUTPUT_SIZE:
data[-1] = "...(remaining elements truncated)..." data[-1] = "...(remaining elements truncated)..."
self.rewind()
return repr(data) return repr(data)
def select_related(self, max_depth=1): def select_related(self, max_depth=1):

View File

@ -636,17 +636,38 @@ class QuerySetTest(unittest.TestCase):
self.assertEqual(people1, people2) self.assertEqual(people1, people2)
self.assertEqual(people1, people3) self.assertEqual(people1, people3)
def test_repr_iteration(self): def test_repr(self):
"""Ensure that QuerySet __repr__ can handle loops """Test repr behavior isnt destructive"""
"""
self.Person(name='Person 1').save()
self.Person(name='Person 2').save()
queryset = self.Person.objects class Doc(Document):
self.assertEquals('[<Person: Person object>, <Person: Person object>]', repr(queryset)) number = IntField()
for person in queryset:
self.assertEquals('.. queryset mid-iteration ..', repr(queryset))
def __repr__(self):
return "<Doc: %s>" % self.number
Doc.drop_collection()
for i in xrange(1000):
Doc(number=i).save()
docs = Doc.objects.order_by('number')
self.assertEquals(docs.count(), 1000)
self.assertEquals(len(docs), 1000)
docs_string = "%s" % docs
self.assertTrue("Doc: 0" in docs_string)
self.assertEquals(docs.count(), 1000)
self.assertEquals(len(docs), 1000)
# Limit and skip
self.assertEquals('[<Doc: 1>, <Doc: 2>, <Doc: 3>]', "%s" % docs[1:4])
self.assertEquals(docs.count(), 3)
self.assertEquals(len(docs), 3)
for doc in docs:
self.assertEqual('.. queryset mid-iteration ..', repr(docs))
def test_regex_query_shortcuts(self): def test_regex_query_shortcuts(self):
"""Ensure that contains, startswith, endswith, etc work. """Ensure that contains, startswith, endswith, etc work.