- Removed deprecated append(val, **kw)

- dict/set/list proxies are now docstring'd like their python counterparts
This commit is contained in:
Jason Kirtland
2008-05-21 15:43:00 +00:00
parent 8adc6f2008
commit cfc59b1713
+125 -100
View File
@@ -4,8 +4,8 @@ The ``AssociationProxy`` is a Python property object which provides
transparent proxied access to the endpoint of an association object.
See the example ``examples/association/proxied_association.py``.
"""
"""
import itertools
import weakref
from sqlalchemy import exceptions
@@ -14,31 +14,32 @@ from sqlalchemy import util
from sqlalchemy.orm import collections
def association_proxy(targetcollection, attr, **kw):
"""Convenience function for use in mapped classes. Implements a Python
property representing a relation as a collection of simpler values. The
proxied property will mimic the collection type of the target (list, dict
or set), or in the case of a one to one relation, a simple scalar value.
def association_proxy(target_collection, attr, **kw):
"""Convenience function for use in mapped classes.
targetcollection
Implements a Python property representing a relation as a collection of
simpler values. The proxied property will mimic the collection type of
the target (list, dict or set), or, in the case of a one to one relation,
a simple scalar value.
target_collection
Name of the relation attribute we'll proxy to, usually created with
'relation()' in a mapper setup.
attr
Attribute on the associated 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)]
property would look like [getattr(obj1, attr), getattr(obj2, attr)]
If the relation is one-to-one or otherwise uselist=False, then simply:
getattr(obj, attr)
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.
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.
@@ -47,69 +48,68 @@ def association_proxy(targetcollection, attr, **kw):
If the target is present, set operations are proxied to setattr() on the
associated object.
If you have an associated object with multiple attributes, you may set up
multiple association proxies mapping to different attributes. See the
unit tests for examples, and for examples of how creator() functions can
be used to construct the scalar relation on-demand in this situation.
If you have an associated object with multiple attributes, you may set
up multiple association proxies mapping to different attributes. See
the unit tests for examples, and for examples of how creator() functions
can be used to construct the scalar relation on-demand in this
situation.
Passes along any other arguments to AssociationProxy
"""
return AssociationProxy(targetcollection, attr, **kw)
"""
return AssociationProxy(target_collection, attr, **kw)
class AssociationProxy(object):
"""A property object that automatically sets up `AssociationLists`
on an object."""
"""A descriptor that presents a read/write view of an object attribute."""
def __init__(self, targetcollection, attr, creator=None,
def __init__(self, target_collection, attr, creator=None,
getset_factory=None, proxy_factory=None, proxy_bulk_set=None):
"""Arguments are:
targetcollection
Name of the collection we'll proxy to, usually created with
'relation()' in a mapper setup.
target_collection
Name of the collection we'll proxy to, usually created with
'relation()' in a mapper setup.
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)]
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)]
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.
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.
If you want to construct instances differently, supply a 'creator'
function that takes arguments as above and returns instances.
getset_factory
Optional. Proxied attribute access is automatically handled
by routines that get and set values based on the `attr` argument
for this proxy.
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.
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.
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 relations.
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 relations.
proxy_bulk_set
Optional, use with proxy_factory. See the _set() method for
details.
proxy_bulk_set
Optional, use with proxy_factory. See the _set() method for
details.
"""
self.target_collection = targetcollection # backwards compat name...
self.target_collection = target_collection
self.value_attr = attr
self.creator = creator
self.getset_factory = getset_factory
@@ -118,12 +118,13 @@ class AssociationProxy(object):
self.scalar = None
self.owning_class = None
self.key = '_%s_%s_%s' % (type(self).__name__,
targetcollection, id(self))
self.key = '_%s_%s_%s' % (
type(self).__name__, target_collection, id(self))
self.collection_class = None
def _get_property(self):
return orm.class_mapper(self.owning_class).get_property(self.target_collection)
return (orm.class_mapper(self.owning_class).
get_property(self.target_collection))
def _target_class(self):
return self._get_property().mapper.class_
@@ -250,20 +251,21 @@ class AssociationProxy(object):
'no proxy_bulk_set supplied for custom '
'collection_class implementation')
class _AssociationList(object):
"""Generic proxying list which proxies list operations to a another list,
converting association objects to and from a simplified value.
"""
"""Generic, converting, list-to-list proxy."""
def __init__(self, lazy_collection, creator, getter, setter):
"""
"""Constructs an _AssociationList.
lazy_collection
A callable returning a list-based collection of entities (usually
an object attribute managed by a SQLAlchemy relation())
A callable returning a list-based collection of entities (usually an
object attribute managed by a SQLAlchemy relation())
creator
A function that creates new target entities. Given one parameter:
value. The assertion is assumed:
value. This assertion is assumed::
obj = creator(somevalue)
assert getter(obj) == somevalue
@@ -271,10 +273,10 @@ class _AssociationList(object):
A function. Given an associated object, return the 'value'.
setter
A function. Given an associated object and a value, store
that value on the object.
"""
A function. Given an associated object and a value, store that
value on the object.
"""
self.lazy_collection = lazy_collection
self.creator = creator
self.getter = getter
@@ -282,10 +284,8 @@ class _AssociationList(object):
col = property(lambda self: self.lazy_collection())
# For compatibility with 0.3.1 through 0.3.7- pass kw through to creator.
# (see append() below)
def _create(self, value, **kw):
return self.creator(value, **kw)
def _create(self, value):
return self.creator(value)
def _get(self, object):
return self.getter(object)
@@ -366,10 +366,8 @@ class _AssociationList(object):
yield self._get(member)
raise StopIteration
# For compatibility with 0.3.1 through 0.3.7- pass kw through to creator
# on append() only. (Can't on __setitem__, __contains__, etc., obviously.)
def append(self, value, **kw):
item = self._create(value, **kw)
def append(self, value):
item = self._create(value)
self.col.append(item)
def count(self, value):
@@ -473,32 +471,39 @@ class _AssociationList(object):
def __hash__(self):
raise TypeError("%s objects are unhashable" % type(self).__name__)
for func_name, func in locals().items():
if (callable(func) and func.func_name == func_name and
not func.__doc__ and hasattr(list, func_name)):
func.__doc__ = getattr(list, func_name).__doc__
_NotProvided = util.symbol('_NotProvided')
class _AssociationDict(object):
"""Generic proxying list which proxies dict operations to a another dict,
converting association objects to and from a simplified value.
"""
"""Generic, converting, dict-to-dict proxy."""
def __init__(self, lazy_collection, creator, getter, setter):
"""
"""Constructs an _AssociationDict.
lazy_collection
A callable returning a dict-based collection of entities (usually
an object attribute managed by a SQLAlchemy relation())
A callable returning a dict-based collection of entities (usually an
object attribute managed by a SQLAlchemy relation())
creator
A function that creates new target entities. Given two parameters:
key and value. The assertion is assumed:
key and value. The assertion is assumed::
obj = creator(somekey, somevalue)
assert getter(somekey) == somevalue
getter
A function. Given an associated object and a key, return the 'value'.
A function. Given an associated object and a key, return the
'value'.
setter
A function. Given an associated object, a key and a value, store
that value on the object.
"""
"""
self.lazy_collection = lazy_collection
self.creator = creator
self.getter = getter
@@ -539,7 +544,10 @@ class _AssociationDict(object):
def __contains__(self, key):
# testlib.pragma exempt:__hash__
return key in self.col
has_key = __contains__
def has_key(self, key):
# testlib.pragma exempt:__hash__
return key in self.col
def __iter__(self):
return self.col.iterkeys()
@@ -586,11 +594,13 @@ class _AssociationDict(object):
def keys(self):
return self.col.keys()
def iterkeys(self):
return self.col.iterkeys()
def values(self):
return [ self._get(member) for member in self.col.values() ]
def itervalues(self):
for key in self.col:
yield self._get(self.col[key])
@@ -598,6 +608,7 @@ class _AssociationDict(object):
def items(self):
return [(k, self._get(self.col[k])) for k in self]
def iteritems(self):
for key in self.col:
yield (key, self._get(self.col[key]))
@@ -635,20 +646,26 @@ class _AssociationDict(object):
def __hash__(self):
raise TypeError("%s objects are unhashable" % type(self).__name__)
for func_name, func in locals().items():
if (callable(func) and func.func_name == func_name and
not func.__doc__ and hasattr(dict, func_name)):
func.__doc__ = getattr(dict, func_name).__doc__
class _AssociationSet(object):
"""Generic proxying list which proxies set operations to a another set,
converting association objects to and from a simplified value.
"""
"""Generic, converting, set-to-set proxy."""
def __init__(self, lazy_collection, creator, getter, setter):
"""
"""Constructs an _AssociationSet.
collection
A callable returning a set-based collection of entities (usually an
object attribute managed by a SQLAlchemy relation())
creator
A function that creates new target entities. Given one parameter:
value. The assertion is assumed:
value. The assertion is assumed::
obj = creator(somevalue)
assert getter(obj) == somevalue
@@ -656,10 +673,10 @@ class _AssociationSet(object):
A function. Given an associated object, return the 'value'.
setter
A function. Given an associated object and a value, store
that value on the object.
"""
A function. Given an associated object and a value, store that
value on the object.
"""
self.lazy_collection = lazy_collection
self.creator = creator
self.getter = getter
@@ -693,9 +710,12 @@ class _AssociationSet(object):
return False
def __iter__(self):
"""Iterate over proxied values. For the actual domain objects,
iterate over .col instead or just use the underlying collection
directly from its property on the parent."""
"""Iterate over proxied values.
For the actual domain objects, iterate over .col instead or just use
the underlying collection directly from its property on the parent.
"""
for member in self.col:
yield self._get(member)
raise StopIteration
@@ -851,3 +871,8 @@ class _AssociationSet(object):
def __hash__(self):
raise TypeError("%s objects are unhashable" % type(self).__name__)
for func_name, func in locals().items():
if (callable(func) and func.func_name == func_name and
not func.__doc__ and hasattr(util.Set, func_name)):
func.__doc__ = getattr(util.Set, func_name).__doc__