Example #1
0
def replicate_relation(source, target, attr, target_attr, cache=None):
    if attr.property.cascade.delete_orphan:
        process_scalar = replicate_no_merge
        process_list = replicate_filter
    else:
        process_scalar = reflect
        process_list = reflect_filter
    value = getattr(source, attr.key)
    target_attr_model = target_attr.property.mapper.class_
    if attr.property.uselist:
        adapter = collection_adapter(value)
        if adapter:
            # XXX The magic passes below are adapted from logic in
            # CollectionAttributeImpl.set() method without proper
            # understanding.  The `elif` branch isn't even coverered by tests.
            if hasattr(value, '_sa_iterator'):
                value = value._sa_iterator()
            elif duck_type_collection(value) is dict:
                value = value.values()
        reflection = process_list(value, target_attr_model, cache=cache)
        impl = instance_state(target).get_impl(attr.key)
        impl.set(instance_state(target), instance_dict(target), reflection,
                 # XXX We either have to convert reflection back to original
                 # collection type or use this private parameter.
                 _adapt=False)
    else:
        reflection = process_scalar(value, target_attr_model, cache=cache)
        setattr(target, attr.key, reflection)
        if (reflection is None and
                attr.property.direction is MANYTOONE and
                any(col.primary_key and not col.nullable
                    for col in attr.property.local_columns)):
            raise _PrimaryKeyIsNull()
    def test_no_orphan(self):
        """test that a lazily loaded child object is not marked as an orphan"""

        users, Address, addresses, User = (
            self.tables.users,
            self.classes.Address,
            self.tables.addresses,
            self.classes.User,
        )

        mapper(
            User,
            users,
            properties={
                "addresses": relationship(
                    Address, cascade="all,delete-orphan", lazy="select"
                )
            },
        )
        mapper(Address, addresses)

        sess = create_session()
        user = sess.query(User).get(7)
        assert getattr(User, "addresses").hasparent(
            attributes.instance_state(user.addresses[0]), optimistic=True
        )
        assert not sa.orm.class_mapper(Address)._is_orphan(
            attributes.instance_state(user.addresses[0])
        )
Example #3
0
    def test_lazytrackparent(self):
        """test that the "hasparent" flag works properly when lazy loaders and backrefs are used"""

        class Post(object):pass
        class Blog(object):pass
        attributes.register_class(Post)
        attributes.register_class(Blog)

        # set up instrumented attributes with backrefs
        attributes.register_attribute(Post, 'blog', uselist=False, extension=attributes.GenericBackrefExtension('posts'), trackparent=True, useobject=True)
        attributes.register_attribute(Blog, 'posts', uselist=True, extension=attributes.GenericBackrefExtension('blog'), trackparent=True, useobject=True)

        # create objects as if they'd been freshly loaded from the database (without history)
        b = Blog()
        p1 = Post()
        attributes.instance_state(b).set_callable('posts', lambda:[p1])
        attributes.instance_state(p1).set_callable('blog', lambda:b)
        p1, attributes.instance_state(b).commit_all()

        # no orphans (called before the lazy loaders fire off)
        assert attributes.has_parent(Blog, p1, 'posts', optimistic=True)
        assert attributes.has_parent(Post, b, 'blog', optimistic=True)

        # assert connections
        assert p1.blog is b
        assert p1 in b.posts

        # manual connections
        b2 = Blog()
        p2 = Post()
        b2.posts.append(p2)
        assert attributes.has_parent(Blog, p2, 'posts')
        assert attributes.has_parent(Post, b2, 'blog')
    def test_basic(self):
        for base in (object, MyBaseClass, MyClass):
            class User(base):
                pass

            register_class(User)
            attributes.register_attribute(
                User, 'user_id', uselist=False, useobject=False)
            attributes.register_attribute(
                User, 'user_name', uselist=False, useobject=False)
            attributes.register_attribute(
                User, 'email_address', uselist=False, useobject=False)

            u = User()
            u.user_id = 7
            u.user_name = 'john'
            u.email_address = '*****@*****.**'

            eq_(u.user_id, 7)
            eq_(u.user_name, "john")
            eq_(u.email_address, "*****@*****.**")
            attributes.instance_state(u)._commit_all(
                attributes.instance_dict(u))
            eq_(u.user_id, 7)
            eq_(u.user_name, "john")
            eq_(u.email_address, "*****@*****.**")

            u.user_name = 'heythere'
            u.email_address = '*****@*****.**'
            eq_(u.user_id, 7)
            eq_(u.user_name, "heythere")
            eq_(u.email_address, "*****@*****.**")
Example #5
0
    def test_lazy_backref_collections(self):
        class Foo(_base.BasicEntity):
            pass
        class Bar(_base.BasicEntity):
            pass

        lazy_load = []
        def lazyload(instance):
            def load():
                return lazy_load
            return load

        attributes.register_class(Foo)
        attributes.register_class(Bar)
        attributes.register_attribute(Foo, 'bars', uselist=True, extension=attributes.GenericBackrefExtension('foo'), trackparent=True, callable_=lazyload, useobject=True)
        attributes.register_attribute(Bar, 'foo', uselist=False, extension=attributes.GenericBackrefExtension('bars'), trackparent=True, useobject=True)

        bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)]
        lazy_load = [bar1, bar2, bar3]

        f = Foo()
        bar4 = Bar()
        bar4.foo = f
        eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([bar4], [bar1, bar2, bar3], []))

        lazy_load = None
        f = Foo()
        bar4 = Bar()
        bar4.foo = f
        eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([bar4], [], []))

        lazy_load = [bar1, bar2, bar3]
        attributes.instance_state(f).expire_attributes(['bars'])
        eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ((), [bar1, bar2, bar3], ()))
