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 bc5c25e

Browse filesBrowse files
committed
Merge remote-tracking branch 'mysqldb/python3'
Conflicts: README.md
2 parents c498e7d + 7a6b221 commit bc5c25e
Copy full SHA for bc5c25e
Expand file treeCollapse file tree

17 files changed

+290
-543
lines changed

‎.travis.yml

Copy file name to clipboard
+8-6Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
language: python
2-
python:
3-
- "2.6"
4-
- "2.7"
5-
- "pypy"
6-
install: python setup.py install
2+
before_install:
3+
- sudo apt-get update -qq -y
4+
- sudo apt-get install python3.4-dev
5+
6+
install:
7+
- pip install tox six
8+
79
before_script: mysql -e 'create database mysqldb_test charset utf8;'
8-
script: TESTDB=travis.cnf nosetests
10+
script: TESTDB=travis.cnf tox

‎MANIFEST.in

Copy file name to clipboardExpand all lines: MANIFEST.in
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ include HISTORY
66
include INSTALL
77
include README.md
88
include GPL-2.0
9-
include pymemcompat.h
109
include metadata.cfg
1110
include site.cfg
1211
include setup_common.py

‎MySQLdb/__init__.py

Copy file name to clipboardExpand all lines: MySQLdb/__init__.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def test_DBAPISet_set_inequality_membership():
7373
assert FIELD_TYPE.DATE != STRING
7474

7575
def Binary(x):
76-
return str(x)
76+
return bytes(x)
7777

7878
def Connect(*args, **kwargs):
7979
"""Factory function for connections.Connection."""

‎MySQLdb/compat.py

Copy file name to clipboard
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import sys
2+
3+
if sys.version_info[0] == 3:
4+
PY2 = False
5+
unicode = str
6+
unichr = chr
7+
long = int
8+
else:
9+
PY2 = True
10+
unicode = unicode
11+
unichr = unichr
12+
long = long

‎MySQLdb/connections.py

Copy file name to clipboardExpand all lines: MySQLdb/connections.py
+29-8Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
88
"""
99
from MySQLdb import cursors
10+
from MySQLdb.compat import unicode, PY2
1011
from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \
1112
DatabaseError, OperationalError, IntegrityError, InternalError, \
1213
NotSupportedError, ProgrammingError
13-
import types, _mysql
14+
import _mysql
1415
import re
1516

1617

@@ -33,7 +34,11 @@ def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
3334
connection.messages.append(error)
3435
del cursor
3536
del connection
36-
raise errorclass, errorvalue
37+
if errorclass is not None:
38+
raise errorclass(errorvalue)
39+
else:
40+
raise Exception(errorvalue)
41+
3742

3843
re_numeric_part = re.compile(r"^(\d+)")
3944

@@ -115,6 +120,7 @@ class object, used to create cursors (keyword only)
115120
columns are returned as strings. columns are returned as
116121
normal strings. Unicode objects will always be encoded to
117122
the connection's character set regardless of this setting.
123+
Default to False on Python 2 and True on Python 3.
118124
119125
charset
120126
If supplied, the connection character set will be changed
@@ -170,7 +176,7 @@ class object, used to create cursors (keyword only)
170176
cursorclass = kwargs2.pop('cursorclass', self.default_cursor)
171177
charset = kwargs2.pop('charset', '')
172178

173-
if charset:
179+
if charset or not PY2:
174180
use_unicode = True
175181
else:
176182
use_unicode = False
@@ -199,13 +205,20 @@ class object, used to create cursors (keyword only)
199205

200206
db = proxy(self)
201207
def _get_string_literal():
208+
# Note: string_literal() is called for bytes object on Python 3.
202209
def string_literal(obj, dummy=None):
203210
return db.string_literal(obj)
204211
return string_literal
205212

206213
def _get_unicode_literal():
207-
def unicode_literal(u, dummy=None):
208-
return db.literal(u.encode(unicode_literal.charset))
214+
if PY2:
215+
# unicode_literal is called for only unicode object.
216+
def unicode_literal(u, dummy=None):
217+
return db.literal(u.encode(unicode_literal.charset))
218+
else:
219+
# unicode_literal() is called for arbitrary object.
220+
def unicode_literal(u, dummy=None):
221+
return db.literal(str(u).encode(unicode_literal.charset))
209222
return unicode_literal
210223

211224
def _get_string_decoder():
@@ -229,8 +242,8 @@ def string_decoder(s):
229242
self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder))
230243
self.converter[FIELD_TYPE.BLOB].append((None, string_decoder))
231244

232-
self.encoders[types.StringType] = string_literal
233-
self.encoders[types.UnicodeType] = unicode_literal
245+
self.encoders[bytes] = string_literal
246+
self.encoders[unicode] = unicode_literal
234247
self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS
235248
if self._transactional:
236249
if autocommit is not None:
@@ -275,7 +288,15 @@ def literal(self, o):
275288
applications.
276289
277290
"""
278-
return self.escape(o, self.encoders)
291+
s = self.escape(o, self.encoders)
292+
# Python 3 doesn't support % operation for bytes object.
293+
# We should decode it before using %.
294+
# Decoding with ascii and surrogateescape allows convert arbitrary
295+
# bytes to unicode and back again.
296+
# See http://python.org/dev/peps/pep-0383/
297+
if not PY2 and isinstance(s, bytes):
298+
return s.decode('ascii', 'surrogateescape')
299+
return s
279300

