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 7431683

Browse filesBrowse files
authored
Merge pull request PyMySQL#101 from vtermanis/warning_args
Warning propagation improvements
2 parents c7d2168 + ad935e4 commit 7431683
Copy full SHA for 7431683

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
@@ -4,6 +4,8 @@
44
from datetime import timedelta
55
import unittest
66
import MySQLdb
7+
from MySQLdb.compat import unicode
8+
from MySQLdb import cursors
79
import warnings
810

911

@@ -156,6 +158,28 @@ def test_reraise_exception(self):
156158
return
157159
self.fail("Should raise ProgrammingError")
158160

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

160184
if __name__ == '__main__':
161185
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.