Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 7 additions & 18 deletions src/MySQLdb/cursors.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from ._exceptions import ProgrammingError


#: Regular expression for ``Cursor.executemany```.
#: executemany only supports simple bulk insert.
#: You can use it to load large dataset.
Expand Down Expand Up @@ -329,7 +328,13 @@ def _fetch_row(self, size=1):
return self._result.fetch_row(size, self._fetch_type)

def __iter__(self):
return iter(self.fetchone, None)
return self

def __next__(self):
row = self.fetchone()
if row is None:
raise StopIteration
return row

def __getattr__(self, name):
# DB-API 2.0 optional extension says these errors can be accessed
Expand Down Expand Up @@ -419,11 +424,6 @@ def scroll(self, value, mode="relative"):
raise IndexError("out of range")
self.rownumber = r

def __iter__(self):
self._check_executed()
result = self.rownumber and self._rows[self.rownumber :] or self._rows
return iter(result)


class CursorUseResultMixIn:
"""This is a MixIn class which causes the result set to be stored
Expand Down Expand Up @@ -464,17 +464,6 @@ def fetchall(self):
self.rownumber = self.rownumber + len(r)
return r

def __iter__(self):
return self

def next(self):
row = self.fetchone()
if row is None:
raise StopIteration
return row

__next__ = next


class CursorTupleRowsMixIn:
"""This is a MixIn class that causes all rows to be returned as tuples,
Expand Down
24 changes: 24 additions & 0 deletions tests/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,27 @@ def test_sscursor_warning_count():
rows = cursor.fetchmany(2)
assert len(rows) == 1
assert cursor.warning_count == 1


@pytest.mark.parametrize("Cursor", [MySQLdb.cursors.Cursor, MySQLdb.cursors.SSCursor])
def test_cursor_is_iterator(Cursor):
conn = connect()
cursor = conn.cursor(Cursor)

cursor.execute("DROP TABLE IF EXISTS test_cursor_is_iterator")
cursor.execute(
"CREATE TABLE test_cursor_is_iterator (id INT PRIMARY KEY, name VARCHAR(20))"
)
_tables.append("test_cursor_is_iterator")
cursor.executemany(
"INSERT INTO test_cursor_is_iterator (id, name) VALUES (%s, %s)",
[(1, "a"), (2, "b"), (3, "c")],
)

cursor.execute("SELECT name FROM test_cursor_is_iterator ORDER BY id")
assert iter(cursor) is cursor
assert next(cursor) == ("a",)
assert next(cursor) == ("b",)
assert next(cursor) == ("c",)
with pytest.raises(StopIteration):
next(cursor)
Loading