]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add __next__(), next() to ResultProxy
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 15 Sep 2017 15:14:36 +0000 (11:14 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 15 Sep 2017 18:03:27 +0000 (14:03 -0400)
Added ``__next__()`` and ``next()`` methods to :class:`.ResultProxy`,
so that the ``next()`` builtin function works on the object directly.
:class:`.ResultProxy` has long had an ``__iter__()`` method which already
allows it to respond to the ``iter()`` builtin.   The implementation
for ``__iter__()`` is unchanged, as performance testing has indicated
that iteration using a ``__next__()`` method with ``StopIteration``
is about 20% slower in both Python 2.7 and 3.6.

Change-Id: I70569a4c48ad85a3c21a7ad422f270a559926cfb
Fixes: #4077
doc/build/changelog/unreleased_12/4077.rst [new file with mode: 0644]
lib/sqlalchemy/engine/result.py
test/sql/test_resultset.py

diff --git a/doc/build/changelog/unreleased_12/4077.rst b/doc/build/changelog/unreleased_12/4077.rst
new file mode 100644 (file)
index 0000000..b051d47
--- /dev/null
@@ -0,0 +1,11 @@
+.. change::
+    :tags: feature, engine
+    :tickets: 4077
+
+    Added ``__next__()`` and ``next()`` methods to :class:`.ResultProxy`,
+    so that the ``next()`` builtin function works on the object directly.
+    :class:`.ResultProxy` has long had an ``__iter__()`` method which already
+    allows it to respond to the ``iter()`` builtin.   The implementation
+    for ``__iter__()`` is unchanged, as performance testing has indicated
+    that iteration using a ``__next__()`` method with ``StopIteration``
+    is about 20% slower in both Python 2.7 and 3.6.
\ No newline at end of file
index 3aae932f28d477d7e5c9a7e763178cd31f60ce7b..79f3625008e1c26f01be24da90ccbd712cbc7640 100644 (file)
@@ -862,6 +862,8 @@ class ResultProxy(object):
             self.closed = True
 
     def __iter__(self):
+        """Implement iteration protocol."""
+
         while True:
             row = self.fetchone()
             if row is None:
@@ -869,6 +871,20 @@ class ResultProxy(object):
             else:
                 yield row
 
+    def __next__(self):
+        """Implement the next() protocol.
+
+        .. versionadded:: 1.2
+
+        """
+        row = self.fetchone()
+        if row is None:
+            raise StopIteration()
+        else:
+            return row
+
+    next = __next__
+
     @util.memoized_property
     def inserted_primary_key(self):
         """Return the primary key for the row just inserted.
index 41092efe9ecbd5f3524a152ad15d6920e46906fc..5c7108ca09ffa537ac999ea069254751c2fdea6d 100644 (file)
@@ -61,6 +61,23 @@ class ResultProxyTest(fixtures.TablesTest):
             rows.append(row)
         eq_(len(rows), 3)
 
+    def test_row_next(self):
+        users = self.tables.users
+
+        users.insert().execute(
+            {'user_id': 7, 'user_name': 'jack'},
+            {'user_id': 8, 'user_name': 'ed'},
+            {'user_id': 9, 'user_name': 'fred'},
+        )
+        r = users.select().execute()
+        rows = []
+        while True:
+            row = next(r, 'foo')
+            if row == 'foo':
+                break
+            rows.append(row)
+        eq_(len(rows), 3)
+
     @testing.requires.subqueries
     def test_anonymous_rows(self):
         users = self.tables.users