Skip to content

Commit

Permalink
Work around (apparent) Python bug for issue #206
Browse files Browse the repository at this point in the history
It looks like PyCodec_Encode can set an extraneous exception even when it works.  (It should
return 0 if it fails.)  This causes Cursor.fetchall() to fail since it looks for exceptions.

Fixes #206
  • Loading branch information
mkleehammer committed Mar 1, 2017
1 parent a5912eb commit 13cf350
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 6 deletions.
18 changes: 17 additions & 1 deletion src/textenc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,23 @@ PyObject* TextEnc::Encode(PyObject* obj) const
}
#endif

return PyCodec_Encode(obj, name, "strict");
PyObject* bytes = PyCodec_Encode(obj, name, "strict");

if (bytes && PyErr_Occurred())
{
// REVIEW: Issue #206. I am not sure what is going on here, but PyCodec_Encode
// sometimes returns bytes but *also* sets an exception saying "'ascii' codec can't
// encode characters...". I assume the ascii is from my sys encoding, but it seems to
// be a superflous error. Since Cursor.fetchall() looks for exceptions this extraneous
// error causes us to throw an exception.
//
// I'm putting in a work around but we should track down the root cause and report it
// to the Python project if it is not ours.

PyErr_Clear();
}

return bytes;
}


Expand Down
17 changes: 17 additions & 0 deletions tests2/sqlservertests.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,23 @@ def test_empty_unicode_encoding(self):
def test_unicode_query(self):
self.cursor.execute(u"select 1")

# From issue #206
def _maketest(value):
def t(self):
self._test_strtype('nvarchar', value, colsize=len(value))
return t
locals()['test_chinese_param'] = _maketest(u'我的')

def test_chinese(self):
v = u'我的'
self.cursor.execute(u"SELECT N'我的' AS [Name]")
row = self.cursor.fetchone()
self.assertEqual(row[0], v)

self.cursor.execute(u"SELECT N'我的' AS [Name]")
rows = self.cursor.fetchall()
self.assertEqual(rows[0][0], v)

def test_negative_row_index(self):
self.cursor.execute("create table t1(s varchar(20))")
self.cursor.execute("insert into t1 values(?)", "1")
Expand Down
27 changes: 22 additions & 5 deletions tests3/sqlservertests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/python
# -*- coding: latin-1 -*-
# -*- coding: utf-8 -*-

x = 1 # Getting an error if starting with usage for some reason.

Expand Down Expand Up @@ -82,7 +82,6 @@ def setUp(self):
# different collation, you'll need to update this. If someone knows of
# a good way for this to be dynamic, please update. (I suppose we
# could maintain a map from collation to encoding?)
self.cnxn.setencoding('latin1')
self.cnxn.setdecoding(pyodbc.SQL_CHAR, 'latin1')

for i in range(3):
Expand Down Expand Up @@ -317,7 +316,7 @@ def test_varchar_many(self):
self.assertEqual(v3, row.c3)

#
# unicode
# nvarchar
#

def test_unicode_null(self):
Expand All @@ -339,6 +338,24 @@ def test_unicode_longmax(self):
return # so pass / ignore
self.cursor.execute("select cast(replicate(N'x', 512) as nvarchar(max))")

# From issue #206
def _maketest(value):
def t(self):
self._test_strtype('nvarchar', value, colsize=len(value))
return t
locals()['test_chinese_param'] = _maketest('我的')

def test_chinese(self):
v = '我的'
self.cursor.execute(u"SELECT N'我的' AS [Name]")
row = self.cursor.fetchone()
self.assertEqual(row[0], v)

self.cursor.execute(u"SELECT N'我的' AS [Name]")
rows = self.cursor.fetchall()
self.assertEqual(rows[0][0], v)


#
# binary
#
Expand Down Expand Up @@ -1337,8 +1354,8 @@ def test_decode_meta(self):
# This is from GitHub issue #190
self.cursor.execute("create table t1(a int)")
self.cursor.execute("insert into t1 values (1)")
self.cursor.execute('select a as "Tipología" from t1')
self.assertEqual(self.cursor.description[0][0], "Tipología")
self.cursor.execute('select a as "Tipología" from t1')
self.assertEqual(self.cursor.description[0][0], "Tipología")


def main():
Expand Down

0 comments on commit 13cf350

Please sign in to comment.