def test_very_deep_attributes(self): """ Test attributes where the total length of the key, including the separators, would be longer than the field length in the DB. """ from aiida.backends.djsite.db import models n = Node() semi_long_string = "abcdefghijklmnopqrstuvwxyz" value = "some value" attribute = {semi_long_string: value} key_len = len(semi_long_string) max_len = models.DbAttribute._meta.get_field_by_name( 'key')[0].max_length while key_len < 2 * max_len: # Create a deep, recursive attribute attribute = {semi_long_string: attribute} key_len += len(semi_long_string) + len(models.DbAttribute._sep) n._set_attr(semi_long_string, attribute) n.store() all_keys = models.DbAttribute.objects.filter( dbnode=n.dbnode).values_list('key', flat=True) print max(len(i) for i in all_keys)
def test_attrs_and_extras_wrong_keyname(self): """ Attribute keys cannot include the separator symbol in the key """ 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_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_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_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_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_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_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_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_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)