[Sqlalchemy-commits] [1304] sqlalchemy/branches/schema/test: session interface....
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-20 18:04:29
|
<!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>[1304] sqlalchemy/branches/schema/test: session interface....</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1304</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-04-20 13:04:16 -0500 (Thu, 20 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>session interface....</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesschemalibsqlalchemymappingmapperpy">sqlalchemy/branches/schema/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemymappingobjectstorepy">sqlalchemy/branches/schema/lib/sqlalchemy/mapping/objectstore.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemymappingunitofworkpy">sqlalchemy/branches/schema/lib/sqlalchemy/mapping/unitofwork.py</a></li> <li><a href="#sqlalchemybranchesschematestobjectstorepy">sqlalchemy/branches/schema/test/objectstore.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesschemalibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/mapping/mapper.py (1303 => 1304)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/mapping/mapper.py 2006-04-20 02:30:21 UTC (rev 1303) +++ sqlalchemy/branches/schema/lib/sqlalchemy/mapping/mapper.py 2006-04-20 18:04:16 UTC (rev 1304) </span><span class="lines">@@ -49,8 +49,7 @@ </span><span class="cx"> allow_column_override = False, </span><span class="cx"> entity_name = None, </span><span class="cx"> always_refresh = False, </span><del>- version_id_col = None, - **kwargs): </del><ins>+ version_id_col = None): </ins><span class="cx"> </span><span class="cx"> if primarytable is not None: </span><span class="cx"> sys.stderr.write("'primarytable' argument to mapper is deprecated\n") </span><span class="lines">@@ -333,6 +332,11 @@ </span><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><ins>+ def _assign_entity_name(self, instance): + """assigns this Mapper's entity name to the given instance. subsequent Mapper lookups for this + instance will return the primary mapper corresponding to this Mapper's class and entity name.""" + instance._entity_name = self.entity_name + </ins><span class="cx"> def _init_class(self): </span><span class="cx"> """sets up our classes' overridden __init__ method, this mappers hash key as its </span><span class="cx"> '_mapper' property, and our columns as its 'c' property. if the class already had a </span><span class="lines">@@ -355,7 +359,7 @@ </span><span class="cx"> # register new with the correct session, before the object's </span><span class="cx"> # constructor is called, since further assignments within the </span><span class="cx"> # constructor would otherwise bind it to whatever get_session() is. </span><del>- session.register_new(self) </del><ins>+ session._register_new(self) </ins><span class="cx"> else: </span><span class="cx"> session._bind_to(self) </span><span class="cx"> if oldinit is not None: </span><span class="lines">@@ -403,7 +407,7 @@ </span><span class="cx"> </span><span class="cx"> # store new stuff in the identity map </span><span class="cx"> for value in imap.values(): </span><del>- session.register_clean(value) </del><ins>+ session._register_clean(value) </ins><span class="cx"> </span><span class="cx"> if mappers: </span><span class="cx"> result = [result] + otherresults </span><span class="lines">@@ -955,13 +959,16 @@ </span><span class="cx"> else: </span><span class="cx"> return repr(obj) </span><span class="cx"> </span><del>-def object_mapper(object): </del><ins>+def object_mapper(object, raiseerror=True): </ins><span class="cx"> """given an object, returns the primary Mapper associated with the object </span><span class="cx"> or the object's class.""" </span><span class="cx"> try: </span><span class="cx"> return mapper_registry[ClassKey(object.__class__, getattr(object, '_entity_name', None))] </span><span class="cx"> except KeyError: </span><del>- raise InvalidRequestError("Class '%s' entity name '%s' has no mapper associated with it" % (object.__class__.__name__, getattr(object, '_entity_name', None))) </del><ins>+ if raiseerror: + raise InvalidRequestError("Class '%s' entity name '%s' has no mapper associated with it" % (object.__class__.__name__, getattr(object, '_entity_name', None))) + else: + return None </ins><span class="cx"> </span><span class="cx"> def class_mapper(class_, entity_name=None): </span><span class="cx"> """given a ClassKey, returns the primary Mapper associated with the key.""" </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemymappingobjectstorepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/mapping/objectstore.py (1303 => 1304)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/mapping/objectstore.py 2006-04-20 02:30:21 UTC (rev 1303) +++ sqlalchemy/branches/schema/lib/sqlalchemy/mapping/objectstore.py 2006-04-20 18:04:16 UTC (rev 1304) </span><span class="lines">@@ -80,27 +80,59 @@ </span><span class="cx"> """returns a unique connection corresponding to the given mapper. this connection </span><span class="cx"> will not be part of any pre-existing transactional context.""" </span><span class="cx"> return self.get_bind(mapper).connect(**kwargs) </span><del>- def connection(self, mapper): - """returns a connection corresponding to the given mapper. used by the execute() </del><ins>+ def connection(self, mapper, **kwargs): + """returns a Connection corresponding to the given mapper. used by the execute() </ins><span class="cx"> method which performs select operations for Mapper and Query. </span><span class="cx"> if this Session is transactional, </span><span class="cx"> the connection will be in the context of this session's transaction. otherwise, the connection </span><del>- will be unique, and will also have the close_with_result flag set to True so that the connection - can be closed out using the result alone.""" </del><ins>+ will be unique. + + the given **kwargs will be sent to the engine's connect() method, if no transaction is in progress.""" </ins><span class="cx"> if self.transaction is not None: </span><span class="cx"> return self.transaction.connection(mapper) </span><span class="cx"> else: </span><del>- return self.connect(mapper, close_with_result=True) </del><ins>+ return self.connect(mapper, **kwargs) </ins><span class="cx"> def execute(self, mapper, clause, params, **kwargs): </span><del>- return self.connection(mapper).execute(clause, params, **kwargs) </del><ins>+ """using the given mapper to identify the appropriate Engine or Connection to be used for statement execution, + executes the given ClauseElement using the provided parameter dictionary. Returns a ResultProxy corresponding + to the execution's results. If this method allocates a new Connection for the operation, then the ResultProxy's close() + method will release the resources of the underlying Connection, otherwise its a no-op. + """ + return self.connection(mapper, close_with_result=True).execute(clause, params, **kwargs) </ins><span class="cx"> def close(self): </span><ins>+ """closes this Session. + + TODO: what should we do here ? + """ </ins><span class="cx"> if self.transaction is not None: </span><span class="cx"> self.transaction.close() </span><span class="cx"> def bind_mapper(self, mapper, bindto): </span><ins>+ """binds the given Mapper to the given Engine or Connection. All subsequent operations involving this + Mapper will use the given bindto.""" </ins><span class="cx"> self.binds[mapper] = bindto </span><span class="cx"> def bind_table(self, table, bindto): </span><ins>+ """binds the given Table to the given Engine or Connection. All subsequent operations involving this + Table will use the given bindto.""" </ins><span class="cx"> self.binds[table] = bindto </span><span class="cx"> def get_bind(self, mapper): </span><ins>+ """given a Mapper, returns the Engine or Connection which is used to execute statements on behalf of this + Mapper. Calling connect() on the return result will always result in a Connection object. This method + disregards any SessionTransaction that may be in progress. + + The order of searching is as follows: + + if an Engine or Connection was bound to this Mapper specifically within this Session, returns that + Engine or Connection. + + if an Engine or Connection was bound to this Mapper's underlying Table within this Session + (i.e. not to the Table directly), returns that Engine or Conneciton. + + if an Engine or Connection was bound to this Session, returns that Engine or Connection. + + finally, returns the Engine which was bound directly to the Table's MetaData object. + + If no Engine is bound to the Table, an exception is raised. + """ </ins><span class="cx"> if mapper is None: </span><span class="cx"> return self.bind_to </span><span class="cx"> elif self.binds.has_key(mapper): </span><span class="lines">@@ -112,6 +144,7 @@ </span><span class="cx"> else: </span><span class="cx"> return mapper.table.engine </span><span class="cx"> def query(self, mapper_or_class): </span><ins>+ """given a mapper or Class, returns a new Query object corresponding to this Session and the mapper, or the classes' primary mapper.""" </ins><span class="cx"> if isinstance(mapper_or_class, type): </span><span class="cx"> return query.Query(class_mapper(mapper_or_class), self) </span><span class="cx"> else: </span><span class="lines">@@ -158,11 +191,15 @@ </span><span class="cx"> get_row_key = staticmethod(get_row_key) </span><span class="cx"> </span><span class="cx"> def begin(self, *obj): </span><ins>+ """deprecated""" </ins><span class="cx"> raise InvalidRequestError("Session.begin() is deprecated. use install_mod('legacy_session') to enable the old behavior") </span><span class="cx"> def commit(self, *obj): </span><ins>+ """deprecated""" </ins><span class="cx"> raise InvalidRequestError("Session.commit() is deprecated. use install_mod('legacy_session') to enable the old behavior") </span><span class="cx"> </span><span class="cx"> def flush(self, *obj): </span><ins>+ """flushes all the object modifications present in this session to the database. if object + arguments are given, then only those objects (and immediate dependencies) are flushed.""" </ins><span class="cx"> self.uow.flush(self, *obj) </span><span class="cx"> </span><span class="cx"> def refresh(self, *obj): </span><span class="lines">@@ -178,97 +215,149 @@ </span><span class="cx"> self.uow.expire(o) </span><span class="cx"> </span><span class="cx"> def expunge(self, *obj): </span><ins>+ """removes the given objects from this Session. this will free all internal references to the objects.""" </ins><span class="cx"> for o in obj: </span><span class="cx"> self.uow.expunge(o) </span><span class="cx"> </span><del>- def register_clean(self, *obj): </del><ins>+ def add(self, *obj, **kwargs): + """adds unsaved objects to this Session. + + The 'entity_name' keyword argument can also be given which will be assigned + to the instances if given. + """ </ins><span class="cx"> for o in obj: </span><del>- self._bind_to(o) - self.uow.register_clean(o) - - def add(self, *obj): - """given some objects, if they have no identity they will be registered as new in this session. - if they have an identity, its verified that they are already part of this session.""" - for o in obj: </del><span class="cx"> if hasattr(o, '_instance_key'): </span><span class="cx"> if not self.uow.has_key(o._instance_key): </span><del>- raise InvalidRequestError("Instance '%s' is not bound to this Session" % repr(o)) </del><ins>+ raise InvalidRequestError("Instance '%s' is not bound to this Session; use session.import(instance)" % repr(o)) </ins><span class="cx"> else: </span><del>- self.register_new(o) </del><ins>+ entity_name = kwargs.get('entity_name', None) + if entity_name is not None: + m = class_mapper(o.__class__, entity_name=entity_name) + m._assign_entity_name(o) + self._register_new(o) </ins><span class="cx"> </span><del>- def register_new(self, *obj): - """registers the given objects as "new" and binds them to this session.""" - for o in obj: - self._bind_to(o) - self.uow.register_new(o) - </del><ins>+ def _register_new(self, obj): + self._bind_to(obj) + self.uow.register_new(obj) + def _register_dirty(self, obj): + self._bind_to(obj) + self.uow.register_dirty(obj) + def _register_clean(self, obj): + self._bind_to(obj) + self.uow.register_clean(obj) + def _register_deleted(self, obj): + self._bind_to(obj) + self.uow.register_deleted(obj) </ins><span class="cx"> def _bind_to(self, obj): </span><span class="cx"> """given an object, binds it to this session. changes on the object will affect </span><span class="cx"> the currently scoped UnitOfWork maintained by this session.""" </span><span class="cx"> obj._sa_session_id = self.hash_key </span><del>- - def __getattr__(self, key): - """proxy other methods to our underlying UnitOfWork""" - return getattr(self.uow, key) - </del><ins>+ def _is_bound(self, obj): + return getattr(obj, '_sa_session_id', None) == self.hash_key + + def _get(self, key): + return self.uow._get(key) + def has_key(self, key): + return self.uow.has_key(key) + def is_expired(self, instance, **kwargs): + return self.uow.is_expired(instance, **kwargs) + + dirty = property(lambda s:s.uow.dirty) + deleted = property(lambda s:s.uow.deleted) + new = property(lambda s:s.uow.new) + modified_lists = property(lambda s:s.uow.modified_lists) + identity_map = property(lambda s:s.uow.identity_map) + </ins><span class="cx"> def clear(self): </span><ins>+ """removes all object instances from this Session. this is equivalent to calling expunge() for all + objects in this Session.""" </ins><span class="cx"> self.uow = unitofwork.UnitOfWork() </span><span class="cx"> </span><del>- def delete(self, *obj): - """registers the given objects as to be deleted upon the next commit""" </del><ins>+ def delete(self, *obj, **kwargs): + """registers the given objects to be deleted upon the next flush(). If the given objects are not part of this + Session, they will be imported. the objects are expected to either have an _instance_key + attribute or have all of their primary key attributes populated. + + the keyword argument 'entity_name' can also be provided which will be used by the import.""" </ins><span class="cx"> for o in obj: </span><ins>+ if not self._is_bound(o): + o = self.import_(o, **kwargs) </ins><span class="cx"> self.uow.register_deleted(o) </span><span class="cx"> </span><del>- def import_instance(self, instance): - """places the given instance in the current thread's unit of work context, - either in the current IdentityMap or marked as "new". Returns either the object - or the current corresponding version in the Identity Map. </del><ins>+ def import_(self, instance, entity_name=None): + """given an instance that represents a saved item, adds it to this session. + the return value is either the given instance, or if an instance corresponding to the + identity of the given instance already exists within this session, then that instance is returned; + the returned instance should always be used following this method. + + if the given instance does not have an _instance_key and also does not have all + of its primary key attributes populated, an exception is raised. similarly, if no + mapper can be located for the given instance, an exception is raised. </ins><span class="cx"> </span><span class="cx"> this method should be used for any object instance that is coming from a serialized </span><del>- storage, from another thread (assuming the regular threaded unit of work model), or any - case where the instance was loaded/created corresponding to a different base unitofwork - than the current one.""" </del><ins>+ storage, or was loaded by a Session other than this one. + + the keyword parameter entity_name is optional and is used to locate a Mapper for this + class which also specifies the given entity name. + """ </ins><span class="cx"> if instance is None: </span><span class="cx"> return None </span><span class="cx"> key = getattr(instance, '_instance_key', None) </span><del>- mapper = object_mapper(instance) </del><ins>+ mapper = object_mapper(instance, raiseerror=False) + if mapper is None: + mapper = class_mapper(instance, entity_name=entity_name) + if key is None: + ident = mapper.identity(instance) + for k in ident: + if k is None: + raise InvalidRequestError("Instance '%s' does not have a full set of identity values, and does not represent a saved entity in the database. Use the add() method to add unsaved instances to this Session." % str(instance)) + key = mapper.identity_key(*ident) </ins><span class="cx"> u = self.uow </span><del>- if key is not None: - if u.identity_map.has_key(key): - return u.identity_map[key] - else: - instance._instance_key = key - u.identity_map[key] = instance - self._bind_to(instance) </del><ins>+ if u.identity_map.has_key(key): + return u.identity_map[key] </ins><span class="cx"> else: </span><del>- u.register_new(instance) - return instance </del><ins>+ instance._instance_key = key + u.identity_map[key] = instance + self._bind_to(instance) + return instance + + def import_instance(self, *args, **kwargs): + """deprecated; a synynom for import()""" + return self.import_(*args, **kwargs) </ins><span class="cx"> </span><del>- </del><span class="cx"> def get_id_key(ident, class_, entity_name=None): </span><span class="cx"> return Session.get_id_key(ident, class_, entity_name) </span><span class="cx"> </span><span class="cx"> def get_row_key(row, class_, primary_key, entity_name=None): </span><span class="cx"> return Session.get_row_key(row, class_, primary_key, entity_name) </span><span class="cx"> </span><del>- </del><span class="cx"> def mapper(*args, **params): </span><span class="cx"> return sqlalchemy.mapping.mapper(*args, **params) </span><span class="cx"> </span><span class="cx"> def object_mapper(obj): </span><span class="cx"> return sqlalchemy.mapping.object_mapper(obj) </span><span class="cx"> </span><del>-def class_mapper(class_): - return sqlalchemy.mapping.class_mapper(class_) </del><ins>+def class_mapper(class_, **kwargs): + return sqlalchemy.mapping.class_mapper(class_, **kwargs) </ins><span class="cx"> </span><ins>+# this is the AttributeManager instance used to provide attribute behavior on objects. +# to all the "global variable police" out there: its a stateless object. </ins><span class="cx"> global_attributes = unitofwork.global_attributes </span><span class="cx"> </span><del>-_sessions = weakref.WeakValueDictionary() # all referenced sessions (including user-created) </del><ins>+# this dictionary maps the hash key of a Session to the Session itself, and +# acts as a Registry with which to locate Sessions. this is to enable +# object instances to be associated with Sessions without having to attach the +# actual Session object directly to the object instance. +_sessions = weakref.WeakValueDictionary() </ins><span class="cx"> </span><span class="cx"> def get_session(obj=None, raiseerror=True): </span><ins>+ """returns the Session corrseponding to the given object instance. By default, if the object is not bound + to any Session, then an error is raised (or None is returned if raiseerror=False). This behavior can be changed + using the "threadlocal" mod, which will add an additional step to return a Session that is bound to the current + thread.""" </ins><span class="cx"> if obj is None: </span><span class="cx"> if raiseerror: </span><del>- raise InvalidRequestError("Thread-local Sessions are disabled by default. Use install_mods('threadlocal') to enable.") </del><ins>+ raise InvalidRequestError("Thread-local Sessions are disabled by default. Use 'import sqlalchemy.mods.threadlocal' to enable.") </ins><span class="cx"> else: </span><span class="cx"> return None </span><span class="cx"> # does it have a hash key ? </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemymappingunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/mapping/unitofwork.py (1303 => 1304)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/mapping/unitofwork.py 2006-04-20 02:30:21 UTC (rev 1303) +++ sqlalchemy/branches/schema/lib/sqlalchemy/mapping/unitofwork.py 2006-04-20 18:04:16 UTC (rev 1304) </span><span class="lines">@@ -53,7 +53,7 @@ </span><span class="cx"> del sess.deleted[item] </span><span class="cx"> sess.modified_lists.append(self) </span><span class="cx"> if self.deleteremoved and isdelete: </span><del>- sess.register_deleted(item) </del><ins>+ sess._register_deleted(item) </ins><span class="cx"> def append(self, item, _mapper_nohistory = False): </span><span class="cx"> if _mapper_nohistory: </span><span class="cx"> self.append_nohistory(item) </span><span class="lines">@@ -69,9 +69,9 @@ </span><span class="cx"> sess = get_session(obj, raiseerror=False) </span><span class="cx"> if sess is not None: </span><span class="cx"> if hasattr(obj, '_instance_key'): </span><del>- sess.register_dirty(obj) </del><ins>+ sess._register_dirty(obj) </ins><span class="cx"> else: </span><del>- sess.register_new(obj) </del><ins>+ sess._register_new(obj) </ins><span class="cx"> </span><span class="cx"> def create_prop(self, class_, key, uselist, callable_, **kwargs): </span><span class="cx"> return UOWProperty(class_, self, key, uselist, callable_, **kwargs) </span></span></pre></div> <a id="sqlalchemybranchesschematestobjectstorepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/objectstore.py (1303 => 1304)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/objectstore.py 2006-04-20 02:30:21 UTC (rev 1303) +++ sqlalchemy/branches/schema/test/objectstore.py 2006-04-20 18:04:16 UTC (rev 1304) </span><span class="lines">@@ -43,7 +43,7 @@ </span><span class="cx"> self.assert_result([u], data[0], *data[1:]) </span><span class="cx"> </span><span class="cx"> self.echo(repr(u.addresses)) </span><del>- objectstore.get_session().rollback_object(u) </del><ins>+ objectstore.get_session().uow.rollback_object(u) </ins><span class="cx"> data = [User, </span><span class="cx"> {'user_name' : None, </span><span class="cx"> 'addresses' : (Address, []) </span><span class="lines">@@ -62,7 +62,7 @@ </span><span class="cx"> </span><span class="cx"> u = User() </span><span class="cx"> a = Address() </span><del>- s.register_new(u, a) </del><ins>+ s.add(u, a) </ins><span class="cx"> a.user = u </span><span class="cx"> #print repr(a.__class__._attribute_manager.get_history(a, 'user').added_items()) </span><span class="cx"> #print repr(u.addresses.added_items()) </span><span class="lines">@@ -421,7 +421,7 @@ </span><span class="cx"> u2 = User() </span><span class="cx"> u2.user_name = 'savetester2' </span><span class="cx"> </span><del>- objectstore.get_session().register_new(u) </del><ins>+ objectstore.get_session().add(u) </ins><span class="cx"> </span><span class="cx"> objectstore.get_session().flush(u) </span><span class="cx"> objectstore.get_session().flush() </span><span class="lines">@@ -549,7 +549,7 @@ </span><span class="cx"> u.address.email_address = 'myo...@fo...' </span><span class="cx"> objectstore.get_session().flush() </span><span class="cx"> self.echo("\n\n\n") </span><del>- objectstore.get_session().register_deleted(u) </del><ins>+ objectstore.get_session().delete(u) </ins><span class="cx"> objectstore.get_session().flush() </span><span class="cx"> self.assert_(a.address_id is not None and a.user_id is None and not objectstore.get_session().identity_map.has_key(u._instance_key) and objectstore.get_session().identity_map.has_key(a._instance_key)) </span><span class="cx"> </span><span class="lines">@@ -613,8 +613,7 @@ </span><span class="cx"> self.assert_result(l, data[0], *data[1:]) </span><span class="cx"> </span><span class="cx"> self.echo("\n\n\n") </span><del>- objectstore.get_session().register_deleted(l[0]) - objectstore.get_session().register_deleted(l[2]) </del><ins>+ objectstore.get_session().delete(l[0], l[2]) </ins><span class="cx"> objectstore.flush() </span><span class="cx"> return </span><span class="cx"> res = self.capture_exec(db, lambda: objectstore.get_session().flush()) </span></span></pre> </div> </div> </body> </html> |