summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/orm/__init__.py64
-rw-r--r--lib/sqlalchemy/orm/properties.py12
-rw-r--r--lib/sqlalchemy/orm/query.py4
-rw-r--r--lib/sqlalchemy/orm/strategies.py7
4 files changed, 54 insertions, 33 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index 42964545d..3d8461dfd 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -253,30 +253,46 @@ def composite(class_, *cols, **kwargs):
"""Return a composite column-based property for use with a Mapper.
This is very much like a column-based property except the given class
- is used to construct values composed of one or more columns. The class must
- implement a constructor with positional arguments matching the order of
- columns given, as well as a __colset__() method which returns its attributes
- in column order.
+ is used to represent "composite" values composed of one or more columns.
+
+ The class must implement a constructor with positional arguments matching
+ the order of columns supplied here, as well as a __composite_values__()
+ method which returns values in the same order.
+
+ A simple example is representing separate two columns in a table as a
+ single, first-class "Point" object::
+
+ class Point(object):
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+ def __composite_values__(self):
+ return (self.x, self.y)
+
+ # and then in the mapping:
+ ... composite(Point, mytable.c.x, mytable.c.y) ...
+
+ Arguments are:
- class\_
- the "composite type" class.
+ class\_
+ The "composite type" class.
- \*cols
- list of Column objects to be mapped.
+ \*cols
+ List of Column objects to be mapped.
- group
- a group name for this property when marked as deferred.
+ group
+ A group name for this property when marked as deferred.
- deferred
- when True, the column property is "deferred", meaning that
- it does not load immediately, and is instead loaded when the
- attribute is first accessed on an instance. See also
- [sqlalchemy.orm#deferred()].
+ deferred
+ When True, the column property is "deferred", meaning that
+ it does not load immediately, and is instead loaded when the
+ attribute is first accessed on an instance. See also
+ [sqlalchemy.orm#deferred()].
- comparator
- an optional instance of [sqlalchemy.orm#PropComparator] which
- provides SQL expression generation functions for this composite
- type.
+ comparator
+ An optional instance of [sqlalchemy.orm#PropComparator] which
+ provides SQL expression generation functions for this composite
+ type.
"""
return CompositeProperty(class_, *cols, **kwargs)
@@ -483,8 +499,7 @@ def extension(ext):
return ExtensionOption(ext)
def eagerload(name):
- """Return a ``MapperOption`` that will convert the property of the
- given name into an eager load.
+ """Return a ``MapperOption`` that will convert the property of the given name into an eager load.
Used with ``query.options()``.
"""
@@ -492,11 +507,10 @@ def eagerload(name):
return strategies.EagerLazyOption(name, lazy=False)
def eagerload_all(name):
- """Return a ``MapperOption`` that will convert all
- properties along the given dot-separated path into an
- eager load.
+ """Return a ``MapperOption`` that will convert all properties along the given dot-separated path into an eager load.
- e.g::
+ For example, this::
+
query.options(eagerload_all('orders.items.keywords'))...
will set all of 'orders', 'orders.items', and 'orders.items.keywords'
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index 600dab41f..c7bdc4274 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -100,12 +100,12 @@ class CompositeProperty(ColumnProperty):
obj = getattr(object, self.key, None)
if obj is None:
obj = self.composite_class(*[None for c in self.columns])
- for a, b in zip(self.columns, value.__colset__()):
+ for a, b in zip(self.columns, value.__composite_values__()):
if a is column:
setattr(obj, b, value)
def get_col_value(self, column, value):
- for a, b in zip(self.columns, value.__colset__()):
+ for a, b in zip(self.columns, value.__composite_values__()):
if a is column:
return b
@@ -114,10 +114,14 @@ class CompositeProperty(ColumnProperty):
if other is None:
return sql.and_(*[a==None for a in self.prop.columns])
else:
- return sql.and_(*[a==b for a, b in zip(self.prop.columns, other.__colset__())])
+ return sql.and_(*[a==b for a, b in
+ zip(self.prop.columns,
+ other.__composite_values__())])
def __ne__(self, other):
- return sql.or_(*[a!=b for a, b in zip(self.prop.columns, other.__colset__())])
+ return sql.or_(*[a!=b for a, b in
+ zip(self.prop.columns,
+ other.__composite_values__())])
class PropertyLoader(StrategizedProperty):
"""Describes an object property that holds a single item or list
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 37d5b10a3..1b5871858 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -76,8 +76,8 @@ class Query(object):
# convert composite types to individual args
# TODO: account for the order of columns in the
# ColumnProperty it corresponds to
- if hasattr(ident, '__colset__'):
- ident = ident.__colset__()
+ if hasattr(ident, '__composite_values__'):
+ ident = ident.__composite_values__()
key = self.mapper.identity_key_from_primary_key(ident)
return self._get(key, ident, **kwargs)
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 8a0cc6035..6e2860f3a 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -37,9 +37,12 @@ class ColumnLoader(LoaderStrategy):
def _init_composite_attribute(self):
self.logger.info("register managed composite attribute %s on class %s" % (self.key, self.parent.class_.__name__))
def copy(obj):
- return self.parent_property.composite_class(*obj.__colset__())
+ return self.parent_property.composite_class(
+ *obj.__composite_values__())
def compare(a, b):
- for col, aprop, bprop in zip(self.columns, a.__colset__(), b.__colset__()):
+ for col, aprop, bprop in zip(self.columns,
+ a.__composite_values__(),
+ b.__composite_values__()):
if not col.type.compare_values(aprop, bprop):
return False
else: