def skip_if_missing(package_name: str, reason: Optional[str] = None): """ Helper function to generate a pytest.mark.skipif decorator for any package. This allows tests to be skipped if some optional dependency is not found. Parameters ---------- package_name : str The name of the package that is required for a test(s) reason : str, optional Explanation of why the skipped it to be tested Returns ------- requires_package : _pytest.mark.structures.MarkDecorator A pytest decorator that will skip tests if the package is not available """ import pytest if not reason: reason = f"Package {package_name} is required, but was not found." requires_package = pytest.mark.skipif(not has_package(package_name), reason=reason) return requires_package
def validate_type(cls, val): """Process an array tagged with units into one tagged with "OpenFF" style units""" unit_ = getattr(cls, "__unit__", Any) if unit_ is Any: if isinstance(val, (list, np.ndarray)): # TODO: Can this exception be raised with knowledge of the field it's in? raise MissingUnitError( f"Value {val} needs to be tagged with a unit" ) elif isinstance(val, unit.Quantity): # Redundant cast? Maybe this handles pint vs openff.interchange.unit? return unit.Quantity(val) elif isinstance(val, simtk_unit.Quantity): return _from_omm_quantity(val) else: raise UnitValidationError( f"Could not validate data of type {type(val)}" ) else: unit_ = unit(unit_) if isinstance(val, unit.Quantity): assert unit_.dimensionality == val.dimensionality return val.to(unit_) if isinstance(val, simtk_unit.Quantity): return _from_omm_quantity(val).to(unit_) if isinstance(val, (np.ndarray, list)): if has_package("unyt"): # Must check for unyt_array, not unyt_quantity, which is a subclass if isinstance(val, unyt.unyt_array): return _from_unyt_quantity(val).to(unit_) else: return val * unit_ else: return val * unit_ if isinstance(val, bytes): # Define outside loop dt = np.dtype(int) dt.newbyteorder("<") return np.frombuffer(val, dtype=dt) * unit_ if isinstance(val, str): # could do custom deserialization here? raise NotImplementedError # return unit.Quantity(val).to(unit_) raise UnitValidationError( f"Could not validate data of type {type(val)}" )
def validate_type(cls, val): """Process a value tagged with units into one tagged with "OpenFF" style units""" unit_ = getattr(cls, "__unit__", Any) if unit_ is Any: if isinstance(val, (float, int)): # TODO: Can this exception be raised with knowledge of the field it's in? raise MissingUnitError(f"Value {val} needs to be tagged with a unit") elif isinstance(val, unit.Quantity): return unit.Quantity(val) elif isinstance(val, simtk_unit.Quantity): return _from_omm_quantity(val) else: raise UnitValidationError( f"Could not validate data of type {type(val)}" ) else: unit_ = unit(unit_) if isinstance(val, unit.Quantity): # some custom behavior could go here assert unit_.dimensionality == val.dimensionality # return through converting to some intended default units (taken from the class) return val.to(unit_) # could return here, without converting # (could be inconsistent with data model - heteregenous but compatible units) # return val if isinstance(val, simtk_unit.Quantity): return _from_omm_quantity(val).to(unit_) if has_package("unyt"): if isinstance(val, unyt.unyt_quantity): return _from_unyt_quantity(val).to(unit_) if isinstance(val, (float, int)) and not isinstance(val, bool): return val * unit_ if isinstance(val, str): # could do custom deserialization here? return unit.Quantity(val).to(unit_) raise UnitValidationError(f"Could not validate data of type {type(val)}")
from typing import TYPE_CHECKING from openff.toolkit.topology import Molecule, Topology from openff.utilities.utilities import has_package, requires_package from simtk import unit if has_package("mbuild") or TYPE_CHECKING: import mbuild as mb @requires_package("mbuild") def offmol_to_compound(off_mol: "Molecule") -> "mb.Compound": """Covert an OpenFF Molecule into an mBuild Compound. Examples -------- .. code-block:: pycon >>> from openff.toolkit.topology import Molecule >>> from openff.interchange.components.mbuild import offmol_to_compound >>> mol = Molecule.from_smiles("CCO") >>> compound = offmol_to_compound(mol) >>> type(compound), compound.n_particles, compound.n_bonds (<class 'mbuild.compound.Compound'>, 9, 8) """ if not off_mol.has_unique_atom_names: off_mol.generate_unique_atom_names() if off_mol.n_conformers == 0:
import json from typing import TYPE_CHECKING, Any, Dict import numpy as np from openff.units import unit from openff.utilities.utilities import has_package, requires_package from simtk import unit as simtk_unit from openff.interchange.exceptions import ( MissingUnitError, UnitValidationError, UnsupportedExportError, ) if TYPE_CHECKING or has_package("unyt"): import unyt class _FloatQuantityMeta(type): def __getitem__(self, t): return type("FloatQuantity", (FloatQuantity,), {"__unit__": t}) class FloatQuantity(float, metaclass=_FloatQuantityMeta): @classmethod def __get_validators__(cls): yield cls.validate_type @classmethod def validate_type(cls, val): """Process a value tagged with units into one tagged with "OpenFF" style units"""
def test_has_executable(): assert has_executable("pwd") assert has_executable("pytest") assert not has_package("pyyyyython")
def test_has_package(): assert has_package("os") assert has_package("pytest") assert not has_package("nummmmmmpy")
@skip_if_missing("openeye.oechem") @pytest.mark.skipif("OE_LICENSE" in os.environ, reason="Requires an OpenEye license is NOT set up") def test_requires_oe_module_installed_missing_license(): """Tests that the ``requires_package`` utility behaves as expected while OpenEye toolkits are installed but no OpenEye license is set up.""" def dummy_function(): pass with pytest.raises(MissingOptionalDependencyError) as error_info: requires_oe_module("oechem")(dummy_function)() assert "oechem" in str(error_info.value) assert "conda-forge" not in str(error_info.value) @pytest.mark.skipif(has_package("openeye.oechem"), reason="Requires OpenEye toolkits are NOT installed") def test_requires_oe_module_not_installed(): """Tests that the ``requires_package`` utility behaves as expected while OpenEye toolkits are installed.""" def dummy_function(): pass with pytest.raises(MissingOptionalDependencyError) as error_info: requires_oe_module("oechem")(dummy_function)() assert "oechem" in str(error_info.value) assert "conda-forge" not in str(error_info.value)
from openff.utilities.utilities import has_package from openff.interchange.components.potentials import Potential, PotentialHandler from openff.interchange.models import PotentialKey, TopologyKey from openff.interchange.types import FloatQuantity if TYPE_CHECKING: from foyer.forcefield import Forcefield from foyer.topology_graph import TopologyGraph from openff.interchange.components.mdtraj import OFFBioTop # Is this the safest way to achieve PotentialKey id separation? POTENTIAL_KEY_SEPARATOR = "-" if has_package("foyer"): from foyer.topology_graph import TopologyGraph # noqa def _copy_params(params: Dict[str, float], *drop_keys: str, param_units: Dict = None) -> Dict: """copy parameters from a dictionary""" params_copy = copy(params) for drop_key in drop_keys: params_copy.pop(drop_key, None) if param_units: for unit_item, units in param_units.items(): params_copy[unit_item] = params_copy[unit_item] * units return params_copy