self.merge = "merge" in values or "all" in values
self.expunge = "expunge" in values or "all" in values
self.refresh_expire = "refresh-expire" in values or "all" in values
-
+
if self.delete_orphan and not self.delete:
util.warn("The 'delete-orphan' cascade option requires "
"'delete'. This will raise an error in 0.6.")
-
+
for x in values:
if x not in all_cascades:
raise sa_exc.ArgumentError("Invalid cascade option '%s'" % x)
class Validator(AttributeExtension):
"""Runs a validation method on an attribute value to be set or appended.
-
+
The Validator class is used by the :func:`~sqlalchemy.orm.validates`
decorator, and direct access is usually not needed.
-
+
"""
-
+
def __init__(self, key, validator):
"""Construct a new Validator.
-
+
key - name of the attribute to be validated;
- will be passed as the second argument to
+ will be passed as the second argument to
the validation method (the first is the object instance itself).
-
+
validator - an function or instance method which accepts
three arguments; an instance (usually just 'self' for a method),
the key name of the attribute, and the value. The function should
return the same value given, unless it wishes to modify it.
-
+
"""
self.key = key
self.validator = validator
-
+
def append(self, state, value, initiator):
return self.validator(state.obj(), self.key, value)
def set(self, state, value, oldvalue, initiator):
return self.validator(state.obj(), self.key, value)
-
+
def polymorphic_union(table_map, typecolname, aliasname='p_union'):
"""Create a ``UNION`` statement used by a polymorphic mapper.
% ", ".join(kwargs.keys()))
mapper = object_mapper(instance)
return mapper.identity_key_from_instance(instance)
-
+
class ExtensionCarrier(dict):
"""Fronts an ordered collection of MapperExtension objects.
def _register(self, extension):
"""Register callable fronts for overridden interface methods."""
-
+
for method in self.interface.difference(self):
impl = getattr(extension, method, None)
if impl and impl is not getattr(MapperExtension, method):
def __getattr__(self, key):
"""Delegate MapperExtension methods to bundled fronts."""
-
+
if key not in self.interface:
raise AttributeError(key)
return self.get(key, self._pass)
class ORMAdapter(sql_util.ColumnAdapter):
"""Extends ColumnAdapter to accept ORM entities.
-
+
The selectable is extracted from the given entity,
and the AliasedClass if any is referenced.
-
+
"""
def __init__(self, entity, equivalents=None, chain_to=None):
self.mapper, selectable, is_aliased_class = _entity_info(entity)
class AliasedClass(object):
"""Represents an 'alias'ed form of a mapped class for usage with Query.
-
+
The ORM equivalent of a :class:`~sqlalchemy.sql.expression.Alias`
- object, this object mimics the mapped class using a
+ object, this object mimics the mapped class using a
__getattr__ scheme and maintains a reference to a
- real Alias object. It indicates to Query that the
+ real Alias object. It indicates to Query that the
selectable produced for this class should be aliased,
and also adapts PropComparators produced by the class'
- InstrumentedAttributes so that they adapt the
+ InstrumentedAttributes so that they adapt the
"local" side of SQL expressions against the alias.
-
+
"""
def __init__(self, cls, alias=None, name=None):
self.__mapper = _class_to_mapper(cls)
def __getstate__(self):
return {'mapper':self.__mapper, 'alias':self.__alias, 'name':self._sa_label_name}
-
+
def __setstate__(self, state):
self.__mapper = state['mapper']
self.__target = self.__mapper.class_
name = state['name']
self._sa_label_name = name
self.__name__ = 'AliasedClass_' + str(self.__target)
-
+
def __adapt_element(self, elem):
return self.__adapter.traverse(elem)._annotate({'parententity': self, 'parentmapper':self.__mapper})
-
+
def __adapt_prop(self, prop):
existing = getattr(self.__target, prop.key)
comparator = existing.comparator.adapted(self.__adapt_element)
def _orm_annotate(element, exclude=None):
"""Deep copy the given ClauseElement, annotating each element with the "_orm_adapt" flag.
-
+
Elements within the exclude collection will be cloned but not annotated.
-
+
"""
return sql_util._deep_annotate(element, {'_orm_adapt':True}, exclude)
_orm_deannotate = sql_util._deep_deannotate
-
+
class _ORMJoin(expression.Join):
"""Extend Join to support ORM constructs as input."""
-
+
__visit_name__ = expression.Join.__visit_name__
def __init__(self, left, right, onclause=None, isouter=False, join_to_left=True):
adapt_from = None
-
+
if hasattr(left, '_orm_mappers'):
left_mapper = left._orm_mappers[1]
if join_to_left:
left_mapper, left, left_is_aliased = _entity_info(left)
if join_to_left and (left_is_aliased or not left_mapper):
adapt_from = left
-
+
right_mapper, right, right_is_aliased = _entity_info(right)
if right_is_aliased:
adapt_to = right
if prop:
pj, sj, source, dest, secondary, target_adapter = prop._create_joins(
- source_selectable=adapt_from,
- dest_selectable=adapt_to,
- source_polymorphic=True,
- dest_polymorphic=True,
+ source_selectable=adapt_from,
+ dest_selectable=adapt_to,
+ source_polymorphic=True,
+ dest_polymorphic=True,
of_type=right_mapper)
if sj:
else:
onclause = pj
self._target_adapter = target_adapter
-
+
expression.Join.__init__(self, left, right, onclause, isouter)
def join(self, right, onclause=None, isouter=False, join_to_left=True):
def join(left, right, onclause=None, isouter=False, join_to_left=True):
"""Produce an inner join between left and right clauses.
-
- In addition to the interface provided by
- :func:`~sqlalchemy.sql.expression.join()`, left and right may be mapped
- classes or AliasedClass instances. The onclause may be a
- string name of a relation(), or a class-bound descriptor
+
+ In addition to the interface provided by
+ :func:`~sqlalchemy.sql.expression.join()`, left and right may be mapped
+ classes or AliasedClass instances. The onclause may be a
+ string name of a relation(), or a class-bound descriptor
representing a relation.
-
+
join_to_left indicates to attempt aliasing the ON clause,
in whatever form it is passed, to the selectable
passed as the left side. If False, the onclause
is used as is.
-
+
"""
return _ORMJoin(left, right, onclause, isouter, join_to_left)
def outerjoin(left, right, onclause=None, join_to_left=True):
"""Produce a left outer join between left and right clauses.
-
- In addition to the interface provided by
- :func:`~sqlalchemy.sql.expression.outerjoin()`, left and right may be mapped
- classes or AliasedClass instances. The onclause may be a
- string name of a relation(), or a class-bound descriptor
+
+ In addition to the interface provided by
+ :func:`~sqlalchemy.sql.expression.outerjoin()`, left and right may be mapped
+ classes or AliasedClass instances. The onclause may be a
+ string name of a relation(), or a class-bound descriptor
representing a relation.
-
+
"""
return _ORMJoin(left, right, onclause, True, join_to_left)
instance
a parent instance, which should be persistent or detached.
- property
- a class-attached descriptor, MapperProperty or string property name
- attached to the parent instance.
+ property
+ a class-attached descriptor, MapperProperty or string property name
+ attached to the parent instance.
- \**kwargs
- all extra keyword arguments are propagated to the constructor of
- Query.
+ \**kwargs
+ all extra keyword arguments are propagated to the constructor of
+ Query.
"""
if isinstance(prop, basestring):
def _entity_info(entity, compile=True):
"""Return mapping information given a class, mapper, or AliasedClass.
-
+
Returns 3-tuple of: mapper, mapped selectable, boolean indicating if this
is an aliased() construct.
-
+
If the given entity is not a mapper, mapped class, or aliased construct,
returns None, the entity, False. This is typically used to allow
unmapped selectables through.
-
+
"""
if isinstance(entity, AliasedClass):
return entity._AliasedClass__mapper, entity._AliasedClass__alias, True
def _entity_descriptor(entity, key):
"""Return attribute/property information given an entity and string name.
-
+
Returns a 2-tuple representing InstrumentedAttribute/MapperProperty.
-
+
"""
if isinstance(entity, AliasedClass):
desc = getattr(entity, key)
def object_mapper(instance):
"""Given an object, return the primary Mapper associated with the object instance.
-
+
Raises UnmappedInstanceError if no mapping is configured.
-
+
"""
try:
state = attributes.instance_state(instance)
"""Given a class (or an object), return the primary Mapper associated with the key.
Raises UnmappedClassError if no mapping is configured.
-
+
"""
try:
class_manager = attributes.manager_of_class(class_)
mapper = class_manager.mapper
-
+
# HACK until [ticket:1142] is complete
if mapper is None:
raise AttributeError
-
+
except exc.NO_STATE:
raise exc.UnmappedClassError(class_)
def state_str(state):
"""Return a string describing an instance via its InstanceState."""
-
+
if state is None:
return "None"
else: