[Sqlalchemy-commits] [1343] sqlalchemy/branches/schema: improvements to polymorphic mapping and supp
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-26 18:24:30
|
<!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>[1343] sqlalchemy/branches/schema: improvements to polymorphic mapping and supporting fixes in properties/backrefs.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1343</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-04-26 13:24:17 -0500 (Wed, 26 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>improvements to polymorphic mapping and supporting fixes in properties/backrefs. getting ready to add polymorphic behavior to the core. also fixed [ticket:154] pending further testing. updated CHANGES with the general things happening in 0.2 as well as affected tickets</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesschemaCHANGES">sqlalchemy/branches/schema/CHANGES</a></li> <li><a href="#sqlalchemybranchesschemaexamplespolymorphpolymorphpy">sqlalchemy/branches/schema/examples/polymorph/polymorph.py</a></li> <li><a href="#sqlalchemybranchesschemaexamplespolymorphpolymorph2py">sqlalchemy/branches/schema/examples/polymorph/polymorph2.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyansisqlpy">sqlalchemy/branches/schema/lib/sqlalchemy/ansisql.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyengineurlpy">sqlalchemy/branches/schema/lib/sqlalchemy/engine/url.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyormmapperpy">sqlalchemy/branches/schema/lib/sqlalchemy/orm/mapper.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyormpropertiespy">sqlalchemy/branches/schema/lib/sqlalchemy/orm/properties.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyormquerypy">sqlalchemy/branches/schema/lib/sqlalchemy/orm/query.py</a></li> <li><a href="#sqlalchemybranchesschematestparseconnectpy">sqlalchemy/branches/schema/test/parseconnect.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesschemaCHANGES"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/CHANGES (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/CHANGES 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/CHANGES 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -1,5 +1,53 @@ </span><del>-next -- some fixes to topological sort algorithm </del><ins>+0.2 +- overhaul to Engine system so that what was formerly the SQLEngine +is now a ComposedSQLEngine which consists of a variety of components, +including a Dialect, ConnectionProvider, etc. This impacted all the +db modules as well as Session and Mapper. +- create_engine now takes only RFC-1738-style strings: +driver://user:password@host:port/database +- total rewrite of connection-scoping methodology, Connection objects +can now execute clause elements directly, added explicit "close" as +well as support throughout Engine/ORM to handle closing properly, +no longer relying upon __del__ internally to return connections +to the pool [ticket:152]. +- overhaul to Session interface and scoping. uses hibernate-style +methods, including query(class), save(), save_or_update(), etc. +no threadlocal scope is installed by default. Provides a binding +interface to specific Engines and/or Connections so that underlying +Schema objects do not need to be bound to an Engine. Added a basic +SessionTransaction object that can simplistically aggregate transactions +across multiple engines. +- overhaul to mapper's dependency and "cascade" behavior; dependency logic +factored out of properties.py into a separate module "dependency.py". +"cascade" behavior is now explicitly controllable, proper implementation +of "delete", "delete-orphan", etc. dependency system can now determine at +flush time if a child object has a parent or not so that it makes better +decisions on how that child should be updated in the DB with regards to deletes. +- overhaul to Schema to build upon MetaData object instead of an Engine. +Entire SQL/Schema system can be used with no Engines whatsoever, executed +solely by an explicit Connection object. the "bound" methodlogy exists via the +BoundMetaData for schema objects. ProxyEngine is generally not needed +anymore and is replaced by DynamicMetaData. +- "oid" system has been totally moved into compile-time behavior; +if they are used in an order_by where they are not available, the order_by +doesnt get compiled, fixes [ticket:147] +- overhaul to packaging; "mapping" is now "orm", "objectstore" is now +"session", the old "objectstore" namespace gets loaded in via the +"threadlocal" mod if used +- mods now called in via "import <modname>". extensions favored over +mods as mods are globally-monkeypatching +- fix to add_property so that it propigates properties to inheriting +mappers [ticket:154] +- backrefs create themselves against primary mapper of its originating +property, priamry/secondary join arguments can be specified to override. +helps their usage with polymorphic mappers +- "table exists" function has been implemented [ticket:31] +- "create_all/drop_all" added to MetaData object [ticket:98] +- improvements and fixes to topological sort algorithm, as well as more +unit tests +- tutorial page added to docs which also can be run with a custom doctest +runner to insure its properly working. docs generally overhauled to +deal with new code patterns </ins><span class="cx"> </span><span class="cx"> 0.1.6 </span><span class="cx"> - support for MS-SQL added courtesy Rick Morrison, Runar Petursson </span></span></pre></div> <a id="sqlalchemybranchesschemaexamplespolymorphpolymorphpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/examples/polymorph/polymorph.py (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/examples/polymorph/polymorph.py 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/examples/polymorph/polymorph.py 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -32,6 +32,9 @@ </span><span class="cx"> </span><span class="cx"> # create our classes. The Engineer and Manager classes extend from Person. </span><span class="cx"> class Person(object): </span><ins>+ def __init__(self, **kwargs): + for key, value in kwargs.iteritems(): + setattr(self, key, value) </ins><span class="cx"> def __repr__(self): </span><span class="cx"> return "Ordinary person %s" % self.name </span><span class="cx"> class Engineer(Person): </span><span class="lines">@@ -41,6 +44,9 @@ </span><span class="cx"> def __repr__(self): </span><span class="cx"> return "Manager %s, description %s" % (self.name, self.description) </span><span class="cx"> class Company(object): </span><ins>+ def __init__(self, **kwargs): + for key, value in kwargs.iteritems(): + setattr(self, key, value) </ins><span class="cx"> def __repr__(self): </span><span class="cx"> return "Company %s" % self.name </span><span class="cx"> </span><span class="lines">@@ -48,9 +54,9 @@ </span><span class="cx"> # creating for these classes, they automatically become the "primary mappers", which </span><span class="cx"> # define the dependency relationships between the classes, so we do a straight </span><span class="cx"> # inheritance setup, i.e. no modifications to how objects are loaded or anything like that. </span><del>-assign_mapper(Person, people) -assign_mapper(Engineer, engineers, inherits=Person.mapper) -assign_mapper(Manager, managers, inherits=Person.mapper) </del><ins>+mapper(Person, people) +mapper(Engineer, engineers, inherits=class_mapper(Person)) +mapper(Manager, managers, inherits=class_mapper(Person)) </ins><span class="cx"> </span><span class="cx"> # next, we define a query that is going to load Managers and Engineers in one shot. </span><span class="cx"> # we will use a UNION ALL with an extra hardcoded column to indicate the type of object. </span><span class="lines">@@ -81,7 +87,7 @@ </span><span class="cx"> </span><span class="cx"> # MapperExtension object. </span><span class="cx"> class PersonLoader(MapperExtension): </span><del>- def create_instance(self, mapper, row, imap, class_): </del><ins>+ def create_instance(self, session, mapper, row, imap, class_): </ins><span class="cx"> if row['pjoin_type'] =='engineer': </span><span class="cx"> e = Engineer() </span><span class="cx"> e.special_description = row['pjoin_description'] </span><span class="lines">@@ -94,8 +100,11 @@ </span><span class="cx"> </span><span class="cx"> # set up the polymorphic mapper, which maps the person_join we set up to </span><span class="cx"> # the Person class, using an instance of PersonLoader. </span><del>-people_mapper = mapper(Person, person_join, extension=ext) </del><ins>+people_mapper = mapper(Person, person_join, extension=ext, non_primary=True) </ins><span class="cx"> </span><ins>+# TODO: polymorphic options, i.e.: +# people_mapper = mapper(Person, person_join, polymorphic_on=person_join.c.type, polymorphic_map={'engineer':Engineer, 'manager':Manager}) + </ins><span class="cx"> # create a mapper for Company. the 'employees' relationship points to </span><span class="cx"> # our new people_mapper. </span><span class="cx"> # </span><span class="lines">@@ -107,36 +116,38 @@ </span><span class="cx"> # themselves as dependent on the Person mapper's save operations. </span><span class="cx"> # (translation: it'll work) </span><span class="cx"> # TODO: get the eager loading to work (the compound select alias doesnt like being aliased itself) </span><del>-assign_mapper(Company, companies, properties={ - 'employees': relation(people_mapper, lazy=False, private=True) </del><ins>+mapper(Company, companies, properties={ + 'employees': relation(people_mapper, lazy=False, cascade="save-update,delete,delete-orphan", backref=backref("company")) </ins><span class="cx"> }) </span><span class="cx"> </span><ins>+session = create_session() </ins><span class="cx"> c = Company(name='company1') </span><span class="cx"> c.employees.append(Manager(name='pointy haired boss', description='manager1')) </span><span class="cx"> c.employees.append(Engineer(name='dilbert', special_description='engineer1')) </span><span class="cx"> c.employees.append(Engineer(name='wally', special_description='engineer2')) </span><span class="cx"> c.employees.append(Manager(name='jsmith', description='manager2')) </span><del>-objectstore.commit() </del><ins>+session.save(c) +session.flush() </ins><span class="cx"> </span><del>-objectstore.clear() </del><ins>+session.clear() </ins><span class="cx"> </span><del>-c = Company.get(1) </del><ins>+c = session.query(Company).get(1) </ins><span class="cx"> for e in c.employees: </span><span class="cx"> print e, e._instance_key </span><span class="cx"> </span><span class="cx"> print "\n" </span><span class="cx"> </span><del>-dilbert = Engineer.mapper.get_by(name='dilbert') </del><ins>+dilbert = session.query(Engineer).get_by(name='dilbert') </ins><span class="cx"> dilbert.special_description = 'hes dibert!' </span><del>-objectstore.commit() </del><ins>+session.flush() </ins><span class="cx"> </span><del>-objectstore.clear() -c = Company.get(1) </del><ins>+session.clear() +c = session.query(Company).get(1) </ins><span class="cx"> for e in c.employees: </span><del>- print e, e._instance_key </del><ins>+ print e, e._instance_key, e.company </ins><span class="cx"> </span><del>-objectstore.delete(c) -objectstore.commit() </del><ins>+session.delete(c) +session.flush() </ins><span class="cx"> </span><span class="cx"> </span><span class="cx"> managers.drop() </span></span></pre></div> <a id="sqlalchemybranchesschemaexamplespolymorphpolymorph2py"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/examples/polymorph/polymorph2.py (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/examples/polymorph/polymorph2.py 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/examples/polymorph/polymorph2.py 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -96,7 +96,7 @@ </span><span class="cx"> else: </span><span class="cx"> return sqlalchemy.mapping.EXT_PASS </span><span class="cx"> </span><del>-people_mapper = mapper(Person, person_join, extension=PersonLoader()) </del><ins>+people_mapper = mapper(Person, person_join, polymorphic_on=person_join.c.type, polymorphic_map={'engineer':Engineer, 'manager':Manager}) </ins><span class="cx"> </span><span class="cx"> assign_mapper(Company, companies, properties={ </span><span class="cx"> 'employees': relation(people_mapper, lazy=False, private=True) </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyansisqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/ansisql.py (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/ansisql.py 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/lib/sqlalchemy/ansisql.py 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -15,8 +15,8 @@ </span><span class="cx"> 'CURRENT_TIME', </span><span class="cx"> 'CURRENT_TIMESTAMP', </span><span class="cx"> 'CURRENT_DATE', </span><del>-'LOCAL_TIME', -'LOCAL_TIMESTAMP', </del><ins>+'LOCALTIME', +'LOCALTIMESTAMP', </ins><span class="cx"> 'CURRENT_USER', </span><span class="cx"> 'SESSION_USER', </span><span class="cx"> 'USER' </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyengineurlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/engine/url.py (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/engine/url.py 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/lib/sqlalchemy/engine/url.py 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -9,6 +9,8 @@ </span><span class="cx"> self.host = host </span><span class="cx"> self.port = port </span><span class="cx"> self.database= database </span><ins>+ def __str__(self): + return "%s:%s@%s:%s/%s" % (self.username,self.password, self.host,self.port,self.database) </ins><span class="cx"> def get_module(self): </span><span class="cx"> return getattr(__import__('sqlalchemy.databases.%s' % self.drivername).databases, self.drivername) </span><span class="cx"> def translate_connect_args(self, names): </span><span class="lines">@@ -43,13 +45,13 @@ </span><span class="cx"> (?: </span><span class="cx"> ([^/:]*) </span><span class="cx"> (?::([^/]*))? </span><del>- ) </del><ins>+ )? </ins><span class="cx"> (?:/(.*))? </span><span class="cx"> ''' </span><span class="cx"> , re.X) </span><span class="cx"> </span><span class="cx"> m = pattern.match(name) </span><del>- if m is not None and (m.group(4) or m.group(6)): </del><ins>+ if m is not None: </ins><span class="cx"> (name, username, password, host, port, database) = m.group(1, 2, 3, 4, 5, 6) </span><span class="cx"> opts = {'username':username,'password':password,'host':host,'port':port,'database':database} </span><span class="cx"> return URL(name, **opts) </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/orm/mapper.py (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/orm/mapper.py 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/lib/sqlalchemy/orm/mapper.py 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -76,6 +76,7 @@ </span><span class="cx"> self._options = {} </span><span class="cx"> self.always_refresh = always_refresh </span><span class="cx"> self.version_id_col = version_id_col </span><ins>+ self._inheriting_mappers = sets.Set() </ins><span class="cx"> </span><span class="cx"> if not issubclass(class_, object): </span><span class="cx"> raise ArgumentError("Class '%s' is not a new-style class" % class_.__name__) </span><span class="lines">@@ -199,6 +200,7 @@ </span><span class="cx"> raise ArgumentError("Class '%s' already has a primary mapper defined. Use is_primary=True to assign a new primary mapper to the class, or use non_primary=True to create a non primary Mapper" % self.class_) </span><span class="cx"> </span><span class="cx"> if inherits is not None: </span><ins>+ inherits._inheriting_mappers.add(self) </ins><span class="cx"> for key, prop in inherits.props.iteritems(): </span><span class="cx"> if not self.props.has_key(key): </span><span class="cx"> self.props[key] = prop.copy() </span><span class="lines">@@ -319,6 +321,11 @@ </span><span class="cx"> </span><span class="cx"> if init: </span><span class="cx"> prop.init(key, self) </span><ins>+ + for mapper in self._inheriting_mappers: + p = prop.copy() + p.parent = mapper + mapper.add_property(key, p, init=False) </ins><span class="cx"> </span><span class="cx"> def __str__(self): </span><span class="cx"> return "Mapper|" + self.class_.__name__ + "|" + (self.entity_name is not None and "/%s" % self.entity_name or "") + self.primarytable.name </span><span class="lines">@@ -332,7 +339,7 @@ </span><span class="cx"> return mapper_registry[self.class_key] </span><span class="cx"> </span><span class="cx"> def is_assigned(self, instance): </span><del>- """returns True if this mapper is the primary mapper for the given instance. this is dependent </del><ins>+ """returns True if this mapper handles the given instance. this is dependent </ins><span class="cx"> not only on class assignment but the optional "entity_name" parameter as well.""" </span><span class="cx"> return instance.__class__ is self.class_ and getattr(instance, '_entity_name', None) == self.entity_name </span><span class="cx"> </span><span class="lines">@@ -485,7 +492,10 @@ </span><span class="cx"> </span><span class="cx"> def _setattrbycolumn(self, obj, column, value): </span><span class="cx"> self.columntoproperty[column.original][0].setattr(obj, value) </span><del>- </del><ins>+ + def primary_mapper(self): + return mapper_registry[self.class_key] + </ins><span class="cx"> def save_obj(self, objects, uow, postupdate=False): </span><span class="cx"> """called by a UnitOfWork object to save objects, which involves either an INSERT or </span><span class="cx"> an UPDATE statement for each table used by this mapper, for each element of the </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyormpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/orm/properties.py (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/orm/properties.py 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/lib/sqlalchemy/orm/properties.py 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -375,13 +375,16 @@ </span><span class="cx"> def lazyload(): </span><span class="cx"> params = {} </span><span class="cx"> allparams = True </span><del>- session = sessionlib.get_session(instance) - #print "setting up loader, lazywhere", str(self.lazywhere) - for col, bind in self.lazybinds.iteritems(): - params[bind.key] = self.parent._getattrbycolumn(instance, col) - if params[bind.key] is None: - allparams = False - break </del><ins>+ session = sessionlib.get_session(instance, raiseerror=False) + #print "setting up loader, lazywhere", str(self.lazywhere), "binds", self.lazybinds + if session is not None: + for col, bind in self.lazybinds.iteritems(): + params[bind.key] = self.parent._getattrbycolumn(instance, col) + if params[bind.key] is None: + allparams = False + break + else: + allparams = False </ins><span class="cx"> if allparams: </span><span class="cx"> # if we have a simple straight-primary key load, use mapper.get() </span><span class="cx"> # to possibly save a DB round trip </span><span class="lines">@@ -656,25 +659,35 @@ </span><span class="cx"> """called by the owning PropertyLoader to set up a backreference on the </span><span class="cx"> PropertyLoader's mapper.""" </span><span class="cx"> # try to set a LazyLoader on our mapper referencing the parent mapper </span><ins>+ mapper = prop.mapper.primary_mapper() </ins><span class="cx"> if not prop.mapper.props.has_key(self.key): </span><del>- if prop.secondaryjoin is not None: - # if setting up a backref to a many-to-many, reverse the order - # of the "primary" and "secondary" joins - pj = prop.secondaryjoin - sj = prop.primaryjoin - else: - pj = prop.primaryjoin - sj = None </del><ins>+ pj = self.kwargs.pop('primaryjoin', None) + sj = self.kwargs.pop('secondaryjoin', None) + # TODO: we are going to have the newly backref'd property create its + # primary/secondary join through normal means, and only override if they are + # specified to the constructor. think about if this is really going to work + # all the way. + #if pj is None: + # if prop.secondaryjoin is not None: + # # if setting up a backref to a many-to-many, reverse the order + # # of the "primary" and "secondary" joins + # pj = prop.secondaryjoin + # sj = prop.primaryjoin + # else: + # pj = prop.primaryjoin + # sj = None </ins><span class="cx"> lazy = self.kwargs.pop('lazy', True) </span><span class="cx"> if lazy: </span><span class="cx"> cls = LazyLoader </span><span class="cx"> else: </span><span class="cx"> cls = EagerLoader </span><del>- relation = cls(prop.parent, prop.secondary, pj, sj, backref=prop.key, is_backref=True, **self.kwargs) - prop.mapper.add_property(self.key, relation); </del><ins>+ # the backref property is set on the primary mapper + parent = prop.parent.primary_mapper() + relation = cls(parent, prop.secondary, pj, sj, backref=prop.key, is_backref=True, **self.kwargs) + mapper.add_property(self.key, relation); </ins><span class="cx"> else: </span><span class="cx"> # else set one of us as the "backreference" </span><del>- if not prop.mapper.props[self.key].is_backref: </del><ins>+ if not mapper.props[self.key].is_backref: </ins><span class="cx"> prop.is_backref=True </span><span class="cx"> prop._dependency_processor.is_backref=True </span><span class="cx"> def get_extension(self): </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyormquerypy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/orm/query.py (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/orm/query.py 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/lib/sqlalchemy/orm/query.py 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -40,7 +40,7 @@ </span><span class="cx"> if not found. The *ident argument is a </span><span class="cx"> list of primary key columns in the order of the table def's primary key columns.""" </span><span class="cx"> key = self.mapper.identity_key(*ident) </span><del>- #print "key: " + repr(key) + " ident: " + repr(ident) </del><ins>+ print "key: " + repr(key) + " ident: " + repr(ident) </ins><span class="cx"> return self._get(key, ident, **kwargs) </span><span class="cx"> </span><span class="cx"> def get_by(self, *args, **params): </span><span class="lines">@@ -203,6 +203,7 @@ </span><span class="cx"> except KeyError: </span><span class="cx"> pass </span><span class="cx"> </span><ins>+ print "_GET!", key, ident </ins><span class="cx"> if ident is None: </span><span class="cx"> ident = key[1] </span><span class="cx"> i = 0 </span></span></pre></div> <a id="sqlalchemybranchesschematestparseconnectpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/parseconnect.py (1342 => 1343)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/parseconnect.py 2006-04-26 14:55:05 UTC (rev 1342) +++ sqlalchemy/branches/schema/test/parseconnect.py 2006-04-26 18:24:17 UTC (rev 1343) </span><span class="lines">@@ -1,10 +1,10 @@ </span><span class="cx"> from testbase import PersistTest </span><del>-import sqlalchemy.engine.strategies as strategies </del><ins>+import sqlalchemy.engine.url as url </ins><span class="cx"> import unittest </span><span class="cx"> </span><span class="cx"> class ParseConnectTest(PersistTest): </span><span class="cx"> def testrfc1738(self): </span><del>- for url in ( </del><ins>+ for text in ( </ins><span class="cx"> 'dbtype://username:password@hostspec:110//usr/db_file.db', </span><span class="cx"> 'dbtype://username:password@hostspec/database', </span><span class="cx"> 'dbtype://username:password@hostspec', </span><span class="lines">@@ -14,21 +14,13 @@ </span><span class="cx"> 'dbtype://hostspec/database', </span><span class="cx"> 'dbtype://hostspec', </span><span class="cx"> 'dbtype:///database', </span><del>- 'dbtype:///:memory:' </del><ins>+ 'dbtype:///:memory:', + 'dbtype://' </ins><span class="cx"> ): </span><del>- (name, opts) = strategies._parse_rfc1738_args(url, {}) </del><ins>+ u = url.make_url(text) </ins><span class="cx"> # TODO: assertion conditions </span><del>- print name, opts </del><ins>+ print u </ins><span class="cx"> </span><del>- def testurl(self): - for url in ( - 'dbtype://username=user&password=pw&host=host&port=1234&db=foo', - ): - #foo = strategies._parse_rfc1738_args(url, {}) - #assert foo is None - (name, opts) = strategies._parse_keyvalue_args(url, {}) - # TODO: assertion conditions - print name, opts </del><span class="cx"> </span><span class="cx"> if __name__ == "__main__": </span><span class="cx"> unittest.main() </span></span></pre> </div> </div> </body> </html> |