Example #6
0
def replicate_relation(source, target, attr, target_attr, cache=None):
    if attr.property.cascade.delete_orphan:
        process_scalar = replicate_no_merge
        process_list = replicate_filter
    else:
        process_scalar = reflect
        process_list = reflect_filter
    value = getattr(source, attr.key)
    target_attr_model = target_attr.property.mapper.class_
    if attr.property.uselist:
        adapter = collection_adapter(value)
        if adapter:
            # Convert any collection to flat iterable
            value = adapter.adapt_like_to_iterable(value)
        reflection = process_list(value, target_attr_model, cache=cache)
        impl = instance_state(target).get_impl(attr.key)
        # Set any collection value from flat list
        impl._set_iterable(instance_state(target),
                           instance_dict(target),
                           reflection)
    else:
        reflection = process_scalar(value, target_attr_model, cache=cache)
        setattr(target, attr.key, reflection)
        if (reflection is None and
                attr.property.direction is MANYTOONE and
                any(col.primary_key and not col.nullable
                    for col in attr.property.local_columns)):
            raise _PrimaryKeyIsNull()
Example #7
0
    def test_lazyhistory(self):
        """tests that history functions work with lazy-loading attributes"""

        class Foo(_base.BasicEntity):
            pass
        class Bar(_base.BasicEntity):
            pass

        attributes.register_class(Foo)
        attributes.register_class(Bar)

        bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)]
        def func1():
            return "this is func 1"
        def func2():
            return [bar1, bar2, bar3]

        attributes.register_attribute(Foo, 'col1', uselist=False, callable_=lambda o:func1, useobject=True)
        attributes.register_attribute(Foo, 'col2', uselist=True, callable_=lambda o:func2, useobject=True)
        attributes.register_attribute(Bar, 'id', uselist=False, useobject=True)

        x = Foo()
        attributes.instance_state(x).commit_all()
        x.col2.append(bar4)
        eq_(attributes.get_history(attributes.instance_state(x), 'col2'), ([bar4], [bar1, bar2, bar3], []))
Example #8
0
 def preprocess_dependencies(self, task, deplist, uowcommit, delete=False):
     if self.post_update:
         return
     if delete:
         if self.cascade.delete or self.cascade.delete_orphan:
             for state in deplist:
                 history = uowcommit.get_attribute_history(state, self.key, passive=self.passive_deletes)
                 if history:
                     if self.cascade.delete_orphan:
                         todelete = history.sum()
                     else:
                         todelete = history.non_deleted()
                     for child in todelete:
                         if child is None:
                             continue
                         uowcommit.register_object(child, isdelete=True)
                         for c, m in self.mapper.cascade_iterator('delete', child):
                             uowcommit.register_object(
                                 attributes.instance_state(c), isdelete=True)
     else:
         for state in deplist:
             uowcommit.register_object(state)
             if self.cascade.delete_orphan:
                 history = uowcommit.get_attribute_history(state, self.key, passive=self.passive_deletes)
                 if history:
                     for child in history.deleted:
                         if self.hasparent(child) is False:
                             uowcommit.register_object(child, isdelete=True)
                             for c, m in self.mapper.cascade_iterator('delete', child):
                                 uowcommit.register_object(
                                     attributes.instance_state(c),
                                     isdelete=True)
Example #9
0
    def test_state_noload_to_lazy(self):
        """Behavioral test to verify the current activity of loader callables."""

        users, Address, addresses, User = (
            self.tables.users,
            self.classes.Address,
            self.tables.addresses,
            self.classes.User,
        )

        mapper(User, users, properties={"addresses": relationship(Address, lazy="noload")})
        mapper(Address, addresses)

        sess = create_session()
        u1 = sess.query(User).options(lazyload(User.addresses)).first()
        assert isinstance(attributes.instance_state(u1).callables["addresses"], strategies.LoadLazyAttribute)
        # expire, it stays
        sess.expire(u1)
        assert isinstance(attributes.instance_state(u1).callables["addresses"], strategies.LoadLazyAttribute)

        # load over it.  callable goes away.
        sess.query(User).first()
        assert "addresses" not in attributes.instance_state(u1).callables

        sess.expunge_all()
        u1 = sess.query(User).options(lazyload(User.addresses)).first()
        sess.expire(u1, ["addresses"])
        assert isinstance(attributes.instance_state(u1).callables["addresses"], strategies.LoadLazyAttribute)

        # load the attr, goes away
        u1.addresses
        assert "addresses" not in attributes.instance_state(u1).callables
Example #10
0
    def test_state_deferred_to_col(self):
        """Behavioral test to verify the current activity of loader callables."""

        users, User = self.tables.users, self.classes.User

        mapper(User, users, properties={"name": deferred(users.c.name)})

        sess = create_session()
        u1 = sess.query(User).options(undefer(User.name)).first()
        assert "name" not in attributes.instance_state(u1).callables

        # mass expire, the attribute was loaded,
        # the attribute gets the callable
        sess.expire(u1)
        assert isinstance(attributes.instance_state(u1).callables["name"], state.InstanceState)

        # load it, callable is gone
        u1.name
        assert "name" not in attributes.instance_state(u1).callables

        # mass expire, attribute was loaded but then deleted,
        # the callable goes away - the state wants to flip
        # it back to its "deferred" loader.
        sess.expunge_all()
        u1 = sess.query(User).options(undefer(User.name)).first()
        del u1.name
        sess.expire(u1)
        assert "name" not in attributes.instance_state(u1).callables

        # single attribute expire, the attribute gets the callable
        sess.expunge_all()
        u1 = sess.query(User).options(undefer(User.name)).first()
        sess.expire(u1, ["name"])
        assert isinstance(attributes.instance_state(u1).callables["name"], state.InstanceState)
