def test_delete_extras(self): """ Checks the ability of deleting extras, also when they are dictionaries or lists. """ a = Node().store() extras_to_set = { 'bool': self.boolval, 'integer': self.intval, 'float': self.floatval, 'string': self.stringval, 'dict': self.dictval, 'list': self.listval, 'further': 267, } for k, v in extras_to_set.iteritems(): a.set_extra(k, v) self.assertEquals({k: v for k, v in a.iterextras()}, extras_to_set) # I pregenerate it, it cannot change during iteration list_keys = list(extras_to_set.keys()) for k in list_keys: # I delete one by one the keys and check if the operation is # performed correctly a.del_extra(k) del extras_to_set[k] self.assertEquals({k: v for k, v in a.iterextras()}, extras_to_set)
def fill_repo(self): from aiida.orm import JobCalculation, CalculationFactory, Data, DataFactory extra_name = self.__class__.__name__ + "/test_with_subclasses" calc_params = { 'computer': self.computer, 'resources': { 'num_machines': 1, 'num_mpiprocs_per_machine': 1 } } TemplateReplacerCalc = CalculationFactory( 'simpleplugins.templatereplacer') ParameterData = DataFactory('parameter') a1 = JobCalculation(**calc_params).store() # To query only these nodes later a1.set_extra(extra_name, True) a2 = TemplateReplacerCalc(**calc_params).store() # To query only these nodes later a2.set_extra(extra_name, True) a3 = Data().store() a3.set_extra(extra_name, True) a4 = ParameterData(dict={'a': 'b'}).store() a4.set_extra(extra_name, True) a5 = Node().store() a5.set_extra(extra_name, True) # I don't set the extras, just to be sure that the filtering works # The filtering is needed because other tests will put stuff int he DB a6 = JobCalculation(**calc_params) a6.store() a7 = Node() a7.store()
def test_with_subclasses(self, computer): extra_name = self.__class__.__name__ + "/test_with_subclasses" calc_params = { 'computer': computer, 'resources': { 'num_machines': 1, 'num_mpiprocs_per_machine': 1 } } TemplateReplacerCalc = CalculationFactory( 'simpleplugins.templatereplacer') ParameterData = DataFactory('parameter') a1 = JobCalculation(**calc_params).store() # To query only these nodes later a1.set_extra(extra_name, True) a2 = TemplateReplacerCalc(**calc_params).store() # To query only these nodes later a2.set_extra(extra_name, True) a3 = Data().store() a3.set_extra(extra_name, True) a4 = ParameterData(dict={'a': 'b'}).store() a4.set_extra(extra_name, True) a5 = Node().store() a5.set_extra(extra_name, True) # I don't set the extras, just to be sure that the filtering works # The filtering is needed because other tests will put stuff int he DB a6 = JobCalculation(**calc_params) a6.store() a7 = Node() a7.store() # Query by calculation results = list(JobCalculation.query(dbextras__key=extra_name)) # a3, a4, a5 should not be found because they are not JobCalculations. # a6, a7 should not be found because they have not the attribute set. self.assertEquals(set([i.pk for i in results]), set([a1.pk, a2.pk])) # Same query, but by the generic Node class results = list(Node.query(dbextras__key=extra_name)) self.assertEquals(set([i.pk for i in results]), set([a1.pk, a2.pk, a3.pk, a4.pk, a5.pk])) # Same query, but by the Data class results = list(Data.query(dbextras__key=extra_name)) self.assertEquals(set([i.pk for i in results]), set([a3.pk, a4.pk])) # Same query, but by the ParameterData subclass results = list(ParameterData.query(dbextras__key=extra_name)) self.assertEquals(set([i.pk for i in results]), set([a4.pk])) # Same query, but by the TemplateReplacerCalc subclass results = list(TemplateReplacerCalc.query(dbextras__key=extra_name)) self.assertEquals(set([i.pk for i in results]), set([a2.pk]))
def test_attr_and_extras_multikey(self): """ Multiple nodes with the same key. This should not be a problem I test only extras because the two tables are formally identical """ n1 = Node().store() n2 = Node().store() n1.set_extra('samename', 1) # No problem, they are two different nodes n2.set_extra('samename', 1)
def test_replace_extras(self): """ Checks the ability of replacing extras, removing the subkeys also when these are dictionaries or lists. """ 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) self.assertEquals({k: v for k, v in a.iterextras()}, extras_to_set) 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) self.assertEquals({k: v for k, v in a.iterextras()}, extras_to_set)
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_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_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_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_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_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)