create_engine doesn't parse dburi's correctly
engine.create_engine doesn't work as advertised
The docstring claims: In the second, the "name" argument is a URL in the form <enginename>://opt1=val1&opt2=val2. Where <enginename> is the name as above, and the contents of the option dictionary are spelled out as a URL encoded string. The "opts" argument is not used.
However, the code doesn't decode the string:
This is a problem for oracle, where:
from cx_Oracle import makedsn
dsn = makedsn( "localhost", 1521, "vis" ) # host, port, sid
# this works ...
opts = {'dsn': dsn, 'user': 'scott', 'password': 'tiger'}
engine1 = create_engine( 'oracle', opts=opts )
# ... and these don't
engine2 = create_engine( 'oracle://' + '&'.join( [ "%s=%s" for opt,val in opts.iteritems() ] ) ) # fails because the regexp being used chokes on the ='s in the dsn
from urllib import urlencode
engine3 = create_engine( 'oracle://' + urlencode( opts ) ) # fails because nothing is decoded
Current (installed from 0.1.4 egg) code:
__all__ = ['engine_descriptors']('create_engine',)
def create_engine(name, opts=None,**kwargs):
"""
__doc__
"""
m = re.match(r'(\w+)://(.*)', name)
if m is not None:
(name, args) = m.group(1, 2)
opts = {}
def assign(m):
opts[m.group(1)](m.group(1)) = m.group(2)
re.sub(r'([^&](^&)+)=([^&](^&)*)', assign, args)
module = getattr(__import__('sqlalchemy.databases.%s' % name).databases, name)
return module.engine(opts, **kwargs)
The above can be replaced with the python doc-recommended url decoder, cgi.parse_qsl from the standard library. This has the benefit of getting rid of a regexp and avoiding wheel-reinvention. Suggested code:
from cgi import parse_qsl
__all__ = [ 'create_engine', 'engine_descriptors', 'uri_re' ]
# store the compiled regexp, for re-use
uri_re = re.compile( r'(\w+)://(.*)' )
def create_engine(name, opts=None,**kwargs):
"""
__doc__
"""
global uri_re
if not uri_re:
uri_re = re.compile( r'(\w+)://(.*)' )
m = uri_re.match( name )
if m is not None:
(name, args) = m.group(1, 2)
opts = dict( parse_qsl( args ) )
module = getattr(__import__('sqlalchemy.databases.%s' % name).databases, name)
return module.engine(opts, **kwargs)
Note: I don't have a checkout of the svn repository, but I can generate the Unix patch format diff if necessary (bug accepted).
Comments (3)
-
Account Deleted -
repo owner - changed status to resolved
didnt try out the test since i dont have an Oracle install handy at the moment, but taking your word for it; checked this in changeset:1282....but keep in mind rfc-1738 style urls is where we're going for SA 0.2....but ill keep this in also
-
repo owner - removed milestone
Removing milestone: 0.2.0 (automated comment)
- Log in to comment
Sorry, wrong code in the example. It should be: