Source code for aiida_crystal17.tests.resources

"""Retrieval of test resources."""
from contextlib import contextmanager
import pathlib
import shutil
import tempfile

import importlib_resources

from aiida_crystal17.tests import raw_files as resource_module

# __package__ returns None in python 2.7
RESOURCE_MODULE = resource_module.__package__ or "aiida_crystal17.tests.raw_files"


[docs]@contextmanager def resource_context(*path, **kwargs): """Provide a context manager that yields a pathlib.Path object to a resource file or directory. If the resource does not already exist on its own on the file system, a temporary directory/file will be created. If the directory/file was created, it will be deleted upon exiting the context manager (no exception is raised if the directory was deleted prior to the context manager exiting). """ if len(path) == 0: raise TypeError("must provide a path") final_name = path[-1] package = ".".join([RESOURCE_MODULE] + list(path[:-1])) ignore = kwargs.pop("ignore", (".DS_Store", "__init__.py")) if importlib_resources.is_resource(package, final_name): # the resource is a file with importlib_resources.path(package, final_name) as path: yield path.absolute() else: # the resource is a directory package = package + "." + final_name # TODO if the package folder exists on the file system it would be ideal to just return that # but importlib_resources doesn't provide a public API for that resources = [ c for c in importlib_resources.contents(package) if importlib_resources.is_resource(package, c) and c not in ignore ] folder_path = pathlib.Path(tempfile.mkdtemp()) try: for resource in resources: with (folder_path / resource).open("wb") as handle: handle.write(importlib_resources.read_binary(package, resource)) yield folder_path finally: if folder_path.exists(): shutil.rmtree(str(folder_path))
[docs]def read_resource_text(*path, **kwargs): # Note: can't use encoding=None in python 2.7 """Return the decoded string of the resource. The decoding-related arguments have the same semantics as those of bytes.decode(). """ if len(path) == 0: raise TypeError("must provide a path") file_name = path[-1] package = ".".join([RESOURCE_MODULE] + list(path[:-1])) encoding = kwargs.pop("encoding", "utf-8") return importlib_resources.read_text(package, file_name, encoding)
[docs]def read_resource_binary(*path): """Return the binary contents of the resource.""" if len(path) == 0: raise TypeError("must provide a path") file_name = path[-1] package = ".".join([RESOURCE_MODULE] + list(path[:-1])) return importlib_resources.read_binary(package, file_name)
[docs]def open_resource_text(*path, **kwargs): # Note: can't use encoding=None in python 2.7 """Return a file-like object opened for text reading of the resource. If the resource does not already exist on its own on the file system, a temporary file will be created. If the file was created, it will be deleted upon exiting the context manager (no exception is raised if the directory was deleted prior to the context manager exiting). """ if len(path) == 0: raise TypeError("must provide a path") file_name = path[-1] package = ".".join([RESOURCE_MODULE] + list(path[:-1])) encoding = kwargs.pop("encoding", "utf-8") return importlib_resources.open_text(package, file_name, encoding)
[docs]def open_resource_binary(*path): """Return a file-like object opened for binary reading of the resource. If the resource does not already exist on its own on the file system, a temporary file will be created. If the file was created, it will be deleted upon exiting the context manager (no exception is raised if the directory was deleted prior to the context manager exiting). """ if len(path) == 0: raise TypeError("must provide a path") file_name = path[-1] package = ".".join([RESOURCE_MODULE] + list(path[:-1])) return importlib_resources.open_binary(package, file_name)
[docs]def get_test_structure(name): """Return an aiida.StructureData for testing.""" from aiida.plugins import DataFactory from ase.spacegroup import crystal from aiida_crystal17.symmetry import convert_structure structure_data_cls = DataFactory("structure") if name == "MgO": atoms = crystal( symbols=[12, 8], basis=[[0, 0, 0], [0.5, 0.5, 0.5]], spacegroup=225, cellpar=[4.21, 4.21, 4.21, 90, 90, 90], ) return structure_data_cls(ase=atoms) elif name == "NiO_afm": atoms = crystal( symbols=[28, 8], basis=[[0, 0, 0], [0.5, 0.5, 0.5]], spacegroup=225, cellpar=[4.164, 4.164, 4.164, 90, 90, 90], ) atoms.set_tags([1, 1, 2, 2, 0, 0, 0, 0]) return structure_data_cls(ase=atoms) elif name == "pyrite": structure_data = { "lattice": [ [5.38, 0.000000, 0.000000], [0.000000, 5.38, 0.000000], [0.000000, 0.000000, 5.38], ], "fcoords": [ [0.0, 0.0, 0.0], [0.5, 0.0, 0.5], [0.0, 0.5, 0.5], [0.5, 0.5, 0.0], [0.338, 0.338, 0.338], [0.662, 0.662, 0.662], [0.162, 0.662, 0.838], [0.838, 0.338, 0.162], [0.662, 0.838, 0.162], [0.338, 0.162, 0.838], [0.838, 0.162, 0.662], [0.162, 0.838, 0.338], ], "symbols": ["Fe"] * 4 + ["S"] * 8, "pbc": [True, True, True], } return convert_structure(structure_data, "aiida") elif name == "marcasite": structure_data = { "lattice": [ [3.37, 0.000000, 0.000000], [0.000000, 4.44, 0.000000], [0.000000, 0.000000, 5.39], ], "ccoords": [ [0.0, 0.0, 0.0], [1.685000, 2.220000, 2.695000], [0.000000, 0.901320, 2.021250], [0.000000, 3.538680, 3.368750], [1.685000, 1.318680, 4.716250], [1.685000, 3.121320, 0.673750], ], "symbols": ["Fe"] * 2 + ["S"] * 4, "pbc": [True, True, True], } return convert_structure(structure_data, "aiida") elif name == "zincblende": structure_data = { "pbc": [True, True, True], "atomic_numbers": [26, 26, 26, 26, 16, 16, 16, 16], "ccoords": [ [0.0, 0.0, 0.0], [2.71, 2.71, 0.0], [0.0, 2.71, 2.71], [2.71, 0.0, 2.71], [1.355, 1.355, 1.355], [4.065, 4.065, 1.355], [1.355, 4.065, 4.065], [4.065, 1.355, 4.065], ], "lattice": [[5.42, 0.0, 0.0], [0.0, 5.42, 0.0], [0.0, 0.0, 5.42]], "equivalent": [0, 0, 0, 0, 0, 0, 0, 0], } return convert_structure(structure_data, "aiida") elif name == "s2_molecule": structure_data = { "pbc": [True, False, False], "atomic_numbers": [16, 16], "ccoords": [[0.0, 0.0, 0.0], [1.89, 0.0, 0.0]], "lattice": [[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]], "equivalent": [0, 0], } return convert_structure(structure_data, "aiida") raise ValueError(name)
[docs]def get_test_structure_and_symm(name, symprec=0.01, primitive=True): """Return an aiida.StructureData and related aiida_crystal17.SymmetryData for testing. SymmetryData is computed by the `crystal17.sym3d` WorkChain. """ from aiida.engine import run_get_node from aiida.orm import Dict from aiida.plugins import WorkflowFactory instruct = get_test_structure(name) sym_calc = run_get_node( WorkflowFactory("crystal17.sym3d"), structure=instruct, settings=Dict(dict={"symprec": symprec, "compute_primitive": primitive}), ).node return sym_calc.outputs.structure, sym_calc.outputs.symmetry