summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty Taylor <mordred@inaugust.com>2014-01-02 11:31:00 -0600
committerMonty Taylor <mordred@inaugust.com>2014-01-02 11:31:00 -0600
commit7dd57dcf5f50271d12a6c6bba3d3ca2b3a59348c (patch)
tree3b80095e3d4ae7e802a0003797bb25f66718ef22
parentb739fb06aa484e121395d17245d420aed6def202 (diff)
parent5ce7d5f8a6f7b5a48cc1ccbfb799ff613e682d2d (diff)
downloadmysqldb1-7dd57dcf5f50271d12a6c6bba3d3ca2b3a59348c.tar.gz
Merge https://github.com/farcepest/MySQLdb1 into merge-upstream
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml1
-rw-r--r--MySQLdb/connections.py19
-rw-r--r--MySQLdb/converters.py7
-rw-r--r--MySQLdb/cursors.py16
-rw-r--r--MySQLdb/times.py29
-rw-r--r--_mysql.c44
-rw-r--r--setup_posix.py5
-rw-r--r--tests/test_MySQLdb_capabilities.py2
-rw-r--r--tox.ini11
10 files changed, 109 insertions, 26 deletions
diff --git a/.gitignore b/.gitignore
index 77d358c..968f0e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,5 +7,6 @@
*.zip
*.egg
*.egg-info/
+.tox/
build/
dist/
diff --git a/.travis.yml b/.travis.yml
index 7676e24..e4fdfda 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
language: python
python:
- - "2.5"
- "2.6"
- "2.7"
- "pypy"
diff --git a/MySQLdb/connections.py b/MySQLdb/connections.py
index 6bc1613..908706a 100644
--- a/MySQLdb/connections.py
+++ b/MySQLdb/connections.py
@@ -139,6 +139,11 @@ class Connection(_mysql.connection):
local_infile
integer, non-zero enables LOAD LOCAL INFILE; zero disables
+ autocommit
+ If False (default), autocommit is disabled.
+ If True, autocommit is enabled.
+ If None, autocommit isn't set and server default is used.
+
There are a number of undocumented, non-standard methods. See the
documentation for the MySQL C API for some hints on what they do.
@@ -182,6 +187,9 @@ class Connection(_mysql.connection):
kwargs2['client_flag'] = client_flag
+ # PEP-249 requires autocommit to be initially off
+ autocommit = kwargs2.pop('autocommit', False)
+
super(Connection, self).__init__(*args, **kwargs2)
self.cursorclass = cursorclass
self.encoders = dict([ (k, v) for k, v in conv.items()
@@ -225,10 +233,15 @@ class Connection(_mysql.connection):
self.encoders[types.UnicodeType] = unicode_literal
self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS
if self._transactional:
- # PEP-249 requires autocommit to be initially off
- self.autocommit(False)
+ if autocommit is not None:
+ self.autocommit(autocommit)
self.messages = []
+ def autocommit(self, on):
+ on = bool(on)
+ if self.get_autocommit() != on:
+ _mysql.connection.autocommit(self, on)
+
def cursor(self, cursorclass=None):
"""
@@ -241,6 +254,8 @@ class Connection(_mysql.connection):
return (cursorclass or self.cursorclass)(self)
def __enter__(self):
+ if self.get_autocommit():
+ self.query("BEGIN")
return self.cursor()
def __exit__(self, exc, value, tb):
diff --git a/MySQLdb/converters.py b/MySQLdb/converters.py
index 491d49b..26c1f90 100644
--- a/MySQLdb/converters.py
+++ b/MySQLdb/converters.py
@@ -129,13 +129,16 @@ def char_array(s):
def array2Str(o, d):
return Thing2Literal(o.tostring(), d)
+def quote_tuple(t, d):
+ return "(%s)" % (','.join(escape_sequence(t, d)))
+
conversions = {
IntType: Thing2Str,
LongType: Long2Int,
FloatType: Float2Str,
NoneType: None2NULL,
- TupleType: escape_sequence,
- ListType: escape_sequence,
+ TupleType: quote_tuple,
+ ListType: quote_tuple,
DictType: escape_dict,
InstanceType: Instance2Str,
ArrayType: array2Str,
diff --git a/MySQLdb/cursors.py b/MySQLdb/cursors.py
index 7e5a887..348a586 100644
--- a/MySQLdb/cursors.py
+++ b/MySQLdb/cursors.py
@@ -26,7 +26,7 @@ restr = r"""
(?:
(?:\(
# ( - editor hightlighting helper
- [^)]*
+ .*
\))
|
'
@@ -180,7 +180,11 @@ class BaseCursor(object):
if isinstance(query, unicode):
query = query.encode(db.unicode_literal.charset)
if args is not None:
- query = query % db.literal(args)
+ if isinstance(args, dict):
+ query = query % dict((key, db.literal(item))
+ for key, item in args.iteritems())
+ else:
+ query = query % tuple([db.literal(item) for item in args])
try:
r = None
r = self._query(query)
@@ -236,7 +240,13 @@ class BaseCursor(object):
e = m.end(1)
qv = m.group(1)
try:
- q = [ qv % db.literal(a) for a in args ]
+ q = []
+ for a in args:
+ if isinstance(a, dict):
+ q.append(qv % dict((key, db.literal(item))
+ for key, item in a.iteritems()))
+ else:
+ q.append(qv % tuple([db.literal(item) for item in a]))
except TypeError, msg:
if msg.args[0] in ("not enough arguments for format string",
"not all arguments converted"):
diff --git a/MySQLdb/times.py b/MySQLdb/times.py
index bc92eb4..0ff7476 100644
--- a/MySQLdb/times.py
+++ b/MySQLdb/times.py
@@ -51,7 +51,12 @@ def DateTime_or_None(s):
try:
d, t = s.split(sep, 1)
- return datetime(*[ int(x) for x in d.split('-')+t.split(':') ])
+ if '.' in t:
+ t, ms = t.split('.',1)
+ ms = ms.ljust(6, '0')
+ else:
+ ms = 0
+ return datetime(*[ int(x) for x in d.split('-')+t.split(':')+[ms] ])
except (SystemExit, KeyboardInterrupt):
raise
except:
@@ -60,9 +65,14 @@ def DateTime_or_None(s):
def TimeDelta_or_None(s):
try:
h, m, s = s.split(':')
- h, m, s = int(h), int(m), float(s)
- td = timedelta(hours=abs(h), minutes=m, seconds=int(s),
- microseconds=int(math.modf(s)[0] * 1000000))
+ if '.' in s:
+ s, ms = s.split('.')
+ ms = ms.ljust(6, '0')
+ else:
+ ms = 0
+ h, m, s, ms = int(h), int(m), int(s), int(ms)
+ td = timedelta(hours=abs(h), minutes=m, seconds=s,
+ microseconds=ms)
if h < 0:
return -td
else:
@@ -74,9 +84,14 @@ def TimeDelta_or_None(s):
def Time_or_None(s):
try:
h, m, s = s.split(':')
- h, m, s = int(h), int(m), float(s)
- return time(hour=h, minute=m, second=int(s),
- microsecond=int(math.modf(s)[0] * 1000000))
+ if '.' in s:
+ s, ms = s.split('.')
+ ms = ms.ljust(6, '0')
+ else:
+ ms = 0
+ h, m, s, ms = int(h), int(m), int(s), int(ms)
+ return time(hour=h, minute=m, second=s,
+ microsecond=ms)
except ValueError:
return None
diff --git a/_mysql.c b/_mysql.c
index c0ffddb..5b81c79 100644
--- a/_mysql.c
+++ b/_mysql.c
@@ -121,7 +121,7 @@ static int _mysql_server_init_done = 0;
/* According to https://dev.mysql.com/doc/refman/5.1/en/mysql-options.html
The MYSQL_OPT_READ_TIMEOUT apear in the version 5.1.12 */
#if MYSQL_VERSION_ID > 50112
-#define HAVE_MYSQL_OPT_READ_TIMEOUT 1
+#define HAVE_MYSQL_OPT_TIMEOUTS 1
#endif
PyObject *
@@ -566,13 +566,15 @@ _mysql_ConnectionObject_Initialize(
"read_default_file", "read_default_group",
"client_flag", "ssl",
"local_infile",
-#ifdef HAVE_MYSQL_OPT_READ_TIMEOUT
+#ifdef HAVE_MYSQL_OPT_TIMEOUTS
"read_timeout",
+ "write_timeout",
#endif
NULL } ;
int connect_timeout = 0;
-#ifdef HAVE_MYSQL_OPT_READ_TIMEOUT
+#ifdef HAVE_MYSQL_OPT_TIMEOUTS
int read_timeout = 0;
+ int write_timeout = 0;
#endif
int compress = -1, named_pipe = -1, local_infile = -1;
char *init_command=NULL,
@@ -584,8 +586,8 @@ _mysql_ConnectionObject_Initialize(
check_server_init(-1);
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
-#ifdef HAVE_MYSQL_OPT_READ_TIMEOUT
- "|ssssisOiiisssiOii:connect",
+#ifdef HAVE_MYSQL_OPT_TIMEOUTS
+ "|ssssisOiiisssiOiii:connect",
#else
"|ssssisOiiisssiOi:connect",
#endif
@@ -598,8 +600,9 @@ _mysql_ConnectionObject_Initialize(
&read_default_group,
&client_flag, &ssl,
&local_infile
-#ifdef HAVE_MYSQL_OPT_READ_TIMEOUT
+#ifdef HAVE_MYSQL_OPT_TIMEOUTS
, &read_timeout
+ , &write_timeout
#endif
))
return -1;
@@ -636,12 +639,17 @@ _mysql_ConnectionObject_Initialize(
mysql_options(&(self->connection), MYSQL_OPT_CONNECT_TIMEOUT,
(char *)&timeout);
}
-#ifdef HAVE_MYSQL_OPT_READ_TIMEOUT
+#ifdef HAVE_MYSQL_OPT_TIMEOUTS
if (read_timeout) {
unsigned int timeout = read_timeout;
mysql_options(&(self->connection), MYSQL_OPT_READ_TIMEOUT,
(char *)&timeout);
}
+ if (write_timeout) {
+ unsigned int timeout = write_timeout;
+ mysql_options(&(self->connection), MYSQL_OPT_WRITE_TIMEOUT,
+ (char *)&timeout);
+ }
#endif
if (compress != -1) {
mysql_options(&(self->connection), MYSQL_OPT_COMPRESS, 0);
@@ -891,7 +899,21 @@ _mysql_ConnectionObject_autocommit(
if (err) return _mysql_Exception(self);
Py_INCREF(Py_None);
return Py_None;
-}
+}
+
+static char _mysql_ConnectionObject_get_autocommit__doc__[] =
+"Get the autocommit mode. True when enable; False when disable.\n";
+
+static PyObject *
+_mysql_ConnectionObject_get_autocommit(
+ _mysql_ConnectionObject *self,
+ PyObject *args)
+{
+ if (self->connection.server_status & SERVER_STATUS_AUTOCOMMIT) {
+ Py_RETURN_TRUE;
+ }
+ Py_RETURN_FALSE;
+}
static char _mysql_ConnectionObject_commit__doc__[] =
"Commits the current transaction\n\
@@ -2318,6 +2340,12 @@ static PyMethodDef _mysql_ConnectionObject_methods[] = {
_mysql_ConnectionObject_autocommit__doc__
},
{
+ "get_autocommit",
+ (PyCFunction)_mysql_ConnectionObject_get_autocommit,
+ METH_NOARGS,
+ _mysql_ConnectionObject_get_autocommit__doc__
+ },
+ {
"commit",
(PyCFunction)_mysql_ConnectionObject_commit,
METH_VARARGS,
diff --git a/setup_posix.py b/setup_posix.py
index f7cb588..cfcf33c 100644
--- a/setup_posix.py
+++ b/setup_posix.py
@@ -71,8 +71,9 @@ def get_config():
if i.startswith(compiler_flag('I')) ]
if static:
- extra_objects.append(os.path.join(
- library_dirs[0],'lib%s.a' % client))
+ extra_objects.append(os.path.join(library_dirs[0],'lib%s.a' % client))
+ if client in libraries:
+ libraries.remove(client)
name = "MySQL-python"
if enabled(options, 'embedded'):
diff --git a/tests/test_MySQLdb_capabilities.py b/tests/test_MySQLdb_capabilities.py
index ebec1e6..ead6982 100644
--- a/tests/test_MySQLdb_capabilities.py
+++ b/tests/test_MySQLdb_capabilities.py
@@ -77,7 +77,7 @@ class test_MySQLdb(capabilities.DatabaseTest):
try:
self.cursor.execute("describe some_non_existent_table");
except self.connection.ProgrammingError, msg:
- self.assertTrue(msg[0] == ER.NO_SUCH_TABLE)
+ self.assertEquals(msg[0], ER.NO_SUCH_TABLE)
def test_bug_3514287(self):
c = self.cursor
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..e7bb971
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,11 @@
+[tox]
+envlist = py25, py26, py27, py33
+
+[testenv]
+setenv =
+ TESTDB=travis.cnf
+commands =
+ nosetests {posargs:-w tests -v}
+deps =
+ ipdb
+ nose