def test_create_from_folder_duplicate(filepath_pseudos): """Test that `SsspFamily.create_from_folder` raises for duplicate label.""" label = 'SSSP/1.1/PBE/efficiency' SsspFamily(label=label).store() with pytest.raises(ValueError, match=r'the SsspFamily `.*` already exists'): SsspFamily.create_from_folder(filepath_pseudos('upf'), label)
def test_constructor(): """Test that the `SsspFamily` constructor validates the label.""" with pytest.raises( ValueError, match=r'the label `.*` is not a valid SSSP configuration label'): SsspFamily() with pytest.raises( ValueError, match=r'the label `.*` is not a valid SSSP configuration label'): SsspFamily(label='SSSP_1.1_PBE_efficiency') label = SsspFamily.format_configuration_label( SsspFamily.default_configuration) family = SsspFamily(label=label) assert isinstance(family, SsspFamily)
def test_get_valid_labels(): """Test the `SsspFamily.get_valid_labels` class method.""" valid_labels = SsspFamily.get_valid_labels() assert isinstance(valid_labels, tuple) for entry in valid_labels: assert isinstance(entry, str)
def cmd_install_sssp(version, functional, protocol, traceback): """Install an SSSP configuration. The SSSP configuration will be automatically downloaded from the Materials Cloud Archive entry to create a new `SsspFamily`. """ # pylint: disable=too-many-locals import requests from aiida.common.files import md5_file from aiida.orm import Group, QueryBuilder from aiida_pseudo import __version__ from aiida_pseudo.groups.family import SsspConfiguration, SsspFamily from .utils import attempt, create_family_from_archive configuration = SsspConfiguration(version, functional, protocol) label = SsspFamily.format_configuration_label(configuration) description = f'SSSP v{version} {functional} {protocol} installed with aiida-pseudo v{__version__}' if configuration not in SsspFamily.valid_configurations: echo.echo_critical( f'{version} {functional} {protocol} is not a valid SSSP configuration' ) if QueryBuilder().append(SsspFamily, filters={'label': label}).first(): echo.echo_critical( f'{SsspFamily.__name__}<{label}> is already installed') with tempfile.TemporaryDirectory() as dirpath: url_archive = f'{URL_SSSP_BASE}/SSSP_{version}_{functional}_{protocol}.tar.gz' filepath_archive = os.path.join(dirpath, 'archive.tar.gz') url_metadata = f'{URL_SSSP_BASE}/SSSP_{version}_{functional}_{protocol}.json' filepath_metadata = os.path.join(dirpath, 'metadata.json') with attempt('downloading selected pseudo potentials archive... ', include_traceback=traceback): response = requests.get(url_archive) response.raise_for_status() with open(filepath_archive, 'wb') as handle: handle.write(response.content) handle.flush() description += f'\nArchive pseudos md5: {md5_file(filepath_archive)}' with attempt('downloading selected pseudo potentials metadata... ', include_traceback=traceback): response = requests.get(url_metadata) response.raise_for_status() with open(filepath_metadata, 'a+b') as handle: handle.write(response.content) handle.flush() handle.seek(0) metadata = json.load(handle) description += f'\nPseudo metadata md5: {md5_file(filepath_metadata)}' with attempt('unpacking archive and parsing pseudos... ', include_traceback=traceback): family = create_family_from_archive(SsspFamily, label, filepath_archive) cutoffs = {} for element, values in metadata.items(): if family.get_pseudo(element).md5 != values['md5']: Group.objects.delete(family.pk) msg = f"md5 of pseudo for element {element} does not match that of the metadata {values['md5']}" echo.echo_critical(msg) cutoffs[element] = { 'cutoff_wfc': values['cutoff_wfc'], 'cutoff_rho': values['cutoff_rho'] } family.description = description family.set_cutoffs(cutoffs) echo.echo_success( f'installed `{label}` containing {family.count()} pseudo potentials' )
def test_format_configuration_label(): """Test the `SsspFamily.format_configuration_label` class method.""" configuration = SsspConfiguration(1.1, 'PBE', 'efficiency') assert SsspFamily.format_configuration_label( configuration) == 'SSSP/1.1/PBE/efficiency'
def test_create_from_folder(filepath_pseudos): """Test the `SsspFamily.create_from_folder` class method.""" family = SsspFamily.create_from_folder(filepath_pseudos('upf'), 'SSSP/1.1/PBE/efficiency', pseudo_type=UpfData) assert isinstance(family, SsspFamily)
def cmd_install_sssp(version, functional, protocol, download_only, traceback): """Install an SSSP configuration. The SSSP configuration will be automatically downloaded from the Materials Cloud Archive entry to create a new `SsspFamily`. """ # pylint: disable=too-many-locals from aiida.common.files import md5_file from aiida.orm import Group, QueryBuilder from aiida_pseudo import __version__ from aiida_pseudo.groups.family import SsspFamily from .utils import attempt, create_family_from_archive configuration = SsspConfiguration(version, functional, protocol) label = SsspFamily.format_configuration_label(configuration) description = f'SSSP v{version} {functional} {protocol} installed with aiida-pseudo v{__version__}' if configuration not in SsspFamily.valid_configurations: echo.echo_critical(f'{version} {functional} {protocol} is not a valid SSSP configuration') if not download_only and QueryBuilder().append(SsspFamily, filters={'label': label}).first(): echo.echo_critical(f'{SsspFamily.__name__}<{label}> is already installed') with tempfile.TemporaryDirectory() as dirpath: dirpath = pathlib.Path(dirpath) filepath_archive = dirpath / 'archive.tar.gz' filepath_metadata = dirpath / 'metadata.json' download_sssp(configuration, filepath_archive, filepath_metadata, traceback) description += f'\nArchive pseudos md5: {md5_file(filepath_archive)}' description += f'\nPseudo metadata md5: {md5_file(filepath_metadata)}' if download_only: for filepath in [filepath_archive, filepath_metadata]: filepath_target = pathlib.Path.cwd() / filepath.name if filepath_target.exists(): echo.echo_warning(f'the file `{filepath_target}` already exists, skipping.') else: # Cannot use ``pathlib.Path.rename`` because this will fail if it moves across file systems. shutil.move(filepath, filepath_target) echo.echo_success(f'`{filepath_target.name}` written to the current directory.') return with open(filepath_metadata, 'rb') as handle: handle.seek(0) metadata = json.load(handle) with attempt('unpacking archive and parsing pseudos... ', include_traceback=traceback): family = create_family_from_archive(SsspFamily, label, filepath_archive) cutoffs = {} for element, values in metadata.items(): if family.get_pseudo(element).md5 != values['md5']: Group.objects.delete(family.pk) msg = f"md5 of pseudo for element {element} does not match that of the metadata {values['md5']}" echo.echo_critical(msg) cutoffs[element] = {'cutoff_wfc': values['cutoff_wfc'], 'cutoff_rho': values['cutoff_rho']} family.description = description family.set_cutoffs(cutoffs, 'normal', unit='Ry') echo.echo_success(f'installed `{label}` containing {family.count()} pseudo potentials')