def _collect_tags(node, calc,parameters=None, dump_aiida_database=default_options['dump_aiida_database'], exclude_external_contents=default_options['exclude_external_contents'], gzip=default_options['gzip'], gzip_threshold=default_options['gzip_threshold']): """ Retrieve metadata from attached calculation and pseudopotentials and prepare it to be saved in TCOD CIF. """ import os, json tags = { '_audit_creation_method': "AiiDA version {}".format(__version__) } # Recording the dictionaries (if any) if len(conforming_dictionaries): for postfix in ['name', 'version', 'location']: key = '_audit_conform_dict_{}'.format(postfix) if key not in tags: tags[key] = [] for dictionary in conforming_dictionaries: tags['_audit_conform_dict_name'].append(dictionary['name']) tags['_audit_conform_dict_version'].append(dictionary['version']) tags['_audit_conform_dict_location'].append(dictionary['url']) # Collecting metadata from input files: calc_data = [] if calc is not None: calc_data = _collect_calculation_data(calc) for tag in tcod_loops['_tcod_computation'] + tcod_loops['_tcod_file']: tags[tag] = [] export_files = [] sn = 0 fn = 0 for step in calc_data: tags['_tcod_computation_step'].append(sn) tags['_tcod_computation_command'].append( 'cd {}; ./{}'.format(sn,aiida_executable_name)) tags['_tcod_computation_reference_uuid'].append(step['uuid']) if 'env' in step: tags['_tcod_computation_environment'].append( "\n".join(["%s=%s" % (key,step['env'][key]) for key in step['env']])) else: tags['_tcod_computation_environment'].append('') if 'stdout' in step and step['stdout'] is not None: if cif_encode_contents(step['stdout'])[1] is not None: raise ValueError("Standard output of computation step {} " "can not be stored in a CIF file: " "encoding is required, but not currently " "supported".format(sn)) tags['_tcod_computation_stdout'].append(step['stdout']) else: tags['_tcod_computation_stdout'].append('') if 'stderr' in step and step['stderr'] is not None: if cif_encode_contents(step['stderr'])[1] is not None: raise ValueError("Standard error of computation step {} " "can not be stored in a CIF file: " "encoding is required, but not currently " "supported".format(sn)) tags['_tcod_computation_stderr'].append(step['stderr']) else: tags['_tcod_computation_stderr'].append('') export_files.append( {'name': "{}{}".format(sn, os.sep), 'type': 'folder'} ) for f in step['files']: f['name'] = os.path.join(str(sn), f['name']) export_files.extend( step['files'] ) sn = sn + 1 # Creating importable AiiDA database dump in CIF tags if dump_aiida_database and node.is_stored: import json from aiida.common.exceptions import LicensingException from aiida.common.folders import SandboxFolder from aiida.orm.importexport import export_tree with SandboxFolder() as folder: try: export_tree([node.dbnode], folder=folder, silent=True, allowed_licenses=['CC0']) except LicensingException as e: raise LicensingException(e.message + \ ". Only CC0 license is accepted.") files = _collect_files(folder.abspath) with open(folder.get_abs_path('data.json')) as f: data = json.loads(f.read()) md5_to_url = {} if exclude_external_contents: for pk in data['node_attributes']: n = data['node_attributes'][pk] if 'md5' in n.keys() and 'source' in n.keys() and \ 'uri' in n['source'].keys(): md5_to_url[n['md5']] = n['source']['uri'] for f in files: f['name'] = os.path.join('aiida',f['name']) if f['type'] == 'file' and f['md5'] in md5_to_url.keys(): f['uri'] = md5_to_url[f['md5']] export_files.extend(files) # Describing seen files in _tcod_file_* loop encodings = list() fn = 0 for f in export_files: # ID and name tags['_tcod_file_id'].append(fn) tags['_tcod_file_name'].append(f['name']) # Checksums md5sum = None sha1sum = None if f['type'] == 'file': md5sum = f['md5'] sha1sum = f['sha1'] else: md5sum = '.' sha1sum = '.' tags['_tcod_file_md5sum'].append(md5sum) tags['_tcod_file_sha1sum'].append(sha1sum) # Content, encoding and URI contents = '?' encoding = None if 'uri' in f.keys(): contents = '.' tags['_tcod_file_URI'].append(f['uri']) else: tags['_tcod_file_URI'].append('?') if f['type'] == 'file': contents,encoding = \ cif_encode_contents(f['contents'], gzip=gzip, gzip_threshold=gzip_threshold) else: contents = '.' if encoding is None: encoding = '.' elif encoding not in encodings: encodings.append(encoding) tags['_tcod_file_contents'].append(contents) tags['_tcod_file_content_encoding'].append(encoding) # Role role = '?' if 'role' in f.keys(): role = f['role'] tags['_tcod_file_role'].append(role) fn = fn + 1 # Describing the encodings if encodings: for tag in tcod_loops['_tcod_content_encoding']: tags[tag] = [] for encoding in encodings: layers = encoding.split('+') for i in range(0, len(layers)): tags['_tcod_content_encoding_id'].append(encoding) tags['_tcod_content_encoding_layer_id'].append(i+1) tags['_tcod_content_encoding_layer_type'].append(layers[i]) # Describing Brillouin zone (if used) if calc is not None: from aiida.orm.data.array.kpoints import KpointsData kpoints_list = calc.get_inputs(KpointsData) # TODO: stop if more than one KpointsData is used? if len(kpoints_list) == 1: kpoints = kpoints_list[0] density, shift = kpoints.get_kpoints_mesh() tags['_dft_BZ_integration_grid_X'] = density[0] tags['_dft_BZ_integration_grid_Y'] = density[1] tags['_dft_BZ_integration_grid_Z'] = density[2] tags['_dft_BZ_integration_grid_shift_X'] = shift[0] tags['_dft_BZ_integration_grid_shift_Y'] = shift[1] tags['_dft_BZ_integration_grid_shift_Z'] = shift[2] # Collecting code-specific data from aiida.common.pluginloader import BaseFactory, existing_plugins from aiida.tools.dbexporters.tcod_plugins import BaseTcodtranslator plugin_path = "aiida.tools.dbexporters.tcod_plugins" plugins = list() if calc is not None: for plugin in existing_plugins(BaseTcodtranslator, plugin_path): cls = BaseFactory(plugin, BaseTcodtranslator, plugin_path) if calc._plugin_type_string.endswith(cls._plugin_type_string + '.'): plugins.append(cls) from aiida.common.exceptions import MultipleObjectsError if len(plugins) > 1: raise MultipleObjectsError("more than one plugin found for " "{}".calc._plugin_type_string) if len(plugins) == 1: plugin = plugins[0] translated_tags = translate_calculation_specific_values(calc, plugin) tags.update(translated_tags) return tags
def test_4(self): """ Test control of licenses. """ from aiida.common.exceptions import LicensingException from aiida.common.folders import SandboxFolder from aiida.orm.importexport import export_tree from aiida.orm import DataFactory StructureData = DataFactory('structure') sd = StructureData() sd.source = {'license': 'GPL'} sd.store() folder = SandboxFolder() export_tree([sd.dbnode], folder=folder, silent=True, allowed_licenses=['GPL']) # Folder should contain two files of metadata + nodes/ self.assertEquals(len(folder.get_content_list()), 3) folder = SandboxFolder() export_tree([sd.dbnode], folder=folder, silent=True, forbidden_licenses=['Academic']) # Folder should contain two files of metadata + nodes/ self.assertEquals(len(folder.get_content_list()), 3) folder = SandboxFolder() with self.assertRaises(LicensingException): export_tree([sd.dbnode], folder=folder, silent=True, allowed_licenses=['CC0']) folder = SandboxFolder() with self.assertRaises(LicensingException): export_tree([sd.dbnode], folder=folder, silent=True, forbidden_licenses=['GPL']) def cc_filter(license): return license.startswith('CC') def gpl_filter(license): return license == 'GPL' def crashing_filter(license): raise NotImplementedError("not implemented yet") folder = SandboxFolder() with self.assertRaises(LicensingException): export_tree([sd.dbnode], folder=folder, silent=True, allowed_licenses=cc_filter) folder = SandboxFolder() with self.assertRaises(LicensingException): export_tree([sd.dbnode], folder=folder, silent=True, forbidden_licenses=gpl_filter) folder = SandboxFolder() with self.assertRaises(LicensingException): export_tree([sd.dbnode], folder=folder, silent=True, allowed_licenses=crashing_filter) folder = SandboxFolder() with self.assertRaises(LicensingException): export_tree([sd.dbnode], folder=folder, silent=True, forbidden_licenses=crashing_filter)