[Sqlalchemy-commits] [1335] sqlalchemy/branches/schema/lib/sqlalchemy: added URL class, various fixe
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-25 01:58:12
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1335] sqlalchemy/branches/schema/lib/sqlalchemy: added URL class, various fixes/tweaks, changes to contextual_connection</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1335</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-04-24 20:57:51 -0500 (Mon, 24 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>added URL class, various fixes/tweaks, changes to contextual_connection</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesschemalibsqlalchemydatabasesmysqlpy">sqlalchemy/branches/schema/lib/sqlalchemy/databases/mysql.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemydatabasespostgrespy">sqlalchemy/branches/schema/lib/sqlalchemy/databases/postgres.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemydatabasessqlitepy">sqlalchemy/branches/schema/lib/sqlalchemy/databases/sqlite.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyengine__init__py">sqlalchemy/branches/schema/lib/sqlalchemy/engine/__init__.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyenginebasepy">sqlalchemy/branches/schema/lib/sqlalchemy/engine/base.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyenginedefaultpy">sqlalchemy/branches/schema/lib/sqlalchemy/engine/default.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyenginestrategiespy">sqlalchemy/branches/schema/lib/sqlalchemy/engine/strategies.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyormsessionpy">sqlalchemy/branches/schema/lib/sqlalchemy/orm/session.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyormunitofworkpy">sqlalchemy/branches/schema/lib/sqlalchemy/orm/unitofwork.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyschemapy">sqlalchemy/branches/schema/lib/sqlalchemy/schema.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemybranchesschemalibsqlalchemyengineurlpy">sqlalchemy/branches/schema/lib/sqlalchemy/engine/url.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesschemalibsqlalchemydatabasesmysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/databases/mysql.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/databases/mysql.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/databases/mysql.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -124,9 +124,9 @@ </span><span class="cx"> return {'name':'mysql', </span><span class="cx"> 'description':'MySQL', </span><span class="cx"> 'arguments':[ </span><del>- ('user',"Database Username",None), - ('passwd',"Database Password",None), - ('db',"Database Name",None), </del><ins>+ ('username',"Database Username",None), + ('password',"Database Password",None), + ('database',"Database Name",None), </ins><span class="cx"> ('host',"Hostname", None), </span><span class="cx"> ]} </span><span class="cx"> </span><span class="lines">@@ -142,8 +142,8 @@ </span><span class="cx"> self.module = mysql </span><span class="cx"> ansisql.ANSIDialect.__init__(self, **kwargs) </span><span class="cx"> </span><del>- def create_connect_args(self, opts): - opts = self._translate_connect_args(('host', 'db', 'user', 'passwd'), opts) </del><ins>+ def create_connect_args(self, url): + opts = url.translate_connect_args(['host', 'db', 'user', 'passwd', 'port']) </ins><span class="cx"> return [[], opts] </span><span class="cx"> </span><span class="cx"> def create_execution_context(self): </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemydatabasespostgrespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/databases/postgres.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/databases/postgres.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/databases/postgres.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -174,7 +174,7 @@ </span><span class="cx"> return {'name':'postgres', </span><span class="cx"> 'description':'PostGres', </span><span class="cx"> 'arguments':[ </span><del>- ('user',"Database Username",None), </del><ins>+ ('username',"Database Username",None), </ins><span class="cx"> ('password',"Database Password",None), </span><span class="cx"> ('database',"Database Name",None), </span><span class="cx"> ('host',"Hostname", None), </span><span class="lines">@@ -216,8 +216,8 @@ </span><span class="cx"> self.version = 1 </span><span class="cx"> ansisql.ANSIDialect.__init__(self, **params) </span><span class="cx"> </span><del>- def create_connect_args(self, opts): - opts = self._translate_connect_args(('host', 'database', 'user', 'password'), opts) </del><ins>+ def create_connect_args(self, url): + opts = url.translate_connect_args(['host', 'database', 'user', 'password', 'port']) </ins><span class="cx"> if opts.has_key('port'): </span><span class="cx"> if self.version == 2: </span><span class="cx"> opts['port'] = int(opts['port']) </span><span class="lines">@@ -275,9 +275,6 @@ </span><span class="cx"> return self.module </span><span class="cx"> </span><span class="cx"> def has_table(self, connection, table_name): </span><del>- """ - return boolean whether or not the engine/schema contains this table - """ </del><span class="cx"> cursor = connection.execute("""select relname from pg_class where relname = %(name)s""", {'name':table_name}) </span><span class="cx"> return bool( not not cursor.rowcount ) </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemydatabasessqlitepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/databases/sqlite.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/databases/sqlite.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/databases/sqlite.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -116,7 +116,7 @@ </span><span class="cx"> return {'name':'sqlite', </span><span class="cx"> 'description':'SQLite', </span><span class="cx"> 'arguments':[ </span><del>- ('filename', "Database Filename",None) </del><ins>+ ('host', "Database Filename",None) </ins><span class="cx"> ]} </span><span class="cx"> </span><span class="cx"> </span><span class="lines">@@ -130,8 +130,8 @@ </span><span class="cx"> return SQLiteCompiler(self, statement, bindparams, **kwargs) </span><span class="cx"> def schemagenerator(self, *args, **kwargs): </span><span class="cx"> return SQLiteSchemaGenerator(*args, **kwargs) </span><del>- def create_connect_args(self, opts): - filename = opts.pop('filename', ':memory:') </del><ins>+ def create_connect_args(self, url): + filename = url.host or ':memory:' </ins><span class="cx"> return ([filename], {}) </span><span class="cx"> def type_descriptor(self, typeobj): </span><span class="cx"> return sqltypes.adapt_type(typeobj, colspecs) </span><span class="lines">@@ -154,6 +154,10 @@ </span><span class="cx"> def push_session(self): </span><span class="cx"> raise InvalidRequestError("SQLite doesn't support nested sessions") </span><span class="cx"> </span><ins>+ def has_table(self, connection, table_name): + cursor = connection.execute("PRAGMA table_info(" + table_name + ")", {}) + return bool(cursor.rowcount>0) + </ins><span class="cx"> def reflecttable(self, connection, table): </span><span class="cx"> c = connection.execute("PRAGMA table_info(" + table.name + ")", {}) </span><span class="cx"> while True: </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyengine__init__py"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/engine/__init__.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/engine/__init__.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/engine/__init__.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -26,7 +26,8 @@ </span><span class="cx"> query the user for database and connection information. </span><span class="cx"> """ </span><span class="cx"> result = [] </span><del>- for module in sqlalchemy.databases.__all__: </del><ins>+ #for module in sqlalchemy.databases.__all__: + for module in ['sqlite', 'postgres', 'mysql']: </ins><span class="cx"> module = getattr(__import__('sqlalchemy.databases.%s' % module).databases, module) </span><span class="cx"> result.append(module.descriptor()) </span><span class="cx"> return result </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyenginebasepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/engine/base.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/engine/base.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/engine/base.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -166,7 +166,7 @@ </span><span class="cx"> def connect(self): </span><span class="cx"> """connect() is implemented to return self so that an incoming Engine or Connection object can be treated similarly.""" </span><span class="cx"> return self </span><del>- def contextual_connect(self): </del><ins>+ def contextual_connect(self, **kwargs): </ins><span class="cx"> """contextual_connect() is implemented to return self so that an incoming Engine or Connection object can be treated similarly.""" </span><span class="cx"> return self </span><span class="cx"> def begin(self): </span><span class="lines">@@ -182,8 +182,9 @@ </span><span class="cx"> if self.transaction is None and re.match(r'UPDATE|INSERT|CREATE|DELETE|DROP', statement.lstrip().upper()): </span><span class="cx"> self.engine.dialect.do_commit(self.connection) </span><span class="cx"> def close(self): </span><del>- self.connection.close() - self.connection = None </del><ins>+ if self.connection is not None: + self.connection.close() + self.connection = None </ins><span class="cx"> def scalar(self, object, parameters, **kwargs): </span><span class="cx"> row = self.execute(object, parameters, **kwargs).fetchone() </span><span class="cx"> if row is not None: </span><span class="lines">@@ -363,7 +364,7 @@ </span><span class="cx"> </span><span class="cx"> def _run_visitor(self, visitorcallable, element, connection=None, **kwargs): </span><span class="cx"> if connection is None: </span><del>- conn = self.contextual_connect() </del><ins>+ conn = self.contextual_connect(close_with_result=False) </ins><span class="cx"> else: </span><span class="cx"> conn = connection </span><span class="cx"> try: </span><span class="lines">@@ -374,7 +375,7 @@ </span><span class="cx"> </span><span class="cx"> def run_callable(self, callable_, connection=None): </span><span class="cx"> if connection is None: </span><del>- conn = self.contextual_connect() </del><ins>+ conn = self.contextual_connect(close_with_result=False) </ins><span class="cx"> else: </span><span class="cx"> conn = connection </span><span class="cx"> try: </span><span class="lines">@@ -384,11 +385,11 @@ </span><span class="cx"> conn.close() </span><span class="cx"> </span><span class="cx"> def execute(self, *args, **kwargs): </span><del>- connection = self.contextual_connect() </del><ins>+ connection = self.contextual_connect(close_with_result=True) </ins><span class="cx"> return connection.execute(*args, **kwargs) </span><span class="cx"> </span><span class="cx"> def execute_compiled(self, compiled, parameters, **kwargs): </span><del>- connection = self.contextual_connect() </del><ins>+ connection = self.contextual_connect(close_with_result=True) </ins><span class="cx"> return connection.execute_compiled(compiled, parameters, **kwargs) </span><span class="cx"> </span><span class="cx"> def compiler(self, statement, parameters, **kwargs): </span><span class="lines">@@ -398,15 +399,15 @@ </span><span class="cx"> """returns a newly allocated Connection object.""" </span><span class="cx"> return Connection(self, **kwargs) </span><span class="cx"> </span><del>- def contextual_connect(self, **kwargs): </del><ins>+ def contextual_connect(self, close_with_result=False, **kwargs): </ins><span class="cx"> """returns a Connection object which may be newly allocated, or may be part of some </span><span class="cx"> ongoing context. This Connection is meant to be used by the various "auto-connecting" operations.""" </span><del>- return Connection(self, close_with_result=True, **kwargs) </del><ins>+ return Connection(self, close_with_result=close_with_result, **kwargs) </ins><span class="cx"> </span><span class="cx"> def reflecttable(self, table, connection=None): </span><span class="cx"> """given a Table object, reflects its columns and properties from the database.""" </span><span class="cx"> if connection is None: </span><del>- conn = self.contextual_connect() </del><ins>+ conn = self.contextual_connect(close_with_result=False) </ins><span class="cx"> else: </span><span class="cx"> conn = connection </span><span class="cx"> try: </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyenginedefaultpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/engine/default.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/engine/default.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/engine/default.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -14,8 +14,8 @@ </span><span class="cx"> </span><span class="cx"> </span><span class="cx"> class PoolConnectionProvider(base.ConnectionProvider): </span><del>- def __init__(self, dialect, connectopts, poolclass=None, pool=None, **kwargs): - (cargs, cparams) = dialect.create_connect_args(connectopts) </del><ins>+ def __init__(self, dialect, url, poolclass=None, pool=None, **kwargs): + (cargs, cparams) = dialect.create_connect_args(url) </ins><span class="cx"> if pool is None: </span><span class="cx"> kwargs.setdefault('echo', False) </span><span class="cx"> kwargs.setdefault('use_threadlocal',True) </span><span class="lines">@@ -80,25 +80,6 @@ </span><span class="cx"> cursor.execute(statement, parameters) </span><span class="cx"> def defaultrunner(self, engine, proxy): </span><span class="cx"> return base.DefaultRunner(engine, proxy) </span><del>- def _translate_connect_args(self, names, args): - """translates a dictionary of connection arguments to those used by a specific dbapi. - the names parameter is a tuple of argument names in the form ('host', 'database', 'user', 'password') - where the given strings match the corresponding argument names for the dbapi. Will return a dictionary - with the dbapi-specific parameters, the generic ones removed, and any additional parameters still remaining, - from the dictionary represented by args. Will return a blank dictionary if args is null.""" - if args is None: - return {} - a = {} #args.copy() - standard_names = [('host','hostname'), ('database', 'dbname'), ('user', 'username'), ('password', 'passwd', 'pw')] - for n in names: - sname = standard_names.pop(0) - if n is None: - continue - for sn in sname: - if args.has_key(sn): - a[n] = args[sn] - #del a[sn] - return a </del><span class="cx"> </span><span class="cx"> def _set_paramstyle(self, style): </span><span class="cx"> self._paramstyle = style </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyenginestrategiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/engine/strategies.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/engine/strategies.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/engine/strategies.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -4,10 +4,8 @@ </span><span class="cx"> list of available strategies here, or replace one of the existing name. </span><span class="cx"> this can be accomplished via a mod; see the sqlalchemy/mods package for details.""" </span><span class="cx"> </span><del>-import re -import cgi </del><span class="cx"> </span><del>-from sqlalchemy.engine import base, default, threadlocal </del><ins>+from sqlalchemy.engine import base, default, threadlocal, url </ins><span class="cx"> </span><span class="cx"> strategies = {} </span><span class="cx"> </span><span class="lines">@@ -27,8 +25,9 @@ </span><span class="cx"> class PlainEngineStrategy(EngineStrategy): </span><span class="cx"> def __init__(self): </span><span class="cx"> EngineStrategy.__init__(self, 'plain') </span><del>- def create(self, name, opts=None, **kwargs): - (module, opts) = _parse_db_args(name, opts) </del><ins>+ def create(self, name_or_url, **kwargs): + u = url.make_url(name_or_url) + module = u.get_module() </ins><span class="cx"> </span><span class="cx"> dialect = module.dialect(**kwargs) </span><span class="cx"> </span><span class="lines">@@ -38,7 +37,7 @@ </span><span class="cx"> if poolclass is not None: </span><span class="cx"> poolargs.setdefault('poolclass', poolclass) </span><span class="cx"> poolargs['use_threadlocal'] = False </span><del>- provider = default.PoolConnectionProvider(dialect, opts, **poolargs) </del><ins>+ provider = default.PoolConnectionProvider(dialect, u, **poolargs) </ins><span class="cx"> </span><span class="cx"> return base.ComposedSQLEngine(provider, dialect, **kwargs) </span><span class="cx"> PlainEngineStrategy() </span><span class="lines">@@ -46,8 +45,9 @@ </span><span class="cx"> class ThreadLocalEngineStrategy(EngineStrategy): </span><span class="cx"> def __init__(self): </span><span class="cx"> EngineStrategy.__init__(self, 'threadlocal') </span><del>- def create(self, name, opts=None, **kwargs): - (module, opts) = _parse_db_args(name, opts) </del><ins>+ def create(self, name_or_url, **kwargs): + u = url.make_url(name_or_url) + module = u.get_module() </ins><span class="cx"> </span><span class="cx"> dialect = module.dialect(**kwargs) </span><span class="cx"> </span><span class="lines">@@ -57,52 +57,10 @@ </span><span class="cx"> if poolclass is not None: </span><span class="cx"> poolargs.setdefault('poolclass', poolclass) </span><span class="cx"> poolargs['use_threadlocal'] = True </span><del>- provider = threadlocal.TLocalConnectionProvider(dialect, opts, **poolargs) </del><ins>+ provider = threadlocal.TLocalConnectionProvider(dialect, u, **poolargs) </ins><span class="cx"> </span><span class="cx"> return threadlocal.TLEngine(provider, dialect, **kwargs) </span><span class="cx"> ThreadLocalEngineStrategy() </span><span class="cx"> </span><span class="cx"> </span><del>-def _parse_db_args(name, opts=None): - ret = _parse_rfc1738_args(name, opts=opts) - #if ret is None: - # ret = _parse_keyvalue_args(name, opts=opts) - if ret is not None: - (name, opts) = ret - - module = getattr(__import__('sqlalchemy.databases.%s' % name).databases, name) - return (module, opts) - -def _parse_rfc1738_args(name, opts=None): - pattern = re.compile(r''' - (\w+):// - (?: - ([^:]*) - (?::(.*))? - @)? - (?: - ([^/:]*) - (?::([^/]*))? - ) - (?:/(.*))? - ''' - , re.X) </del><span class="cx"> </span><del>- m = pattern.match(name) - if m is not None and (m.group(4) or m.group(6)): - (name, username, password, host, port, database) = m.group(1, 2, 3, 4, 5, 6) - opts = {'username':username,'password':password,'host':host,'port':port,'database':database,'filename':(database or host)} - return (name, opts) - else: - return None - -def _parse_keyvalue_args(name, opts=None): - m = re.match( r'(\w+)://(.*)', name) - if m is not None: - (name, args) = m.group(1, 2) - opts = dict( cgi.parse_qsl( args ) ) - return (name, opts) - else: - return None - - </del></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyengineurlpy"></a> <div class="addfile"><h4>Added: sqlalchemy/branches/schema/lib/sqlalchemy/engine/url.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/engine/url.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/engine/url.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -0,0 +1,67 @@ </span><ins>+import re +import cgi + +class URL(object): + def __init__(self, drivername, username=None, password=None, host=None, port=None, database=None): + self.drivername = drivername + self.username = username + self.password = password + self.host = host + self.port = port + self.database= database + def get_module(self): + return getattr(__import__('sqlalchemy.databases.%s' % self.drivername).databases, self.drivername) + def translate_connect_args(self, names): + """translates this URL's attributes into a dictionary of connection arguments used by a specific dbapi. + the names parameter is a list of argument names in the form ('host', 'database', 'user', 'password', 'port') + where the given strings match the corresponding argument names for the dbapi. Will return a dictionary + with the dbapi-specific parameters.""" + a = {} + attribute_names = ['host', 'database', 'username', 'password', 'port'] + for n in names: + sname = attribute_names.pop(0) + if n is None: + continue + if getattr(self, sname, None) is not None: + a[n] = getattr(self, sname) + return a + + +def make_url(name_or_url): + if isinstance(name_or_url, str): + return _parse_rfc1738_args(name_or_url) + else: + return name_or_url + +def _parse_rfc1738_args(name): + pattern = re.compile(r''' + (\w+):// + (?: + ([^:]*) + (?::(.*))? + @)? + (?: + ([^/:]*) + (?::([^/]*))? + ) + (?:/(.*))? + ''' + , re.X) + + m = pattern.match(name) + if m is not None and (m.group(4) or m.group(6)): + (name, username, password, host, port, database) = m.group(1, 2, 3, 4, 5, 6) + opts = {'username':username,'password':password,'host':host,'port':port,'database':database} + return URL(name, **opts) + else: + return None + +def _parse_keyvalue_args(name): + m = re.match( r'(\w+)://(.*)', name) + if m is not None: + (name, args) = m.group(1, 2) + opts = dict( cgi.parse_qsl( args ) ) + return URL(name, *opts) + else: + return None + </ins></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyormsessionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/orm/session.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/orm/session.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/orm/session.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -105,7 +105,7 @@ </span><span class="cx"> to the execution's results. If this method allocates a new Connection for the operation, then the ResultProxy's close() </span><span class="cx"> method will release the resources of the underlying Connection, otherwise its a no-op. </span><span class="cx"> """ </span><del>- return self.connection(mapper).execute(clause, params, **kwargs) </del><ins>+ return self.connection(mapper, close_with_result=True).execute(clause, params, **kwargs) </ins><span class="cx"> def close(self): </span><span class="cx"> """closes this Session. </span><span class="cx"> </span><span class="lines">@@ -223,12 +223,12 @@ </span><span class="cx"> def refresh(self, object): </span><span class="cx"> """reloads the attributes for the given object from the database, clears </span><span class="cx"> any changes made.""" </span><del>- self.uow.refresh(object) </del><ins>+ self.uow.refresh(self, object) </ins><span class="cx"> </span><span class="cx"> def expire(self, object): </span><span class="cx"> """invalidates the data in the given object and sets them to refresh themselves </span><span class="cx"> the next time they are requested.""" </span><del>- self.uow.expire(object) </del><ins>+ self.uow.expire(self, object) </ins><span class="cx"> </span><span class="cx"> def expunge(self, object): </span><span class="cx"> """removes the given object from this Session. this will free all internal references to the object.""" </span><span class="lines">@@ -271,6 +271,7 @@ </span><span class="cx"> self.uow.register_deleted(c) </span><span class="cx"> </span><span class="cx"> def merge(self, object, entity_name=None): </span><ins>+ instance = None </ins><span class="cx"> for obj in object_mapper(object, entity_name=entity_name).cascade_iterator('merge', object): </span><span class="cx"> key = getattr(obj, '_instance_key', None) </span><span class="cx"> if key is None: </span><span class="lines">@@ -282,12 +283,14 @@ </span><span class="cx"> key = mapper.identity_key(*ident) </span><span class="cx"> u = self.uow </span><span class="cx"> if u.identity_map.has_key(key): </span><del>- return u.identity_map[key] </del><ins>+ # TODO: copy the state of the given object into this one. tricky ! + inst = u.identity_map[key] </ins><span class="cx"> else: </span><del>- obj._instance_key = key - u.identity_map[key] = obj - self._bind_to(instance) - return instance </del><ins>+ inst = self.get(*key[1]) + if obj is object: + instance = inst + + return instance </ins><span class="cx"> </span><span class="cx"> def _save_impl(self, object, **kwargs): </span><span class="cx"> if hasattr(object, '_instance_key'): </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/orm/unitofwork.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/orm/unitofwork.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/orm/unitofwork.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -108,14 +108,14 @@ </span><span class="cx"> def _put(self, key, obj): </span><span class="cx"> self.identity_map[key] = obj </span><span class="cx"> </span><del>- def refresh(self, obj): </del><ins>+ def refresh(self, sess, obj): </ins><span class="cx"> self.rollback_object(obj) </span><del>- object_mapper(obj)._get(obj._instance_key, reload=True) </del><ins>+ sess.query(obj.__class__)._get(obj._instance_key, reload=True) </ins><span class="cx"> </span><del>- def expire(self, obj): </del><ins>+ def expire(self, sess, obj): </ins><span class="cx"> self.rollback_object(obj) </span><span class="cx"> def exp(): </span><del>- object_mapper(obj)._get(obj._instance_key, reload=True) </del><ins>+ sess.query(obj.__class__)._get(obj._instance_key, reload=True) </ins><span class="cx"> global_attributes.trigger_history(obj, exp) </span><span class="cx"> </span><span class="cx"> def is_expired(self, obj, unexpire=False): </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyschemapy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/schema.py (1334 => 1335)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/schema.py 2006-04-24 22:11:13 UTC (rev 1334) +++ sqlalchemy/branches/schema/lib/sqlalchemy/schema.py 2006-04-25 01:57:51 UTC (rev 1335) </span><span class="lines">@@ -426,7 +426,7 @@ </span><span class="cx"> schema = self.parent.original.table.schema </span><span class="cx"> else: </span><span class="cx"> (schema,tname,colname) = m.group(1,2,3) </span><del>- table = Table(tname, self.parent.metadata, mustexist=True, schema=schema) </del><ins>+ table = Table(tname, self.parent.original.metadata, mustexist=True, schema=schema) </ins><span class="cx"> if colname is None: </span><span class="cx"> key = self.parent </span><span class="cx"> self._column = table.c[self.parent.key] </span></span></pre> </div> </div> </body> </html> |