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')
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()
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)
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)
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'))
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'), ])
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)
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()
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() })
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)
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')
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)
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)
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([]))
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)
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)
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)
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()})
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)
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)
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)
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)
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)
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)
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)