summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Stanworth <shaun.stanworth@onefinestay.com>2014-11-09 14:52:31 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2015-01-26 18:43:19 -0500
commitf94d75ede5f5d2ed28d72ff98ca7caca016e5506 (patch)
treecb10a74016216a849423d0878219d15e5bc3b371
parent987f40b5aa325fe8a6655bcb0be2329c0a24025d (diff)
downloadsqlalchemy-f94d75ede5f5d2ed28d72ff98ca7caca016e5506.tar.gz
Added psycopg2cffi dialect
-rw-r--r--lib/sqlalchemy/dialects/postgresql/__init__.py2
-rw-r--r--lib/sqlalchemy/dialects/postgresql/psycopg2.py17
-rw-r--r--lib/sqlalchemy/dialects/postgresql/psycopg2cffi.py46
-rw-r--r--setup.cfg1
-rw-r--r--test/dialect/postgresql/test_dialect.py2
-rw-r--r--test/dialect/postgresql/test_query.py1
-rw-r--r--test/dialect/postgresql/test_types.py7
-rw-r--r--test/engine/test_execute.py2
-rw-r--r--test/requirements.py4
-rw-r--r--test/sql/test_types.py1
10 files changed, 74 insertions, 9 deletions
diff --git a/lib/sqlalchemy/dialects/postgresql/__init__.py b/lib/sqlalchemy/dialects/postgresql/__init__.py
index 1cff8e3a0..01a846314 100644
--- a/lib/sqlalchemy/dialects/postgresql/__init__.py
+++ b/lib/sqlalchemy/dialects/postgresql/__init__.py
@@ -5,7 +5,7 @@
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
-from . import base, psycopg2, pg8000, pypostgresql, zxjdbc
+from . import base, psycopg2, pg8000, pypostgresql, zxjdbc, psycopg2cffi
base.dialect = psycopg2.dialect
diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py
index fe27da8b6..5246abf1c 100644
--- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py
+++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py
@@ -512,9 +512,19 @@ class PGDialect_psycopg2(PGDialect):
import psycopg2
return psycopg2
+ @classmethod
+ def _psycopg2_extensions(cls):
+ from psycopg2 import extensions
+ return extensions
+
+ @classmethod
+ def _psycopg2_extras(cls):
+ from psycopg2 import extras
+ return extras
+
@util.memoized_property
def _isolation_lookup(self):
- from psycopg2 import extensions
+ extensions = self._psycopg2_extensions()
return {
'AUTOCOMMIT': extensions.ISOLATION_LEVEL_AUTOCOMMIT,
'READ COMMITTED': extensions.ISOLATION_LEVEL_READ_COMMITTED,
@@ -536,7 +546,8 @@ class PGDialect_psycopg2(PGDialect):
connection.set_isolation_level(level)
def on_connect(self):
- from psycopg2 import extras, extensions
+ extras = self._psycopg2_extras()
+ extensions = self._psycopg2_extensions()
fns = []
if self.client_encoding is not None:
@@ -586,7 +597,7 @@ class PGDialect_psycopg2(PGDialect):
@util.memoized_instancemethod
def _hstore_oids(self, conn):
if self.psycopg2_version >= (2, 4):
- from psycopg2 import extras
+ extras = self._psycopg2_extras()
oids = extras.HstoreAdapter.get_oids(conn)
if oids is not None and oids[0]:
return oids[0:2]
diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2cffi.py b/lib/sqlalchemy/dialects/postgresql/psycopg2cffi.py
new file mode 100644
index 000000000..5217c5561
--- /dev/null
+++ b/lib/sqlalchemy/dialects/postgresql/psycopg2cffi.py
@@ -0,0 +1,46 @@
+# testing/engines.py
+# Copyright (C) 2005-2014 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:: postgresql+psycopg2cffi
+ :name: psycopg2cffi
+ :dbapi: psycopg2cffi
+ :connectstring: \
+postgresql+psycopg2cffi://user:password@host:port/dbname\
+[?key=value&key=value...]
+ :url: http://pypi.python.org/pypi/psycopg2cffi/
+
+`psycopg2cffi` is an adaptation of `psycopg2`, using CFFI for the C
+layer. This makes it suitable for use in e.g. PyPy. Documentation
+is as per `psycopg2`.
+
+.. seealso::
+
+ :mod:`sqlalchemy.dialects.postgresql.psycopg2`
+
+"""
+from .psycopg2 import PGDialect_psycopg2
+
+
+class PGDialect_psycopg2cffi(PGDialect_psycopg2):
+ driver = 'psycopg2cffi'
+
+ @classmethod
+ def dbapi(cls):
+ return __import__('psycopg2cffi')
+
+ @classmethod
+ def _psycopg2_extensions(cls):
+ root = __import__('psycopg2cffi', fromlist=['extensions'])
+ return root.extensions
+
+ @classmethod
+ def _psycopg2_extras(cls):
+ root = __import__('psycopg2cffi', fromlist=['extras'])
+ return root.extras
+
+
+dialect = PGDialect_psycopg2cffi
diff --git a/setup.cfg b/setup.cfg
index 51a4e30bf..5eb35469f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -42,6 +42,7 @@ postgresql=postgresql://scott:tiger@127.0.0.1:5432/test
pg8000=postgresql+pg8000://scott:tiger@127.0.0.1:5432/test
postgres=postgresql://scott:tiger@127.0.0.1:5432/test
postgresql_jython=postgresql+zxjdbc://scott:tiger@127.0.0.1:5432/test
+postgresql_psycopg2cffi=postgresql+psycopg2cffi://127.0.0.1:5432/test
mysql=mysql://scott:tiger@127.0.0.1:3306/test
mysqlconnector=mysql+mysqlconnector://scott:tiger@127.0.0.1:3306/test
mssql=mssql+pyodbc://scott:tiger@ms_2008
diff --git a/test/dialect/postgresql/test_dialect.py b/test/dialect/postgresql/test_dialect.py
index b751bbcdd..2166bca32 100644
--- a/test/dialect/postgresql/test_dialect.py
+++ b/test/dialect/postgresql/test_dialect.py
@@ -118,7 +118,7 @@ class MiscTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiledSQL):
eq_(c.connection.connection.encoding, test_encoding)
@testing.only_on(
- ['postgresql+psycopg2', 'postgresql+pg8000'],
+ ['postgresql+psycopg2', 'postgresql+pg8000', 'postgresql+psycopg2cffi'],
'psycopg2 / pg8000 - specific feature')
@engines.close_open_connections
def test_autocommit_isolation_level(self):
diff --git a/test/dialect/postgresql/test_query.py b/test/dialect/postgresql/test_query.py
index 26ff5e93b..73319438d 100644
--- a/test/dialect/postgresql/test_query.py
+++ b/test/dialect/postgresql/test_query.py
@@ -729,6 +729,7 @@ class MatchTest(fixtures.TestBase, AssertsCompiledSQL):
@testing.fails_on('postgresql+psycopg2', 'uses pyformat')
@testing.fails_on('postgresql+pypostgresql', 'uses pyformat')
@testing.fails_on('postgresql+zxjdbc', 'uses qmark')
+ @testing.fails_on('postgresql+psycopg2cffi', 'uses pyformat')
def test_expression_positional(self):
self.assert_compile(matchtable.c.title.match('somstr'),
'matchtable.title @@ to_tsquery(%s)')
diff --git a/test/dialect/postgresql/test_types.py b/test/dialect/postgresql/test_types.py
index c62ca79a8..5f1d37b24 100644
--- a/test/dialect/postgresql/test_types.py
+++ b/test/dialect/postgresql/test_types.py
@@ -379,10 +379,11 @@ class NumericInterpretationTest(fixtures.TestBase):
__backend__ = True
def test_numeric_codes(self):
- from sqlalchemy.dialects.postgresql import pg8000, psycopg2, base
-
- for dialect in (pg8000.dialect(), psycopg2.dialect()):
+ from sqlalchemy.dialects.postgresql import psycopg2cffi, pg8000, \
+ psycopg2, base
+ dialects = pg8000.dialect(), psycopg2.dialect(), psycopg2cffi.dialect()
+ for dialect in dialects:
typ = Numeric().dialect_impl(dialect)
for code in base._INT_TYPES + base._FLOAT_TYPES + \
base._DECIMAL_TYPES:
diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py
index 725dcebe0..b5b414af2 100644
--- a/test/engine/test_execute.py
+++ b/test/engine/test_execute.py
@@ -174,7 +174,7 @@ class ExecuteTest(fixtures.TestBase):
@testing.skip_if(
lambda: testing.against('mysql+mysqldb'), 'db-api flaky')
@testing.fails_on_everything_except(
- 'postgresql+psycopg2',
+ 'postgresql+psycopg2', 'postgresql+psycopg2cffi',
'postgresql+pypostgresql', 'mysql+mysqlconnector',
'mysql+pymysql', 'mysql+cymysql')
def test_raw_python(self):
diff --git a/test/requirements.py b/test/requirements.py
index ffbdfba23..6b8ba504c 100644
--- a/test/requirements.py
+++ b/test/requirements.py
@@ -756,6 +756,10 @@ class DefaultRequirements(SuiteRequirements):
"+psycopg2", None, None,
"psycopg2 2.4 no longer accepts percent "
"sign in bind placeholders"),
+ (
+ "+psycopg2cffi", None, None,
+ "psycopg2cffi does not accept percent signs in "
+ "bind placeholders"),
("mysql", None, None, "executemany() doesn't work here")
]
)
diff --git a/test/sql/test_types.py b/test/sql/test_types.py
index 38b3ced13..5e1542853 100644
--- a/test/sql/test_types.py
+++ b/test/sql/test_types.py
@@ -952,6 +952,7 @@ class UnicodeTest(fixtures.TestBase):
expected = (testing.db.name, testing.db.driver) in \
(
('postgresql', 'psycopg2'),
+ ('postgresql', 'psycopg2cffi'),
('postgresql', 'pypostgresql'),
('postgresql', 'pg8000'),
('postgresql', 'zxjdbc'),