[Sqlalchemy-commits] [1326] sqlalchemy/branches/schema/test: session methods become single argument,
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-23 22:19:18
|
<!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>[1326] sqlalchemy/branches/schema/test: session methods become single argument, less ambiguous</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1326</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-04-23 17:19:06 -0500 (Sun, 23 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>session methods become single argument, less ambiguous</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesschemalibsqlalchemymodsthreadlocalpy">sqlalchemy/branches/schema/lib/sqlalchemy/mods/threadlocal.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemyormmapperpy">sqlalchemy/branches/schema/lib/sqlalchemy/orm/mapper.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="#sqlalchemybranchesschematestobjectstorepy">sqlalchemy/branches/schema/test/objectstore.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesschemalibsqlalchemymodsthreadlocalpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/mods/threadlocal.py (1325 => 1326)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/mods/threadlocal.py 2006-04-23 21:41:36 UTC (rev 1325) +++ sqlalchemy/branches/schema/lib/sqlalchemy/mods/threadlocal.py 2006-04-23 22:19:06 UTC (rev 1326) </span><span class="lines">@@ -22,13 +22,13 @@ </span><span class="cx"> get_session = session.get_session </span><span class="cx"> </span><span class="cx"> class Objectstore(object): </span><del>- def begin(self, *obj): - return get_session().begin(*obj) - def commit(self, *obj): - return get_session().commit(*obj) </del><ins>+ def begin(self, obj): + return get_session().begin(obj) + def commit(self, obj): + return get_session().commit(obj) </ins><span class="cx"> def get_session(self, obj=None): </span><span class="cx"> return get_session(obj=obj) </span><del>- def flush(self, *obj): </del><ins>+ def flush(self, obj): </ins><span class="cx"> """flushes the current UnitOfWork transaction. if a transaction was begun </span><span class="cx"> via begin(), flushes only those objects that were created, modified, or deleted </span><span class="cx"> since that begin statement. otherwise flushes all objects that have been </span><span class="lines">@@ -36,7 +36,7 @@ </span><span class="cx"> </span><span class="cx"> if individual objects are submitted, then only those objects are committed, and the </span><span class="cx"> begin/commit cycle is not affected.""" </span><del>- get_session().flush(*obj) </del><ins>+ get_session().flush(obj) </ins><span class="cx"> </span><span class="cx"> def clear(self): </span><span class="cx"> """removes all current UnitOfWorks and IdentityMaps for this thread and </span><span class="lines">@@ -44,22 +44,22 @@ </span><span class="cx"> current mapped object instances, as they are no longer in the Identity Map.""" </span><span class="cx"> get_session().clear() </span><span class="cx"> </span><del>- def refresh(self, *obj): </del><ins>+ def refresh(self, obj): </ins><span class="cx"> """reloads the state of this object from the database, and cancels any in-memory </span><span class="cx"> changes.""" </span><del>- get_session().refresh(*obj) </del><ins>+ get_session().refresh(obj) </ins><span class="cx"> </span><del>- def expire(self, *obj): </del><ins>+ def expire(self, obj): </ins><span class="cx"> """invalidates the data in the given objects and sets them to refresh themselves </span><span class="cx"> the next time they are requested.""" </span><del>- get_session().expire(*obj) </del><ins>+ get_session().expire(obj) </ins><span class="cx"> </span><del>- def expunge(self, *obj): - get_session().expunge(*obj) </del><ins>+ def expunge(self, obj): + get_session().expunge(obj) </ins><span class="cx"> </span><del>- def delete(self, *obj): </del><ins>+ def delete(self, obj): </ins><span class="cx"> """registers the given objects as to be deleted upon the next commit""" </span><del>- s = get_session().delete(*obj) </del><ins>+ s = get_session().delete(obj) </ins><span class="cx"> </span><span class="cx"> def has_key(self, key): </span><span class="cx"> """returns True if the current thread-local IdentityMap contains the given instance key""" </span><span class="lines">@@ -91,7 +91,7 @@ </span><span class="cx"> m = mapper(class_, *args, **params) </span><span class="cx"> class_.mapper = m </span><span class="cx"> class_.get = m.get </span><del>- class_.select = m.select </del><ins>+ class_.select = m.selectobj </ins><span class="cx"> class_.select_by = m.select_by </span><span class="cx"> class_.selectone = m.selectone </span><span class="cx"> class_.get_by = m.get_by </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/orm/mapper.py (1325 => 1326)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/orm/mapper.py 2006-04-23 21:41:36 UTC (rev 1325) +++ sqlalchemy/branches/schema/lib/sqlalchemy/orm/mapper.py 2006-04-23 22:19:06 UTC (rev 1326) </span><span class="lines">@@ -978,11 +978,11 @@ </span><span class="cx"> else: </span><span class="cx"> return repr(obj) </span><span class="cx"> </span><del>-def object_mapper(object, raiseerror=True): </del><ins>+def object_mapper(object, raiseerror=True, entity_name=None): </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><del>- return mapper_registry[ClassKey(object.__class__, getattr(object, '_entity_name', None))] </del><ins>+ return mapper_registry[ClassKey(object.__class__, getattr(object, '_entity_name', entity_name))] </ins><span class="cx"> except KeyError: </span><span class="cx"> if raiseerror: </span><span class="cx"> raise InvalidRequestError("Class '%s' entity name '%s' has no mapper associated with it" % (object.__class__.__name__, getattr(object, '_entity_name', None))) </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyormsessionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/orm/session.py (1325 => 1326)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/orm/session.py 2006-04-23 21:41:36 UTC (rev 1325) +++ sqlalchemy/branches/schema/lib/sqlalchemy/orm/session.py 2006-04-23 22:19:06 UTC (rev 1326) </span><span class="lines">@@ -204,61 +204,87 @@ </span><span class="cx"> """deprecated""" </span><span class="cx"> raise InvalidRequestError("Session.commit() is deprecated. use install_mod('legacy_session') to enable the old behavior") </span><span class="cx"> </span><del>- def flush(self, *obj): - """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.""" - self.uow.flush(self, *obj) - </del><ins>+ def flush(self, objects=None): + """flushes all the object modifications present in this session to the database. 'objects' + is a list or tuple of objects specifically to be flushed.""" + self.uow.flush(self, objects) + + def get(self, class_, *ident): + """given a class and a primary key identifier, loads the corresponding object.""" + return self.query(class_).get(*ident) + </ins><span class="cx"> def load(self, class_, *ident): </span><span class="cx"> """given a class and a primary key identifier, loads the corresponding object.""" </span><span class="cx"> return self.query(class_).get(*ident) </span><span class="cx"> </span><del>- def refresh(self, *obj): - """reloads the attributes for the given objects from the database, clears </del><ins>+ def refresh(self, object): + """reloads the attributes for the given object from the database, clears </ins><span class="cx"> any changes made.""" </span><del>- for o in obj: - self.uow.refresh(o) </del><ins>+ self.uow.refresh(object) </ins><span class="cx"> </span><del>- def expire(self, *obj): - """invalidates the data in the given objects and sets them to refresh themselves </del><ins>+ def expire(self, object): + """invalidates the data in the given object and sets them to refresh themselves </ins><span class="cx"> the next time they are requested.""" </span><del>- for o in obj: - self.uow.expire(o) </del><ins>+ self.uow.expire(object) </ins><span class="cx"> </span><del>- def expunge(self, *obj): - """removes the given objects from this Session. this will free all internal references to the objects.""" - for o in obj: - self.uow.expunge(o) </del><ins>+ def expunge(self, object): + """removes the given object from this Session. this will free all internal references to the object.""" + self.uow.expunge(object) </ins><span class="cx"> </span><del>- def save(self, *obj, **kwargs): - """adds unsaved objects to this Session. </del><ins>+ def save(self, object, entity_name=None): + """adds an unsaved object to this Session. </ins><span class="cx"> </span><span class="cx"> The 'entity_name' keyword argument can also be given which will be assigned </span><span class="cx"> to the instances if given. </span><span class="cx"> """ </span><del>- for o in obj: - for c in object_mapper(o, **kwargs).cascade_iterator('save-update', o): - if c is o: - self._save_impl(c, **kwargs) - else: - self.save_or_update(c, **kwargs) </del><ins>+ for c in object_mapper(object, entity_name=entity_name).cascade_iterator('save-update', object): + if c is object: + self._save_impl(c, entity_name=entity_name) + else: + self.save_or_update(c, entity_name=entity_name) </ins><span class="cx"> </span><del>- def update(self, *obj, **kwargs): - for o in obj: - for c in object_mapper(o, **kwargs).cascade_iterator('save-update', o): - if c is o: - self._update_impl(c, **kwargs) - else: - self.save_or_update(c, **kwargs) </del><ins>+ def update(self, object, entity_name=None): + for c in object_mapper(object, entity_name=entity_name).cascade_iterator('save-update', object): + if c is o: + self._update_impl(c, entity_name=entity_name) + else: + self.save_or_update(c, entity_name=entity_name) </ins><span class="cx"> </span><del>- def save_or_update(self, *obj, **kwargs): - for o in obj: - for c in object_mapper(o, *kwargs).cascade_iterator('save-update', o): - key = getattr(o, '_instance_key', None) - if key is None: - self._save_impl(c, **kwargs) - else: - self._update_impl(c, **kwargs) </del><ins>+ def save_or_update(self, object, entity_name=None): + for c in object_mapper(object, entity_name=entity_name).cascade_iterator('save-update', object): + key = getattr(object, '_instance_key', None) + if key is None: + self._save_impl(c, entity_name=entity_name) + else: + self._update_impl(c, entity_name=entity_name) + + def clear(self): + """removes all object instances from this Session. this is equivalent to calling expunge() for all + objects in this Session.""" + self.uow = unitofwork.UnitOfWork() + + def delete(self, object, entity_name=None): + for c in object_mapper(object, entity_name=entity_name).cascade_iterator('delete', object): + self.uow.register_deleted(c) + + def merge(self, object, entity_name=None): + for obj in object_mapper(object, entity_name=entity_name).cascade_iterator('merge', object): + key = getattr(obj, '_instance_key', None) + if key is None: + mapper = object_mapper(object, entity_name=entity_name) + ident = mapper.identity(object) + 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(obj)) + key = mapper.identity_key(*ident) + u = self.uow + if u.identity_map.has_key(key): + return u.identity_map[key] + else: + obj._instance_key = key + u.identity_map[key] = obj + self._bind_to(instance) + 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 class="lines">@@ -293,9 +319,9 @@ </span><span class="cx"> def _register_deleted(self, obj): </span><span class="cx"> self._bind_to(obj) </span><span class="cx"> self.uow.register_deleted(obj) </span><ins>+ </ins><span class="cx"> def _bind_to(self, obj): </span><del>- """given an object, binds it to this session. changes on the object will affect - the currently scoped UnitOfWork maintained by this session.""" </del><ins>+ """given an object, binds it to this session. """ </ins><span class="cx"> if getattr(obj, '_sa_session_id', None) != self.hash_key: </span><span class="cx"> old = getattr(obj, '_sa_session_id', None) </span><span class="cx"> # remove from old session. we do this gingerly since _sessions is a WeakValueDict </span><span class="lines">@@ -307,6 +333,9 @@ </span><span class="cx"> sess = None </span><span class="cx"> if sess is not None: </span><span class="cx"> sess.expunge(old) </span><ins>+ key = getattr(obj, '_instance_key', None) + if key is not None: + self.identity_map[key] = obj </ins><span class="cx"> obj._sa_session_id = self.hash_key </span><span class="cx"> def _is_bound(self, obj): </span><span class="cx"> return getattr(obj, '_sa_session_id', None) == self.hash_key </span><span class="lines">@@ -320,71 +349,14 @@ </span><span class="cx"> def is_expired(self, instance, **kwargs): </span><span class="cx"> return self.uow.is_expired(instance, **kwargs) </span><span class="cx"> </span><del>- dirty = property(lambda s:s.uow.dirty) - deleted = property(lambda s:s.uow.deleted) - new = property(lambda s:s.uow.new) - identity_map = property(lambda s:s.uow.identity_map) </del><ins>+ dirty = property(lambda s:s.uow.dirty, doc="a Set of all objects marked as 'dirty' within this Session") + deleted = property(lambda s:s.uow.deleted, doc="a Set of all objects marked as 'deleted' within this Session") + new = property(lambda s:s.uow.new, doc="a Set of all objects marked as 'new' within this Session.") + identity_map = property(lambda s:s.uow.identity_map, doc="a WeakValueDictionary consisting of all objects within this Session keyed to their _instance_key value.") </ins><span class="cx"> </span><del>- def clear(self): - """removes all object instances from this Session. this is equivalent to calling expunge() for all - objects in this Session.""" - self.uow = unitofwork.UnitOfWork() - - 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.""" - for o in obj: - for c in object_mapper(o, **kwargs).cascade_iterator('delete', o): - if not self._is_bound(c): - c = self.import_(c, **kwargs) - self.uow.register_deleted(c) - - - def merge(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. - - this method should be used for any object instance that is coming from a serialized - 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. - """ - if instance is None: - return None - key = getattr(object, '_instance_key', None) - if key is None: - mapper = object_mapper(object, raiseerror=False) - if mapper is None: - mapper = class_mapper(object, entity_name=entity_name) - ident = mapper.identity(object) - for k in ident: - if k is None: - if raiseerror: - 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(object)) - else: - return None - key = mapper.identity_key(*ident) - u = self.uow - 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) - return instance </del><span class="cx"> </span><span class="cx"> def import_instance(self, *args, **kwargs): </span><del>- """deprecated; a synynom for import()""" </del><ins>+ """deprecated; a synynom for merge()""" </ins><span class="cx"> return self.merge(*args, **kwargs) </span><span class="cx"> </span><span class="cx"> def get_id_key(ident, class_, entity_name=None): </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/orm/unitofwork.py (1325 => 1326)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/orm/unitofwork.py 2006-04-23 21:41:36 UTC (rev 1325) +++ sqlalchemy/branches/schema/lib/sqlalchemy/orm/unitofwork.py 2006-04-23 22:19:06 UTC (rev 1326) </span><span class="lines">@@ -214,10 +214,10 @@ </span><span class="cx"> except KeyError: </span><span class="cx"> pass </span><span class="cx"> </span><del>- def flush(self, session, *objects): </del><ins>+ def flush(self, session, objects=None): </ins><span class="cx"> flush_context = UOWTransaction(self, session) </span><span class="cx"> </span><del>- if len(objects): </del><ins>+ if objects is not None: </ins><span class="cx"> objset = util.HashSet(iter=objects) </span><span class="cx"> else: </span><span class="cx"> objset = None </span></span></pre></div> <a id="sqlalchemybranchesschematestobjectstorepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/objectstore.py (1325 => 1326)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/objectstore.py 2006-04-23 21:41:36 UTC (rev 1325) +++ sqlalchemy/branches/schema/test/objectstore.py 2006-04-23 22:19:06 UTC (rev 1326) </span><span class="lines">@@ -62,7 +62,8 @@ </span><span class="cx"> </span><span class="cx"> u = User() </span><span class="cx"> a = Address() </span><del>- s.save(u, a) </del><ins>+ s.save(u) + s.save(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">@@ -268,10 +269,10 @@ </span><span class="cx"> a.bs.append(b2) </span><span class="cx"> </span><span class="cx"> # inserts both A and Bs </span><del>- objectstore.flush(a) </del><ins>+ objectstore.flush([a]) </ins><span class="cx"> </span><span class="cx"> objectstore.delete(a) </span><del>- objectstore.flush(a) </del><ins>+ objectstore.flush([a]) </ins><span class="cx"> </span><span class="cx"> assert b_table.count().scalar() == 0 </span><span class="cx"> </span><span class="lines">@@ -421,7 +422,7 @@ </span><span class="cx"> </span><span class="cx"> objectstore.get_session().save(u) </span><span class="cx"> </span><del>- objectstore.get_session().flush(u) </del><ins>+ objectstore.get_session().flush([u]) </ins><span class="cx"> objectstore.get_session().flush() </span><span class="cx"> </span><span class="cx"> # assert the first one retreives the same from the identity map </span></span></pre> </div> </div> </body> </html> |