summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/__init__.py3
-rw-r--r--lib/sqlalchemy/orm/descriptor_props.py27
-rw-r--r--lib/sqlalchemy/orm/interfaces.py77
-rw-r--r--lib/sqlalchemy/orm/properties.py43
4 files changed, 138 insertions, 12 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index 1a22fe3d1..2078b2396 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -760,6 +760,9 @@ def composite(class_, *cols, **kwargs):
See the mapping documentation section :ref:`mapper_composite` for a full
usage example.
+ The :class:`.MapperProperty` returned by :func:`.composite`
+ is the :class:`.CompositeProperty`.
+
:param class\_:
The "composite type" class.
diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py
index 91717974d..f4c2e1a90 100644
--- a/lib/sqlalchemy/orm/descriptor_props.py
+++ b/lib/sqlalchemy/orm/descriptor_props.py
@@ -73,7 +73,17 @@ class DescriptorProperty(MapperProperty):
class CompositeProperty(DescriptorProperty):
+ """Defines a "composite" mapped attribute, representing a collection
+ of columns as one attribute.
+ :class:`.CompositeProperty` is constructed using the :func:`.composite`
+ function.
+
+ See also:
+
+ :ref:`mapper_composite`
+
+ """
def __init__(self, class_, *attrs, **kwargs):
self.attrs = attrs
self.composite_class = class_
@@ -279,6 +289,23 @@ class CompositeProperty(DescriptorProperty):
return self.comparator_factory(self)
class Comparator(PropComparator):
+ """Produce boolean, comparison, and other operators for
+ :class:`.CompositeProperty` attributes.
+
+ See the example in :ref:`composite_operations` for an overview
+ of usage , as well as the documentation for :class:`.PropComparator`.
+
+ See also:
+
+ :class:`.PropComparator`
+
+ :class:`.ColumnOperators`
+
+ :ref:`types_operators`
+
+ :attr:`.TypeEngine.comparator_factory`
+
+ """
def __init__(self, prop, adapter=None):
self.prop = self.property = prop
self.adapter = adapter
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index d0732b913..f41c5894e 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -196,28 +196,91 @@ class MapperProperty(_InspectionAttr):
return operator(self.comparator, value)
class PropComparator(operators.ColumnOperators):
- """Defines comparison operations for MapperProperty objects.
+ """Defines boolean, comparison, and other operators for
+ :class:`.MapperProperty` objects.
+
+ SQLAlchemy allows for operators to
+ be redefined at both the Core and ORM level. :class:`.PropComparator`
+ is the base class of operator redefinition for ORM-level operations,
+ including those of :class:`.ColumnProperty`, :class:`.RelationshipProperty`,
+ and :class:`.CompositeProperty`.
+
+ .. note:: With the advent of Hybrid properties introduced in SQLAlchemy
+ 0.7, as well as Core-level operator redefinition in
+ SQLAlchemy 0.8, the use case for user-defined :class:`.PropComparator`
+ instances is extremely rare. See :ref:`hybrids_toplevel` as well
+ as :ref:`types_operators`.
User-defined subclasses of :class:`.PropComparator` may be created. The
built-in Python comparison and math operator methods, such as
- ``__eq__()``, ``__lt__()``, ``__add__()``, can be overridden to provide
+ :meth:`.operators.ColumnOperators.__eq__`,
+ :meth:`.operators.ColumnOperators.__lt__`, and
+ :meth:`.operators.ColumnOperators.__add__`, can be overridden to provide
new operator behavior. The custom :class:`.PropComparator` is passed to
- the mapper property via the ``comparator_factory`` argument. In each case,
+ the :class:`.MapperProperty` instance via the ``comparator_factory``
+ argument. In each case,
the appropriate subclass of :class:`.PropComparator` should be used::
+ # definition of custom PropComparator subclasses
+
from sqlalchemy.orm.properties import \\
ColumnProperty,\\
CompositeProperty,\\
RelationshipProperty
class MyColumnComparator(ColumnProperty.Comparator):
- pass
+ def __eq__(self, other):
+ return self.__clause_element__() == other
+
+ class MyRelationshipComparator(RelationshipProperty.Comparator):
+ def any(self, expression):
+ "define the 'any' operation"
+ # ...
class MyCompositeComparator(CompositeProperty.Comparator):
- pass
+ def __gt__(self, other):
+ "redefine the 'greater than' operation"
- class MyRelationshipComparator(RelationshipProperty.Comparator):
- pass
+ return sql.and_(*[a>b for a, b in
+ zip(self.__clause_element__().clauses,
+ other.__composite_values__())])
+
+
+ # application of custom PropComparator subclasses
+
+ from sqlalchemy.orm import column_property, relationship, composite
+ from sqlalchemy import Column, String
+
+ class SomeMappedClass(Base):
+ some_column = column_property(Column("some_column", String),
+ comparator_factory=MyColumnComparator)
+
+ some_relationship = relationship(SomeOtherClass,
+ comparator_factory=MyRelationshipComparator)
+
+ some_composite = composite(
+ Column("a", String), Column("b", String),
+ comparator_factory=MyCompositeComparator
+ )
+
+ Note that for column-level operator redefinition, it's usually
+ simpler to define the operators at the Core level, using the
+ :attr:`.TypeEngine.comparator_factory` attribute. See
+ :ref:`types_operators` for more detail.
+
+ See also:
+
+ :class:`.ColumnProperty.Comparator`
+
+ :class:`.RelationshipProperty.Comparator`
+
+ :class:`.CompositeProperty.Comparator`
+
+ :class:`.ColumnOperators`
+
+ :ref:`types_operators`
+
+ :attr:`.TypeEngine.comparator_factory`
"""
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index 62e4672d3..f52e914f7 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -161,6 +161,22 @@ class ColumnProperty(StrategizedProperty):
dest_state._expire_attributes(dest_dict, [self.key])
class Comparator(PropComparator):
+ """Produce boolean, comparison, and other operators for
+ :class:`.ColumnProperty` attributes.
+
+ See the documentation for :class:`.PropComparator` for a brief overview.
+
+ See also:
+
+ :class:`.PropComparator`
+
+ :class:`.ColumnOperators`
+
+ :ref:`types_operators`
+
+ :attr:`.TypeEngine.comparator_factory`
+
+ """
@util.memoized_instancemethod
def __clause_element__(self):
if self.adapter:
@@ -198,9 +214,9 @@ class RelationshipProperty(StrategizedProperty):
Public constructor is the :func:`.orm.relationship` function.
- Of note here is the :class:`.RelationshipProperty.Comparator`
- class, which implements comparison operations for scalar-
- and collection-referencing mapped attributes.
+ See also:
+
+ :ref:`relationship_config_toplevel`
"""
@@ -304,8 +320,25 @@ class RelationshipProperty(StrategizedProperty):
)
class Comparator(PropComparator):
- """Produce comparison operations for :func:`~.orm.relationship`-based
- attributes."""
+ """Produce boolean, comparison, and other operators for
+ :class:`.RelationshipProperty` attributes.
+
+ See the documentation for :class:`.PropComparator` for a brief overview
+ of ORM level operator definition.
+
+ See also:
+
+ :class:`.PropComparator`
+
+ :class:`.ColumnProperty.Comparator`
+
+ :class:`.ColumnOperators`
+
+ :ref:`types_operators`
+
+ :attr:`.TypeEngine.comparator_factory`
+
+ """
def __init__(self, prop, mapper, of_type=None, adapter=None):
"""Construction of :class:`.RelationshipProperty.Comparator`