Example #11
0
    def set_(state, newvalue, oldvalue, initiator):
        # process "save_update" cascade rules for when an instance
        # is attached to another instance
        if oldvalue is newvalue:
            return newvalue

        sess = session._state_session(state)
        if sess:
            prop = state.manager.mapper._props[key]
            if newvalue is not None:
                newvalue_state = attributes.instance_state(newvalue)
                if prop.cascade.save_update and \
                    (prop.cascade_backrefs or key == initiator.key) and \
                    not sess._contains_state(newvalue_state):
                    sess._save_or_update_state(newvalue_state)

            if oldvalue is not None and \
                oldvalue is not attributes.PASSIVE_NO_RESULT and \
                prop.cascade.delete_orphan:
                # possible to reach here with attributes.NEVER_SET ?
                oldvalue_state = attributes.instance_state(oldvalue)

                if oldvalue_state in sess._new and \
                    prop.mapper._is_orphan(oldvalue_state):
                    sess.expunge(oldvalue)
        return newvalue
Example #12
0
    def test_option_state(self):
        """test that the merged takes on the MapperOption characteristics
        of that which is merged.

        """

        users, User = self.tables.users, self.classes.User

        class Option(MapperOption):
            propagate_to_loaders = True

        opt1, opt2 = Option(), Option()

        sess = sessionmaker()()

        umapper = mapper(User, users)

        sess.add_all([
            User(id=1, name='u1'),
            User(id=2, name='u2'),
        ])
        sess.commit()

        sess2 = sessionmaker()()
        s2_users = sess2.query(User).options(opt2).all()

        # test 1.  no options are replaced by merge options
        sess = sessionmaker()()
        s1_users = sess.query(User).all()

        for u in s1_users:
            ustate = attributes.instance_state(u)
            eq_(ustate.load_path, ())
            eq_(ustate.load_options, set())

        for u in s2_users:
            sess.merge(u)

        for u in s1_users:
            ustate = attributes.instance_state(u)
            eq_(ustate.load_path.path, (umapper, ))
            eq_(ustate.load_options, set([opt2]))

        # test 2.  present options are replaced by merge options
        sess = sessionmaker()()
        s1_users = sess.query(User).options(opt1).all()
        for u in s1_users:
            ustate = attributes.instance_state(u)
            eq_(ustate.load_path.path, (umapper, ))
            eq_(ustate.load_options, set([opt1]))

        for u in s2_users:
            sess.merge(u)

        for u in s1_users:
            ustate = attributes.instance_state(u)
            eq_(ustate.load_path.path, (umapper, ))
            eq_(ustate.load_options, set([opt2]))
    def test_deferred(self):
        for base in (object, MyBaseClass, MyClass):
            class Foo(base):
                pass

            data = {'a': 'this is a', 'b': 12}

            def loader(state, keys):
                for k in keys:
                    state.dict[k] = data[k]
                return attributes.ATTR_WAS_SET

            manager = register_class(Foo)
            manager.deferred_scalar_loader = loader
            attributes.register_attribute(
                Foo, 'a', uselist=False, useobject=False)
            attributes.register_attribute(
                Foo, 'b', uselist=False, useobject=False)

            if base is object:
                assert Foo not in \
                    instrumentation._instrumentation_factory._state_finders
            else:
                assert Foo in \
                    instrumentation._instrumentation_factory._state_finders

            f = Foo()
            attributes.instance_state(f)._expire(
                attributes.instance_dict(f), set())
            eq_(f.a, "this is a")
            eq_(f.b, 12)

            f.a = "this is some new a"
            attributes.instance_state(f)._expire(
                attributes.instance_dict(f), set())
            eq_(f.a, "this is a")
            eq_(f.b, 12)

            attributes.instance_state(f)._expire(
                attributes.instance_dict(f), set())
            f.a = "this is another new a"
            eq_(f.a, "this is another new a")
            eq_(f.b, 12)

            attributes.instance_state(f)._expire(
                attributes.instance_dict(f), set())
            eq_(f.a, "this is a")
            eq_(f.b, 12)

            del f.a
            eq_(f.a, None)
            eq_(f.b, 12)

            attributes.instance_state(f)._commit_all(
                attributes.instance_dict(f))
            eq_(f.a, None)
            eq_(f.b, 12)
Example #14
0
    def test_commit_removes_pending(self):
        global lazy_load
        lazy_load = (p1, ) = [Post("post 1"), ]
        called[0] = 0

        b = Blog("blog 1")
        p1.blog = b
        attributes.instance_state(b).commit_all()
        attributes.instance_state(p1).commit_all()
        assert b.posts == [Post("post 1")]
Example #15
0
    def test_expire_cascade(self):
        mapper(User, users, properties={"addresses": relation(Address, cascade="all, refresh-expire")})
        mapper(Address, addresses)
        s = create_session()
        u = s.query(User).get(8)
        assert u.addresses[0].email_address == "*****@*****.**"

        u.addresses[0].email_address = "someotheraddress"
        s.expire(u)
        u.name
        print attributes.instance_state(u).dict
        assert u.addresses[0].email_address == "*****@*****.**"
