diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-12-09 17:32:43 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-12-09 19:31:58 -0500 |
commit | a287cda53f01872f9d6654893b8d8b3d29e695ed (patch) | |
tree | ce1767905948b958619b98f5437331181ff09bf9 /lib/sqlalchemy/orm/attributes.py | |
parent | b606e47ddc541952c1d4c1b6d010fc72249af234 (diff) | |
download | sqlalchemy-ticket_3604.tar.gz |
- dictlike wipticket_3604
Diffstat (limited to 'lib/sqlalchemy/orm/attributes.py')
-rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 8605df785..03c48151e 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -855,7 +855,7 @@ class CollectionAttributeImpl(AttributeImpl): __slots__ = ( 'copy', 'collection_factory', '_append_token', '_remove_token', - '_duck_typed_as' + '_duck_typed_as', '_dictlike' ) def __init__(self, class_, key, callable_, dispatch, @@ -878,6 +878,7 @@ class CollectionAttributeImpl(AttributeImpl): self._remove_token = None self._duck_typed_as = util.duck_type_collection( self.collection_factory()) + self._dictlike = self._duck_typed_as is dict if getattr(self.collection_factory, "_sa_linker", None): @@ -1025,12 +1026,15 @@ class CollectionAttributeImpl(AttributeImpl): passive=PASSIVE_OFF, pop=False, _adapt=True): iterable = orig_iterable = value + dictlike = self._dictlike + # pulling a new collection first so that an adaptation exception does # not trigger a lazy load of the old collection. new_collection, user_data = self._initialize_collection(state) if _adapt: if new_collection._converter is not None: iterable = new_collection._converter(iterable) + dictlike = False else: setting_type = util.duck_type_collection(iterable) receiving_type = self._duck_typed_as @@ -1047,15 +1051,20 @@ class CollectionAttributeImpl(AttributeImpl): # adapter. if hasattr(iterable, '_sa_iterator'): iterable = iterable._sa_iterator() + dictlike = False elif setting_type is dict: - if util.py3k: - iterable = iterable.values() + if dictlike: + iterable = iterable.items() else: - iterable = getattr( - iterable, 'itervalues', iterable.values)() + iterable = iterable.values() else: + assert not dictlike iterable = iter(iterable) - new_values = list(iterable) + + if dictlike: + new_values = dict(iterable) + else: + new_values = list(iterable) old = self.get(state, dict_, passive=PASSIVE_ONLY_PERSISTENT) if old is PASSIVE_NO_RESULT: @@ -1072,8 +1081,12 @@ class CollectionAttributeImpl(AttributeImpl): dict_[self.key] = user_data - collections.bulk_replace( - new_values, old_collection, new_collection) + if dictlike: + collections.bulk_replace_dictlike( + new_values, old_collection, new_collection) + else: + collections.bulk_replace( + new_values, old_collection, new_collection) del old._sa_adapter self.dispatch.dispose_collection(state, old, old_collection) |