diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-09-15 11:14:36 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-09-15 14:03:27 -0400 |
commit | 339416b821ed543f289fccff8f6fc9c44dbc9d23 (patch) | |
tree | 694b8be639abeb14c89e8101b3d8d1c2670c6abf | |
parent | 31f80b9eaeb3c3435b7f6679b41e434478b1d11c (diff) | |
download | sqlalchemy-review/mike_bayer/ticket_4077.tar.gz |
Add __next__(), next() to ResultProxyreview/mike_bayer/ticket_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.
Change-Id: I70569a4c48ad85a3c21a7ad422f270a559926cfb
Fixes: #4077
-rw-r--r-- | doc/build/changelog/unreleased_12/4077.rst | 11 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/result.py | 16 | ||||
-rw-r--r-- | test/sql/test_resultset.py | 17 |
3 files changed, 44 insertions, 0 deletions
diff --git a/doc/build/changelog/unreleased_12/4077.rst b/doc/build/changelog/unreleased_12/4077.rst new file mode 100644 index 000000000..b051d47ba --- /dev/null +++ b/doc/build/changelog/unreleased_12/4077.rst @@ -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 diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py index 3aae932f2..79f362500 100644 --- a/lib/sqlalchemy/engine/result.py +++ b/lib/sqlalchemy/engine/result.py @@ -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. diff --git a/test/sql/test_resultset.py b/test/sql/test_resultset.py index 41092efe9..5c7108ca0 100644 --- a/test/sql/test_resultset.py +++ b/test/sql/test_resultset.py @@ -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 |