From: Mike Bayer Date: Mon, 13 Feb 2012 21:04:57 +0000 (-0500) Subject: - [bug] Fixed bug whereby MappedCollection X-Git-Tag: rel_0_7_6~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1aeb637e70e4f9f098ab8b4c4462975b805e9965;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - [bug] Fixed bug whereby MappedCollection would not get the appropriate collection instrumentation if it were only used in a custom subclass that used @collection.internally_instrumented. [ticket:2406] - added docs for collection --- diff --git a/CHANGES b/CHANGES index 0c4267fb0a..29e8c2ba0f 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,13 @@ CHANGES 0.7.6 ===== - orm + - [bug] Fixed bug whereby MappedCollection + would not get the appropriate collection + instrumentation if it were only used + in a custom subclass that used + @collection.internally_instrumented. + [ticket:2406] + - [feature] Added the ability to query for Table-bound column names when using query(sometable).filter_by(colname=value). diff --git a/doc/build/orm/collections.rst b/doc/build/orm/collections.rst index 4e0d660917..eaba3e6a85 100644 --- a/doc/build/orm/collections.rst +++ b/doc/build/orm/collections.rst @@ -301,7 +301,7 @@ for examples. Custom Collection Implementations ================================== -You can use your own types for collections as well. In simple cases, +You can use your own types for collections as well. In simple cases, inherting from ``list`` or ``set``, adding custom behavior, is all that's needed. In other cases, special decorators are needed to tell SQLAlchemy more detail about how the collection operates. @@ -507,6 +507,20 @@ must decorate appender and remover methods, however- there are no compatible methods in the basic dictionary interface for SQLAlchemy to use by default. Iteration will go through ``itervalues()`` unless otherwise decorated. +.. note:: + + Due to a bug in MappedCollection prior to version 0.7.6, this + workaround usually needs to be called before a custom subclass + of :class:`.MappedCollection` which uses :meth:`.collection.internally_instrumented` + can be used:: + + from sqlalchemy.orm.collections import _instrument_class, MappedCollection + _instrument_class(MappedCollection) + + This will ensure that the :class:`.MappedCollection` has been properly + initialized with custom ``__setitem__()`` and ``__delitem__()`` + methods before used in a custom subclass. + .. autoclass:: sqlalchemy.orm.collections.MappedCollection :members: @@ -540,6 +554,8 @@ Various internal methods. .. autofunction:: bulk_replace +.. autoclass:: collection + .. autofunction:: collection_adapter .. autoclass:: CollectionAdapter diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py index 7872715eb9..2eebfbca29 100644 --- a/lib/sqlalchemy/orm/collections.py +++ b/lib/sqlalchemy/orm/collections.py @@ -814,6 +814,7 @@ def _instrument_class(cls): methods[name] = None, None, after # apply ABC auto-decoration to methods that need it + for method, decorator in decorators.items(): fn = getattr(cls, method, None) if (fn and method not in methods and @@ -1465,3 +1466,13 @@ class MappedCollection(dict): incoming_key, value, new_key)) yield value _convert = collection.converter(_convert) + +# ensure instrumentation is associated with +# these built-in classes; if a user-defined class +# subclasses these and uses @internally_instrumented, +# the superclass is otherwise not instrumented. +# see [ticket:2406]. +_instrument_class(MappedCollection) +_instrument_class(InstrumentedList) +_instrument_class(InstrumentedSet) +