Example #16
0
    def test_no_orphan(self):
        """test that a lazily loaded child object is not marked as an orphan"""

        mapper(User, users, properties={
            'addresses':relation(Address, cascade="all,delete-orphan", lazy=True)
        })
        mapper(Address, addresses)

        sess = create_session()
        user = sess.query(User).get(7)
        assert getattr(User, 'addresses').hasparent(attributes.instance_state(user.addresses[0]), optimistic=True)
        assert not sa.orm.class_mapper(Address)._is_orphan(attributes.instance_state(user.addresses[0]))
Example #17
0
    def test_multi_level_no_base(self):
        pjoin = polymorphic_union({
            'manager': managers_table,
            'engineer': engineers_table,
            'hacker': hackers_table
        }, 'type', 'pjoin')

        pjoin2 = polymorphic_union({
            'engineer': engineers_table,
            'hacker': hackers_table
        }, 'type', 'pjoin2')

        employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type)
        manager_mapper = mapper(Manager, managers_table, 
                                inherits=employee_mapper, concrete=True, 
                                polymorphic_identity='manager')
        engineer_mapper = mapper(Engineer, engineers_table, 
                                 with_polymorphic=('*', pjoin2), 
                                 polymorphic_on=pjoin2.c.type,
                                 inherits=employee_mapper, concrete=True,
                                 polymorphic_identity='engineer')
        hacker_mapper = mapper(Hacker, hackers_table, 
                               inherits=engineer_mapper,
                               concrete=True, polymorphic_identity='hacker')

        session = create_session()
        tom = Manager('Tom', 'knows how to manage things')
        jerry = Engineer('Jerry', 'knows how to program')
        hacker = Hacker('Kurt', 'Badass', 'knows how to hack')
        session.add_all((tom, jerry, hacker))
        session.flush()

        # ensure "readonly" on save logic didn't pollute the expired_attributes
        # collection
        assert 'nickname' not in attributes.instance_state(jerry).expired_attributes
        assert 'name' not in attributes.instance_state(jerry).expired_attributes
        assert 'name' not in attributes.instance_state(hacker).expired_attributes
        assert 'nickname' not in attributes.instance_state(hacker).expired_attributes
        def go():
            self.assertEquals(jerry.name, "Jerry")
            self.assertEquals(hacker.nickname, "Badass")
        self.assert_sql_count(testing.db, go, 0)
        
        session.expunge_all()

        assert repr(session.query(Employee).filter(Employee.name=='Tom').one()) == "Manager Tom knows how to manage things"
        assert repr(session.query(Manager).filter(Manager.name=='Tom').one()) == "Manager Tom knows how to manage things"
        
        
        assert set([repr(x) for x in session.query(Employee).all()]) == set(["Engineer Jerry knows how to program", "Manager Tom knows how to manage things", "Hacker Kurt 'Badass' knows how to hack"])
        assert set([repr(x) for x in session.query(Manager).all()]) == set(["Manager Tom knows how to manage things"])
        assert set([repr(x) for x in session.query(Engineer).all()]) == set(["Engineer Jerry knows how to program", "Hacker Kurt 'Badass' knows how to hack"])
        assert set([repr(x) for x in session.query(Hacker).all()]) == set(["Hacker Kurt 'Badass' knows how to hack"])
Example #18
0
 def clear_modified(self):
     '''
     Unconditionally clear all modified state from the attibutes on
     this instance.
     '''
     # Uses this method: http://www.sqlalchemy.org/docs/orm/internals.html?highlight=commit_all#sqlalchemy.orm.state.InstanceState.commit_all
     if int(sa_min_ver) > 7:
         # the methods became private in SA 8, need to check if
         # this is a problem
         return instance_state(self)._commit_all({})
     else:
         return instance_state(self).commit_all({})
Example #19
0
def identity_equal(a, b):
    if a is b:
        return True
    if a is None or b is None:
        return False
    try:
        state_a = attributes.instance_state(a)
        state_b = attributes.instance_state(b)
    except exc.NO_STATE:
        return False
    if state_a.key is None or state_b.key is None:
        return False
    return state_a.key == state_b.key
Example #20
0
 def _fixture(self):
     A, B = self.classes.A, self.classes.B
     session = create_session()
     uowcommit = self._get_test_uow(session)
     a_mapper = class_mapper(A)
     b_mapper= class_mapper(B)
     self.a1 = a1 = A()
     self.b1 = b1 = B()
     uowcommit = self._get_test_uow(session)
     return uowcommit,\
         attributes.instance_state(a1),\
         attributes.instance_state(b1),\
         a_mapper, b_mapper
Example #21
0
    def test_partial_expire(self):
        orders, Order = self.tables.orders, self.classes.Order

        mapper(Order, orders)

        sess = create_session()
        o = sess.query(Order).get(3)

        sess.expire(o, attribute_names=["description"])
        assert "id" in o.__dict__
        assert "description" not in o.__dict__
        assert attributes.instance_state(o).dict["isopen"] == 1

        orders.update(orders.c.id == 3).execute(description="order 3 modified")

        def go():
            assert o.description == "order 3 modified"

        self.assert_sql_count(testing.db, go, 1)
        assert attributes.instance_state(o).dict["description"] == "order 3 modified"

        o.isopen = 5
        sess.expire(o, attribute_names=["description"])
        assert "id" in o.__dict__
        assert "description" not in o.__dict__
        assert o.__dict__["isopen"] == 5
        assert attributes.instance_state(o).committed_state["isopen"] == 1

        def go():
            assert o.description == "order 3 modified"

        self.assert_sql_count(testing.db, go, 1)
        assert o.__dict__["isopen"] == 5
        assert attributes.instance_state(o).dict["description"] == "order 3 modified"
        assert attributes.instance_state(o).committed_state["isopen"] == 1

        sess.flush()

        sess.expire(o, attribute_names=["id", "isopen", "description"])
        assert "id" not in o.__dict__
        assert "isopen" not in o.__dict__
        assert "description" not in o.__dict__

        def go():
            assert o.description == "order 3 modified"
            assert o.id == 3
            assert o.isopen == 5

        self.assert_sql_count(testing.db, go, 1)
Example #22
0
    def value_as_iterable(self, dict_, key, passive=PASSIVE_OFF):
        """Return a list of tuples (state, obj) for the given
        key.

        returns an empty list if the value is None/empty/PASSIVE_NO_RESULT
        """

        impl = self.manager[key].impl
        x = impl.get(self, dict_, passive=passive)
        if x is PASSIVE_NO_RESULT or x is None:
            return []
        elif hasattr(impl, "get_collection"):
            return [(attributes.instance_state(o), o) for o in impl.get_collection(self, dict_, x, passive=passive)]
        else:
            return [(attributes.instance_state(x), x)]
Example #23
0
 def add(self, state):
     if state.key in self:
         if attributes.instance_state(dict.__getitem__(self, state.key)) is not state:
             raise AssertionError("A conflicting state is already present in the identity map for key %r" % (state.key, ))
     else:
         dict.__setitem__(self, state.key, state.obj())
         self._manage_incoming_state(state)
Example #24
0
    def test_basic(self):
        class A(_fixtures.Base):
            pass
        class B(_fixtures.Base):
            pass

        mapper(A, table_a, properties={
            'bs':relation(B, cascade="all, delete-orphan")
            })
        mapper(B, table_b)

        a1 = A(name='a1', bs=[B(name='b1'), B(name='b2'), B(name='b3')])

        sess = create_session()
        sess.add(a1)
        sess.flush()

        sess.expunge_all()

        eq_(sess.query(A).get(a1.id),
            A(name='a1', bs=[B(name='b1'), B(name='b2'), B(name='b3')]))

        a1 = sess.query(A).get(a1.id)
        assert not class_mapper(B)._is_orphan(
            attributes.instance_state(a1.bs[0]))
        a1.bs[0].foo='b2modified'
        a1.bs[1].foo='b3modified'
        sess.flush()

        sess.expunge_all()
        eq_(sess.query(A).get(a1.id),
            A(name='a1', bs=[B(name='b1'), B(name='b2'), B(name='b3')]))
Example #25
0
    def test_gced_delete_on_rollback(self):
        User, users = self.classes.User, self.tables.users

        s = self.session()
        u1 = User(name='ed')
        s.add(u1)
        s.commit()

        s.delete(u1)
        u1_state = attributes.instance_state(u1)
        assert u1_state in s.identity_map.all_states()
        assert u1_state in s._deleted
        s.flush()
        assert u1_state not in s.identity_map.all_states()
        assert u1_state not in s._deleted
        del u1
        gc_collect()
        assert u1_state.obj() is None

        s.rollback()
        # new in 1.1, not in identity map if the object was
        # gc'ed and we restore snapshot; we've changed update_impl
        # to just skip this object
        assert u1_state not in s.identity_map.all_states()

        # in any version, the state is replaced by the query
        # because the identity map would switch it
        u1 = s.query(User).filter_by(name='ed').one()
        assert u1_state not in s.identity_map.all_states()
        assert s.scalar(users.count()) == 1
        s.delete(u1)
        s.flush()
        assert s.scalar(users.count()) == 0
        s.commit()
Example #26
0
 def discard(self, state):
     obj = dict.get(self, state.key, None)
     if obj is not None:
         st = attributes.instance_state(obj)
         if st is state:
             dict.pop(self, state.key, None)
             self._manage_removed_state(state)
Example #27
0
 def test_gced_delete_on_rollback(self):
     s = self.session()
     u1 = User(name='ed')
     s.add(u1)
     s.commit()
     
     s.delete(u1)
     u1_state = attributes.instance_state(u1)
     assert u1_state in s.identity_map.all_states()
     assert u1_state in s._deleted
     s.flush()
     assert u1_state not in s.identity_map.all_states()
     assert u1_state not in s._deleted
     del u1
     gc.collect()
     assert u1_state.obj() is None
     
     s.rollback()
     assert u1_state in s.identity_map.all_states()
     u1 = s.query(User).filter_by(name='ed').one()
     assert u1_state not in s.identity_map.all_states()
     assert s.scalar(users.count()) == 1
     s.delete(u1)
     s.flush()
     assert s.scalar(users.count()) == 0
     s.commit()
Example #28
0
 def is_modified(self):
     '''Check if SQLAlchemy believes this instance is modified.'''
     # TODO: Using this internal flag, is this a private internal
     # behavior? Is there a better, public-api way of getting this info?
     # alternatively is session.is_modified(self) although will this fail
     # if the instance isn't part of the session?
     return instance_state(self).modified
Example #29
0
    def test_m2o_lazy_loader_on_transient(self):
        for loadonpending in (False, True):
            for attach in (False, True):
                for autoflush in (False, True):
                    for manualflush in (False, True):
                        for enable_relationship_rel in (False, True):
                            Child.parent.property.load_on_pending = loadonpending
                            sess.autoflush = autoflush
                            c2 = Child()

                            if attach:
                                state = instance_state(c2)
                                state.session_id = sess.hash_key

                            if enable_relationship_rel:
                                sess.enable_relationship_loading(c2)

                            c2.parent_id = p2.id

                            if manualflush:
                               sess.flush()

                            if (loadonpending and attach) or enable_relationship_rel:
                                assert c2.parent is p2
                            else:
                                assert c2.parent is None

                            sess.rollback()
Example #30
0
    def presort_saves(self, uowcommit, states):
        if not self.passive_updates:
            # if no passive updates, load history on 
            # each collection where parent has changed PK,
            # so that prop_has_changes() returns True
            for state in states:
                if self._pks_changed(uowcommit, state):
                    history = uowcommit.get_attribute_history(
                                        state, 
                                        self.key, 
                                        False)

        if not self.cascade.delete_orphan:
            return
        
        # check for child items removed from the collection
        # if delete_orphan check is turned on.
        for state in states:
            history = uowcommit.get_attribute_history(
                                        state, 
                                        self.key, 
                                        passive=True)
            if history:
                for child in history.deleted:
                    if self.hasparent(child) is False:
                        uowcommit.register_object(child, isdelete=True)
                        for c, m in self.mapper.cascade_iterator(
                                                    'delete', 
                                                    child):
                            uowcommit.register_object(
                                attributes.instance_state(c), isdelete=True)
Example #31
0
def create_version(obj, session, deleted=False):
    obj_mapper = object_mapper(obj)
    history_mapper = obj.__history_mapper__
    history_cls = history_mapper.class_

    obj_state = attributes.instance_state(obj)

    attr = {}

    obj_changed = False

    for om, hm in zip(obj_mapper.iterate_to_root(),
                      history_mapper.iterate_to_root()):
        if hm.single:
            continue

        for hist_col in hm.local_table.c:
            if _is_versioning_col(hist_col):
                continue

            obj_col = om.local_table.c[hist_col.key]

            # get the value of the
            # attribute based on the MapperProperty related to the
            # mapped column.  this will allow usage of MapperProperties
            # that have a different keyname than that of the mapped column.
            try:
                prop = obj_mapper.get_property_by_column(obj_col)
            except UnmappedColumnError:
                # in the case of single table inheritance, there may be
                # columns on the mapped table intended for the subclass only.
                # the "unmapped" status of the subclass column on the
                # base class is a feature of the declarative module.
                continue

            # expired object attributes and also deferred cols might not
            # be in the dict.  force it to load no matter what by
            # using getattr().
            if prop.key not in obj_state.dict:
                getattr(obj, prop.key)

            a, u, d = attributes.get_history(obj, prop.key)

            if d:
                attr[hist_col.key] = d[0]
                obj_changed = True
            elif u:
                attr[hist_col.key] = u[0]
            else:
                # if the attribute had no value.
                attr[hist_col.key] = a[0]
                obj_changed = True

    if not obj_changed:
        # not changed, but we have relationships.  OK
        # check those too
        for prop in obj_mapper.iterate_properties:
            if isinstance(prop, RelationshipProperty) and \
                attributes.get_history(
                    obj, prop.key,
                    passive=attributes.PASSIVE_NO_INITIALIZE).has_changes():
                for p in prop.local_columns:
                    if p.foreign_keys:
                        obj_changed = True
                        break
                if obj_changed is True:
                    break

    if not obj_changed and not deleted:
        return

    attr['version'] = obj.version
    hist = history_cls()
    for key, value in attr.items():
        setattr(hist, key, value)
    session.add(hist)
    obj.version += 1
Example #32
0
 def keyfunc(value):
     state = instance_state(value)
     m = _state_mapper(state)
     return tuple(m._get_state_attr_by_column(state, c)
                  for c in mapping_spec)
    def test_multi_level_no_base(self):
        pjoin = polymorphic_union(
            {
                'manager': managers_table,
                'engineer': engineers_table,
                'hacker': hackers_table
            }, 'type', 'pjoin')
        pjoin2 = polymorphic_union(
            {
                'engineer': engineers_table,
                'hacker': hackers_table
            }, 'type', 'pjoin2')
        employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type)
        manager_mapper = mapper(Manager,
                                managers_table,
                                inherits=employee_mapper,
                                concrete=True,
                                polymorphic_identity='manager')
        engineer_mapper = mapper(Engineer,
                                 engineers_table,
                                 with_polymorphic=('*', pjoin2),
                                 polymorphic_on=pjoin2.c.type,
                                 inherits=employee_mapper,
                                 concrete=True,
                                 polymorphic_identity='engineer')
        hacker_mapper = mapper(Hacker,
                               hackers_table,
                               inherits=engineer_mapper,
                               concrete=True,
                               polymorphic_identity='hacker')
        session = create_session()
        tom = Manager('Tom', 'knows how to manage things')

        assert_raises_message(
            AttributeError,
            "does not implement attribute .?'type' at the instance level.",
            setattr, tom, "type", "sometype")

        jerry = Engineer('Jerry', 'knows how to program')
        hacker = Hacker('Kurt', 'Badass', 'knows how to hack')

        assert_raises_message(
            AttributeError,
            "does not implement attribute .?'type' at the instance level.",
            setattr, hacker, "type", "sometype")

        session.add_all((tom, jerry, hacker))
        session.flush()

        # ensure "readonly" on save logic didn't pollute the
        # expired_attributes collection

        assert 'nickname' \
            not in attributes.instance_state(jerry).expired_attributes
        assert 'name' \
            not in attributes.instance_state(jerry).expired_attributes
        assert 'name' \
            not in attributes.instance_state(hacker).expired_attributes
        assert 'nickname' \
            not in attributes.instance_state(hacker).expired_attributes

        def go():
            eq_(jerry.name, 'Jerry')
            eq_(hacker.nickname, 'Badass')

        self.assert_sql_count(testing.db, go, 0)
        session.expunge_all()
        assert repr(session.query(Employee).filter(Employee.name == 'Tom')
                    .one()) \
            == 'Manager Tom knows how to manage things'
        assert repr(session.query(Manager)
                    .filter(Manager.name == 'Tom').one()) \
            == 'Manager Tom knows how to manage things'
        assert set([repr(x) for x in session.query(Employee).all()]) \
            == set(['Engineer Jerry knows how to program',
                    'Manager Tom knows how to manage things',
                    "Hacker Kurt 'Badass' knows how to hack"])
        assert set([repr(x) for x in session.query(Manager).all()]) \
            == set(['Manager Tom knows how to manage things'])
        assert set([repr(x) for x in session.query(Engineer).all()]) \
            == set(['Engineer Jerry knows how to program',
                    "Hacker Kurt 'Badass' knows how to hack"])
        assert set([repr(x) for x in session.query(Hacker).all()]) \
            == set(["Hacker Kurt 'Badass' knows how to hack"])
Example #34
0
def child_relationships(obj):
    '''Get instances with child relationships to this obj.'''
    for related_obj, mapper, state, data in obj.__mapper__.cascade_iterator(
            "save-update", instance_state(obj)):
        yield related_obj
Example #35
0
def _organize_states_for_save(base_mapper, states, uowtransaction):
    """Make an initial pass across a set of states for INSERT or
    UPDATE.
    
    This includes splitting out into distinct lists for
    each, calling before_insert/before_update, obtaining
    key information for each state including its dictionary,
    mapper, the connection to use for the execution per state,
    and the identity flag.
    
    """

    states_to_insert = []
    states_to_update = []

    for state, dict_, mapper, connection in _connections_for_states(
                                            base_mapper, uowtransaction, 
                                            states):

        has_identity = bool(state.key)
        instance_key = state.key or mapper._identity_key_from_state(state)

        row_switch = None

        # call before_XXX extensions
        if not has_identity:
            mapper.dispatch.before_insert(mapper, connection, state)
        else:
            mapper.dispatch.before_update(mapper, connection, state)

        # detect if we have a "pending" instance (i.e. has 
        # no instance_key attached to it), and another instance 
        # with the same identity key already exists as persistent. 
        # convert to an UPDATE if so.
        if not has_identity and \
            instance_key in uowtransaction.session.identity_map:
            instance = \
                uowtransaction.session.identity_map[instance_key]
            existing = attributes.instance_state(instance)
            if not uowtransaction.is_deleted(existing):
                raise orm_exc.FlushError(
                    "New instance %s with identity key %s conflicts "
                    "with persistent instance %s" % 
                    (state_str(state), instance_key,
                     state_str(existing)))

            base_mapper._log_debug(
                "detected row switch for identity %s.  "
                "will update %s, remove %s from "
                "transaction", instance_key, 
                state_str(state), state_str(existing))

            # remove the "delete" flag from the existing element
            uowtransaction.remove_state_actions(existing)
            row_switch = existing

        if not has_identity and not row_switch:
            states_to_insert.append(
                (state, dict_, mapper, connection, 
                has_identity, instance_key, row_switch)
            )
        else:
            states_to_update.append(
                (state, dict_, mapper, connection, 
                has_identity, instance_key, row_switch)
            )

    return states_to_insert, states_to_update
Example #36
0
 def keyfunc(value):
     state = instance_state(value)
     m = _state_mapper(state)
     return m._get_state_attr_by_column(state, cols[0])
Example #37
0
 def all_states(self):
     return [attributes.instance_state(o) for o in self.itervalues()]
Example #38
0
 def contains_state(self, state):
     return state.key in self and attributes.instance_state(
         self[state.key]) is state
Example #39
0
 def remove(self, state):
     if attributes.instance_state(dict.pop(self, state.key)) is not state:
         raise AssertionError(
             "State %s is not present in this identity map" % state)
     self._manage_removed_state(state)
Example #40
0
 def remove_key(self, key):
     state = attributes.instance_state(dict.__getitem__(self, key))
     self.remove(state)
Example #41
0
 def get_all_pending(self, state, dict_):
     c = self._get_collection_history(state, True)
     return [(attributes.instance_state(x), x)
             for x in c.added_items + c.unchanged_items + c.deleted_items]
Example #42
0
 def append(self, item):
     self.attr.append(attributes.instance_state(self.instance),
                      attributes.instance_dict(self.instance), item, None)
Example #43
0
def has_identity(object):
    state = attributes.instance_state(object)
    return _state_has_identity(state)
