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 ba5ccd9

Browse filesBrowse files
committed
Merge branch 'master' of github.com:PyMySQL/mysqlclient-python
2 parents b493d2e + 074f152 commit ba5ccd9
Copy full SHA for ba5ccd9

File tree

Expand file treeCollapse file tree

5 files changed

+133
-8
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+133
-8
lines changed

‎MySQLdb/connections.py

Copy file name to clipboardExpand all lines: MySQLdb/connections.py
+15-2Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ class Connection(_mysql.connection):
6363
"""MySQL Database Connection Object"""
6464

6565
default_cursor = cursors.Cursor
66+
waiter = None
6667

6768
def __init__(self, *args, **kwargs):
6869
"""
69-
7070
Create a connection to the database. It is strongly recommended
7171
that you only use keyword parameters. Consult the MySQL C API
7272
documentation for more information.
@@ -150,9 +150,13 @@ class object, used to create cursors (keyword only)
150150
If True, autocommit is enabled.
151151
If None, autocommit isn't set and server default is used.
152152
153+
waiter
154+
Callable accepts fd as an argument. It is called after sending
155+
query and before reading response.
156+
This is useful when using with greenlet and async io.
157+
153158
There are a number of undocumented, non-standard methods. See the
154159
documentation for the MySQL C API for some hints on what they do.
155-
156160
"""
157161
from MySQLdb.constants import CLIENT, FIELD_TYPE
158162
from MySQLdb.converters import conversions
@@ -195,6 +199,7 @@ class object, used to create cursors (keyword only)
195199

196200
# PEP-249 requires autocommit to be initially off
197201
autocommit = kwargs2.pop('autocommit', False)
202+
self.waiter = kwargs2.pop('waiter', None)
198203

