diff options
author | Monty Taylor <mordred@inaugust.com> | 2014-01-02 11:31:00 -0600 |
---|---|---|
committer | Monty Taylor <mordred@inaugust.com> | 2014-01-02 11:31:00 -0600 |
commit | 7dd57dcf5f50271d12a6c6bba3d3ca2b3a59348c (patch) | |
tree | 3b80095e3d4ae7e802a0003797bb25f66718ef22 | |
parent | b739fb06aa484e121395d17245d420aed6def202 (diff) | |
parent | 5ce7d5f8a6f7b5a48cc1ccbfb799ff613e682d2d (diff) | |
download | mysqldb1-7dd57dcf5f50271d12a6c6bba3d3ca2b3a59348c.tar.gz |
Merge https://github.com/farcepest/MySQLdb1 into merge-upstream
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | MySQLdb/connections.py | 19 | ||||
-rw-r--r-- | MySQLdb/converters.py | 7 | ||||
-rw-r--r-- | MySQLdb/cursors.py | 16 | ||||
-rw-r--r-- | MySQLdb/times.py | 29 | ||||
-rw-r--r-- | _mysql.c | 44 | ||||
-rw-r--r-- | setup_posix.py | 5 | ||||
-rw-r--r-- | tests/test_MySQLdb_capabilities.py | 2 | ||||
-rw-r--r-- | tox.ini | 11 |
10 files changed, 109 insertions, 26 deletions
@@ -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 @@ -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
@@ -0,0 +1,11 @@ +[tox] +envlist = py25, py26, py27, py33 + +[testenv] +setenv = + TESTDB=travis.cnf +commands = + nosetests {posargs:-w tests -v} +deps = + ipdb + nose |