error when accessing history w/ backref + make_transient object

Issue #2773 resolved
Mike Bayer repo owner created an issue
from sqlalchemy.orm import attributes, instrumentation
from sqlalchemy.testing.assertions import eq_
from mock import Mock

class Post(object):
    def __init__(self, name):
        self.name = name
    __hash__ = None
    def __eq__(self, other):
        return other is not None and other.name == self.name

class Blog(object):
    def __init__(self, name):
        self.name = name
    __hash__ = None
    def __eq__(self, other):
        return other is not None and other.name == self.name

lazy_posts = Mock()

instrumentation.register_class(Post)
instrumentation.register_class(Blog)
attributes.register_attribute(Post, 'blog', uselist=False,
        backref='posts', trackparent=True, useobject=True)
attributes.register_attribute(Blog, 'posts', uselist=True,
        backref='blog', callable_=lazy_posts, trackparent=True,
        useobject=True)

lazy_posts.return_value = attributes.PASSIVE_NO_RESULT

b = Blog("blog 1")
p = Post("post 1")

state, dict_ = attributes.instance_state(b), attributes.instance_dict(b)

# this sets up NEVER_SET on b.posts
p.blog = b

eq_(state.committed_state, {"posts": attributes.NEVER_SET})
assert 'posts' not in dict_

# then suppose the object was made transient again,
# the lazy loader would return this
lazy_posts.return_value = attributes.ATTR_EMPTY

p2 = Post('asdf')
p2.blog = b

eq_(state.committed_state, {"posts": attributes.NEVER_SET})
eq_(dict_['posts']('posts'), [p2](p2))

# then this would fail.
eq_(
    Blog.posts.impl.get_history(state, dict_, passive=True),
    ([p2](p2), [[](],))
)

eq_(
    Blog.posts.impl.get_all_pending(state, dict_),
    [p2)]((attributes.instance_state(p2),)
)



Traceback (most recent call last):
  File "test.py", line 54, in <module>
    Blog.posts.impl.get_history(state, dict_, passive=True),
  File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/attributes.py", line 876, in get_history
    return History.from_collection(self, state, current)
  File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/attributes.py", line 1345, in from_collection
    for c in original
TypeError: 'symbol' object is not iterable

Comments (2)

  1. Log in to comment