def test_delete(self): """Test `verdi group delete` command.""" orm.Group(label='group_test_delete_01').store() orm.Group(label='group_test_delete_02').store() result = self.cli_runner.invoke(cmd_group.group_delete, ['--force', 'group_test_delete_01']) self.assertClickResultNoException(result) # Verify that removed group is not present in list result = self.cli_runner.invoke(cmd_group.group_list) self.assertClickResultNoException(result) self.assertNotIn('group_test_delete_01', result.output) node_01 = orm.CalculationNode().store() node_02 = orm.CalculationNode().store() # Add some nodes and then use `verdi group delete` to delete a group that contains nodes group = orm.load_group(label='group_test_delete_02') group.add_nodes([node_01, node_02]) self.assertEqual(group.count(), 2) result = self.cli_runner.invoke(cmd_group.group_delete, ['--force', 'group_test_delete_02']) self.assertClickResultNoException(result) with self.assertRaises(exceptions.NotExistent): orm.load_group(label='group_test_delete_02')
def test_querying(): """Test querying for groups with and without subclassing.""" orm.Group(label='group').store() orm.AutoGroup(label='auto-group').store() # Fake a subclass by manually setting the type string group = orm.Group(label='custom-group') group.backend_entity.dbmodel.type_string = 'custom.group' group.store() assert orm.QueryBuilder().append(orm.AutoGroup).count() == 1 assert orm.QueryBuilder().append(orm.AutoGroup, subclassing=False).count() == 1 assert orm.QueryBuilder().append(orm.Group, subclassing=False).count() == 1 assert orm.QueryBuilder().append(orm.Group).count() == 3 assert orm.QueryBuilder().append(orm.Group, filters={ 'type_string': 'custom.group' }).count() == 1 # Removing it as other methods might get a warning instead group_pk = group.pk del group orm.Group.objects.delete(id=group_pk)
def test_group_import_existing(self, temp_dir): """ Testing what happens when I try to import a group that already exists in the database. This should raise an appropriate exception """ grouplabel = 'node_group_existing' # Create another user new_email = '[email protected]' user = orm.User(email=new_email) user.store() # Create a structure data node sd1 = orm.StructureData() sd1.user = user sd1.label = 'sd' sd1.store() # Create a group and add the data inside group = orm.Group(label=grouplabel) group.store() group.add_nodes([sd1]) # At this point we export the generated data filename = os.path.join(temp_dir, 'export1.tar.gz') export([group], outfile=filename, silent=True) self.clean_db() self.insert_data() # Creating a group of the same name group = orm.Group(label='node_group_existing') group.store() import_data(filename, silent=True) # The import should have created a new group with a suffix # I check for this: builder = orm.QueryBuilder().append( orm.Group, filters={'label': { 'like': grouplabel + '%' }}) self.assertEqual(builder.count(), 2) # Now I check for the group having one member, and whether the name is different: builder = orm.QueryBuilder() builder.append(orm.Group, filters={'label': { 'like': grouplabel + '%' }}, tag='g', project='label') builder.append(orm.StructureData, with_group='g') self.assertEqual(builder.count(), 1) # I check that the group name was changed: self.assertTrue(builder.all()[0][0] != grouplabel) # I import another name, the group should not be imported again import_data(filename, silent=True) builder = orm.QueryBuilder() builder.append(orm.Group, filters={'label': { 'like': grouplabel + '%' }}) self.assertEqual(builder.count(), 2)
def test_delete(self): """Test `verdi group delete` command.""" orm.Group(label='group_test_delete_01').store() orm.Group(label='group_test_delete_02').store() result = self.cli_runner.invoke(cmd_group.group_delete, ['--force', 'group_test_delete_01']) self.assertClickResultNoException(result) # Verify that removed group is not present in list result = self.cli_runner.invoke(cmd_group.group_list) self.assertClickResultNoException(result) self.assertNotIn('group_test_delete_01', result.output) node_01 = orm.CalculationNode().store() node_02 = orm.CalculationNode().store() # Add some nodes and then use `verdi group delete --clear` to delete a node even when it contains nodes group = orm.load_group(label='group_test_delete_02') group.add_nodes([node_01, node_02]) self.assertEqual(group.count(), 2) # Calling delete on a group without the `--clear` option should raise result = self.cli_runner.invoke(cmd_group.group_delete, ['--force', 'group_test_delete_02']) self.assertIsNotNone(result.exception, result.output) # With `--clear` option should delete group and nodes result = self.cli_runner.invoke( cmd_group.group_delete, ['--force', '--clear', 'group_test_delete_02']) self.assertClickResultNoException(result) with self.assertRaises(exceptions.NotExistent): group = orm.load_group(label='group_test_delete_02')
def test_description(self): """Test the update of the description both for stored and unstored groups.""" node = orm.Data().store() group_01 = orm.Group(label='testgroupdescription1', description='group_01').store() group_01.add_nodes(node) group_02 = orm.Group(label='testgroupdescription2', description='group_02') # Preliminary checks self.assertTrue(group_01.is_stored) self.assertFalse(group_02.is_stored) self.assertEqual(group_01.description, 'group_01') self.assertEqual(group_02.description, 'group_02') # Change group_01.description = 'new1' group_02.description = 'new2' # Test that the groups remained in their proper stored state and that # the description was updated self.assertTrue(group_01.is_stored) self.assertFalse(group_02.is_stored) self.assertEqual(group_01.description, 'new1') self.assertEqual(group_02.description, 'new2') # Store group_02 and check that the description is OK group_02.store() self.assertTrue(group_02.is_stored) self.assertEqual(group_02.description, 'new2')
def test_delete(self): """Test `verdi group delete` command.""" orm.Group(label='group_test_delete_01').store() orm.Group(label='group_test_delete_02').store() orm.Group(label='group_test_delete_03').store() # dry run result = self.cli_runner.invoke(cmd_group.group_delete, ['--dry-run', 'group_test_delete_01']) self.assertClickResultNoException(result) orm.load_group(label='group_test_delete_01') result = self.cli_runner.invoke(cmd_group.group_delete, ['--force', 'group_test_delete_01']) self.assertClickResultNoException(result) # Verify that removed group is not present in list result = self.cli_runner.invoke(cmd_group.group_list) self.assertClickResultNoException(result) self.assertNotIn('group_test_delete_01', result.output) node_01 = orm.CalculationNode().store() node_02 = orm.CalculationNode().store() node_pks = {node_01.pk, node_02.pk} # Add some nodes and then use `verdi group delete` to delete a group that contains nodes group = orm.load_group(label='group_test_delete_02') group.add_nodes([node_01, node_02]) self.assertEqual(group.count(), 2) result = self.cli_runner.invoke(cmd_group.group_delete, ['--force', 'group_test_delete_02']) with self.assertRaises(exceptions.NotExistent): orm.load_group(label='group_test_delete_02') # check nodes still exist for pk in node_pks: orm.load_node(pk) # delete the group and the nodes it contains group = orm.load_group(label='group_test_delete_03') group.add_nodes([node_01, node_02]) result = self.cli_runner.invoke( cmd_group.group_delete, ['--force', '--delete-nodes', 'group_test_delete_03']) self.assertClickResultNoException(result) # check group and nodes no longer exist with self.assertRaises(exceptions.NotExistent): orm.load_group(label='group_test_delete_03') for pk in node_pks: with self.assertRaises(exceptions.NotExistent): orm.load_node(pk)
def test_querying(): """Test querying for groups with and without subclassing.""" orm.Group(label='group').store() orm.AutoGroup(label='auto-group').store() # Fake a subclass by manually setting the type string group = orm.Group(label='custom-group') group.backend_entity.dbmodel.type_string = 'custom.group' group.store() assert orm.QueryBuilder().append(orm.AutoGroup).count() == 1 assert orm.QueryBuilder().append(orm.AutoGroup, subclassing=False).count() == 1 assert orm.QueryBuilder().append(orm.Group, subclassing=False).count() == 1 assert orm.QueryBuilder().append(orm.Group).count() == 3 assert orm.QueryBuilder().append(orm.Group, filters={'type_string': 'custom.group'}).count() == 1
def test_group_uuid_hashing_for_querybuidler(self): """QueryBuilder results should be reusable and shouldn't brake hashing.""" group = orm.Group(label='test_group') group.store() # Search for the UUID of the stored group builder = orm.QueryBuilder() builder.append(orm.Group, project=['uuid'], filters={'label': { '==': 'test_group' }}) [uuid] = builder.first() # Look the node with the previously returned UUID builder = orm.QueryBuilder() builder.append(orm.Group, project=['id'], filters={'uuid': { '==': uuid }}) # Check that the query doesn't fail builder.all() # And that the results are correct self.assertEqual(builder.count(), 1) self.assertEqual(builder.first()[0], group.id)
def test_creation(self): """Test the creation of Groups.""" node = orm.Data() stored_node = orm.Data().store() group = orm.Group(label='testgroup') with self.assertRaises(exceptions.ModificationNotAllowed): # group unstored group.add_nodes(node) with self.assertRaises(exceptions.ModificationNotAllowed): # group unstored group.add_nodes(stored_node) group.store() with self.assertRaises(ValueError): # node unstored group.add_nodes(node) group.add_nodes(stored_node) nodes = list(group.nodes) self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].pk, stored_node.pk)
def test_node_show(self): """Test `verdi node show`""" node = orm.Data().store() node.label = 'SOMELABEL' options = [str(node.pk)] result = self.cli_runner.invoke(cmd_node.node_show, options) self.assertClickResultNoException(result) # Let's check some content in the output. At least the UUID and the label should be in there self.assertIn(node.label, result.output) self.assertIn(node.uuid, result.output) ## Let's now test the '--print-groups' option options.append('--print-groups') result = self.cli_runner.invoke(cmd_node.node_show, options) self.assertClickResultNoException(result) # I don't check the list of groups - it might be in an autogroup # Let's create a group and put the node in there group_name = 'SOMEGROUPNAME' group = orm.Group(group_name).store() group.add_nodes(node) result = self.cli_runner.invoke(cmd_node.node_show, options) self.assertClickResultNoException(result) # Now the group should be in there self.assertIn(group_name, result.output)
def test_remove_nodes(self): """Test node removal.""" node_01 = orm.Data().store() node_02 = orm.Data().store() node_03 = orm.Data().store() node_04 = orm.Data().store() nodes = [node_01, node_02, node_03] group = orm.Group(label='test_remove_nodes').store() # Add initial nodes group.add_nodes(nodes) self.assertEqual(set(_.pk for _ in nodes), set(_.pk for _ in group.nodes)) # Remove a node that is not in the group: nothing should happen group.remove_nodes(node_04) self.assertEqual(set(_.pk for _ in nodes), set(_.pk for _ in group.nodes)) # Remove one orm.Node nodes.remove(node_03) group.remove_nodes(node_03) self.assertEqual(set(_.pk for _ in nodes), set(_.pk for _ in group.nodes)) # Remove a list of Nodes and check nodes.remove(node_01) nodes.remove(node_02) group.remove_nodes([node_01, node_02]) self.assertEqual(set(_.pk for _ in nodes), set(_.pk for _ in group.nodes))
def test_node_iterator(self): """Test the indexing and slicing functionality of the node iterator.""" node_00 = orm.Data().store() node_01 = orm.Data().store() node_02 = orm.Data().store() node_03 = orm.Data().store() nodes = [node_00, node_01, node_02, node_03] group = orm.Group(label='label', description='description').store() group.add_nodes(nodes) # Indexing node_indexed = group.nodes[0] self.assertTrue(isinstance(node_indexed, orm.Data)) self.assertIn(node_indexed.uuid, [node.uuid for node in nodes]) # Slicing nodes_sliced = group.nodes[1:3] self.assertTrue(isinstance(nodes_sliced, list)) self.assertEqual(len(nodes_sliced), 2) self.assertTrue( all([isinstance(node, orm.Data) for node in nodes_sliced])) self.assertTrue( all([ node.uuid in set(node.uuid for node in nodes) for node in nodes_sliced ]))
def test_explicit_type_string(): """Test that passing explicit `type_string` to `Group` constructor is still possible despite being deprecated. Both constructing a group while passing explicit `type_string` as well as loading a group with unregistered type string should emit a warning, but it should be possible. """ type_string = 'data.potcar' # An unregistered custom type string with pytest.warns(UserWarning): group = orm.Group(label='group', type_string=type_string) group.store() assert group.type_string == type_string with pytest.warns(UserWarning): loaded = orm.Group.get(label=group.label, type_string=type_string) assert isinstance(loaded, orm.Group) assert loaded.pk == group.pk assert loaded.type_string == group.type_string queried = orm.QueryBuilder().append(orm.Group, filters={ 'id': group.pk, 'type_string': type_string }).one()[0] assert isinstance(queried, orm.Group) assert queried.pk == group.pk assert queried.type_string == group.type_string
def setUpClass(cls): super().setUpClass() from aiida import orm cls.computer = orm.Computer(label='comp', hostname='localhost', transport_type='local', scheduler_type='direct', workdir='/tmp/aiida').store() cls.code = orm.Code(remote_computer_exec=(cls.computer, '/bin/true')).store() cls.group = orm.Group(label='test_group').store() cls.node = orm.Data().store() # some of the export tests write in the current directory, # make sure it is writeable and we don't pollute the current one cls.old_cwd = os.getcwd() cls.cwd = tempfile.mkdtemp(__name__) os.chdir(cls.cwd) # Utility helper cls.fixture_archive = 'export/migrate' cls.newest_archive = f'export_v{EXPORT_VERSION}_simple.aiida' cls.penultimate_archive = 'export_v0.6_simple.aiida'
def test_remove_nodes_bulk(): """Test node removal with `skip_orm=True`.""" group = orm.Group(label='test_removing_nodes').store().backend_entity node_01 = orm.Data().store().backend_entity node_02 = orm.Data().store().backend_entity node_03 = orm.Data().store().backend_entity node_04 = orm.Data().store().backend_entity nodes = [node_01, node_02, node_03] group.add_nodes(nodes) assert set(_.pk for _ in nodes) == set(_.pk for _ in group.nodes) # Remove a node that is not in the group: nothing should happen group.remove_nodes([node_04], skip_orm=True) assert set(_.pk for _ in nodes) == set(_.pk for _ in group.nodes) # Remove one Node nodes.remove(node_03) group.remove_nodes([node_03], skip_orm=True) assert set(_.pk for _ in nodes) == set(_.pk for _ in group.nodes) # Remove a list of Nodes and check nodes.remove(node_01) nodes.remove(node_02) group.remove_nodes([node_01, node_02], skip_orm=True) assert set(_.pk for _ in nodes) == set(_.pk for _ in group.nodes)
def test_serialize_group_round_trip(self): """Test you can serialize and deserialize a group""" group = orm.Group(label='test_serialize_group_round_trip').store() deserialized = serialize.deserialize(serialize.serialize(group)) self.assertEqual(group.uuid, deserialized.uuid) self.assertEqual(group.label, deserialized.label)
def test_show_limit(self): """Test `--limit` option of the `verdi group show` command.""" label = 'test_group_limit' nodes = [orm.Data().store(), orm.Data().store()] group = orm.Group(label=label).store() group.add_nodes(nodes) # Default should include all nodes in the output result = self.cli_runner.invoke(cmd_group.group_show, [label]) self.assertClickResultNoException(result) for node in nodes: self.assertIn(str(node.pk), result.output) # Repeat test with `limit=1`, use also the `--raw` option to only display nodes result = self.cli_runner.invoke(cmd_group.group_show, [label, '--limit', '1', '--raw']) self.assertClickResultNoException(result) # The current `verdi group show` does not support ordering so we cannot rely on that for now to test if only # one of the nodes is shown self.assertEqual(len(result.output.strip().split('\n')), 1) self.assertTrue( str(nodes[0].pk) in result.output or str(nodes[1].pk) in result.output)
def test_loading(): """Test that loading instances from the database returns the correct subclass of `Group`.""" group = orm.Group('normal-group').store() loaded = orm.load_group(group.pk) assert isinstance(loaded, orm.Group) group = orm.AutoGroup('auto-group').store() loaded = orm.load_group(group.pk) assert isinstance(group, orm.AutoGroup)
def test_cif_import(clear_database, run_cli_command): """Test the `aiida-codtools data cif import` CLI command.""" max_entries = 10 # Default call group = orm.Group(UUID()).store() run_cli_command(launch_cif_import, ['-G', group.pk, '-M', max_entries]) assert group.count() == max_entries # Dry run group = orm.Group(UUID()).store() run_cli_command(launch_cif_import, ['-G', group.pk, '-M', max_entries, '--dry-run']) assert group.count() == 0 # Skip partial occupations group = orm.Group(UUID()).store() run_cli_command(launch_cif_import, ['-G', group.pk, '-M', max_entries, '--skip-partial-occupancies']) assert group.count() == max_entries
def setUp(self): """Create runner object to run tests.""" from click.testing import CliRunner self.cli_runner = CliRunner() for group in [ 'dummygroup1', 'dummygroup2', 'dummygroup3', 'dummygroup4' ]: orm.Group(label=group).store()
def test_count(self): """Test the `count` method.""" node_00 = orm.Data().store() node_01 = orm.Data().store() nodes = [node_00, node_01] group = orm.Group(label='label', description='description').store() group.add_nodes(nodes) self.assertEqual(group.count(), len(nodes))
def test_nodes_in_group(self, temp_dir): """ This test checks that nodes that belong to a specific group are correctly imported and exported. """ from aiida.common.links import LinkType # Create another user new_email = '[email protected]' user = orm.User(email=new_email) user.store() # Create a structure data node that has a calculation as output sd1 = orm.StructureData() sd1.user = user sd1.label = 'sd1' sd1.store() jc1 = orm.CalcJobNode() jc1.computer = self.computer jc1.set_option('resources', { 'num_machines': 1, 'num_mpiprocs_per_machine': 1 }) jc1.user = user jc1.label = 'jc1' jc1.add_incoming(sd1, link_type=LinkType.INPUT_CALC, link_label='link') jc1.store() jc1.seal() # Create a group and add the data inside gr1 = orm.Group(label='node_group') gr1.store() gr1.add_nodes([sd1, jc1]) gr1_uuid = gr1.uuid # At this point we export the generated data filename1 = os.path.join(temp_dir, 'export1.tar.gz') export([sd1, jc1, gr1], outfile=filename1, silent=True) n_uuids = [sd1.uuid, jc1.uuid] self.clean_db() self.insert_data() import_data(filename1, silent=True) # Check that the imported nodes are correctly imported and that # the user assigned to the nodes is the right one for uuid in n_uuids: self.assertEqual(orm.load_node(uuid).user.email, new_email) # Check that the exported group is imported correctly builder = orm.QueryBuilder() builder.append(orm.Group, filters={'uuid': {'==': gr1_uuid}}) self.assertEqual(builder.count(), 1, 'The group was not found.')
def test_add_nodes_skip_orm_batch(): """Test the `SqlaGroup.add_nodes` method with the `skip_orm=True` flag and batches.""" nodes = [orm.Data().store().backend_entity for _ in range(100)] # Add nodes to groups using different batch size. Check in the end the correct addition. batch_sizes = (1, 3, 10, 1000) for batch_size in batch_sizes: group = orm.Group(label='test_batches_' + str(batch_size)).store() group.backend_entity.add_nodes(nodes, skip_orm=True, batch_size=batch_size) assert set(_.pk for _ in nodes) == set(_.pk for _ in group.nodes)
def test_rename_existing(self): """Test that renaming to an already existing name is not permitted.""" label_group_a = 'group_a' label_group_b = 'group_b' orm.Group(label=label_group_a, description='I am the Original G').store() # Before storing everything should be fine group_b = orm.Group(label=label_group_a, description='They will try to rename me') # Storing for duplicate group name should trigger UniquenessError with self.assertRaises(exceptions.IntegrityError): group_b.store() # Reverting to unique name before storing group_b.label = label_group_b group_b.store() # After storing name change to existing should raise with self.assertRaises(exceptions.IntegrityError): group_b.label = label_group_a
def add_to_group(node, group_name): if group_name is not None: try: g = orm.Group.get(label=group_name) group_statistics = "that already contains {} nodes".format( len(g.nodes)) except NotExistent: g = orm.Group(label=group_name) group_statistics = "that does not exist yet" g.store() g.add_nodes(node) print("Wannier90BandsWorkChain<{}> will be added to the group {} {}". format(node.pk, group_name, group_statistics))
def test_query_with_group(): """Docs.""" group = orm.Group(label='group').store() data = orm.Data().store() group.add_nodes([data]) builder = orm.QueryBuilder().append(orm.Data, filters={ 'id': data.pk }, tag='data').append(orm.Group, with_node='data') loaded = builder.one()[0] assert loaded.pk == group.pk
def test_clear(self): """Test the `clear` method to remove all nodes.""" node_01 = orm.Data().store() node_02 = orm.Data().store() node_03 = orm.Data().store() nodes = [node_01, node_02, node_03] group = orm.Group(label='test_clear_nodes').store() # Add initial nodes group.add_nodes(nodes) self.assertEqual(set(_.pk for _ in nodes), set(_.pk for _ in group.nodes)) group.clear() self.assertEqual(list(group.nodes), [])
def test_loading_unregistered(): """Test rules around loading `Group` subclasses without a registered entry point. Storing instances of unregistered subclasses is not allowed so we have to create one sneakily by instantiating a normal group and manipulating the type string directly on the database model. """ group = orm.Group(label='group') group.backend_entity.dbmodel.type_string = 'unregistered.subclass' group.store() with pytest.warns(UserWarning): loaded = orm.load_group(group.pk) assert isinstance(loaded, orm.Group)
def test_name_desc(self): """Test Group description.""" group = orm.Group(label='testgroup2', description='some desc') self.assertEqual(group.label, 'testgroup2') self.assertEqual(group.description, 'some desc') self.assertTrue(group.is_user_defined) group.store() # Same checks after storing self.assertEqual(group.label, 'testgroup2') self.assertTrue(group.is_user_defined) self.assertEqual(group.description, 'some desc') # To avoid to find it in further tests orm.Group.objects.delete(group.pk)
def test_serialize_group(self): """ Test that serialization and deserialization of Groups works. Also make sure that the serialized data is json-serializable """ group_name = 'groupie' group_a = orm.Group(label=group_name).store() data = {'group': group_a} serialized_data = serialize.serialize(data) deserialized_data = serialize.deserialize(serialized_data) self.assertEqual(data['group'].uuid, deserialized_data['group'].uuid) self.assertEqual(data['group'].label, deserialized_data['group'].label)