summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/ext/associationproxy.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/ext/associationproxy.py')
-rw-r--r--lib/sqlalchemy/ext/associationproxy.py83
1 files changed, 48 insertions, 35 deletions
diff --git a/lib/sqlalchemy/ext/associationproxy.py b/lib/sqlalchemy/ext/associationproxy.py
index 27c76eb6b..f6c0764e4 100644
--- a/lib/sqlalchemy/ext/associationproxy.py
+++ b/lib/sqlalchemy/ext/associationproxy.py
@@ -27,24 +27,25 @@ def association_proxy(target_collection, attr, **kw):
The returned value is an instance of :class:`.AssociationProxy`.
- Implements a Python property representing a relationship as a collection of
- simpler values, or a scalar value. The proxied property will mimic the collection type of
- the target (list, dict or set), or, in the case of a one to one relationship,
- a simple scalar value.
+ Implements a Python property representing a relationship as a collection
+ of simpler values, or a scalar value. The proxied property will mimic
+ the collection type of the target (list, dict or set), or, in the case of
+ a one to one relationship, a simple scalar value.
:param target_collection: Name of the attribute we'll proxy to.
This attribute is typically mapped by
:func:`~sqlalchemy.orm.relationship` to link to a target collection, but
can also be a many-to-one or non-scalar relationship.
- :param attr: Attribute on the associated instance or instances we'll proxy for.
+ :param attr: Attribute on the associated instance or instances we'll
+ proxy for.
For example, given a target collection of [obj1, obj2], a list created
by this proxy property would look like [getattr(obj1, *attr*),
getattr(obj2, *attr*)]
- If the relationship is one-to-one or otherwise uselist=False, then simply:
- getattr(obj, *attr*)
+ If the relationship is one-to-one or otherwise uselist=False, then
+ simply: getattr(obj, *attr*)
:param creator: optional.
@@ -89,34 +90,36 @@ class AssociationProxy(object):
:param target_collection: Name of the collection we'll proxy to,
usually created with :func:`.relationship`.
- :param attr: Attribute on the collected instances we'll proxy for. For example,
- given a target collection of [obj1, obj2], a list created by this
- proxy property would look like [getattr(obj1, attr), getattr(obj2,
- attr)]
+ :param attr: Attribute on the collected instances we'll proxy
+ for. For example, given a target collection of [obj1, obj2], a
+ list created by this proxy property would look like
+ [getattr(obj1, attr), getattr(obj2, attr)]
- :param creator: Optional. When new items are added to this proxied collection, new
- instances of the class collected by the target collection will be
- created. For list and set collections, the target class constructor
- will be called with the 'value' for the new instance. For dict
- types, two arguments are passed: key and value.
+ :param creator: Optional. When new items are added to this proxied
+ collection, new instances of the class collected by the target
+ collection will be created. For list and set collections, the
+ target class constructor will be called with the 'value' for the
+ new instance. For dict types, two arguments are passed:
+ key and value.
If you want to construct instances differently, supply a 'creator'
function that takes arguments as above and returns instances.
- :param getset_factory: Optional. Proxied attribute access is automatically handled by
- routines that get and set values based on the `attr` argument for
- this proxy.
+ :param getset_factory: Optional. Proxied attribute access is
+ automatically handled by routines that get and set values based on
+ the `attr` argument for this proxy.
If you would like to customize this behavior, you may supply a
`getset_factory` callable that produces a tuple of `getter` and
`setter` functions. The factory is called with two arguments, the
abstract type of the underlying collection and this proxy instance.
- :param proxy_factory: Optional. The type of collection to emulate is determined by
- sniffing the target collection. If your collection type can't be
- determined by duck typing or you'd like to use a different
- collection implementation, you may supply a factory function to
- produce those collections. Only applicable to non-scalar relationships.
+ :param proxy_factory: Optional. The type of collection to emulate is
+ determined by sniffing the target collection. If your collection
+ type can't be determined by duck typing or you'd like to use a
+ different collection implementation, you may supply a factory
+ function to produce those collections. Only applicable to
+ non-scalar relationships.
:param proxy_bulk_set: Optional, use with proxy_factory. See
the _set() method for details.
@@ -279,7 +282,8 @@ class AssociationProxy(object):
self.collection_class = util.duck_type_collection(lazy_collection())
if self.proxy_factory:
- return self.proxy_factory(lazy_collection, creator, self.value_attr, self)
+ return self.proxy_factory(
+ lazy_collection, creator, self.value_attr, self)
if self.getset_factory:
getter, setter = self.getset_factory(self.collection_class, self)
@@ -287,11 +291,14 @@ class AssociationProxy(object):
getter, setter = self._default_getset(self.collection_class)
if self.collection_class is list:
- return _AssociationList(lazy_collection, creator, getter, setter, self)
+ return _AssociationList(
+ lazy_collection, creator, getter, setter, self)
elif self.collection_class is dict:
- return _AssociationDict(lazy_collection, creator, getter, setter, self)
+ return _AssociationDict(
+ lazy_collection, creator, getter, setter, self)
elif self.collection_class is set:
- return _AssociationSet(lazy_collection, creator, getter, setter, self)
+ return _AssociationSet(
+ lazy_collection, creator, getter, setter, self)
else:
raise exc.ArgumentError(
'could not guess which interface to use for '
@@ -340,9 +347,11 @@ class AssociationProxy(object):
"""
if self._value_is_scalar:
- value_expr = getattr(self.target_class, self.value_attr).has(criterion, **kwargs)
+ value_expr = getattr(
+ self.target_class, self.value_attr).has(criterion, **kwargs)
else:
- value_expr = getattr(self.target_class, self.value_attr).any(criterion, **kwargs)
+ value_expr = getattr(
+ self.target_class, self.value_attr).any(criterion, **kwargs)
# check _value_is_scalar here, otherwise
# we're scalar->scalar - call .any() so that
@@ -409,12 +418,13 @@ class _lazy_collection(object):
return getattr(obj, self.target)
def __getstate__(self):
- return {'obj':self.ref(), 'target':self.target}
+ return {'obj': self.ref(), 'target': self.target}
def __setstate__(self, state):
self.ref = weakref.ref(state['obj'])
self.target = state['target']
+
class _AssociationCollection(object):
def __init__(self, lazy_collection, creator, getter, setter, parent):
"""Constructs an _AssociationCollection.
@@ -456,13 +466,14 @@ class _AssociationCollection(object):
return bool(self.col)
def __getstate__(self):
- return {'parent':self.parent, 'lazy_collection':self.lazy_collection}
+ return {'parent': self.parent, 'lazy_collection': self.lazy_collection}
def __setstate__(self, state):
self.parent = state['parent']
self.lazy_collection = state['lazy_collection']
self.parent._inflate(self)
+
class _AssociationList(_AssociationCollection):
"""Generic, converting, list-to-list proxy."""
@@ -652,6 +663,8 @@ class _AssociationList(_AssociationCollection):
_NotProvided = util.symbol('_NotProvided')
+
+
class _AssociationDict(_AssociationCollection):
"""Generic, converting, dict-to-dict proxy."""
@@ -734,7 +747,7 @@ class _AssociationDict(_AssociationCollection):
return self.col.iterkeys()
def values(self):
- return [ self._get(member) for member in self.col.values() ]
+ return [self._get(member) for member in self.col.values()]
def itervalues(self):
for key in self.col:
@@ -766,8 +779,8 @@ class _AssociationDict(_AssociationCollection):
len(a))
elif len(a) == 1:
seq_or_map = a[0]
- # discern dict from sequence - took the advice
- # from http://www.voidspace.org.uk/python/articles/duck_typing.shtml
+ # discern dict from sequence - took the advice from
+ # http://www.voidspace.org.uk/python/articles/duck_typing.shtml
# still not perfect :(
if hasattr(seq_or_map, 'keys'):
for item in seq_or_map: