Exemplo n.º 1
0
    def test_attrs_and_extras_wrong_keyname(self):
        """
        Attribute keys cannot include the separator symbol in the key
        """
        from aiida.backends.djsite.db.models import DbAttributeBaseClass
        from aiida.common.exceptions import ValidationError

        separator = DbAttributeBaseClass._sep

        a = Node()

        with self.assertRaises(ValidationError):
            # I did not store, I cannot modify
            a._set_attr('name' + separator, 'blablabla')

        with self.assertRaises(ValidationError):
            # I did not store, I cannot modify
            a.set_extra('bool' + separator, 'blablabla')
Exemplo n.º 2
0
    def test_description(self):
        """
        Test the update of the description both for stored and unstored
        groups.
        """
        n = Node().store()

        g1 = Group(name='testgroupdescription1', description="g1").store()
        g1.add_nodes(n)

        g2 = Group(name='testgroupdescription2', description="g2")

        # Preliminary checks
        self.assertTrue(g1.is_stored)
        self.assertFalse(g2.is_stored)
        self.assertEquals(g1.description, "g1")
        self.assertEquals(g2.description, "g2")

        # Change
        g1.description = "new1"
        g2.description = "new2"

        # Test that the groups remained in their proper stored state and that
        # the description was updated
        self.assertTrue(g1.is_stored)
        self.assertFalse(g2.is_stored)
        self.assertEquals(g1.description, "new1")
        self.assertEquals(g2.description, "new2")

        # Store g2 and check that the description is OK
        g2.store()
        self.assertTrue(g2.is_stored)
        self.assertEquals(g2.description, "new2")

        # clean-up
        g1.delete()
        g2.delete()
Exemplo n.º 3
0
    def test_datetime_attribute(self):
        from aiida.utils.timezone import (get_current_timezone, is_naive,
                                          make_aware, now)

        a = Node()

        date = now()

        a._set_attr('some_date', date)
        a.store()

        retrieved = a.get_attr('some_date')

        if is_naive(date):
            date_to_compare = make_aware(date, get_current_timezone())
        else:
            date_to_compare = date

        # Do not compare microseconds (they are not stored in the case of MySQL)
        date_to_compare = date_to_compare.replace(microsecond=0)
        retrieved = retrieved.replace(microsecond=0)

        self.assertEquals(date_to_compare, retrieved)
Exemplo n.º 4
0
    def test_attr_listing(self):
        """
        Checks that the list of attributes and extras is ok.
        """
        a = Node()
        attrs_to_set = {
            'none': None,
            'bool': self.boolval,
            'integer': self.intval,
            'float': self.floatval,
            'string': self.stringval,
            'dict': self.dictval,
            'list': self.listval,
        }

        for k, v in attrs_to_set.iteritems():
            a._set_attr(k, v)

        a.store()

        # I now set extras
        extras_to_set = {
            'bool': 'some non-boolean value',
            'some_other_name': 987
        }

        for k, v in extras_to_set.iteritems():
            a.set_extra(k, v)

        self.assertEquals(set(a.attrs()), set(attrs_to_set.keys()))
        self.assertEquals(set(a.extras()), set(extras_to_set.keys()))

        returned_internal_attrs = {k: v for k, v in a.iterattrs()}
        self.assertEquals(returned_internal_attrs, attrs_to_set)

        returned_attrs = {k: v for k, v in a.iterextras()}
        self.assertEquals(returned_attrs, extras_to_set)
Exemplo n.º 5
0
    def test_attr_and_extras(self):
        a = Node()
        a._set_attr('bool', self.boolval)
        a._set_attr('integer', self.intval)
        a._set_attr('float', self.floatval)
        a._set_attr('string', self.stringval)
        a._set_attr('dict', self.dictval)
        a._set_attr('list', self.listval)

        with self.assertRaises(ModificationNotAllowed):
            # I did not store, I cannot modify
            a.set_extra('bool', 'blablabla')

        a.store()

        a_string = 'some non-boolean value'
        # I now set an extra with the same name of an attr
        a.set_extra('bool', a_string)
        # and I check that there is no name clash
        self.assertEquals(self.boolval, a.get_attr('bool'))
        self.assertEquals(a_string, a.get_extra('bool'))
Exemplo n.º 6
0
    def test_comments(self):
        # This is the best way to compare dates with the stored ones, instead of
        # directly loading datetime.datetime.now(), or you can get a
        # "can't compare offset-naive and offset-aware datetimes" error
        user = get_automatic_user()
        a = Node()
        with self.assertRaises(ModificationNotAllowed):
            a.add_comment('text', user=user)
        self.assertEquals(a.get_comments(), [])
        a.store()
        before = timezone.now()
        time.sleep(1)  # I wait 1 second because MySql time precision is 1 sec
        a.add_comment('text', user=user)
        a.add_comment('text2', user=user)
        time.sleep(1)
        after = timezone.now()

        comments = a.get_comments()

        times = [i['mtime'] for i in comments]
        for t in times:
            self.assertTrue(t > before)
            self.assertTrue(t < after)

        self.assertEquals([(i['user__email'], i['content']) for i in comments],
                          [
                              (user.email, 'text'),
                              (user.email, 'text2'),
                          ])
Exemplo n.º 7
0
    def test_links_and_queries(self):
        from aiida.backends.djsite.db.models import DbNode, DbLink

        a = Node()
        a._set_attr('myvalue', 123)
        a.store()

        a2 = Node().store()

        a3 = Node()
        a3._set_attr('myvalue', 145)
        a3.store()

        a4 = Node().store()

        a2.add_link_from(a)
        a3.add_link_from(a2)
        a4.add_link_from(a2)
        a4.add_link_from(a3)

        b = Node.query(pk=a2)
        self.assertEquals(len(b), 1)
        # It is a aiida.orm.Node instance
        self.assertTrue(isinstance(b[0], Node))
        self.assertEquals(b[0].uuid, a2.uuid)

        going_out_from_a2 = Node.query(inputs__in=b)
        # Two nodes going out from a2
        self.assertEquals(len(going_out_from_a2), 2)
        self.assertTrue(isinstance(going_out_from_a2[0], Node))
        self.assertTrue(isinstance(going_out_from_a2[1], Node))
        uuid_set = set([going_out_from_a2[0].uuid, going_out_from_a2[1].uuid])

        # I check that I can query also directly the django DbNode
        # class passing a aiida.orm.Node entity

        going_out_from_a2_db = DbNode.objects.filter(inputs__in=b)
        self.assertEquals(len(going_out_from_a2_db), 2)
        self.assertTrue(isinstance(going_out_from_a2_db[0], DbNode))
        self.assertTrue(isinstance(going_out_from_a2_db[1], DbNode))
        uuid_set_db = set(
            [going_out_from_a2_db[0].uuid, going_out_from_a2_db[1].uuid])

        # I check that doing the query with a Node or DbNode instance,
        # I get the same nodes
        self.assertEquals(uuid_set, uuid_set_db)

        # This time I don't use the __in filter, but I still pass a Node instance
        going_out_from_a2_bis = Node.query(inputs=b[0])
        self.assertEquals(len(going_out_from_a2_bis), 2)
        self.assertTrue(isinstance(going_out_from_a2_bis[0], Node))
        self.assertTrue(isinstance(going_out_from_a2_bis[1], Node))

        # Query for links starting from b[0]==a2 using again the Node class
        output_links_b = DbLink.objects.filter(input=b[0])
        self.assertEquals(len(output_links_b), 2)
        self.assertTrue(isinstance(output_links_b[0], DbLink))
        self.assertTrue(isinstance(output_links_b[1], DbLink))
        uuid_set_db_link = set(
            [output_links_b[0].output.uuid, output_links_b[1].output.uuid])
        self.assertEquals(uuid_set, uuid_set_db_link)

        # Query for related fields using django syntax
        # Note that being myvalue an attribute, it is internally stored starting
        # with an underscore
        nodes_with_given_attribute = Node.query(dbattributes__key='myvalue',
                                                dbattributes__ival=145)
        # should be entry a3
        self.assertEquals(len(nodes_with_given_attribute), 1)
        self.assertTrue(isinstance(nodes_with_given_attribute[0], Node))
        self.assertEquals(nodes_with_given_attribute[0].uuid, a3.uuid)
Exemplo n.º 8
0
    def test_query(self):
        """
        Test if queries are working
        """
        from aiida.orm.group import Group
        from aiida.common.exceptions import NotExistent, MultipleObjectsError
        from aiida.backends.djsite.db.models import DbUser
        from aiida.backends.djsite.utils import get_automatic_user

        g1 = Group(name='testquery1').store()
        g2 = Group(name='testquery2').store()

        n1 = Node().store()
        n2 = Node().store()
        n3 = Node().store()
        n4 = Node().store()

        g1.add_nodes([n1, n2])
        g2.add_nodes([n1, n3])

        newuser = DbUser.objects.create_user(email='*****@*****.**', password='')
        g3 = Group(name='testquery3', user=newuser).store()

        # I should find it
        g1copy = Group.get(uuid=g1.uuid)
        self.assertEquals(g1.pk, g1copy.pk)

        # Try queries
        res = Group.query(nodes=n4)
        self.assertEquals([_.pk for _ in res], [])

        res = Group.query(nodes=n1)
        self.assertEquals([_.pk for _ in res], [_.pk for _ in [g1, g2]])

        res = Group.query(nodes=n2)
        self.assertEquals([_.pk for _ in res], [_.pk for _ in [g1]])

        # I try to use 'get' with zero or multiple results
        with self.assertRaises(NotExistent):
            Group.get(nodes=n4)
        with self.assertRaises(MultipleObjectsError):
            Group.get(nodes=n1)

        self.assertEquals(Group.get(nodes=n2).pk, g1.pk)

        # Query by user
        res = Group.query(user=newuser)
        self.assertEquals(set(_.pk for _ in res), set(_.pk for _ in [g3]))

        # Same query, but using a string (the username=email) instead of
        # a DbUser object
        res = Group.query(user=newuser.email)
        self.assertEquals(set(_.pk for _ in res), set(_.pk for _ in [g3]))

        res = Group.query(user=get_automatic_user())
        self.assertEquals(set(_.pk for _ in res), set(_.pk for _ in [g1, g2]))

        # Final cleanup
        g1.delete()
        g2.delete()
        newuser.delete()
Exemplo n.º 9
0
    def test_replacement_1(self):

        n1 = Node().store()
        n2 = Node().store()

        n1.set_extra("pippo", [1, 2, u'a'])

        n1.set_extra("pippobis", [5, 6, u'c'])

        n2.set_extra("pippo2", [3, 4, u'b'])

        self.assertEqual(
            n1.get_extras(), {
                'pippo': [1, 2, u'a'],
                'pippobis': [5, 6, u'c'],
                '_aiida_hash': n1.get_hash()
            })

        self.assertEquals(n2.get_extras(), {
            'pippo2': [3, 4, 'b'],
            '_aiida_hash': n2.get_hash()
        })

        new_attrs = {"newval1": "v", "newval2": [1, {"c": "d", "e": 2}]}

        n1.reset_extras(new_attrs)
        self.assertEquals(n1.get_extras(), new_attrs)
        self.assertEquals(n2.get_extras(), {
            'pippo2': [3, 4, 'b'],
            '_aiida_hash': n2.get_hash()
        })

        n1.del_extra('newval2')
        del new_attrs['newval2']
        self.assertEquals(n1.get_extras(), new_attrs)
        # Also check that other nodes were not damaged
        self.assertEquals(n2.get_extras(), {
            'pippo2': [3, 4, 'b'],
            '_aiida_hash': n2.get_hash()
        })
Exemplo n.º 10
0
    def test_creation_and_deletion(self):
        """
        Test the creation and deletion of the transitive closure table
        """

        n1 = Node().store()
        n2 = Node().store()
        n3 = Node().store()
        n4 = Node().store()
        n5 = Node().store()
        n6 = Node().store()
        n7 = Node().store()
        n8 = Node().store()
        n9 = Node().store()

        # I create a strange graph, inserting links in a order
        # such that I often have to create the transitive closure
        # between two graphs
        n3.add_link_from(n2)
        n2.add_link_from(n1)
        n5.add_link_from(n3)
        n5.add_link_from(n4)
        n4.add_link_from(n2)

        n7.add_link_from(n6)
        n8.add_link_from(n7)

        # Yet, no links from 1 to 8
        self.assertEquals(
            DbPath.query.filter_by(parent_id=n1.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 0)

        n6.add_link_from(n5)
        # Yet, now 2 links from 1 to 8
        self.assertEquals(
            DbPath.query.filter_by(parent_id=n1.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 2)

        n7.add_link_from(n9)
        # Still two links...
        self.assertEquals(
            DbPath.query.filter_by(parent_id=n1.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 2)

        n9.add_link_from(n6)
        # And now there should be 4 nodes
        self.assertEquals(
            DbPath.query.filter_by(parent_id=n1.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 4)

        ### I start deleting now

        # I cut one branch below: I should loose 2 links
        self.session.delete(
            DbLink.query.filter_by(input_id=n6.dbnode.id,
                                   output_id=n9.dbnode.id).first())
        self.assertEquals(
            DbPath.query.filter_by(parent_id=n1.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 2)

        # I cut another branch above: I should loose one more link
        self.session.delete(
            DbLink.query.filter_by(input_id=n2.dbnode.id,
                                   output_id=n4.dbnode.id).first())

        self.assertEquals(
            DbPath.query.filter_by(parent_id=n1.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 1)

        # Another cut should delete all links
        self.session.delete(
            DbLink.query.filter_by(input_id=n3.dbnode.id,
                                   output_id=n5.dbnode.id).first())

        self.assertEquals(
            DbPath.query.filter_by(parent_id=n1.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 0)

        # But I did not delete everything! For instance, I can check
        # the following links
        self.assertEquals(
            DbPath.query.filter_by(parent_id=n4.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 1)
        self.assertEquals(
            DbPath.query.filter_by(parent_id=n5.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 1)

        # Finally, I reconnect in a different way the two graphs and
        # check that 1 and 8 are again connected
        n4.add_link_from(n3)
        self.assertEquals(
            DbPath.query.filter_by(parent_id=n1.dbnode.id,
                                   child_id=n8.dbnode.id).count(), 1)
Exemplo n.º 11
0
    def test_attr_before_storing(self):
        a = Node()
        a._set_attr('k1', self.boolval)
        a._set_attr('k2', self.intval)
        a._set_attr('k3', self.floatval)
        a._set_attr('k4', self.stringval)
        a._set_attr('k5', self.dictval)
        a._set_attr('k6', self.listval)
        a._set_attr('k7', self.emptydict)
        a._set_attr('k8', self.emptylist)
        a._set_attr('k9', None)

        # Now I check if I can retrieve them, before the storage
        self.assertEquals(self.boolval, a.get_attr('k1'))
        self.assertEquals(self.intval, a.get_attr('k2'))
        self.assertEquals(self.floatval, a.get_attr('k3'))
        self.assertEquals(self.stringval, a.get_attr('k4'))
        self.assertEquals(self.dictval, a.get_attr('k5'))
        self.assertEquals(self.listval, a.get_attr('k6'))
        self.assertEquals(self.emptydict, a.get_attr('k7'))
        self.assertEquals(self.emptylist, a.get_attr('k8'))
        self.assertIsNone(a.get_attr('k9'))

        # And now I try to delete the keys
        a._del_attr('k1')
        a._del_attr('k2')
        a._del_attr('k3')
        a._del_attr('k4')
        a._del_attr('k5')
        a._del_attr('k6')
        a._del_attr('k7')
        a._del_attr('k8')
        a._del_attr('k9')

        with self.assertRaises(AttributeError):
            # I delete twice the same attribute
            a._del_attr('k1')

        with self.assertRaises(AttributeError):
            # I delete a non-existing attribute
            a._del_attr('nonexisting')

        with self.assertRaises(AttributeError):
            # I get a deleted attribute
            a.get_attr('k1')

        with self.assertRaises(AttributeError):
            # I get a non-existing attribute
            a.get_attr('nonexisting')
Exemplo n.º 12
0
    def test_loop_not_allowed(self):
        """
        Test that no loop can be formed when inserting link
        """
        n1 = Node().store()
        n2 = Node().store()
        n3 = Node().store()
        n4 = Node().store()

        n2.add_link_from(n1)
        n3.add_link_from(n2)
        n4.add_link_from(n3)

        with self.assertRaises(ValueError):  # This would generate a loop
            n1.add_link_from(n4)
Exemplo n.º 13
0
    def test_links_and_queries(self):
        a = Node()
        a._set_attr('myvalue', 123)
        a.store()

        a2 = Node().store()

        a3 = Node()
        a3._set_attr('myvalue', 145)
        a3.store()

        a4 = Node().store()

        a2.add_link_from(a)
        a3.add_link_from(a2)
        a4.add_link_from(a2)
        a4.add_link_from(a3)

        b = Node.query(id=a2.id).all()
        self.assertEquals(len(b), 1)
        # It is a aiida.orm.Node instance
        self.assertTrue(isinstance(b[0], Node))
        self.assertEquals(b[0].uuid, a2.uuid)

        going_out_from_a2 = Node.query(inputs__id__in=[_.id for _ in b]).all()
        # Two nodes going out from a2
        self.assertEquals(len(going_out_from_a2), 2)
        self.assertTrue(isinstance(going_out_from_a2[0], Node))
        self.assertTrue(isinstance(going_out_from_a2[1], Node))
        uuid_set = set([going_out_from_a2[0].uuid, going_out_from_a2[1].uuid])

        # I check that I can query also directly the django DbNode
        # class passing a aiida.orm.Node entity

        # # XXX SP: we can't do this using SqlAlchemy => pass a Node instance and
        # # expect a filter on the DbNode id
        # going_out_from_a2_db = DbNode.query.filter(DbNode.inputs.in_(b)).all()
        # self.assertEquals(len(going_out_from_a2_db), 2)
        # self.assertTrue(isinstance(going_out_from_a2_db[0], DbNode))
        # self.assertTrue(isinstance(going_out_from_a2_db[1], DbNode))
        # uuid_set_db = set([going_out_from_a2_db[0].uuid,
        #                    going_out_from_a2_db[1].uuid])
        #
        # # I check that doing the query with a Node or DbNode instance,
        # # I get the same nodes
        # self.assertEquals(uuid_set, uuid_set_db)
        #
        # # This time I don't use the __in filter, but I still pass a Node instance
        # going_out_from_a2_bis = Node.query(inputs=b[0]).all()
        # self.assertEquals(len(going_out_from_a2_bis), 2)
        # self.assertTrue(isinstance(going_out_from_a2_bis[0], Node))
        # self.assertTrue(isinstance(going_out_from_a2_bis[1], Node))
        #
        # # Query for links starting from b[0]==a2 using again the Node class
        # output_links_b = DbLink.query.filter_by(input=b[0])
        # self.assertEquals(len(output_links_b), 2)
        # self.assertTrue(isinstance(output_links_b[0], DbLink))
        # self.assertTrue(isinstance(output_links_b[1], DbLink))
        # uuid_set_db_link = set([output_links_b[0].output.uuid,
        #                         output_links_b[1].output.uuid])
        # self.assertEquals(uuid_set, uuid_set_db_link)

        # Query for related fields using django syntax
        # Note that being myvalue an attribute, it is internally stored starting
        # with an underscore
        nodes_with_given_attribute = Node.query(dbattributes__key='myvalue',
                                                dbattributes__ival=145).all()
        # should be entry a3
        self.assertEquals(len(nodes_with_given_attribute), 1)
        self.assertTrue(isinstance(nodes_with_given_attribute[0], Node))
        self.assertEquals(nodes_with_given_attribute[0].uuid, a3.uuid)
Exemplo n.º 14
0
    def test_get_inputs_and_outputs(self):
        a1 = Node().store()
        a2 = Node().store()
        a3 = Node().store()
        a4 = Node().store()

        a2.add_link_from(a1)
        a3.add_link_from(a2)
        a4.add_link_from(a2)
        a4.add_link_from(a3)

        # I check that I get the correct links
        self.assertEquals(set([n.uuid for n in a1.get_inputs()]), set([]))
        self.assertEquals(set([n.uuid for n in a1.get_outputs()]),
                          set([a2.uuid]))

        self.assertEquals(set([n.uuid for n in a2.get_inputs()]),
                          set([a1.uuid]))
        self.assertEquals(set([n.uuid for n in a2.get_outputs()]),
                          set([a3.uuid, a4.uuid]))

        self.assertEquals(set([n.uuid for n in a3.get_inputs()]),
                          set([a2.uuid]))
        self.assertEquals(set([n.uuid for n in a3.get_outputs()]),
                          set([a4.uuid]))

        self.assertEquals(set([n.uuid for n in a4.get_inputs()]),
                          set([a2.uuid, a3.uuid]))
        self.assertEquals(set([n.uuid for n in a4.get_outputs()]), set([]))
Exemplo n.º 15
0
    def test_node_access_with_sessions(self):
        from aiida.utils import timezone
        from aiida.orm.node import Node
        import aiida.backends.sqlalchemy as sa
        from sqlalchemy.orm import sessionmaker
        from aiida.orm.implementation.sqlalchemy.node import DbNode

        Session = sessionmaker(bind=sa.engine)
        custom_session = Session()

        node = Node().store()
        master_session = node._dbnode.session
        self.assertIsNot(master_session, custom_session)

        # Manually load the DbNode in a different session
        dbnode_reloaded = custom_session.query(DbNode).get(node.id)

        # Now, go through one by one changing the possible attributes (of the model)
        # and check that they're updated when the user reads them from the aiida node

        def check_attrs_match(name):
            node_attr = getattr(node, name)
            dbnode_attr = getattr(dbnode_reloaded, name)
            self.assertEqual(
                node_attr, dbnode_attr,
                "Values of '{}' don't match ({} != {})".format(
                    name, node_attr, dbnode_attr))

        def do_value_checks(attr_name, original, changed):
            try:
                setattr(node, attr_name, original)
            except AttributeError:
                # This may mean that it is immutable, but we should still be able to
                # change it below directly through the dbnode
                pass
            # Refresh the custom session and make sure they match
            custom_session.refresh(dbnode_reloaded, attribute_names=[str_attr])
            check_attrs_match(attr_name)

            # Change the value in the custom session via the DbNode
            setattr(dbnode_reloaded, attr_name, changed)
            custom_session.commit()

            # Check that the Node 'sees' the change
            check_attrs_match(str_attr)

        for str_attr in ['label', 'description']:
            do_value_checks(str_attr, 'original', 'changed')

        do_value_checks('nodeversion', 1, 2)
        do_value_checks('public', True, False)

        # Attributes
        self.assertDictEqual(node._attributes(), dbnode_reloaded.attributes)
        dbnode_reloaded.attributes['test_attrs'] = 'Boo!'
        custom_session.commit()
        self.assertDictEqual(node._attributes(), dbnode_reloaded.attributes)

        # Extras
        self.assertDictEqual(node.get_extras(), dbnode_reloaded.extras)
        dbnode_reloaded.extras['test_extras'] = 'Boo!'
        custom_session.commit()
        self.assertDictEqual(node._attributes(), dbnode_reloaded.attributes)
Exemplo n.º 16
0
    def test_attributes_on_copy(self):
        import copy

        a = Node()
        attrs_to_set = {
            'none': None,
            'bool': self.boolval,
            'integer': self.intval,
            'float': self.floatval,
            'string': self.stringval,
            'dict': self.dictval,
            'list': self.listval,
            'emptydict': {},
            'emptylist': [],
        }

        for k, v in attrs_to_set.iteritems():
            a._set_attr(k, v)

        a.store()

        # I now set extras
        extras_to_set = {
            'bool': 'some non-boolean value',
            'some_other_name': 987
        }

        for k, v in extras_to_set.iteritems():
            a.set_extra(k, v)

            # I make a copy
        b = a.copy()
        # I modify an attribute and add a new one; I mirror it in the dictionary
        # for later checking
        b_expected_attributes = copy.deepcopy(attrs_to_set)
        b._set_attr('integer', 489)
        b_expected_attributes['integer'] = 489
        b._set_attr('new', 'cvb')
        b_expected_attributes['new'] = 'cvb'

        # I check before storing that the attributes are ok
        self.assertEquals({k: v
                           for k, v in b.iterattrs()}, b_expected_attributes)
        # Note that during copy, I do not copy the extras!
        self.assertEquals({k: v for k, v in b.iterextras()}, {})

        # I store now
        b.store()
        # and I finally add a extras
        b.set_extra('meta', 'textofext')
        b_expected_extras = {'meta': 'textofext'}

        # Now I check for the attributes
        # First I check that nothing has changed
        self.assertEquals({k: v for k, v in a.iterattrs()}, attrs_to_set)
        self.assertEquals({k: v for k, v in a.iterextras()}, extras_to_set)

        # I check then on the 'b' copy
        self.assertEquals({k: v
                           for k, v in b.iterattrs()}, b_expected_attributes)
        self.assertEquals({k: v for k, v in b.iterextras()}, b_expected_extras)
Exemplo n.º 17
0
    def test_files(self):
        import tempfile

        a = Node()

        file_content = 'some text ABCDE'
        file_content_different = 'other values 12345'

        with tempfile.NamedTemporaryFile() as f:
            f.write(file_content)
            f.flush()
            a.add_path(f.name, 'file1.txt')
            a.add_path(f.name, 'file2.txt')

        self.assertEquals(set(a.get_folder_list()),
                          set(['file1.txt', 'file2.txt']))
        with open(a.get_abs_path('file1.txt')) as f:
            self.assertEquals(f.read(), file_content)
        with open(a.get_abs_path('file2.txt')) as f:
            self.assertEquals(f.read(), file_content)

        b = a.copy()
        self.assertNotEquals(a.uuid, b.uuid)

        # Check that the content is there
        self.assertEquals(set(b.get_folder_list()),
                          set(['file1.txt', 'file2.txt']))
        with open(b.get_abs_path('file1.txt')) as f:
            self.assertEquals(f.read(), file_content)
        with open(b.get_abs_path('file2.txt')) as f:
            self.assertEquals(f.read(), file_content)

        # I overwrite a file and create a new one in the copy only
        with tempfile.NamedTemporaryFile() as f:
            f.write(file_content_different)
            f.flush()
            b.add_path(f.name, 'file2.txt')
            b.add_path(f.name, 'file3.txt')

        # I check the new content, and that the old one has not changed
        self.assertEquals(set(a.get_folder_list()),
                          set(['file1.txt', 'file2.txt']))
        with open(a.get_abs_path('file1.txt')) as f:
            self.assertEquals(f.read(), file_content)
        with open(a.get_abs_path('file2.txt')) as f:
            self.assertEquals(f.read(), file_content)
        self.assertEquals(set(b.get_folder_list()),
                          set(['file1.txt', 'file2.txt', 'file3.txt']))
        with open(b.get_abs_path('file1.txt')) as f:
            self.assertEquals(f.read(), file_content)
        with open(b.get_abs_path('file2.txt')) as f:
            self.assertEquals(f.read(), file_content_different)
        with open(b.get_abs_path('file3.txt')) as f:
            self.assertEquals(f.read(), file_content_different)

        # This should in principle change the location of the files,
        # so I recheck
        a.store()

        # I now copy after storing
        c = a.copy()
        # I overwrite a file and create a new one in the copy only
        with tempfile.NamedTemporaryFile() as f:
            f.write(file_content_different)
            f.flush()
            c.add_path(f.name, 'file1.txt')
            c.add_path(f.name, 'file4.txt')

        self.assertEquals(set(a.get_folder_list()),
                          set(['file1.txt', 'file2.txt']))
        with open(a.get_abs_path('file1.txt')) as f:
            self.assertEquals(f.read(), file_content)
        with open(a.get_abs_path('file2.txt')) as f:
            self.assertEquals(f.read(), file_content)

        self.assertEquals(set(c.get_folder_list()),
                          set(['file1.txt', 'file2.txt', 'file4.txt']))
        with open(c.get_abs_path('file1.txt')) as f:
            self.assertEquals(f.read(), file_content_different)
        with open(c.get_abs_path('file2.txt')) as f:
            self.assertEquals(f.read(), file_content)
        with open(c.get_abs_path('file4.txt')) as f:
            self.assertEquals(f.read(), file_content_different)
Exemplo n.º 18
0
    def test_replacement_1(self):
        from aiida.backends.djsite.db.models import DbExtra

        n1 = Node().store()
        n2 = Node().store()

        DbExtra.set_value_for_node(n1._dbnode, "pippo", [1, 2, 'a'])
        DbExtra.set_value_for_node(n1._dbnode, "pippobis", [5, 6, 'c'])
        DbExtra.set_value_for_node(n2._dbnode, "pippo2", [3, 4, 'b'])

        self.assertEquals(n1.get_extras(), {'pippo': [1, 2, 'a'],
                                            'pippobis': [5, 6, 'c'],
                                            '_aiida_hash': n1.get_hash()
                                            })
        self.assertEquals(n2.get_extras(), {'pippo2': [3, 4, 'b'],
                                            '_aiida_hash': n2.get_hash()
                                            })

        new_attrs = {"newval1": "v", "newval2": [1, {"c": "d", "e": 2}]}

        DbExtra.reset_values_for_node(n1._dbnode, attributes=new_attrs)
        self.assertEquals(n1.get_extras(), new_attrs)
        self.assertEquals(n2.get_extras(), {'pippo2': [3, 4, 'b'], '_aiida_hash': n2.get_hash()})

        DbExtra.del_value_for_node(n1._dbnode, key='newval2')
        del new_attrs['newval2']
        self.assertEquals(n1.get_extras(), new_attrs)
        # Also check that other nodes were not damaged
        self.assertEquals(n2.get_extras(), {'pippo2': [3, 4, 'b'], '_aiida_hash': n2.get_hash()})
Exemplo n.º 19
0
    def test_folders(self):
        """
        Similar as test_files, but I manipulate a tree of folders
        """
        import tempfile
        import os, shutil
        import random, string

        a = Node()

        # Since Node uses the same method of Folder(),
        # for this test I create a test folder by hand
        # For any non-test usage, use SandboxFolder()!

        directory = os.path.realpath(os.path.join('/', 'tmp', 'tmp_try'))
        while os.path.exists(os.path.join(directory)):
            # I append a random letter/number until it is unique
            directory += random.choice(string.ascii_uppercase + string.digits)

        # create a folder structure to copy around
        tree_1 = os.path.join(directory, 'tree_1')
        os.makedirs(tree_1)
        file_content = 'some text ABCDE'
        file_content_different = 'other values 12345'
        with open(os.path.join(tree_1, 'file1.txt'), 'w') as f:
            f.write(file_content)
        os.mkdir(os.path.join(tree_1, 'dir1'))
        os.mkdir(os.path.join(tree_1, 'dir1', 'dir2'))
        with open(os.path.join(tree_1, 'dir1', 'file2.txt'), 'w') as f:
            f.write(file_content)
        os.mkdir(os.path.join(tree_1, 'dir1', 'dir2', 'dir3'))

        # add the tree to the node

        a.add_path(tree_1, 'tree_1')

        # verify if the node has the structure I expect
        self.assertEquals(set(a.get_folder_list()), set(['tree_1']))
        self.assertEquals(set(a.get_folder_list('tree_1')),
                          set(['file1.txt', 'dir1']))
        self.assertEquals(
            set(a.get_folder_list(os.path.join('tree_1', 'dir1'))),
            set(['dir2', 'file2.txt']))
        with open(a.get_abs_path(os.path.join('tree_1', 'file1.txt'))) as f:
            self.assertEquals(f.read(), file_content)
        with open(a.get_abs_path(os.path.join('tree_1', 'dir1',
                                              'file2.txt'))) as f:
            self.assertEquals(f.read(), file_content)

        # try to exit from the folder
        with self.assertRaises(ValueError):
            a.get_folder_list('..')

        # copy into a new node
        b = a.copy()
        self.assertNotEquals(a.uuid, b.uuid)

        # Check that the content is there
        self.assertEquals(set(b.get_folder_list('.')), set(['tree_1']))
        self.assertEquals(set(b.get_folder_list('tree_1')),
                          set(['file1.txt', 'dir1']))
        self.assertEquals(
            set(b.get_folder_list(os.path.join('tree_1', 'dir1'))),
            set(['dir2', 'file2.txt']))
        with open(b.get_abs_path(os.path.join('tree_1', 'file1.txt'))) as f:
            self.assertEquals(f.read(), file_content)
        with open(b.get_abs_path(os.path.join('tree_1', 'dir1',
                                              'file2.txt'))) as f:
            self.assertEquals(f.read(), file_content)

        # I overwrite a file and create a new one in the copy only
        dir3 = os.path.join(directory, 'dir3')
        os.mkdir(dir3)

        b.add_path(dir3, os.path.join('tree_1', 'dir3'))
        # no absolute path here
        with self.assertRaises(ValueError):
            b.add_path('dir3', os.path.join('tree_1', 'dir3'))

        with tempfile.NamedTemporaryFile() as f:
            f.write(file_content_different)
            f.flush()
            b.add_path(f.name, 'file3.txt')

        # I check the new content, and that the old one has not changed
        # old
        self.assertEquals(set(a.get_folder_list('.')), set(['tree_1']))
        self.assertEquals(set(a.get_folder_list('tree_1')),
                          set(['file1.txt', 'dir1']))
        self.assertEquals(
            set(a.get_folder_list(os.path.join('tree_1', 'dir1'))),
            set(['dir2', 'file2.txt']))
        with open(a.get_abs_path(os.path.join('tree_1', 'file1.txt'))) as f:
            self.assertEquals(f.read(), file_content)
        with open(a.get_abs_path(os.path.join('tree_1', 'dir1',
                                              'file2.txt'))) as f:
            self.assertEquals(f.read(), file_content)
        # new
        self.assertEquals(set(b.get_folder_list('.')),
                          set(['tree_1', 'file3.txt']))
        self.assertEquals(set(b.get_folder_list('tree_1')),
                          set(['file1.txt', 'dir1', 'dir3']))
        self.assertEquals(
            set(b.get_folder_list(os.path.join('tree_1', 'dir1'))),
            set(['dir2', 'file2.txt']))
        with open(b.get_abs_path(os.path.join('tree_1', 'file1.txt'))) as f:
            self.assertEquals(f.read(), file_content)
        with open(b.get_abs_path(os.path.join('tree_1', 'dir1',
                                              'file2.txt'))) as f:
            self.assertEquals(f.read(), file_content)

        # This should in principle change the location of the files,
        # so I recheck
        a.store()

        # I now copy after storing
        c = a.copy()
        # I overwrite a file, create a new one and remove a directory
        # in the copy only
        with tempfile.NamedTemporaryFile() as f:
            f.write(file_content_different)
            f.flush()
            c.add_path(f.name, os.path.join('tree_1', 'file1.txt'))
            c.add_path(f.name, os.path.join('tree_1', 'dir1', 'file4.txt'))
        c.remove_path(os.path.join('tree_1', 'dir1', 'dir2'))

        # check old
        self.assertEquals(set(a.get_folder_list('.')), set(['tree_1']))
        self.assertEquals(set(a.get_folder_list('tree_1')),
                          set(['file1.txt', 'dir1']))
        self.assertEquals(
            set(a.get_folder_list(os.path.join('tree_1', 'dir1'))),
            set(['dir2', 'file2.txt']))
        with open(a.get_abs_path(os.path.join('tree_1', 'file1.txt'))) as f:
            self.assertEquals(f.read(), file_content)
        with open(a.get_abs_path(os.path.join('tree_1', 'dir1',
                                              'file2.txt'))) as f:
            self.assertEquals(f.read(), file_content)

        # check new
        self.assertEquals(set(c.get_folder_list('.')), set(['tree_1']))
        self.assertEquals(set(c.get_folder_list('tree_1')),
                          set(['file1.txt', 'dir1']))
        self.assertEquals(
            set(c.get_folder_list(os.path.join('tree_1', 'dir1'))),
            set(['file2.txt', 'file4.txt']))
        with open(c.get_abs_path(os.path.join('tree_1', 'file1.txt'))) as f:
            self.assertEquals(f.read(), file_content_different)
        with open(c.get_abs_path(os.path.join('tree_1', 'dir1',
                                              'file2.txt'))) as f:
            self.assertEquals(f.read(), file_content)

        # garbage cleaning
        shutil.rmtree(directory)
Exemplo n.º 20
0
    def test_creation_and_deletion(self):
        from aiida.backends.sqlalchemy.models.node import DbLink  # Direct links
        from aiida.backends.sqlalchemy.models.node import DbPath # The transitive closure table
        from aiida.orm.node import Node

        n1 = Node().store()
        n2 = Node().store()
        n3 = Node().store()
        n4 = Node().store()
        n5 = Node().store()
        n6 = Node().store()
        n7 = Node().store()
        n8 = Node().store()
        n9 = Node().store()

        # I create a strange graph, inserting links in a order
        # such that I often have to create the transitive closure
        # between two graphs
        n3.add_link_from(n2)
        n2.add_link_from(n1)
        n5.add_link_from(n3)
        n5.add_link_from(n4)
        n4.add_link_from(n2)

        n7.add_link_from(n6)
        n8.add_link_from(n7)

        # Yet, no links from 1 to 8
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n1.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            0)

        n6.add_link_from(n5)
        # Yet, now 2 links from 1 to 8
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n1.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            2)

        n7.add_link_from(n9)
        # Still two links...
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n1.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            2)

        n9.add_link_from(n6)
        # And now there should be 4 nodes
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n1.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            4)

        ### I start deleting now

        # I cut one branch below: I should loose 2 links
        DbLink.query.filter(DbLink.input == n6.dbnode,
                            DbLink.output == n9.dbnode).delete()
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n1.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            2)

        # I cut another branch above: I should loose one more link
        DbLink.query.filter(DbLink.input == n2.dbnode,
                            DbLink.output == n4.dbnode).delete()
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n1.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            1)

        # Another cut should delete all links
        DbLink.query.filter(DbLink.input == n3.dbnode,
                            DbLink.output == n5.dbnode).delete()

        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n1.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            0)

        # But I did not delete everything! For instance, I can check
        # the following links
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n4.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            1)
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n5.dbnode,
                                DbPath.child == n7.dbnode).distinct().count(),
            1)

        # Finally, I reconnect in a different way the two graphs and
        # check that 1 and 8 are again connected
        n4.add_link_from(n3)
        self.assertEquals(
            DbPath.query.filter(DbPath.parent == n1.dbnode,
                                DbPath.child == n8.dbnode).distinct().count(),
            1)
Exemplo n.º 21
0
    def test_attr_after_storing(self):
        a = Node()
        a._set_attr('none', None)
        a._set_attr('bool', self.boolval)
        a._set_attr('integer', self.intval)
        a._set_attr('float', self.floatval)
        a._set_attr('string', self.stringval)
        a._set_attr('dict', self.dictval)
        a._set_attr('list', self.listval)

        a.store()

        # Now I check if I can retrieve them, before the storage
        self.assertIsNone(a.get_attr('none'))
        self.assertEquals(self.boolval, a.get_attr('bool'))
        self.assertEquals(self.intval, a.get_attr('integer'))
        self.assertEquals(self.floatval, a.get_attr('float'))
        self.assertEquals(self.stringval, a.get_attr('string'))
        self.assertEquals(self.dictval, a.get_attr('dict'))
        self.assertEquals(self.listval, a.get_attr('list'))

        # And now I try to edit/delete the keys; I should not be able to do it
        # after saving. I try only for a couple of attributes
        with self.assertRaises(ModificationNotAllowed):
            a._del_attr('bool')
        with self.assertRaises(ModificationNotAllowed):
            a._set_attr('integer', 13)
Exemplo n.º 22
0
    def test_replace_extras_2(self):
        """
        This is a Django specific test which checks (manually) that,
        when replacing list and dict with objects that have no deepness,
        no junk is left in the DB (i.e., no 'dict.a', 'list.3.h', ...
        """
        from aiida.backends.djsite.db.models import DbExtra

        a = Node().store()
        extras_to_set = {
            'bool': True,
            'integer': 12,
            'float': 26.2,
            'string': "a string",
            'dict': {
                "a": "b",
                "sublist": [1, 2, 3],
                "subdict": {
                    "c": "d"
                }
            },
            'list': [1, True, "ggg", {
                'h': 'j'
            }, [9, 8, 7]],
        }

        # I redefine the keys with more complicated data, and
        # changing the data type too
        new_extras = {
            'bool': 12,
            'integer': [2, [3], 'a'],
            'float': {
                'n': 'm',
                'x': [1, 'r', {}]
            },
            'string': True,
            'dict': 'text',
            'list': 66.3,
        }

        for k, v in extras_to_set.iteritems():
            a.set_extra(k, v)

        for k, v in new_extras.iteritems():
            # I delete one by one the keys and check if the operation is
            # performed correctly
            a.set_extra(k, v)

        # I update extras_to_set with the new entries, and do the comparison
        # again
        extras_to_set.update(new_extras)

        # Check (manually) that, when replacing list and dict with objects
        # that have no deepness, no junk is left in the DB (i.e., no
        # 'dict.a', 'list.3.h', ...
        self.assertEquals(
            len(
                DbExtra.objects.filter(dbnode=a,
                                       key__startswith=('list' +
                                                        DbExtra._sep))), 0)
        self.assertEquals(
            len(
                DbExtra.objects.filter(dbnode=a,
                                       key__startswith=('dict' +
                                                        DbExtra._sep))), 0)
Exemplo n.º 23
0
    def test_attr_with_reload(self):
        a = Node()
        a._set_attr('none', None)
        a._set_attr('bool', self.boolval)
        a._set_attr('integer', self.intval)
        a._set_attr('float', self.floatval)
        a._set_attr('string', self.stringval)
        a._set_attr('dict', self.dictval)
        a._set_attr('list', self.listval)

        a.store()

        b = Node.get_subclass_from_uuid(a.uuid)
        self.assertIsNone(a.get_attr('none'))
        self.assertEquals(self.boolval, b.get_attr('bool'))
        self.assertEquals(self.intval, b.get_attr('integer'))
        self.assertEquals(self.floatval, b.get_attr('float'))
        self.assertEquals(self.stringval, b.get_attr('string'))
        self.assertEquals(self.dictval, b.get_attr('dict'))
        self.assertEquals(self.listval, b.get_attr('list'))

        # Reload directly
        b = Node(dbnode=a.dbnode)
        self.assertIsNone(a.get_attr('none'))
        self.assertEquals(self.boolval, b.get_attr('bool'))
        self.assertEquals(self.intval, b.get_attr('integer'))
        self.assertEquals(self.floatval, b.get_attr('float'))
        self.assertEquals(self.stringval, b.get_attr('string'))
        self.assertEquals(self.dictval, b.get_attr('dict'))
        self.assertEquals(self.listval, b.get_attr('list'))

        with self.assertRaises(ModificationNotAllowed):
            a._set_attr('i', 12)
Exemplo n.º 24
0
    def test_creation_and_deletion(self):
        from aiida.backends.djsite.db.models import DbLink  # Direct links
        from aiida.orm.querybuilder import QueryBuilder
        from aiida.common.links import LinkType

        n1 = Node().store()
        n2 = Node().store()
        n3 = Node().store()
        n4 = Node().store()
        n5 = Node().store()
        n6 = Node().store()
        n7 = Node().store()
        n8 = Node().store()
        n9 = Node().store()

        # I create a strange graph, inserting links in a order
        # such that I often have to create the transitive closure
        # between two graphs
        n3.add_link_from(n2, link_type=LinkType.CREATE)
        n2.add_link_from(n1, link_type=LinkType.CREATE)
        n5.add_link_from(n3, link_type=LinkType.CREATE)
        n5.add_link_from(n4, link_type=LinkType.CREATE)
        n4.add_link_from(n2, link_type=LinkType.CREATE)

        n7.add_link_from(n6, link_type=LinkType.CREATE)
        n8.add_link_from(n7, link_type=LinkType.CREATE)

        # Yet, no links from 1 to 8
        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n1.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 0)

        n6.add_link_from(n5, link_type=LinkType.INPUT)

        # Yet, now 2 links from 1 to 8
        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n1.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 2)

        n7.add_link_from(n9, link_type=LinkType.INPUT)
        # Still two links...
        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n1.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 2)

        n9.add_link_from(n6, link_type=LinkType.INPUT)
        # And now there should be 4 nodes
        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n1.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 4)

        ### I start deleting now

        # I cut one branch below: I should loose 2 links
        DbLink.objects.filter(input=n6, output=n9).delete()

        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n1.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 2)

        DbLink.objects.filter(input=n2, output=n4).delete()

        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n1.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 1)
        #~ self.assertEquals(
        #~ len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 1)

        # Another cut should delete all links
        DbLink.objects.filter(input=n3, output=n5).delete()
        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n1.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 0)
        #~ self.assertEquals(
        #~ len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 0)

        # But I did not delete everything! For instance, I can check
        # the following links
        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n4.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 1)
        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n5.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n7.pk
                                 }).count(), 1)
        #~ self.assertEquals(
        #~ len(DbPath.objects.filter(parent=n4, child=n8).distinct()), 1)
        #~ self.assertEquals(
        #~ len(DbPath.objects.filter(parent=n5, child=n7).distinct()), 1)

        # Finally, I reconnect in a different way the two graphs and
        # check that 1 and 8 are again connected
        n4.add_link_from(n3, link_type=LinkType.INPUT)

        self.assertEquals(
            QueryBuilder().append(Node, filters={
                'id': n1.pk
            }, tag='anc').append(Node,
                                 descendant_of='anc',
                                 filters={
                                     'id': n8.pk
                                 }).count(), 1)
Exemplo n.º 25
0
    def test_creation_and_deletion(self):
        from aiida.backends.djsite.db.models import DbLink  # Direct links
        from aiida.backends.djsite.db.models import DbPath  # The transitive closure table

        n1 = Node().store()
        n2 = Node().store()
        n3 = Node().store()
        n4 = Node().store()
        n5 = Node().store()
        n6 = Node().store()
        n7 = Node().store()
        n8 = Node().store()
        n9 = Node().store()

        # I create a strange graph, inserting links in a order
        # such that I often have to create the transitive closure
        # between two graphs
        n3.add_link_from(n2)
        n2.add_link_from(n1)
        n5.add_link_from(n3)
        n5.add_link_from(n4)
        n4.add_link_from(n2)

        n7.add_link_from(n6)
        n8.add_link_from(n7)

        # Yet, no links from 1 to 8
        self.assertEquals(
            len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 0)

        n6.add_link_from(n5)
        # Yet, now 2 links from 1 to 8
        self.assertEquals(
            len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 2)

        n7.add_link_from(n9)
        # Still two links...
        self.assertEquals(
            len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 2)

        n9.add_link_from(n6)
        # And now there should be 4 nodes
        self.assertEquals(
            len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 4)

        ### I start deleting now

        # I cut one branch below: I should loose 2 links
        DbLink.objects.filter(input=n6, output=n9).delete()
        self.assertEquals(
            len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 2)

        # print "\n".join([str((i.pk, i.input.pk, i.output.pk))
        #                 for i in DbLink.objects.filter()])
        # print "\n".join([str((i.pk, i.parent.pk, i.child.pk, i.depth,
        #                      i.entry_edge_id, i.direct_edge_id,
        #                      i.exit_edge_id)) for i in DbPath.objects.filter()])

        # I cut another branch above: I should loose one more link
        DbLink.objects.filter(input=n2, output=n4).delete()
        # print "\n".join([str((i.pk, i.input.pk, i.output.pk))
        #                 for i in DbLink.objects.filter()])
        # print "\n".join([str((i.pk, i.parent.pk, i.child.pk, i.depth,
        #                      i.entry_edge_id, i.direct_edge_id,
        #                      i.exit_edge_id)) for i in DbPath.objects.filter()])
        self.assertEquals(
            len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 1)

        # Another cut should delete all links
        DbLink.objects.filter(input=n3, output=n5).delete()
        self.assertEquals(
            len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 0)

        # But I did not delete everything! For instance, I can check
        # the following links
        self.assertEquals(
            len(DbPath.objects.filter(parent=n4, child=n8).distinct()), 1)
        self.assertEquals(
            len(DbPath.objects.filter(parent=n5, child=n7).distinct()), 1)

        # Finally, I reconnect in a different way the two graphs and
        # check that 1 and 8 are again connected
        n4.add_link_from(n3)
        self.assertEquals(
            len(DbPath.objects.filter(parent=n1, child=n8).distinct()), 1)