Skip to content

Commit 8828460

Browse files
authored
Merge branch 'master' into fix/opened_conns_on_connect_error
2 parents e19a81e + 293950f commit 8828460

12 files changed

+53
-171
lines changed

.travis.databases.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[
2-
{"host": "localhost", "user": "root", "passwd": "", "db": "test_pymysql", "use_unicode": true, "local_infile": true},
2+
{"host": "localhost", "user": "root", "passwd": "", "db": "test_pymysql", "use_unicode": true},
33
{"host": "localhost", "user": "root", "passwd": "", "db": "test_pymysql2" }
44
]

.travis.yml

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
sudo: false
22
language: python
3-
python: "3.4"
3+
python:
4+
- "3.6"
5+
- "3.5"
6+
- "3.4"
7+
- "2.7"
8+
- "pypy"
9+
410
env:
5-
- TOX_ENV=py27
6-
- TOX_ENV=py33
7-
- TOX_ENV=py34
8-
- TOX_ENV=pypy
9-
- TOX_ENV=pypy3
11+
- PYTHONIOENCODING=utf-8
1012

1113
install:
12-
- pip install -U tox
14+
- pip install -U tornado
1315

1416
before_script:
1517
- "mysql -e 'create database test_pymysql DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;'"
1618
- "mysql -e 'create database test_pymysql2 DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;'"
1719
- cp .travis.databases.json tornado_mysql/tests/databases.json
1820

19-
script: tox -e $TOX_ENV
21+
script: ./runtests.py

README.rst

+18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,24 @@ Tornado-MySQL
99

1010
This package contains a fork of PyMySQL supporting Tornado.
1111

12+
13+
WARNING
14+
-------
15+
16+
This library is experimental and unmaintained. Don't use for production unless you can fix problem yourself.
17+
18+
If you think async is efficient, you're wrong. You shoud try thread pool before this.
19+
See also: http://techspot.zzzeek.org/2015/02/15/asynchronous-python-and-databases/
20+
21+
I don't have motivation to maintain this library. I won't add new features. **Please don't send feature request.**
22+
I'm very lazy about fix bugs. **Don't expect bugs are fixed when you want**.
23+
24+
Instead, you should use your time and energy to port your project to asyncio and newest Python 3.
25+
Please don't pay your time for this project.
26+
27+
You can use aio-libs/aiomysql or ``run_in_executor()`` in asyncio.
28+
29+
1230
Example
1331
-------
1432

pymysql/tests/test_load_local.py

-68
This file was deleted.

