def save_or_update(self, object, entity_name=None): """Save or update the given object into this Session. The presence of an `_instance_key` attribute on the instance determines whether to ``save()`` or ``update()`` the instance. """ self._save_or_update_impl(object, entity_name=entity_name) _object_mapper(object).cascade_callable('save-update', object, lambda c, e:self._save_or_update_impl(c, e), halt_on=lambda c:c in self)
def save_or_update(self, object, entity_name=None): """Save or update the given object into this ``Session``. The presence of an `_instance_key` attribute on the instance determines whether to ``save()`` or ``update()`` the instance. """ self._save_or_update_impl(object, entity_name=entity_name) _object_mapper(object).cascade_callable( 'save-update', object, lambda c, e: self._save_or_update_impl(c, e), halt_on=lambda c: c in self)
def save(self, object, entity_name=None): """Add a transient (unsaved) instance to this Session. This operation cascades the `save_or_update` method to associated instances if the relation is mapped with ``cascade="save-update"``. The `entity_name` keyword argument will further qualify the specific Mapper used to handle this instance. """ self._save_impl(object, entity_name=entity_name) _object_mapper(object).cascade_callable('save-update', object, lambda c, e:self._save_or_update_impl(c, e), halt_on=lambda c:c in self)
def update(self, object, entity_name=None): """Bring the given detached (saved) instance into this Session. If there is a persistent instance with the same identifier already associated with this Session, an exception is thrown. This operation cascades the `save_or_update` method to associated instances if the relation is mapped with ``cascade="save-update"``. """ self._update_impl(object, entity_name=entity_name) _object_mapper(object).cascade_callable('save-update', object, lambda c, e:self._save_or_update_impl(c, e), halt_on=lambda c:c in self)
def refresh(self, instance, attribute_names=None): """Refresh the attributes on the given instance. When called, a query will be issued to the database which will refresh all attributes with their current value. Lazy-loaded relational attributes will remain lazily loaded, so that the instance-wide refresh operation will be followed immediately by the lazy load of that attribute. Eagerly-loaded relational attributes will eagerly load within the single refresh operation. The ``attribute_names`` argument is an iterable collection of attribute names indicating a subset of attributes to be refreshed. """ self._validate_persistent(instance) if ( self.query(_object_mapper(instance))._get( instance._instance_key, refresh_instance=instance._state, only_load_props=attribute_names ) is None ): raise exceptions.InvalidRequestError("Could not refresh instance '%s'" % mapperutil.instance_str(instance))
def merge(self, object, entity_name=None, _recursive=None): """Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with ``cascade="merge"``. """ if _recursive is None: _recursive = util.Set() mapper = _object_mapper(object) key = getattr(object, '_instance_key', None) if key is None: merged = mapper._create_instance(self) else: if key in self.identity_map: merged = self.identity_map[key] else: merged = self.get(mapper.class_, key[1]) for prop in mapper.props.values(): prop.merge(self, object, merged, _recursive) if key is None: self.save(merged) return merged
def identity_key(cls, *args, **kwargs): """Get an identity key. Valid call signatures: * ``identity_key(class, ident, entity_name=None)`` class mapped class (must be a positional argument) ident primary key, if the key is composite this is a tuple entity_name optional entity name * ``identity_key(instance=instance)`` instance object instance (must be given as a keyword arg) * ``identity_key(class, row=row, entity_name=None)`` class mapped class (must be a positional argument) row result proxy row (must be given as a keyword arg) entity_name optional entity name (must be given as a keyword arg) """ if args: if len(args) == 1: class_ = args[0] try: row = kwargs.pop("row") except KeyError: ident = kwargs.pop("ident") entity_name = kwargs.pop("entity_name", None) elif len(args) == 2: class_, ident = args entity_name = kwargs.pop("entity_name", None) elif len(args) == 3: class_, ident, entity_name = args else: raise exceptions.ArgumentError("expected up to three " "positional arguments, got %s" % len(args)) if kwargs: raise exceptions.ArgumentError("unknown keyword arguments: %s" % ", ".join(kwargs.keys())) mapper = _class_mapper(class_, entity_name=entity_name) if "ident" in locals(): return mapper.identity_key_from_primary_key(ident) return mapper.identity_key_from_row(row) instance = kwargs.pop("instance") if kwargs: raise exceptions.ArgumentError("unknown keyword arguments: %s" % ", ".join(kwargs.keys())) mapper = _object_mapper(instance) return mapper.identity_key_from_instance(instance)
def identity_key(self, *args, **kwargs): """Get an identity key. Valid call signatures: identity_key(class\_, ident, entity_name=None) class\_ mapped class (must be a positional argument) ident primary key, if the key is composite this is a tuple entity_name optional entity name identity_key(instance=instance) instance object instance (must be given as a keyword arg) identity_key(class\_, row=row, entity_name=None) class\_ mapped class (must be a positional argument) row result proxy row (must be given as a keyword arg) entity_name optional entity name (must be given as a keyword arg) """ if args: if len(args) == 1: class_ = args[0] try: row = kwargs.pop("row") except KeyError: ident = kwargs.pop("ident") entity_name = kwargs.pop("entity_name", None) elif len(args) == 2: class_, ident = args entity_name = kwargs.pop("entity_name", None) elif len(args) == 3: class_, ident, entity_name = args else: raise exceptions.ArgumentError("expected up to three " "positional arguments, got %s" % len(args)) if kwargs: raise exceptions.ArgumentError( "unknown keyword arguments: %s" % ", ".join(kwargs.keys())) mapper = _class_mapper(class_, entity_name=entity_name) if "ident" in locals(): return mapper.identity_key_from_primary_key(ident) return mapper.identity_key_from_row(row) instance = kwargs.pop("instance") if kwargs: raise exceptions.ArgumentError("unknown keyword arguments: %s" % ", ".join(kwargs.keys())) mapper = _object_mapper(instance) return mapper.identity_key_from_instance(instance)
def save(self, object, entity_name=None): """Add a transient (unsaved) instance to this ``Session``. This operation cascades the `save_or_update` method to associated instances if the relation is mapped with ``cascade="save-update"``. The `entity_name` keyword argument will further qualify the specific ``Mapper`` used to handle this instance. """ self._save_impl(object, entity_name=entity_name) _object_mapper(object).cascade_callable( 'save-update', object, lambda c, e: self._save_or_update_impl(c, e), halt_on=lambda c: c in self)
def delete(self, object): """Mark the given instance as deleted. The delete operation occurs upon ``flush()``. """ for c in [object] + list(_object_mapper(object).cascade_iterator('delete', object)): self.uow.register_deleted(c)
def merge(self, instance, entity_name=None, dont_load=False, _recursive=None): """Copy the state of the given `instance` onto the persistent instance with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with ``cascade="merge"``. """ if _recursive is None: _recursive = {} # TODO: this should be an IdentityDict for instances, but will need a separate # dict for PropertyLoader tuples if entity_name is not None: mapper = _class_mapper(instance.__class__, entity_name=entity_name) else: mapper = _object_mapper(instance) if instance in _recursive: return _recursive[instance] key = getattr(instance, '_instance_key', None) if key is None: if dont_load: raise exceptions.InvalidRequestError("merge() with dont_load=True option does not support objects transient (i.e. unpersisted) objects. flush() all changes on mapped instances before merging with dont_load=True.") key = mapper.identity_key_from_instance(instance) merged = None if key: if key in self.identity_map: merged = self.identity_map[key] elif dont_load: if instance._state.modified: raise exceptions.InvalidRequestError("merge() with dont_load=True option does not support objects marked as 'dirty'. flush() all changes on mapped instances before merging with dont_load=True.") merged = attributes.new_instance(mapper.class_) merged._instance_key = key merged._entity_name = entity_name self._update_impl(merged, entity_name=mapper.entity_name) else: merged = self.get(mapper.class_, key[1]) if merged is None: merged = attributes.new_instance(mapper.class_) self.save(merged, entity_name=mapper.entity_name) _recursive[instance] = merged for prop in mapper.iterate_properties: prop.merge(self, instance, merged, dont_load, _recursive) if dont_load: merged._state.commit_all() # remove any history return merged
def expire(self, obj): """mark the given object as expired. this will add an instrumentation to all mapped attributes on the instance such that when an attribute is next accessed, the session will reload all attributes on the instance from the database. """ for c in [obj] + list(_object_mapper(obj).cascade_iterator('refresh-expire', obj)): self._expire_impl(c)
def update(self, object, entity_name=None): """Bring the given detached (saved) instance into this ``Session``. If there is a persistent instance with the same identifier already associated with this ``Session``, an exception is thrown. This operation cascades the `save_or_update` method to associated instances if the relation is mapped with ``cascade="save-update"``. """ self._update_impl(object, entity_name=entity_name) _object_mapper(object).cascade_callable( 'save-update', object, lambda c, e: self._save_or_update_impl(c, e), halt_on=lambda c: c in self)
def delete(self, object): """Mark the given instance as deleted. The delete operation occurs upon ``flush()``. """ for c in [object] + list( _object_mapper(object).cascade_iterator('delete', object)): self.uow.register_deleted(c)
def expire(self, obj): """mark the given object as expired. this will add an instrumentation to all mapped attributes on the instance such that when an attribute is next accessed, the session will reload all attributes on the instance from the database. """ for c in [obj] + list( _object_mapper(obj).cascade_iterator('refresh-expire', obj)): self._expire_impl(c)
def expunge(self, object): """Remove the given object from this Session. This will free all internal references to the object. Cascading will be applied according to the *expunge* cascade rule. """ for c in [object] + list(_object_mapper(object).cascade_iterator('expunge', object)): self.uow._remove_deleted(c) self._unattach(c)
def expunge(self, object): """Remove the given `object` from this ``Session``. This will free all internal references to the object. Cascading will be applied according to the *expunge* cascade rule. """ self._validate_persistent(object) for c in [object] + list(_object_mapper(object).cascade_iterator('expunge', object)): if c in self: self.uow._remove_deleted(c) self._unattach(c)
def expunge(self, object): """Remove the given object from this Session. This will free all internal references to the object. Cascading will be applied according to the *expunge* cascade rule. """ for c in [object] + list( _object_mapper(object).cascade_iterator('expunge', object)): self.uow._remove_deleted(c) self._unattach(c)
def expunge(self, object): """Remove the given `object` from this ``Session``. This will free all internal references to the object. Cascading will be applied according to the *expunge* cascade rule. """ self._validate_persistent(object) for c in [object] + list( _object_mapper(object).cascade_iterator('expunge', object)): if c in self: self.uow._remove_deleted(c) self._unattach(c)
def merge(self, object, entity_name=None, _recursive=None): """Copy the state of the given `object` onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with ``cascade="merge"``. """ if _recursive is None: _recursive = util.Set() if entity_name is not None: mapper = _class_mapper(object.__class__, entity_name=entity_name) else: mapper = _object_mapper(object) if mapper in _recursive or object in _recursive: return None _recursive.add(mapper) _recursive.add(object) try: key = getattr(object, '_instance_key', None) if key is None: merged = attribute_manager.new_instance(mapper.class_) else: if key in self.identity_map: merged = self.identity_map[key] else: merged = self.get(mapper.class_, key[1]) if merged is None: raise exceptions.AssertionError( "Instance %s has an instance key but is not persisted" % mapperutil.instance_str(object)) for prop in mapper.iterate_properties: prop.merge(self, object, merged, _recursive) if key is None: self.save(merged, entity_name=mapper.entity_name) return merged finally: _recursive.remove(mapper)
def merge(self, object, entity_name=None, _recursive=None): """Copy the state of the given `object` onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with ``cascade="merge"``. """ if _recursive is None: _recursive = util.Set() if entity_name is not None: mapper = _class_mapper(object.__class__, entity_name=entity_name) else: mapper = _object_mapper(object) if mapper in _recursive or object in _recursive: return None _recursive.add(mapper) _recursive.add(object) try: key = getattr(object, '_instance_key', None) if key is None: merged = mapper._create_instance(self) else: if key in self.identity_map: merged = self.identity_map[key] else: merged = self.get(mapper.class_, key[1]) if merged is None: raise exceptions.AssertionError("Instance %s has an instance key but is not persisted" % mapperutil.instance_str(object)) for prop in mapper.props.values(): prop.merge(self, object, merged, _recursive) if key is None: self.save(merged, entity_name=mapper.entity_name) return merged finally: _recursive.remove(mapper)
def _cascade_iterator(cascade, instance, **kwargs): mapper = _object_mapper(instance) for (o, m) in mapper.cascade_iterator(cascade, instance._state, **kwargs): yield o, m