Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ad935e4

Browse filesBrowse files
committed
Warning propagation improvements
1 parent 8c219d9 commit ad935e4
Copy full SHA for ad935e4

File tree

Expand file treeCollapse file tree

2 files changed

+44
-14
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+44
-14
lines changed

‎MySQLdb/cursors.py

Copy file name to clipboardExpand all lines: MySQLdb/cursors.py
+20-14Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ def __init__(self, connection):
7373
self.messages = []
7474
self.errorhandler = connection.errorhandler
7575
self._result = None
76-
self._warnings = 0
77-
self._info = None
76+
self._warnings = None
7877
self.rownumber = None
7978

8079
def close(self):
@@ -128,29 +127,37 @@ def _check_executed(self):
128127

129128
def _warning_check(self):
130129
from warnings import warn
130+
db = self._get_db()
131+
132+
# None => warnings not interrogated for current query yet
133+
# 0 => no warnings exists or have been handled already for this query
134+
if self._warnings is None:
135+
self._warnings = db.warning_count()
131136
if self._warnings:
137+
# Only propagate warnings for current query once
138+
warning_count = self._warnings
139+
self._warnings = 0
132140
# When there is next result, fetching warnings cause "command
133141
# out of sync" error.
134142
if self._result and self._result.has_next:
135-
msg = "There are %d MySQL warnings." % (self._warnings,)
143+
msg = "There are %d MySQL warnings." % (warning_count,)
136144
self.messages.append(msg)
137-
warn(msg, self.Warning, 3)
145+
warn(self.Warning(0, msg), stacklevel=3)
138146
return
139147

140-
warnings = self._get_db().show_warnings()
148+
warnings = db.show_warnings()
141149
if warnings:
142150
# This is done in two loops in case
143151
# Warnings are set to raise exceptions.
144152
for w in warnings:
145153
self.messages.append((self.Warning, w))
146154
for w in warnings:
147-
msg = w[-1]
148-
if not PY2 and isinstance(msg, bytes):
149-
msg = msg.decode()
150-
warn(msg, self.Warning, 3)
151-
elif self._info:
152-
self.messages.append((self.Warning, self._info))
153-
warn(self._info, self.Warning, 3)
155+
warn(self.Warning(*w[1:3]), stacklevel=3)
156+
else:
157+
info = db.info()
158+
if info:
159+
self.messages.append((self.Warning, info))
160+
warn(self.Warning(0, info), stacklevel=3)
154161

155162
def nextset(self):
156163
"""Advance to the next result set.
@@ -180,8 +187,7 @@ def _do_get_result(self):
180187
self.description = self._result and self._result.describe() or None
181188
self.description_flags = self._result and self._result.field_flags() or None
182189
self.lastrowid = db.insert_id()
183-
self._warnings = db.warning_count()
184-
self._info = db.info()
190+
self._warnings = None
185191

186192
def setinputsizes(self, *args):
187193
"""Does nothing, required by DB API."""

‎tests/test_MySQLdb_capabilities.py

Copy file name to clipboardExpand all lines: tests/test_MySQLdb_capabilities.py
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from datetime import timedelta
44
import unittest
55
import MySQLdb
6+
from MySQLdb.compat import unicode
7+
from MySQLdb import cursors
68
import warnings
79

810

@@ -155,6 +157,28 @@ def test_reraise_exception(self):
155157
return
156158
self.fail("Should raise ProgrammingError")
157159

160+
def test_warning_propagation(self):
161+
with warnings.catch_warnings():
162+
# Ignore all warnings other than MySQLdb generated ones
163+
warnings.simplefilter("ignore")
164+
warnings.simplefilter("error", category=MySQLdb.Warning)
165+
166+
# verify for both buffered and unbuffered cursor types
167+
for cursor_class in (cursors.Cursor, cursors.SSCursor):
168+
c = self.connection.cursor(cursor_class)
169+
try:
170+
c.execute("SELECT CAST('124b' AS SIGNED)")
171+
c.fetchall()
172+
except MySQLdb.Warning as e:
173+
# Warnings should have errorcode and string message, just like exceptions
174+
self.assertEqual(len(e.args), 2)
175+
self.assertEqual(e.args[0], 1292)
176+
self.assertTrue(isinstance(e.args[1], unicode))
177+
else:
178+
self.fail("Should raise Warning")
179+
finally:
180+
c.close()
181+
158182

159183
if __name__ == '__main__':
160184
if test_MySQLdb.leak_test:

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.