setup.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
setup(
55
name="Tornado-MySQL",
6-
version="0.5",
6+
version="0.5.1",
77
url='https://github.com/PyMySQL/Tornado-MySQL',
88
author='INADA Naoki',
99
author_email='[email protected]',
@@ -17,6 +17,7 @@
1717
'Programming Language :: Python :: 3',
1818
'Programming Language :: Python :: 3.3',
1919
'Programming Language :: Python :: 3.4',
20+
'Programming Language :: Python :: 3.5',
2021
'Programming Language :: Python :: Implementation :: CPython',
2122
'Programming Language :: Python :: Implementation :: PyPy',
2223
'Development Status :: 3 - Alpha',

tornado_mysql/connections.py

+4-76
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,6 @@ def is_resultset_packet(self):
322322
field_count = ord(self._data[0:1])
323323
return 1 <= field_count <= 250
324324

325-
def is_load_local_packet(self):
326-
return self._data[0:1] == b'\xfb'
327-
328325
def is_error_packet(self):
329326
return self._data[0:1] == b'\xff'
330327

@@ -437,26 +434,6 @@ def __getattr__(self, key):
437434
return getattr(self.packet, key)
438435

439436

440-
class LoadLocalPacketWrapper(object):
441-
"""
442-
Load Local Packet Wrapper. It uses an existing packet object, and wraps
443-
around it, exposing useful variables while still providing access
444-
to the original packet objects variables and methods.
445-
"""
446-
447-
def __init__(self, from_packet):
448-
if not from_packet.is_load_local_packet():
449-
raise ValueError(
450-
"Cannot create '{0}' object from invalid packet type".format(
451-
self.__class__))
452-
453-
self.packet = from_packet
454-
self.filename = self.packet.get_all_data()[1:]
455-
if DEBUG: print("filename=", self.filename)
456-
457-
def __getattr__(self, key):
458-
return getattr(self.packet, key)
459-
460437

461438
class Connection(object):
462439
"""
@@ -476,8 +453,7 @@ def __init__(self, host="localhost", user=None, password="",
476453
client_flag=0, cursorclass=Cursor, init_command=None,
477454
connect_timeout=None, ssl=None, read_default_group=None,
478455
compress=None, named_pipe=None, no_delay=False,
479-
autocommit=False, db=None, passwd=None, local_infile=False,
480-
io_loop=None):
456+
autocommit=False, db=None, passwd=None, io_loop=None):
481457
"""
482458
Establish a connection to the MySQL database. Accepts several
483459
arguments:
@@ -511,7 +487,6 @@ def __init__(self, host="localhost", user=None, password="",
511487
no_delay: Disable Nagle's algorithm on the socket
512488
autocommit: Autocommit mode. None means use server default. (default: False)
513489
io_loop: Tornado IOLoop
514-
local_infile: Boolean to enable the use of LOAD DATA LOCAL command. (default: False)
515490
516491
db: Alias for database. (for compatibility to MySQLdb)
517492
passwd: Alias for password. (for compatibility to MySQLdb)
@@ -529,9 +504,6 @@ def __init__(self, host="localhost", user=None, password="",
529504
if compress or named_pipe:
530505
raise NotImplementedError("compress and named_pipe arguments are not supported")
531506

532-
if local_infile:
533-
client_flag |= CLIENT.LOCAL_FILES
534-
535507
if ssl and ('capath' in ssl or 'cipher' in ssl):
536508
raise NotImplementedError('ssl options capath and cipher are not supported')
537509

@@ -624,6 +596,9 @@ def close(self):
624596
@gen.coroutine
625597
def close_async(self):
626598
"""Send the quit message and close the socket"""
599+
if self._stream is None or self._stream.closed():
600+
self._stream = None
601+
return
627602
send_data = struct.pack('<i', 1) + int2byte(COMMAND.COM_QUIT)
628603
yield self._stream.write(send_data)
629604
self.close()
@@ -1060,8 +1035,6 @@ def read(self):
10601035

10611036
if first_packet.is_ok_packet():
10621037
self._read_ok_packet(first_packet)
1063-
elif first_packet.is_load_local_packet():
1064-
self._read_load_local_packet(first_packet)
10651038
else:
10661039
yield self._read_result_packet(first_packet)
10671040
finally:
@@ -1094,16 +1067,6 @@ def _read_ok_packet(self, first_packet):
10941067
self.message = ok_packet.message
10951068
self.has_next = ok_packet.has_next
10961069

1097-
def _read_load_local_packet(self, first_packet):
1098-
load_packet = LoadLocalPacketWrapper(first_packet)
1099-
sender = LoadLocalFile(load_packet.filename, self.connection)
1100-
sender.send_data()
1101-
1102-
ok_packet = self.connection._read_packet()
1103-
if not ok_packet.is_ok_packet():
1104-
raise OperationalError(2014, "Commands Out of Sync")
1105-
self._read_ok_packet(ok_packet)
1106-
11071070
def _check_packet_is_eof(self, packet):
11081071
if packet.is_eof_packet():
11091072
eof_packet = EOFPacketWrapper(packet)
@@ -1209,39 +1172,4 @@ def _get_descriptions(self):
12091172
self.description = tuple(description)
12101173

12111174

1212-
class LoadLocalFile(object):
1213-
def __init__(self, filename, connection):
1214-
self.filename = filename
1215-
self.connection = connection
1216-
1217-
def send_data(self):
1218-
"""Send data packets from the local file to the server"""
1219-
if not self.connection.socket:
1220-
raise InterfaceError("(0, '')")
1221-
1222-
# sequence id is 2 as we already sent a query packet
1223-
seq_id = 2
1224-
try:
1225-
with open(self.filename, 'rb') as open_file:
1226-
chunk_size = MAX_PACKET_LEN
1227-
prelude = b""
1228-
packet = b""
1229-
packet_size = 0
1230-
1231-
while True:
1232-
chunk = open_file.read(chunk_size)
1233-
if not chunk:
1234-
break
1235-
packet = struct.pack('<i', len(chunk))[:3] + int2byte(seq_id)
1236-
format_str = '!{0}s'.format(len(chunk))
1237-
packet += struct.pack(format_str, chunk)
1238-
self.connection._write_bytes(packet)
1239-
seq_id += 1
1240-
except IOError:
1241-
raise OperationalError(1017, "Can't find file '{0}'".format(self.filename))
1242-
finally:
1243-
# send the empty packet to signify we are done sending data
1244-
packet = struct.pack('<i', 0)[:3] + int2byte(seq_id)
1245-
self.connection._write_bytes(packet)
1246-
12471175
# g:khuno_ignore='E226,E301,E701'

tornado_mysql/cursors.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def callproc(self, procname, args=()):
230230
for i in range_type(len(args))]))
231231
yield self._query(q)
232232
self._executed = q
233-
yield gen.Return(args)
233+
raise gen.Return(args)
234234

235235
def fetchone(self):
236236
''' Fetch the next row '''
@@ -302,7 +302,10 @@ def _do_get_result(self):
302302
def _show_warnings(self, conn):
303303
ws = yield conn.show_warnings()
304304
for w in ws:
305-
warnings.warn(w[-1], err.Warning, 4)
305+
msg = w[-1]
306+
if PY2 and isinstance(msg, unicode):
307+
msg = msg.encode('utf-8', 'replace')
308+
warnings.warn(msg, err.Warning, 4)
306309

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

0 commit comments

Comments
 (0)