diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-03-07 12:36:35 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-03-07 12:36:35 -0500 |
| commit | a98bb5f0cd5d7ef51dbf0f04cc2ba1971768691f (patch) | |
| tree | b6a1dea1efe8f521500fe6c2e86c1099bcb8166e | |
| parent | 029b79052cae9a74c9b4dceea92d8ec00595f175 (diff) | |
| parent | 50cc82b7966f70aeb8c21d881be4ca2b3327f7bf (diff) | |
| download | sqlalchemy-a98bb5f0cd5d7ef51dbf0f04cc2ba1971768691f.tar.gz | |
Merged in nakagami/sqlalchemy/cymysql (pull request #42)
cymysql support
| -rw-r--r-- | lib/sqlalchemy/dialects/mysql/__init__.py | 2 | ||||
| -rw-r--r-- | lib/sqlalchemy/dialects/mysql/cymysql.py | 72 | ||||
| -rw-r--r-- | lib/sqlalchemy/testing/engines.py | 2 | ||||
| -rw-r--r-- | test/dialect/test_mysql.py | 1 | ||||
| -rw-r--r-- | test/engine/test_execute.py | 4 | ||||
| -rw-r--r-- | test/engine/test_reconnect.py | 3 | ||||
| -rw-r--r-- | test/engine/test_transaction.py | 1 | ||||
| -rw-r--r-- | test/requirements.py | 4 | ||||
| -rw-r--r-- | test/sql/test_types.py | 10 |
9 files changed, 94 insertions, 5 deletions
diff --git a/lib/sqlalchemy/dialects/mysql/__init__.py b/lib/sqlalchemy/dialects/mysql/__init__.py index 1f7046410..2bb636ff3 100644 --- a/lib/sqlalchemy/dialects/mysql/__init__.py +++ b/lib/sqlalchemy/dialects/mysql/__init__.py @@ -6,7 +6,7 @@ from . import base, mysqldb, oursql, \ pyodbc, zxjdbc, mysqlconnector, pymysql,\ - gaerdbms + gaerdbms, cymysql # default dialect base.dialect = mysqldb.dialect diff --git a/lib/sqlalchemy/dialects/mysql/cymysql.py b/lib/sqlalchemy/dialects/mysql/cymysql.py new file mode 100644 index 000000000..d9b43869c --- /dev/null +++ b/lib/sqlalchemy/dialects/mysql/cymysql.py @@ -0,0 +1,72 @@ +# mysql/cymysql.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file> +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +""" + +.. dialect:: mysql+cymysql + :name: CyMySQL + :dbapi: cymysql + :connectstring: mysql+cymysql://<username>:<password>@<host>/<dbname>[?<options>] + :url: https://github.com/nakagami/CyMySQL + +""" + +from .mysqldb import MySQLDialect_mysqldb +from .base import (BIT, MySQLDialect) +from ... import util + +class _cymysqlBIT(BIT): + def result_processor(self, dialect, coltype): + """Convert a MySQL's 64 bit, variable length binary string to a long. + """ + + def process(value): + if value is not None: + # Py2K + v = 0L + for i in map(ord, value): + v = v << 8 | i + # end Py2K + # Py3K + #v = 0 + #for i in value: + # v = v << 8 | i + return v + return value + return process + + +class MySQLDialect_cymysql(MySQLDialect_mysqldb): + driver = 'cymysql' + + description_encoding = None + + colspecs = util.update_copy( + MySQLDialect.colspecs, + { + BIT: _cymysqlBIT, + } + ) + + @classmethod + def dbapi(cls): + return __import__('cymysql') + + def _extract_error_code(self, exception): + return exception.errno + + def is_disconnect(self, e, connection, cursor): + if isinstance(e, self.dbapi.OperationalError): + return self._extract_error_code(e) in \ + (2006, 2013, 2014, 2045, 2055) + elif isinstance(e, self.dbapi.InterfaceError): + # if underlying connection is closed, + # this is the error you get + return True + else: + return False + +dialect = MySQLDialect_cymysql diff --git a/lib/sqlalchemy/testing/engines.py b/lib/sqlalchemy/testing/engines.py index 20bcf0317..26f561016 100644 --- a/lib/sqlalchemy/testing/engines.py +++ b/lib/sqlalchemy/testing/engines.py @@ -229,7 +229,7 @@ def utf8_engine(url=None, options=None): from sqlalchemy.engine import url as engine_url if config.db.dialect.name == 'mysql' and \ - config.db.driver in ['mysqldb', 'pymysql']: + config.db.driver in ['mysqldb', 'pymysql', 'cymysql']: # note 1.2.1.gamma.6 or greater of MySQLdb # needed here url = url or config.db_url diff --git a/test/dialect/test_mysql.py b/test/dialect/test_mysql.py index d5ce6e923..f89b0b229 100644 --- a/test/dialect/test_mysql.py +++ b/test/dialect/test_mysql.py @@ -1500,6 +1500,7 @@ class MatchTest(fixtures.TestBase, AssertsCompiledSQL): @testing.fails_on('mysql+mysqldb', 'uses format') @testing.fails_on('mysql+pymysql', 'uses format') + @testing.fails_on('mysql+cymysql', 'uses format') @testing.fails_on('mysql+oursql', 'uses format') @testing.fails_on('mysql+pyodbc', 'uses format') @testing.fails_on('mysql+zxjdbc', 'uses format') diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index 447324d6e..203d7bd71 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -110,7 +110,7 @@ class ExecuteTest(fixtures.TestBase): # some psycopg2 versions bomb this. @testing.fails_on_everything_except('mysql+mysqldb', 'mysql+pymysql', - 'mysql+mysqlconnector', 'postgresql') + 'mysql+cymysql', 'mysql+mysqlconnector', 'postgresql') @testing.fails_on('postgresql+zxjdbc', 'sprintf not supported') def test_raw_sprintf(self): def go(conn): @@ -157,7 +157,7 @@ class ExecuteTest(fixtures.TestBase): 'db-api flaky') @testing.fails_on_everything_except('postgresql+psycopg2', 'postgresql+pypostgresql', 'mysql+mysqlconnector', - 'mysql+pymysql') + 'mysql+pymysql', 'mysql+cymysql') def test_raw_python(self): def go(conn): conn.execute('insert into users (user_id, user_name) ' diff --git a/test/engine/test_reconnect.py b/test/engine/test_reconnect.py index 6416ce149..6b283654b 100644 --- a/test/engine/test_reconnect.py +++ b/test/engine/test_reconnect.py @@ -487,6 +487,9 @@ class InvalidateDuringResultTest(fixtures.TestBase): meta.drop_all() engine.dispose() + @testing.fails_on('+cymysql', + "Buffers the result set and doesn't check for " + "connection close") @testing.fails_on('+pymysql', "Buffers the result set and doesn't check for " "connection close") diff --git a/test/engine/test_transaction.py b/test/engine/test_transaction.py index ad6813f87..5558ff778 100644 --- a/test/engine/test_transaction.py +++ b/test/engine/test_transaction.py @@ -29,6 +29,7 @@ class TransactionTest(fixtures.TestBase): testing.db.execute(users.delete()).close() @classmethod + @testing.crashes('mysql+cymysql', 'deadlock') def teardown_class(cls): users.drop(testing.db) diff --git a/test/requirements.py b/test/requirements.py index 738429158..c20bcbd0a 100644 --- a/test/requirements.py +++ b/test/requirements.py @@ -378,6 +378,7 @@ class DefaultRequirements(SuiteRequirements): """ return fails_on_everything_except('mysql+mysqldb', 'mysql+oursql', 'sqlite+pysqlite', 'mysql+pymysql', + 'mysql+cymysql', 'sybase', 'mssql+pyodbc', 'mssql+mxodbc') @property @@ -393,7 +394,8 @@ class DefaultRequirements(SuiteRequirements): """ return fails_on_everything_except('mysql+mysqldb', 'mysql+oursql', - 'sqlite+pysqlite', 'mysql+pymysql') + 'sqlite+pysqlite', 'mysql+pymysql', + 'mysql+cymysql') @property def sane_multi_rowcount(self): diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 0e6f1b5f0..3c981e539 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -690,6 +690,16 @@ class UnicodeTest(fixtures.TestBase): ('charset' in testing.db.url.query) ) + elif testing.against('mysql+cymysql'): + eq_( + testing.db.dialect.returns_unicode_strings, + # Py3K + #True + # Py2K + False + # end Py2K + ) + else: expected = (testing.db.name, testing.db.driver) in \ ( |