Example #44
0
 def test_get_or_create_report_returns_new_report_if_none_exists(self):
     submission = Submission.newest()
     report = submission.get_or_create_report()
     self.assertFalse(instance_state(report).persistent)
    def test_history(self):
        for base in (object, MyBaseClass, MyClass):
            class Foo(base):
                pass
            class Bar(base):
                pass

            attributes.register_class(Foo)
            attributes.register_class(Bar)
            attributes.register_attribute(Foo, "name", uselist=False, useobject=False)
            attributes.register_attribute(Foo, "bars", uselist=True, trackparent=True, useobject=True)
            attributes.register_attribute(Bar, "name", uselist=False, useobject=False)


            f1 = Foo()
            f1.name = 'f1'

            eq_(attributes.get_state_history(attributes.instance_state(f1), 'name'), (['f1'], (), ()))

            b1 = Bar()
            b1.name = 'b1'
            f1.bars.append(b1)
            eq_(attributes.get_state_history(attributes.instance_state(f1), 'bars'), ([b1], [], []))

            attributes.instance_state(f1).commit_all(attributes.instance_dict(f1))
            attributes.instance_state(b1).commit_all(attributes.instance_dict(b1))

            eq_(attributes.get_state_history(attributes.instance_state(f1), 'name'), ((), ['f1'], ()))
            eq_(attributes.get_state_history(attributes.instance_state(f1), 'bars'), ((), [b1], ()))

            f1.name = 'f1mod'
            b2 = Bar()
            b2.name = 'b2'
            f1.bars.append(b2)
            eq_(attributes.get_state_history(attributes.instance_state(f1), 'name'), (['f1mod'], (), ['f1']))
            eq_(attributes.get_state_history(attributes.instance_state(f1), 'bars'), ([b2], [b1], []))
            f1.bars.remove(b1)
            eq_(attributes.get_state_history(attributes.instance_state(f1), 'bars'), ([b2], [], [b1]))
Example #46
0
 def remove(self, item):
     self.attr.remove(attributes.instance_state(self.instance),
                      attributes.instance_dict(self.instance), item, None)
Example #47
0
    def test_multi_level_no_base(self):
        pjoin = polymorphic_union(
            {
                "manager": managers_table,
                "engineer": engineers_table,
                "hacker": hackers_table,
            },
            "type",
            "pjoin",
        )
        pjoin2 = polymorphic_union(
            {
                "engineer": engineers_table,
                "hacker": hackers_table
            },
            "type",
            "pjoin2",
        )
        employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type)
        mapper(
            Manager,
            managers_table,
            inherits=employee_mapper,
            concrete=True,
            polymorphic_identity="manager",
        )
        engineer_mapper = mapper(
            Engineer,
            engineers_table,
            with_polymorphic=("*", pjoin2),
            polymorphic_on=pjoin2.c.type,
            inherits=employee_mapper,
            concrete=True,
            polymorphic_identity="engineer",
        )
        mapper(
            Hacker,
            hackers_table,
            inherits=engineer_mapper,
            concrete=True,
            polymorphic_identity="hacker",
        )
        session = create_session()
        tom = Manager("Tom", "knows how to manage things")

        assert_raises_message(
            AttributeError,
            "does not implement attribute .?'type' at the instance level.",
            setattr,
            tom,
            "type",
            "sometype",
        )

        jerry = Engineer("Jerry", "knows how to program")
        hacker = Hacker("Kurt", "Badass", "knows how to hack")

        assert_raises_message(
            AttributeError,
            "does not implement attribute .?'type' at the instance level.",
            setattr,
            hacker,
            "type",
            "sometype",
        )

        session.add_all((tom, jerry, hacker))
        session.flush()

        # ensure "readonly" on save logic didn't pollute the
        # expired_attributes collection

        assert ("nickname"
                not in attributes.instance_state(jerry).expired_attributes)
        assert ("name"
                not in attributes.instance_state(jerry).expired_attributes)
        assert ("name"
                not in attributes.instance_state(hacker).expired_attributes)
        assert ("nickname"
                not in attributes.instance_state(hacker).expired_attributes)

        def go():
            eq_(jerry.name, "Jerry")
            eq_(hacker.nickname, "Badass")

        self.assert_sql_count(testing.db, go, 0)
        session.expunge_all()
        assert (repr(
            session.query(Employee).filter(Employee.name == "Tom").one()) ==
                "Manager Tom knows how to manage things")
        assert (repr(
            session.query(Manager).filter(Manager.name == "Tom").one()) ==
                "Manager Tom knows how to manage things")
        assert set([repr(x) for x in session.query(Employee).all()]) == set([
            "Engineer Jerry knows how to program",
            "Manager Tom knows how to manage things",
            "Hacker Kurt 'Badass' knows how to hack",
        ])
        assert set([repr(x) for x in session.query(Manager).all()
                    ]) == set(["Manager Tom knows how to manage things"])
        assert set([repr(x) for x in session.query(Engineer).all()]) == set([
            "Engineer Jerry knows how to program",
            "Hacker Kurt 'Badass' knows how to hack",
        ])
        assert set([repr(x) for x in session.query(Hacker).all()
                    ]) == set(["Hacker Kurt 'Badass' knows how to hack"])
Example #48
0
 def test_instance_state(self):
     User = self.classes.User
     u1 = User()
     insp = inspect(u1)
     is_(insp, instance_state(u1))
Example #49
0
 def init_instance(self, mapper, class_, oldinit, instance, args, kwargs):
     session = self.scoped_session()
     state = attributes.instance_state(instance)
     session._save_impl(state)
     return EXT_CONTINUE
Example #50
0
def instance_str(instance):
    """Return a string describing an instance."""

    return state_str(attributes.instance_state(instance))