-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add a gevent+psycopg2 dialect for sqlalchemy
- Loading branch information
Showing
4 changed files
with
94 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
""" | ||
When RelStorage is installed with psycopg2 and gevent a global wait callback is installed. | ||
That wait callback expects the Relstorage custom connection which creates issues | ||
when trying to use psycopg2 with sqlalchmey. | ||
Install a custom dialect that uses the RelStorage connection for sqlalchemy. | ||
""" | ||
|
||
from __future__ import division | ||
from __future__ import print_function | ||
from __future__ import absolute_import | ||
|
||
logger = __import__('logging').getLogger(__name__) | ||
|
||
try: | ||
from sqlalchemy.dialects.postgresql.psycopg2 import PGDialect_psycopg2 | ||
from relstorage.adapters.postgresql.drivers.psycopg2 import GeventPsycopg2Driver | ||
import psycopg2 | ||
except ImportError: | ||
pass | ||
else: | ||
class geventPostgresclient_dialect(PGDialect_psycopg2): | ||
driver = "gevent+postgres" | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(geventPostgresclient_dialect, self).__init__(*args, **kwargs) | ||
self._conn_class = GeventPsycopg2Driver().connect | ||
|
||
def connect(self, *args, **kwargs): | ||
kwargs['connection_factory'] = self._conn_class | ||
return psycopg2.connect(*args, **kwargs) | ||
|
||
from sqlalchemy.dialects import registry | ||
registry.register("gevent.postgres", __name__, "geventPostgresclient_dialect") | ||
|
||
def patch(): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
from __future__ import division | ||
from __future__ import print_function | ||
from __future__ import absolute_import | ||
|
||
import fudge | ||
|
||
from hamcrest import not_none | ||
from hamcrest import assert_that | ||
from hamcrest import instance_of | ||
|
||
import unittest | ||
|
||
from sqlalchemy import create_engine | ||
|
||
from .._monkey import geventPostgresclient_dialect | ||
|
||
|
||
class TestPatchSqlalchemy(unittest.TestCase): | ||
|
||
def test_postres_engine(self): | ||
from .._monkey import patch | ||
patch() | ||
engine = create_engine('gevent+postgres:///testdb.db') | ||
assert_that(engine, not_none()) | ||
assert_that(engine.dialect, instance_of(geventPostgresclient_dialect)) | ||
|
||
@fudge.patch('psycopg2.connect') | ||
def test_connect_uses_relstorage(self, pconn): | ||
from .._monkey import patch | ||
patch() | ||
engine = create_engine('gevent+postgres:///testdb.db') | ||
|
||
class StopExecution(Exception): | ||
pass | ||
|
||
# Make sure connect get gets called with the right connection_factory | ||
# Make calling it raise to stop all the crazy first connection initialization that sqlalchemy does | ||
# no luck trying to mock all the necessary things | ||
pconn.expects_call().with_args(database='testdb.db', connection_factory=engine.dialect._conn_class).raises(StopExecution) | ||
|
||
try: | ||
engine.connect() | ||
except StopExecution: | ||
pass | ||
|
||
|
||
|
||
|
c2adb66
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jamadden meant to PR this but accidentally pushed it straight on master. mind taking a look?
c2adb66
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Branch protection?
LGTM, matches our discussion. I'm assuming you verified functionality in your real scenario.
Thinking a bit more about zodb/relstorage#394, using Travis it's trivial to spin up PostgreSQL and MySQL instances to talk to. RelStorage already has a testing infrastructure that separates unit and integration (requiring a database) tests, plus the infrastructure to configure those databases. Maybe moving all of our
gevent+
dialects there makes sense in order to take advantage of all that.c2adb66
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thank you.
Originally that sounded odd to me, but seeing as you only need them if you are in a mixed relstorage / SQLAlchemy environment it probably makes sense. +1 to having them somewhere we can share them.