280301
def begin(self):
281302
"""Explicitly begin a connection. Non-standard.

‎MySQLdb/converters.py

Copy file name to clipboardExpand all lines: MySQLdb/converters.py
+19-59Lines changed: 19 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,9 @@
3535
from _mysql import string_literal, escape_sequence, escape_dict, escape, NULL
3636
from MySQLdb.constants import FIELD_TYPE, FLAG
3737
from MySQLdb.times import *
38+
from MySQLdb.compat import PY2, long
3839

39-
try:
40-
from types import IntType, LongType, FloatType, NoneType, TupleType, ListType, DictType, InstanceType, \
41-
StringType, UnicodeType, ObjectType, BooleanType, ClassType, TypeType
42-
except ImportError:
43-
# Python 3
44-
long = int
45-
IntType, LongType, FloatType, NoneType = int, long, float, type(None)
46-
TupleType, ListType, DictType, InstanceType = tuple, list, dict, None
47-
StringType, UnicodeType, ObjectType, BooleanType = bytes, str, object, bool
40+
NoneType = type(None)
4841

4942
import array
5043

@@ -76,8 +69,6 @@ def Unicode2Str(s, d):
7669
is connection-dependent."""
7770
return s.encode()
7871

79-
Long2Int = Thing2Str
80-
8172
def Float2Str(o, d):
8273
return '%.15g' % o
8374

@@ -86,43 +77,13 @@ def None2NULL(o, d):
8677
return NULL # duh
8778

8879
def Thing2Literal(o, d):
89-
9080
"""Convert something into a SQL string literal. If using
9181
MySQL-3.23 or newer, string_literal() is a method of the
9282
_mysql.MYSQL object, and this function will be overridden with
9383
that method when the connection is created."""
94-
9584
return string_literal(o, d)
9685

9786

98-
def Instance2Str(o, d):
99-
100-
"""
101-
102-
Convert an Instance to a string representation. If the __str__()
103-
method produces acceptable output, then you don't need to add the
104-
class to conversions; it will be handled by the default
105-
converter. If the exact class is not found in d, it will use the
106-
first class it can find for which o is an instance.
107-
108-
"""
109-
110-
if o.__class__ in d:
111-
return d[o.__class__](o, d)
112-
cl = filter(lambda x,o=o:
113-
type(x) is ClassType
114-
and isinstance(o, x), d.keys())
115-
if not cl:
116-
cl = filter(lambda x,o=o:
117-
type(x) is TypeType
118-
and isinstance(o, x)
119-
and d[x] is not Instance2Str,
120-
d.keys())
121-
if not cl:
122-
return d[StringType](o,d)
123-
d[o.__class__] = d[cl[0]]
124-
return d[cl[0]](o, d)
125-
12687
def char_array(s):
12788
return array.array('c', s)
12889

@@ -133,21 +94,19 @@ def quote_tuple(t, d):
13394
return "(%s)" % (','.join(escape_sequence(t, d)))
13495

13596
conversions = {
136-
IntType: Thing2Str,
137-
LongType: Long2Int,
138-
FloatType: Float2Str,
97+
int: Thing2Str,
98+
long: Thing2Str,
99+
float: Float2Str,
139100
NoneType: None2NULL,
140-
TupleType: quote_tuple,
141-
ListType: quote_tuple,
142-
DictType: escape_dict,
143-
InstanceType: Instance2Str,
101+
tuple: quote_tuple,
102+
list: quote_tuple,
103+
dict: escape_dict,
144104
ArrayType: array2Str,
145-
StringType: Thing2Literal, # default
146-
UnicodeType: Unicode2Str,
147-
ObjectType: Instance2Str,
148-
BooleanType: Bool2Str,
105+
bool: Bool2Str,
106+
Date: Thing2Literal,
149107
DateTimeType: DateTime2literal,
150108
DateTimeDeltaType: DateTimeDelta2literal,
109+
str: Thing2Literal, # default
151110
set: Set2Str,
152111
FIELD_TYPE.TINY: int,
153112
FIELD_TYPE.SHORT: int,
@@ -165,25 +124,26 @@ def quote_tuple(t, d):
165124
FIELD_TYPE.TIME: TimeDelta_or_None,
166125
FIELD_TYPE.DATE: Date_or_None,
167126
FIELD_TYPE.BLOB: [
168-
(FLAG.BINARY, str),
127+
(FLAG.BINARY, bytes),
169128
],
170129
FIELD_TYPE.STRING: [
171-
(FLAG.BINARY, str),
130+
(FLAG.BINARY, bytes),
172131
],
173132
FIELD_TYPE.VAR_STRING: [
174-
(FLAG.BINARY, str),
133+
(FLAG.BINARY, bytes),
175134
],
176135
FIELD_TYPE.VARCHAR: [
177-
(FLAG.BINARY, str),
136+
(FLAG.BINARY, bytes),
178137
],
179138
}
139+
if PY2:
140+
conversions[unicode] = Unicode2Str
141+
else:
142+
conversions[bytes] = Thing2Literal
180143

181144
try:
182145
from decimal import Decimal
183146
conversions[FIELD_TYPE.DECIMAL] = Decimal
184147
conversions[FIELD_TYPE.NEWDECIMAL] = Decimal
185148
except ImportError:
186149
pass
187-
188-
189-

0 commit comments

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