199204
super(Connection, self).__init__(*args, **kwargs2)
200205
self.cursorclass = cursorclass
@@ -266,6 +271,14 @@ def cursor(self, cursorclass=None):
266271
"""
267272
return (cursorclass or self.cursorclass)(self)
268273

274+
def query(self, query):
275+
if self.waiter is not None:
276+
self.send_query(query)
277+
self.waiter(self.fileno())
278+
self.read_query_result()
279+
else:
280+
_mysql.connection.query(self, query)
281+
269282
def __enter__(self):
270283
if self.get_autocommit():
271284
self.query("BEGIN")

‎README.md

Copy file name to clipboardExpand all lines: README.md
-6Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,3 @@ This is a fork of [MySQLdb1](https://github.com/farcepest/MySQLdb1).
77

88
This project adds Python 3 support and bug fixes.
99
I hope this fork is merged back to MySQLdb1 like distribute was merged back to setuptools.
10-
11-
TODO
12-
----
13-
14-
* A 1.3.0 release that will support Python 2.7 and 3.3-3.4
15-
* Release binary wheel for Windows.

‎_mysql.c

Copy file name to clipboardExpand all lines: _mysql.c
+74Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,16 @@ static int _mysql_ConnectionObject_clear(
756756
return 0;
757757
}
758758

759+
static char _mysql_ConnectionObject_fileno__doc__[] =
760+
"Return underlaying fd for connection";
761+
762+
static PyObject *
763+
_mysql_ConnectionObject_fileno(
764+
_mysql_ConnectionObject *self)
765+
{
766+
return PyInt_FromLong(self->connection.net.fd);
767+
}
768+
759769
static char _mysql_ConnectionObject_close__doc__[] =
760770
"Close the connection. No further activity possible.";
761771

@@ -1963,8 +1973,10 @@ _mysql_ConnectionObject_query(
19631973
{
19641974
char *query;
19651975
int len, r;
1976+
MYSQL *mysql = &(self->connection);
19661977
if (!PyArg_ParseTuple(args, "s#:query", &query, &len)) return NULL;
19671978
check_connection(self);
1979+
19681980
Py_BEGIN_ALLOW_THREADS
19691981
r = mysql_real_query(&(self->connection), query, len);
19701982
Py_END_ALLOW_THREADS
@@ -1974,6 +1986,50 @@ _mysql_ConnectionObject_query(
19741986
}
19751987

19761988

1989+
static char _mysql_ConnectionObject_send_query__doc__[] =
1990+
"Send a query. Same to query() except not wait response.\n\n\
1991+
Use read_query_result() before calling store_result() or use_result()\n";
1992+
1993+
static PyObject *
1994+
_mysql_ConnectionObject_send_query(
1995+
_mysql_ConnectionObject *self,
1996+
PyObject *args)
1997+
{
1998+
char *query;
1999+
int len, r;
2000+
MYSQL *mysql = &(self->connection);
2001+
if (!PyArg_ParseTuple(args, "s#:query", &query, &len)) return NULL;
2002+
check_connection(self);
2003+
2004+
Py_BEGIN_ALLOW_THREADS
2005+
r = mysql_send_query(mysql, query, len);
2006+
Py_END_ALLOW_THREADS
2007+
if (r) return _mysql_Exception(self);
2008+
Py_INCREF(Py_None);
2009+
return Py_None;
2010+
}
2011+
2012+
2013+
static char _mysql_ConnectionObject_read_query_result__doc__[] =
2014+
"Read result of query sent by send_query().\n";
2015+
2016+
static PyObject *
2017+
_mysql_ConnectionObject_read_query_result(
2018+
_mysql_ConnectionObject *self)
2019+
{
2020+
char *query;
2021+
int len, r;
2022+
MYSQL *mysql = &(self->connection);
2023+
check_connection(self);
2024+
2025+
Py_BEGIN_ALLOW_THREADS
2026+
r = (int)mysql_read_query_result(mysql);
2027+
Py_END_ALLOW_THREADS
2028+
if (r) return _mysql_Exception(self);
2029+
Py_INCREF(Py_None);
2030+
return Py_None;
2031+
}
2032+
19772033
static char _mysql_ConnectionObject_select_db__doc__[] =
19782034
"Causes the database specified by db to become the default\n\
19792035
(current) database on the connection specified by mysql. In subsequent\n\
@@ -2344,6 +2400,12 @@ static PyMethodDef _mysql_ConnectionObject_methods[] = {
23442400
METH_VARARGS,
23452401
_mysql_ConnectionObject_close__doc__
23462402
},
2403+
{
2404+
"fileno",
2405+
(PyCFunction)_mysql_ConnectionObject_fileno,
2406+
METH_NOARGS,
2407+
_mysql_ConnectionObject_fileno__doc__
2408+
},
23472409
{
23482410
"dump_debug_info",
23492411
(PyCFunction)_mysql_ConnectionObject_dump_debug_info,
@@ -2428,6 +2490,18 @@ static PyMethodDef _mysql_ConnectionObject_methods[] = {
24282490
METH_VARARGS,
24292491
_mysql_ConnectionObject_query__doc__
24302492
},
2493+
{
2494+
"send_query",
2495+
(PyCFunction)_mysql_ConnectionObject_send_query,
2496+
METH_VARARGS,
2497+
_mysql_ConnectionObject_send_query__doc__,
2498+
},
2499+
{
2500+
"read_query_result",
2501+
(PyCFunction)_mysql_ConnectionObject_read_query_result,
2502+
METH_NOARGS,
2503+
_mysql_ConnectionObject_read_query_result__doc__,
2504+
},
24312505
{
24322506
"select_db",
24332507
(PyCFunction)_mysql_ConnectionObject_select_db,

‎samples/waiter_gevent.py

Copy file name to clipboard
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from __future__ import print_function
2+
"""Demo using Gevent with mysqlclient."""
3+
4+
import gevent.hub
5+
import select
6+
import MySQLdb
7+
8+
9+
def gevent_waiter(fd, hub=gevent.hub.get_hub()):
10+
hub.wait(hub.loop.io(fd, 1))
11+
12+
13+
def f(n):
14+
conn = MySQLdb.connect(user='root', waiter=gevent_waiter)
15+
cur = conn.cursor()
16+
cur.execute("SELECT SLEEP(%s)", (n,))
17+
cur.execute("SELECT 1+%s", (n,))
18+
print(cur.fetchall()[0])
19+
20+
21+
gevent.spawn(f, 1)
22+
gevent.spawn(f, 2)
23+
gevent.spawn(f, 3)
24+
gevent.spawn(f, 4)
25+
gevent.sleep(5)

‎samples/waiter_meinheld.py

Copy file name to clipboard
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import meinheld
2+
import MySQLdb
3+
4+
5+
def meinheld_waiter(fd):
6+
meinheld.server.trampoline(fd, read=True, timeout=10)
7+
8+
9+
def app(env, start):
10+
cont = b"Hello, World\n"
11+
conn = MySQLdb.connect(user="root", waiter=meinheld_waiter)
12+
cur = conn.cursor()
13+
cur.execute("SELECT SLEEP(2)")
14+
start(b"200 OK", [('Content-Type', 'text/plain'), ('Content-Length', str(len(cont)))])
15+
return [cont]
16+
17+
18+
meinheld.server.listen(("0.0.0.0", 8080))
19+
meinheld.server.run(app)

0 commit comments

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