From 708b4b76e522decd1731745d35a424ffd81776e2 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 21 Oct 2026 13:41:34 -0400 Subject: [PATCH 1/4] deprecate diffpy.srfit.structure --- news/structure-dep.rst | 26 ++ pyproject.toml | 1 + src/diffpy/srfit/pdf/basepdfgenerator.py | 6 +- src/diffpy/srfit/structure/__init__.py | 81 ++++-- .../srfit/structure/basestructureparset.py | 30 ++- src/diffpy/srfit/structure/cctbxparset.py | 24 +- src/diffpy/srfit/structure/diffpyparset.py | 4 +- src/diffpy/srfit/structure/objcrystparset.py | 57 ++++- src/diffpy/srfit/structure/srrealparset.py | 42 +++- tests/conftest.py | 16 ++ .../deprecated/test_structure_deprecations.py | 236 ++++++++++++++++++ 11 files changed, 465 insertions(+), 58 deletions(-) create mode 100644 news/structure-dep.rst create mode 100644 tests/deprecated/test_structure_deprecations.py diff --git a/news/structure-dep.rst b/news/structure-dep.rst new file mode 100644 index 00000000..61f3a5ac --- /dev/null +++ b/news/structure-dep.rst @@ -0,0 +1,26 @@ +**Added:** + +* ``diffpy.srfit.structure.structure_to_parameter_set`` and ``SrRealParSet.restrain_bvs``, which take the names they have in ``diffpy.cmistructure``. + +**Changed:** + +* + +**Deprecated:** + +* ``diffpy.srfit.structure``, which moved to ``diffpy.cmistructure``. Importing it now raises a ``DeprecationWarning``. +* ``diffpy.srfit.structure.struToParameterSet``. Please use ``diffpy.cmistructure.structure_to_parameter_set`` instead. +* ``SrRealParSet.restrainBVS``. Please use ``diffpy.cmistructure.srrealparset.SrRealParSet.restrain_bvs`` instead. +* The ``.stru`` attribute of the structure parameter sets and of ``ObjCrystMoleculeParSet``. Please use ``.structure`` in ``diffpy.cmistructure`` instead. + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/pyproject.toml b/pyproject.toml index 54adbdfc..a9ae5e69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,6 +62,7 @@ dependencies = {file = ["requirements/pip.txt"]} # Fail when srfit source calls one of srfit's own deprecated names. filterwarnings = [ "error:'diffpy\\.srfit\\.:DeprecationWarning:diffpy\\.srfit", + "ignore:'diffpy\\.srfit\\.(pdf|sas|structure)' is deprecated:DeprecationWarning", ] [tool.codespell] diff --git a/src/diffpy/srfit/pdf/basepdfgenerator.py b/src/diffpy/srfit/pdf/basepdfgenerator.py index d66f33f6..653368a8 100644 --- a/src/diffpy/srfit/pdf/basepdfgenerator.py +++ b/src/diffpy/srfit/pdf/basepdfgenerator.py @@ -25,7 +25,7 @@ from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.fitbase import ProfileGenerator from diffpy.srfit.fitbase.parameter import ParameterAdapter -from diffpy.srfit.structure import struToParameterSet +from diffpy.srfit.structure import structure_to_parameter_set # FIXME - Parameter creation will have to be smarter once deeper calculator # configuration is enabled. @@ -282,7 +282,7 @@ def setStructure(self, stru, name="phase", periodic=True): PDF calculation. """ # Create the ParameterSet - parset = struToParameterSet(name, stru) + parset = structure_to_parameter_set(name, stru) # Set the phase self.setPhase(parset, periodic) @@ -310,7 +310,7 @@ def setPhase(self, parset, periodic=True): """ # Store the ParameterSet for easy access self._phase = parset - self.stru = self._phase.stru + self.stru = self._phase.structure # Put this ParameterSet in the ProfileGenerator. self.add_parameter_set(parset) diff --git a/src/diffpy/srfit/structure/__init__.py b/src/diffpy/srfit/structure/__init__.py index 0990c76f..70042f83 100644 --- a/src/diffpy/srfit/structure/__init__.py +++ b/src/diffpy/srfit/structure/__init__.py @@ -16,50 +16,95 @@ ParameterSet interface and automatic structure constraint generation from space group information.""" +import warnings + from diffpy.srfit.structure.sgconstraints import ( constrain_as_space_group, constrainAsSpaceGroup, ) +from diffpy.utils._deprecator import build_deprecation_message, deprecated + +removal_version = "4.0.0" + +warnings.warn( + build_deprecation_message( + "diffpy.srfit", + "structure", + "cmistructure", + removal_version, + new_base="diffpy", + ), + DeprecationWarning, + stacklevel=2, +) + +struToParameterSet_dep_msg = build_deprecation_message( + "diffpy.srfit.structure", + "struToParameterSet", + "structure_to_parameter_set", + removal_version, + new_base="diffpy.cmistructure", +) -def struToParameterSet(name, stru): - """Creates a ParameterSet from an structure. +def structure_to_parameter_set(name, structure): + """Create a ParameterSet adapted to a structure object. - This returns a ParameterSet adapted for the structure depending on its - type. + The adapter is chosen from the type of `structure`. Supported types + are diffpy.structure.Structure, pyobjcryst.crystal.Crystal, + pyobjcryst.molecule.Molecule and + cctbx.crystal.special_position_settings. Parameters ---------- - stru - a structure object known by this module - name - A name to give the structure. - - Raises TypeError if stru cannot be adapted + name : str + The name to give the structure. + structure : object + The structure object to adapt. + + Returns + ------- + BaseStructureParSet + The ParameterSet adapting `structure`. + + Raises + ------ + TypeError + If `structure` is not one of the supported structure types. """ from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet - if DiffpyStructureParSet.canAdapt(stru): - return DiffpyStructureParSet(name, stru) + if DiffpyStructureParSet.canAdapt(structure): + return DiffpyStructureParSet(name, structure) from diffpy.srfit.structure.objcrystparset import ObjCrystCrystalParSet - if ObjCrystCrystalParSet.canAdapt(stru): - return ObjCrystCrystalParSet(name, stru) + if ObjCrystCrystalParSet.canAdapt(structure): + return ObjCrystCrystalParSet(name, structure) from diffpy.srfit.structure.objcrystparset import ObjCrystMoleculeParSet - if ObjCrystMoleculeParSet.canAdapt(stru): - return ObjCrystMoleculeParSet(name, stru) + if ObjCrystMoleculeParSet.canAdapt(structure): + return ObjCrystMoleculeParSet(name, structure) from diffpy.srfit.structure.cctbxparset import CCTBXCrystalParSet - if CCTBXCrystalParSet.canAdapt(stru): - return CCTBXCrystalParSet(name, stru) + if CCTBXCrystalParSet.canAdapt(structure): + return CCTBXCrystalParSet(name, structure) raise TypeError("Unadaptable structure format") +@deprecated(struToParameterSet_dep_msg) +def struToParameterSet(name, stru): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use diffpy.cmistructure.structure_to_parameter_set instead. + """ + return structure_to_parameter_set(name, stru) + + # silence pyflakes checker assert constrain_as_space_group assert constrainAsSpaceGroup diff --git a/src/diffpy/srfit/structure/basestructureparset.py b/src/diffpy/srfit/structure/basestructureparset.py index 4c975774..1facd01a 100644 --- a/src/diffpy/srfit/structure/basestructureparset.py +++ b/src/diffpy/srfit/structure/basestructureparset.py @@ -21,6 +21,17 @@ __all__ = ["BaseStructureParSet"] from diffpy.srfit.fitbase.parameterset import ParameterSet +from diffpy.utils._deprecator import build_deprecation_message, deprecated + +removal_version = "4.0.0" + +stru_dep_msg = build_deprecation_message( + "diffpy.srfit.structure.basestructureparset.BaseStructureParSet", + "stru", + "structure", + removal_version, + new_base="diffpy.cmistructure.basestructureparset.BaseStructureParSet", +) class BaseStructureParSet(ParameterSet): @@ -32,10 +43,27 @@ class BaseStructureParSet(ParameterSet): Attributes ---------- - stru + structure The adapted object """ + @property + @deprecated(stru_dep_msg) + def stru(self): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmistructure.basestructureparset.BaseStructureParSet.structure + instead. + """ + return self.structure + + @stru.setter + @deprecated(stru_dep_msg) + def stru(self, value): + self.structure = value + @classmethod def canAdapt(self, stru): """Return whether the structure can be adapted by this class.""" diff --git a/src/diffpy/srfit/structure/cctbxparset.py b/src/diffpy/srfit/structure/cctbxparset.py index d2c89023..65e14184 100644 --- a/src/diffpy/srfit/structure/cctbxparset.py +++ b/src/diffpy/srfit/structure/cctbxparset.py @@ -92,32 +92,32 @@ def __init__(self, name, strups, idx): def _xyzgetter(self, i): def f(dummy): - return self.strups.stru.scatterers()[self.idx].site[i] + return self.strups.structure.scatterers()[self.idx].site[i] return f def _xyzsetter(self, i): def f(dummy, value): - xyz = list(self.strups.stru.scatterers()[self.idx].site) + xyz = list(self.strups.structure.scatterers()[self.idx].site) xyz[i] = value - self.strups.stru.scatterers()[self.idx].site = tuple(xyz) + self.strups.structure.scatterers()[self.idx].site = tuple(xyz) return return f def _getocc(self, dummy): - return self.strups.stru.scatterers()[self.idx].occupancy + return self.strups.structure.scatterers()[self.idx].occupancy def _setocc(self, dummy, value): - self.strups.stru.scatterers()[self.idx].occupancy = value + self.strups.structure.scatterers()[self.idx].occupancy = value return def _getuiso(self, dummy): - return self.strups.stru.scatterers()[self.idx].u_iso + return self.strups.structure.scatterers()[self.idx].u_iso def _setuiso(self, dummy, value): - self.strups.stru.scatterers()[self.idx].u_iso = value + self.strups.structure.scatterers()[self.idx].u_iso = value return def _getelem(self): @@ -161,7 +161,7 @@ def __init__(self, strups): """ ParameterSet.__init__(self, "unitcell") self.strups = strups - self._latpars = list(self.strups.stru.unit_cell().parameters()) + self._latpars = list(self.strups.structure.unit_cell().parameters()) self.add_parameter( ParameterAdapter("a", None, self._latgetter(0), self._latsetter(0)) @@ -236,7 +236,7 @@ def __init__(self, name, stru): A CCTBX structure instance. """ ParameterSet.__init__(self, name) - self.stru = stru + self.structure = stru self.add_parameter_set(CCTBXUnitCellParSet(self)) self.scatterers = [] @@ -272,7 +272,7 @@ def update(self): return self._update = False - stru = self.stru + stru = self.structure sgn = stru.space_group().match_tabulated_settings().number() # Create the symmetry object @@ -289,7 +289,7 @@ def update(self): self.unitcell._latpars = list(newstru.unit_cell().parameters()) - self.stru = newstru + self.structure = newstru return @classmethod @@ -317,7 +317,7 @@ def getScatterers(self): def getSpaceGroup(self): """Get the HM space group symbol for the structure.""" - sg = self.stru.space_group() + sg = self.structure.space_group() t = sg.type() return t.lookup_symbol() diff --git a/src/diffpy/srfit/structure/diffpyparset.py b/src/diffpy/srfit/structure/diffpyparset.py index 6d2d17b6..7bcf800c 100644 --- a/src/diffpy/srfit/structure/diffpyparset.py +++ b/src/diffpy/srfit/structure/diffpyparset.py @@ -285,7 +285,7 @@ def __init__(self, name, stru): A diffpy.structure.Structure instance """ SrRealParSet.__init__(self, name) - self.stru = stru + self.structure = stru self.add_parameter_set(DiffpyLatticeParSet(stru.lattice)) self.atoms = [] @@ -305,7 +305,7 @@ def __init__(self, name, stru): return def __repr__(self): - return repr(self.stru) + return repr(self.structure) def getLattice(self): """Get the ParameterSet containing the lattice Parameters.""" diff --git a/src/diffpy/srfit/structure/objcrystparset.py b/src/diffpy/srfit/structure/objcrystparset.py index 02a821c2..a4412edd 100644 --- a/src/diffpy/srfit/structure/objcrystparset.py +++ b/src/diffpy/srfit/structure/objcrystparset.py @@ -90,6 +90,14 @@ removal_version, ) +molecule_stru_dep_msg = build_deprecation_message( + "diffpy.srfit.structure.objcrystparset.ObjCrystMoleculeParSet", + "stru", + "structure", + removal_version, + new_base="diffpy.cmistructure.objcrystparset.ObjCrystMoleculeParSet", +) + class ObjCrystScattererParSet(ParameterSet): """A base adaptor for an Objcryst Scatterer. @@ -234,7 +242,7 @@ class ObjCrystMoleculeParSet(ObjCrystScattererParSet): ---------- scat The adapted pyobjcryst.molecule.Molecule. - stru + structure The adapted pyobjcryst.molecule.Molecule. parent The ObjCrystCrystalParSet this belongs to. @@ -253,6 +261,23 @@ class ObjCrystMoleculeParSet(ObjCrystScattererParSet): diffpy.srfit.fitbase.parameterset.ParameterSet """ + @property + @deprecated(molecule_stru_dep_msg) + def stru(self): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmistructure.objcrystparset.ObjCrystMoleculeParSet.structure + instead. + """ + return self.structure + + @stru.setter + @deprecated(molecule_stru_dep_msg) + def stru(self, value): + self.structure = value + def __init__(self, name, molecule, parent=None): """Initialize. @@ -266,7 +291,7 @@ def __init__(self, name, molecule, parent=None): The ObjCrystCrystalParSet this belongs to (default None). """ ObjCrystScattererParSet.__init__(self, name, molecule, parent) - self.stru = molecule + self.structure = molecule # Add orientation quaternion self.add_parameter(ParameterAdapter("q0", self.scat, attr="Q0")) @@ -324,7 +349,7 @@ def _get_srreal_structure(self): Molecule objects are never periodic. Return the object and let the SrReal adapters do the proper thing. """ - return self.stru + return self.structure def getLattice(self): """Get the ParameterSet containing the lattice Parameters.""" @@ -1834,23 +1859,29 @@ def __init__(self, name, cryst): """ SrRealParSet.__init__(self, name) self.angunits = "rad" - self.stru = cryst + self.structure = cryst self._sgpars = None - self.add_parameter(ParameterAdapter("a", self.stru, attr="a")) - self.add_parameter(ParameterAdapter("b", self.stru, attr="b")) - self.add_parameter(ParameterAdapter("c", self.stru, attr="c")) - self.add_parameter(ParameterAdapter("alpha", self.stru, attr="alpha")) - self.add_parameter(ParameterAdapter("beta", self.stru, attr="beta")) - self.add_parameter(ParameterAdapter("gamma", self.stru, attr="gamma")) + self.add_parameter(ParameterAdapter("a", self.structure, attr="a")) + self.add_parameter(ParameterAdapter("b", self.structure, attr="b")) + self.add_parameter(ParameterAdapter("c", self.structure, attr="c")) + self.add_parameter( + ParameterAdapter("alpha", self.structure, attr="alpha") + ) + self.add_parameter( + ParameterAdapter("beta", self.structure, attr="beta") + ) + self.add_parameter( + ParameterAdapter("gamma", self.structure, attr="gamma") + ) # Now we must loop over the scatterers and create parameter sets from # them. self.scatterers = [] snames = [] - for j in range(self.stru.GetNbScatterer()): - s = self.stru.GetScatt(j) + for j in range(self.structure.GetNbScatterer()): + s = self.structure.GetScatt(j) name = s.GetName() if not name: raise ValueError("Each Scatterer must have a name") @@ -1876,7 +1907,7 @@ def _constrain_space_group(self): """Constrain the space group.""" if self._sgpars is not None: return self._sgpars - sg = self._create_space_group(self.stru.GetSpaceGroup()) + sg = self._create_space_group(self.structure.GetSpaceGroup()) from diffpy.srfit.structure.sgconstraints import ( _constrain_as_space_group, ) diff --git a/src/diffpy/srfit/structure/srrealparset.py b/src/diffpy/srfit/structure/srrealparset.py index e98f06c7..e1051098 100644 --- a/src/diffpy/srfit/structure/srrealparset.py +++ b/src/diffpy/srfit/structure/srrealparset.py @@ -18,6 +18,17 @@ from diffpy.srfit.structure.basestructureparset import BaseStructureParSet from diffpy.srfit.structure.bvsrestraint import BVSRestraint +from diffpy.utils._deprecator import build_deprecation_message, deprecated + +removal_version = "4.0.0" + +restrainBVS_dep_msg = build_deprecation_message( + "diffpy.srfit.structure.srrealparset.SrRealParSet", + "restrainBVS", + "restrain_bvs", + removal_version, + new_base="diffpy.cmistructure.srrealparset.SrRealParSet", +) class SrRealParSet(BaseStructureParSet): @@ -28,7 +39,7 @@ class SrRealParSet(BaseStructureParSet): Attributes ---------- - stru + structure The adapted object _usesymmetry A flag indicating if SrReal calculators that operate on @@ -39,10 +50,10 @@ class SrRealParSet(BaseStructureParSet): def __init__(self, *args, **kw): BaseStructureParSet.__init__(self, *args, **kw) self._usesymmetry = True - self.stru = None + self.structure = None return - def restrainBVS(self, sig=1, scaled=False): + def restrain_bvs(self, sig=1, scaled=False): """Restrain the bond-valence sum to zero. This adds a penalty to the cost function equal to @@ -54,14 +65,17 @@ def restrainBVS(self, sig=1, scaled=False): Parameters ---------- - sig + sig : float, optional The uncertainty on the BVS (default 1). - scaled - A flag indicating if the restraint is scaled + scaled : bool, optional + The flag indicating if the restraint is scaled (multiplied) by the unrestrained point-average chi^2 (chi^2/numpoints) (default False). - Returns the BVSRestraint object for use with the 'unrestrain' method. + Returns + ------- + BVSRestraint + The restraint, for use with the 'unrestrain' method. """ # Create the Restraint object res = BVSRestraint(self, sig, scaled) @@ -72,6 +86,16 @@ def restrainBVS(self, sig=1, scaled=False): # Return the Restraint object return res + @deprecated(restrainBVS_dep_msg) + def restrainBVS(self, sig=1, scaled=False): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use diffpy.cmistructure.srrealparset.SrRealParSet.restrain_bvs + instead. + """ + return self.restrain_bvs(sig, scaled) + def useSymmetry(self, use=True): """Set this structure to use symmetry. @@ -94,5 +118,5 @@ def _get_srreal_structure(self): from diffpy.srreal.structureadapter import nosymmetry if self._usesymmetry: - return self.stru - return nosymmetry(self.stru) + return self.structure + return nosymmetry(self.structure) diff --git a/tests/conftest.py b/tests/conftest.py index 1a5f4494..ee823774 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -74,11 +74,27 @@ def has_diffpy_srreal(): logger.warning("Cannot import diffpy.srreal, PDF tests skipped.") +@lru_cache() +def has_diffpy_cmistructure(): + try: + import diffpy.cmistructure as m + + del m + return True + except ImportError: + return False + + @pytest.fixture(scope="session") def sas_available(): return has_sas() +@pytest.fixture(scope="session") +def diffpy_cmistructure_available(): + return has_diffpy_cmistructure() + + @pytest.fixture(scope="session") def diffpy_srreal_available(): return has_diffpy_srreal() diff --git a/tests/deprecated/test_structure_deprecations.py b/tests/deprecated/test_structure_deprecations.py new file mode 100644 index 00000000..e712b956 --- /dev/null +++ b/tests/deprecated/test_structure_deprecations.py @@ -0,0 +1,236 @@ +"""Tests for the deprecation of diffpy.srfit.structure, which moved to +diffpy.cmistructure. + +Each test calls a deprecated name, checks that it warns with a message +pointing to diffpy.cmistructure, and checks that it gives the same +result as the new name in srfit. The last tests check that every name a +message points to exists in diffpy.cmistructure. + +Remove this file in version 4.0.0, together with diffpy.srfit.structure. +""" + +import importlib +import re + +import pytest + +import diffpy.srfit.structure +from diffpy.srfit.structure import ( + structure_to_parameter_set, + struToParameterSet, + struToParameterSet_dep_msg, +) +from diffpy.srfit.structure.basestructureparset import stru_dep_msg +from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet +from diffpy.srfit.structure.srrealparset import restrainBVS_dep_msg +from diffpy.structure import Atom, Lattice, Structure + + +def build_expected_message(old_base, old_name, new_base, new_name): + return re.escape( + f"'{old_base}.{old_name}' is deprecated and will be removed in " + f"version 4.0.0. Please use '{new_base}.{new_name}' instead." + ) + + +def get_new_name(message): + """Return the dotted name that a deprecation message points to.""" + new_name = re.search(r"Please use '(.+)' instead\.", message).group(1) + return new_name + + +def resolve_dotted_name(dotted_name): + """Import the longest importable module prefix of a dotted name and + look up the rest as attributes. + + Return None if any part is missing. + """ + parts = dotted_name.split(".") + for split in range(len(parts), 0, -1): + try: + resolved = importlib.import_module(".".join(parts[:split])) + except ImportError: + continue + for attribute in parts[split:]: + resolved = getattr(resolved, attribute, None) + if resolved is None: + return None + return resolved + return None + + +def make_carbon_structure(): + structure = Structure([Atom("C", [0, 0.2, 0.5])]) + return structure + + +def make_nacl_parameter_set(): + lattice = Lattice(5.6, 5.6, 5.6, 90, 90, 90) + atoms = [Atom("Na", [0, 0, 0]), Atom("Cl", [0.5, 0.5, 0.5])] + parameter_set = DiffpyStructureParSet( + "nacl", Structure(atoms, lattice=lattice) + ) + return parameter_set + + +def get_bvs_restraint_state(method_name): + """Restrain the BVS of a fresh NaCl parameter set with the named + method. + + Return the restraint's type, sig and scaled flag, and how many + restraints the parameter set holds afterward. + """ + parameter_set = make_nacl_parameter_set() + restraint = getattr(parameter_set, method_name)(sig=0.5, scaled=True) + return ( + type(restraint).__name__, + restraint.sig, + restraint.scaled, + len(parameter_set._restraints), + ) + + +def test_structure_package_import_warns(): + # Test the warning given when diffpy.srfit.structure is imported. + # C1: The diffpy.srfit.structure package is imported. + # Expected: A DeprecationWarning says it moved to diffpy.cmistructure. + expected_msg = ( + "'diffpy.srfit.structure' is deprecated and will be removed in " + "version 4.0.0. Please use 'diffpy.cmistructure' instead." + ) + with pytest.warns(DeprecationWarning, match=re.escape(expected_msg)): + importlib.reload(diffpy.srfit.structure) + + +def test_stru_to_parameter_set(): + # Test the deprecated diffpy.srfit.structure.struToParameterSet. + # C1: struToParameterSet adapts a diffpy Structure. + # Expected: Warns and gives the same result as + # structure_to_parameter_set. + structure = make_carbon_structure() + expected_msg = build_expected_message( + "diffpy.srfit.structure", + "struToParameterSet", + "diffpy.cmistructure", + "structure_to_parameter_set", + ) + with pytest.warns(DeprecationWarning, match=expected_msg): + old_parameter_set = struToParameterSet("carbon", structure) + new_parameter_set = structure_to_parameter_set("carbon", structure) + actual_old_result = ( + type(old_parameter_set), + old_parameter_set.name, + old_parameter_set.structure, + ) + actual_new_result = ( + type(new_parameter_set), + new_parameter_set.name, + new_parameter_set.structure, + ) + assert actual_old_result == actual_new_result + + +def test_restrain_bvs(diffpy_srreal_available): + # Test the deprecated SrRealParSet.restrainBVS. + # C1: restrainBVS adds a scaled BVS restraint with sig = 0.5 to a + # NaCl parameter set. + # Expected: Warns and gives the same result as restrain_bvs. + if not diffpy_srreal_available: + pytest.skip("diffpy.srreal package not available") + expected_msg = build_expected_message( + "diffpy.srfit.structure.srrealparset.SrRealParSet", + "restrainBVS", + "diffpy.cmistructure.srrealparset.SrRealParSet", + "restrain_bvs", + ) + with pytest.warns(DeprecationWarning, match=expected_msg): + actual_old_result = get_bvs_restraint_state("restrainBVS") + actual_new_result = get_bvs_restraint_state("restrain_bvs") + assert actual_old_result == actual_new_result + + +def test_stru_attribute_get(): + # Test reading the deprecated BaseStructureParSet.stru attribute. + # C1: .stru is read from a DiffpyStructureParSet. + # Expected: Warns and gives the same object as .structure. + structure = make_carbon_structure() + parameter_set = DiffpyStructureParSet("carbon", structure) + expected_msg = build_expected_message( + "diffpy.srfit.structure.basestructureparset.BaseStructureParSet", + "stru", + "diffpy.cmistructure.basestructureparset.BaseStructureParSet", + "structure", + ) + with pytest.warns(DeprecationWarning, match=expected_msg): + actual_old_result = parameter_set.stru + actual_new_result = parameter_set.structure + assert actual_old_result == actual_new_result + + +def test_stru_attribute_set(): + # Test setting the deprecated BaseStructureParSet.stru attribute. + # C1: .stru is set on a DiffpyStructureParSet. + # Expected: Warns and sets .structure. + parameter_set = DiffpyStructureParSet("carbon", make_carbon_structure()) + new_structure = make_carbon_structure() + expected_msg = build_expected_message( + "diffpy.srfit.structure.basestructureparset.BaseStructureParSet", + "stru", + "diffpy.cmistructure.basestructureparset.BaseStructureParSet", + "structure", + ) + with pytest.warns(DeprecationWarning, match=expected_msg): + parameter_set.stru = new_structure + actual_structure = parameter_set.structure + expected_structure = new_structure + assert actual_structure == expected_structure + + +@pytest.mark.parametrize( + "input_message", + [ + # Test that each deprecation message points to a function or + # method that exists in diffpy.cmistructure. + # C1: The message of struToParameterSet. + # Expected: diffpy.cmistructure.structure_to_parameter_set exists. + struToParameterSet_dep_msg, + # C2: The message of SrRealParSet.restrainBVS. + # Expected: diffpy.cmistructure.srrealparset.SrRealParSet.restrain_bvs + # exists. + restrainBVS_dep_msg, + ], +) +def test_new_callable_exists_in_cmistructure( + diffpy_cmistructure_available, input_message +): + if not diffpy_cmistructure_available: + pytest.skip("diffpy.cmistructure package not available") + new_name = get_new_name(input_message) + actual_is_callable = callable(resolve_dotted_name(new_name)) + expected_is_callable = True + assert actual_is_callable == expected_is_callable + + +def test_new_attribute_exists_in_cmistructure(diffpy_cmistructure_available): + # Test that the .stru message points to an attribute that exists in + # diffpy.cmistructure. + # C1: A diffpy.cmistructure DiffpyStructureParSet adapts a structure. + # Expected: It derives from the class the message names, and that + # class's attribute holds the adapted structure. + if not diffpy_cmistructure_available: + pytest.skip("diffpy.cmistructure package not available") + from diffpy.cmistructure.diffpyparset import ( + DiffpyStructureParSet as CmiDiffpyStructureParSet, + ) + + new_class_name, new_attribute_name = get_new_name(stru_dep_msg).rsplit( + ".", 1 + ) + structure = make_carbon_structure() + parameter_set = CmiDiffpyStructureParSet("carbon", structure) + actual_result = ( + issubclass(type(parameter_set), resolve_dotted_name(new_class_name)), + getattr(parameter_set, new_attribute_name), + ) + expected_result = (True, structure) + assert actual_result == expected_result From 456dbf893c9e6b1cdf94e07752bb3f2a03f107f3 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 21 Oct 2026 13:52:39 -0400 Subject: [PATCH 2/4] change deprecation messages to point to cmistructure --- news/structure-dep.rst | 2 +- src/diffpy/srfit/structure/objcrystparset.py | 14 +++++++--- src/diffpy/srfit/structure/sgconstraints.py | 3 ++- .../deprecated/test_structure_deprecations.py | 26 ++++++++++++++++--- tests/test_sgconstraints.py | 8 +++--- 5 files changed, 41 insertions(+), 12 deletions(-) diff --git a/news/structure-dep.rst b/news/structure-dep.rst index 61f3a5ac..9205ec23 100644 --- a/news/structure-dep.rst +++ b/news/structure-dep.rst @@ -4,7 +4,7 @@ **Changed:** -* +* The deprecation messages of ``constrainAsSpaceGroup`` and of ``setConst`` on the ObjCrystParSet bond length, bond angle and dihedral angle parameters now point to ``diffpy.cmistructure`` instead of ``diffpy.srfit.structure``. **Deprecated:** diff --git a/src/diffpy/srfit/structure/objcrystparset.py b/src/diffpy/srfit/structure/objcrystparset.py index a4412edd..1a0d0016 100644 --- a/src/diffpy/srfit/structure/objcrystparset.py +++ b/src/diffpy/srfit/structure/objcrystparset.py @@ -62,32 +62,40 @@ removal_version = "4.0.0" bl_base = "diffpy.srfit.structure.objcrystparset.ObjCrystBondLengthParameter" +bl_new_base = "diffpy.cmistructure.objcrystparset.ObjCrystBondLengthParameter" bl_setConst_dep_msg = build_deprecation_message( bl_base, "setConst", "set_constant", removal_version, + new_base=bl_new_base, ) ba_base = "diffpy.srfit.structure.objcrystparset.ObjCrystBondAngleParameter" +ba_new_base = "diffpy.cmistructure.objcrystparset.ObjCrystBondAngleParameter" ba_setConst_dep_msg = build_deprecation_message( ba_base, "setConst", "set_constant", removal_version, + new_base=ba_new_base, ) da_base = ( "diffpy.srfit.structure.objcrystparset.ObjCrystDihedralAngleParameter" ) +da_new_base = ( + "diffpy.cmistructure.objcrystparset.ObjCrystDihedralAngleParameter" +) da_setConst_dep_msg = build_deprecation_message( da_base, "setConst", "set_constant", removal_version, + new_base=da_new_base, ) molecule_stru_dep_msg = build_deprecation_message( @@ -1443,7 +1451,7 @@ def setConst(self, const=True, value=None): 4.0.0. Please use - diffpy.srfit.structure.objcryst.ObjCrystBondLengthParameter.set_constant + diffpy.cmistructure.objcrystparset.ObjCrystBondLengthParameter.set_constant instead. """ self.set_constant(const, value) @@ -1604,7 +1612,7 @@ def setConst(self, const=True, value=None): version 4.0.0. Please use - diffpy.srfit.structure.objcryst.ObjCrystBondAngleParameter.set_constant + diffpy.cmistructure.objcrystparset.ObjCrystBondAngleParameter.set_constant instead. """ self.set_constant(const, value) @@ -1784,7 +1792,7 @@ def setConst(self, const=True, value=None): version 4.0.0. Please use - diffpy.srfit.structure.objcryst.ObjCrystDihedralAngleParameter.set_constant + diffpy.cmistructure.objcrystparset.ObjCrystDihedralAngleParameter.set_constant instead. """ self.set_constant(const, value) diff --git a/src/diffpy/srfit/structure/sgconstraints.py b/src/diffpy/srfit/structure/sgconstraints.py index 4f956a5a..d61a782d 100644 --- a/src/diffpy/srfit/structure/sgconstraints.py +++ b/src/diffpy/srfit/structure/sgconstraints.py @@ -32,6 +32,7 @@ "constrainAsSpaceGroup", "constrain_as_space_group", removal_version, + new_base="diffpy.cmistructure.sgconstraints", ) @@ -146,7 +147,7 @@ def constrainAsSpaceGroup( 4.0.0. Please use - diffpy.srfit.structure.sgconstraints.constrain_as_space_group + diffpy.cmistructure.sgconstraints.constrain_as_space_group instead. """ return constrain_as_space_group( diff --git a/tests/deprecated/test_structure_deprecations.py b/tests/deprecated/test_structure_deprecations.py index e712b956..579dfbb7 100644 --- a/tests/deprecated/test_structure_deprecations.py +++ b/tests/deprecated/test_structure_deprecations.py @@ -22,6 +22,12 @@ ) from diffpy.srfit.structure.basestructureparset import stru_dep_msg from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet +from diffpy.srfit.structure.objcrystparset import ( + ba_setConst_dep_msg, + bl_setConst_dep_msg, + da_setConst_dep_msg, +) +from diffpy.srfit.structure.sgconstraints import constrainAsSpaceGroup_dep_msg from diffpy.srfit.structure.srrealparset import restrainBVS_dep_msg from diffpy.structure import Atom, Lattice, Structure @@ -198,6 +204,17 @@ def test_stru_attribute_set(): # Expected: diffpy.cmistructure.srrealparset.SrRealParSet.restrain_bvs # exists. restrainBVS_dep_msg, + # C3: The message of sgconstraints.constrainAsSpaceGroup. + # Expected: diffpy.cmistructure.sgconstraints.constrain_as_space_group + # exists. + constrainAsSpaceGroup_dep_msg, + # C4: The setConst messages of the ObjCryst bond length, bond angle + # and dihedral angle parameters. + # Expected: set_constant exists on each matching class in + # diffpy.cmistructure.objcrystparset. + bl_setConst_dep_msg, + ba_setConst_dep_msg, + da_setConst_dep_msg, ], ) def test_new_callable_exists_in_cmistructure( @@ -206,9 +223,12 @@ def test_new_callable_exists_in_cmistructure( if not diffpy_cmistructure_available: pytest.skip("diffpy.cmistructure package not available") new_name = get_new_name(input_message) - actual_is_callable = callable(resolve_dotted_name(new_name)) - expected_is_callable = True - assert actual_is_callable == expected_is_callable + actual_result = ( + new_name.startswith("diffpy.cmistructure."), + callable(resolve_dotted_name(new_name)), + ) + expected_result = (True, True) + assert actual_result == expected_result def test_new_attribute_exists_in_cmistructure(diffpy_cmistructure_available): diff --git a/tests/test_sgconstraints.py b/tests/test_sgconstraints.py index 8789228b..b4a6aa6f 100644 --- a/tests/test_sgconstraints.py +++ b/tests/test_sgconstraints.py @@ -219,11 +219,11 @@ def test_constrainAsSpaceGroup_warns_and_forwards( constrainAsSpaceGroup, ) - module_path = "diffpy.srfit.structure.sgconstraints" expected_msg = ( - f"'{module_path}.constrainAsSpaceGroup' is deprecated and will be " - f"removed in version 4.0.0. Please use " - f"'{module_path}.constrain_as_space_group' instead." + "'diffpy.srfit.structure.sgconstraints.constrainAsSpaceGroup' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmistructure.sgconstraints.constrain_as_space_group' " + "instead." ) parset = DiffpyStructureParSet("LaMnO3", makeLaMnO3_P1(datafile)) From fd64ce8b35f1e958d370c8deb97b889d77c67819 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 21 Oct 2026 15:44:25 -0400 Subject: [PATCH 3/4] simplify testing --- tests/conftest.py | 16 - .../deprecated/test_structure_deprecations.py | 297 +++++------------- 2 files changed, 78 insertions(+), 235 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index ee823774..1a5f4494 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -74,27 +74,11 @@ def has_diffpy_srreal(): logger.warning("Cannot import diffpy.srreal, PDF tests skipped.") -@lru_cache() -def has_diffpy_cmistructure(): - try: - import diffpy.cmistructure as m - - del m - return True - except ImportError: - return False - - @pytest.fixture(scope="session") def sas_available(): return has_sas() -@pytest.fixture(scope="session") -def diffpy_cmistructure_available(): - return has_diffpy_cmistructure() - - @pytest.fixture(scope="session") def diffpy_srreal_available(): return has_diffpy_srreal() diff --git a/tests/deprecated/test_structure_deprecations.py b/tests/deprecated/test_structure_deprecations.py index 579dfbb7..f493197b 100644 --- a/tests/deprecated/test_structure_deprecations.py +++ b/tests/deprecated/test_structure_deprecations.py @@ -1,256 +1,115 @@ """Tests for the deprecation of diffpy.srfit.structure, which moved to diffpy.cmistructure. -Each test calls a deprecated name, checks that it warns with a message -pointing to diffpy.cmistructure, and checks that it gives the same -result as the new name in srfit. The last tests check that every name a -message points to exists in diffpy.cmistructure. - Remove this file in version 4.0.0, together with diffpy.srfit.structure. """ import importlib -import re import pytest import diffpy.srfit.structure -from diffpy.srfit.structure import ( - structure_to_parameter_set, - struToParameterSet, - struToParameterSet_dep_msg, -) -from diffpy.srfit.structure.basestructureparset import stru_dep_msg +from diffpy.srfit.structure import struToParameterSet from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet -from diffpy.srfit.structure.objcrystparset import ( - ba_setConst_dep_msg, - bl_setConst_dep_msg, - da_setConst_dep_msg, -) -from diffpy.srfit.structure.sgconstraints import constrainAsSpaceGroup_dep_msg -from diffpy.srfit.structure.srrealparset import restrainBVS_dep_msg from diffpy.structure import Atom, Lattice, Structure -def build_expected_message(old_base, old_name, new_base, new_name): - return re.escape( - f"'{old_base}.{old_name}' is deprecated and will be removed in " - f"version 4.0.0. Please use '{new_base}.{new_name}' instead." - ) - - -def get_new_name(message): - """Return the dotted name that a deprecation message points to.""" - new_name = re.search(r"Please use '(.+)' instead\.", message).group(1) - return new_name - - -def resolve_dotted_name(dotted_name): - """Import the longest importable module prefix of a dotted name and - look up the rest as attributes. - - Return None if any part is missing. - """ - parts = dotted_name.split(".") - for split in range(len(parts), 0, -1): - try: - resolved = importlib.import_module(".".join(parts[:split])) - except ImportError: - continue - for attribute in parts[split:]: - resolved = getattr(resolved, attribute, None) - if resolved is None: - return None - return resolved - return None - - -def make_carbon_structure(): - structure = Structure([Atom("C", [0, 0.2, 0.5])]) - return structure - - -def make_nacl_parameter_set(): +@pytest.fixture +def nacl_structure(): lattice = Lattice(5.6, 5.6, 5.6, 90, 90, 90) atoms = [Atom("Na", [0, 0, 0]), Atom("Cl", [0.5, 0.5, 0.5])] - parameter_set = DiffpyStructureParSet( - "nacl", Structure(atoms, lattice=lattice) - ) - return parameter_set - - -def get_bvs_restraint_state(method_name): - """Restrain the BVS of a fresh NaCl parameter set with the named - method. - - Return the restraint's type, sig and scaled flag, and how many - restraints the parameter set holds afterward. - """ - parameter_set = make_nacl_parameter_set() - restraint = getattr(parameter_set, method_name)(sig=0.5, scaled=True) - return ( - type(restraint).__name__, - restraint.sig, - restraint.scaled, - len(parameter_set._restraints), - ) + return Structure(atoms, lattice=lattice) def test_structure_package_import_warns(): - # Test the warning given when diffpy.srfit.structure is imported. - # C1: The diffpy.srfit.structure package is imported. - # Expected: A DeprecationWarning says it moved to diffpy.cmistructure. + # Case: diffpy.srfit.structure is imported. + # Expected: A DeprecationWarning points to diffpy.cmistructure. expected_msg = ( "'diffpy.srfit.structure' is deprecated and will be removed in " "version 4.0.0. Please use 'diffpy.cmistructure' instead." ) - with pytest.warns(DeprecationWarning, match=re.escape(expected_msg)): + with pytest.warns(DeprecationWarning) as record: importlib.reload(diffpy.srfit.structure) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg -def test_stru_to_parameter_set(): - # Test the deprecated diffpy.srfit.structure.struToParameterSet. - # C1: struToParameterSet adapts a diffpy Structure. - # Expected: Warns and gives the same result as - # structure_to_parameter_set. - structure = make_carbon_structure() - expected_msg = build_expected_message( - "diffpy.srfit.structure", - "struToParameterSet", - "diffpy.cmistructure", - "structure_to_parameter_set", - ) - with pytest.warns(DeprecationWarning, match=expected_msg): - old_parameter_set = struToParameterSet("carbon", structure) - new_parameter_set = structure_to_parameter_set("carbon", structure) - actual_old_result = ( - type(old_parameter_set), - old_parameter_set.name, - old_parameter_set.structure, - ) - actual_new_result = ( - type(new_parameter_set), - new_parameter_set.name, - new_parameter_set.structure, +def test_struToParameterSet(nacl_structure): + # Case: struToParameterSet adapts a diffpy Structure. + # Expected: A DeprecationWarning points to + # diffpy.cmistructure.structure_to_parameter_set, and a + # DiffpyStructureParSet is still returned. + expected_msg = ( + "'diffpy.srfit.structure.struToParameterSet' is deprecated and will " + "be removed in version 4.0.0. Please use " + "'diffpy.cmistructure.structure_to_parameter_set' instead." ) - assert actual_old_result == actual_new_result + with pytest.warns(DeprecationWarning) as record: + parameter_set = struToParameterSet("nacl", nacl_structure) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + actual_type = type(parameter_set) + expected_type = DiffpyStructureParSet + assert actual_type == expected_type + actual_structure = parameter_set.structure + expected_structure = nacl_structure + assert actual_structure == expected_structure -def test_restrain_bvs(diffpy_srreal_available): - # Test the deprecated SrRealParSet.restrainBVS. - # C1: restrainBVS adds a scaled BVS restraint with sig = 0.5 to a - # NaCl parameter set. - # Expected: Warns and gives the same result as restrain_bvs. - if not diffpy_srreal_available: - pytest.skip("diffpy.srreal package not available") - expected_msg = build_expected_message( - "diffpy.srfit.structure.srrealparset.SrRealParSet", - "restrainBVS", - "diffpy.cmistructure.srrealparset.SrRealParSet", - "restrain_bvs", +def test_restrainBVS(nacl_structure): + # Case: restrainBVS is called on a DiffpyStructureParSet. + # Expected: A DeprecationWarning points to + # diffpy.cmistructure's restrain_bvs, and the restraint is still added. + parameter_set = DiffpyStructureParSet("nacl", nacl_structure) + expected_msg = ( + "'diffpy.srfit.structure.srrealparset.SrRealParSet.restrainBVS' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmistructure.srrealparset.SrRealParSet.restrain_bvs' " + "instead." ) - with pytest.warns(DeprecationWarning, match=expected_msg): - actual_old_result = get_bvs_restraint_state("restrainBVS") - actual_new_result = get_bvs_restraint_state("restrain_bvs") - assert actual_old_result == actual_new_result - - -def test_stru_attribute_get(): - # Test reading the deprecated BaseStructureParSet.stru attribute. - # C1: .stru is read from a DiffpyStructureParSet. - # Expected: Warns and gives the same object as .structure. - structure = make_carbon_structure() - parameter_set = DiffpyStructureParSet("carbon", structure) - expected_msg = build_expected_message( - "diffpy.srfit.structure.basestructureparset.BaseStructureParSet", - "stru", - "diffpy.cmistructure.basestructureparset.BaseStructureParSet", - "structure", + with pytest.warns(DeprecationWarning) as record: + restraint = parameter_set.restrainBVS(sig=0.5) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + actual_sig = restraint.sig + expected_sig = 0.5 + assert actual_sig == expected_sig + + +def test_stru_get(nacl_structure): + # Case: .stru is read from a DiffpyStructureParSet. + # Expected: A DeprecationWarning points to .structure in + # diffpy.cmistructure, and the adapted structure is returned. + parameter_set = DiffpyStructureParSet("nacl", nacl_structure) + expected_msg = ( + "'diffpy.srfit.structure.basestructureparset.BaseStructureParSet." + "stru' is deprecated and will be removed in version 4.0.0. Please " + "use 'diffpy.cmistructure.basestructureparset.BaseStructureParSet." + "structure' instead." ) - with pytest.warns(DeprecationWarning, match=expected_msg): - actual_old_result = parameter_set.stru - actual_new_result = parameter_set.structure - assert actual_old_result == actual_new_result + with pytest.warns(DeprecationWarning) as record: + actual_structure = parameter_set.stru + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + expected_structure = nacl_structure + assert actual_structure == expected_structure -def test_stru_attribute_set(): - # Test setting the deprecated BaseStructureParSet.stru attribute. - # C1: .stru is set on a DiffpyStructureParSet. - # Expected: Warns and sets .structure. - parameter_set = DiffpyStructureParSet("carbon", make_carbon_structure()) - new_structure = make_carbon_structure() - expected_msg = build_expected_message( - "diffpy.srfit.structure.basestructureparset.BaseStructureParSet", - "stru", - "diffpy.cmistructure.basestructureparset.BaseStructureParSet", - "structure", +def test_stru_set(nacl_structure): + # Case: .stru is set on a DiffpyStructureParSet. + # Expected: A DeprecationWarning points to .structure in + # diffpy.cmistructure, and .structure is updated. + parameter_set = DiffpyStructureParSet("nacl", Structure()) + expected_msg = ( + "'diffpy.srfit.structure.basestructureparset.BaseStructureParSet." + "stru' is deprecated and will be removed in version 4.0.0. Please " + "use 'diffpy.cmistructure.basestructureparset.BaseStructureParSet." + "structure' instead." ) - with pytest.warns(DeprecationWarning, match=expected_msg): - parameter_set.stru = new_structure + with pytest.warns(DeprecationWarning) as record: + parameter_set.stru = nacl_structure + actual_msg = str(record[0].message) + assert actual_msg == expected_msg actual_structure = parameter_set.structure - expected_structure = new_structure + expected_structure = nacl_structure assert actual_structure == expected_structure - - -@pytest.mark.parametrize( - "input_message", - [ - # Test that each deprecation message points to a function or - # method that exists in diffpy.cmistructure. - # C1: The message of struToParameterSet. - # Expected: diffpy.cmistructure.structure_to_parameter_set exists. - struToParameterSet_dep_msg, - # C2: The message of SrRealParSet.restrainBVS. - # Expected: diffpy.cmistructure.srrealparset.SrRealParSet.restrain_bvs - # exists. - restrainBVS_dep_msg, - # C3: The message of sgconstraints.constrainAsSpaceGroup. - # Expected: diffpy.cmistructure.sgconstraints.constrain_as_space_group - # exists. - constrainAsSpaceGroup_dep_msg, - # C4: The setConst messages of the ObjCryst bond length, bond angle - # and dihedral angle parameters. - # Expected: set_constant exists on each matching class in - # diffpy.cmistructure.objcrystparset. - bl_setConst_dep_msg, - ba_setConst_dep_msg, - da_setConst_dep_msg, - ], -) -def test_new_callable_exists_in_cmistructure( - diffpy_cmistructure_available, input_message -): - if not diffpy_cmistructure_available: - pytest.skip("diffpy.cmistructure package not available") - new_name = get_new_name(input_message) - actual_result = ( - new_name.startswith("diffpy.cmistructure."), - callable(resolve_dotted_name(new_name)), - ) - expected_result = (True, True) - assert actual_result == expected_result - - -def test_new_attribute_exists_in_cmistructure(diffpy_cmistructure_available): - # Test that the .stru message points to an attribute that exists in - # diffpy.cmistructure. - # C1: A diffpy.cmistructure DiffpyStructureParSet adapts a structure. - # Expected: It derives from the class the message names, and that - # class's attribute holds the adapted structure. - if not diffpy_cmistructure_available: - pytest.skip("diffpy.cmistructure package not available") - from diffpy.cmistructure.diffpyparset import ( - DiffpyStructureParSet as CmiDiffpyStructureParSet, - ) - - new_class_name, new_attribute_name = get_new_name(stru_dep_msg).rsplit( - ".", 1 - ) - structure = make_carbon_structure() - parameter_set = CmiDiffpyStructureParSet("carbon", structure) - actual_result = ( - issubclass(type(parameter_set), resolve_dotted_name(new_class_name)), - getattr(parameter_set, new_attribute_name), - ) - expected_result = (True, structure) - assert actual_result == expected_result From b571573109491cb56eecd2590d47fd988071abe7 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 21 Oct 2026 16:18:39 -0400 Subject: [PATCH 4/4] readd diffpy.srreal test skip --- tests/deprecated/test_structure_deprecations.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/deprecated/test_structure_deprecations.py b/tests/deprecated/test_structure_deprecations.py index f493197b..dac4c899 100644 --- a/tests/deprecated/test_structure_deprecations.py +++ b/tests/deprecated/test_structure_deprecations.py @@ -56,10 +56,12 @@ def test_struToParameterSet(nacl_structure): assert actual_structure == expected_structure -def test_restrainBVS(nacl_structure): +def test_restrainBVS(diffpy_srreal_available, nacl_structure): # Case: restrainBVS is called on a DiffpyStructureParSet. # Expected: A DeprecationWarning points to # diffpy.cmistructure's restrain_bvs, and the restraint is still added. + if not diffpy_srreal_available: + pytest.skip("diffpy.srreal package not available") parameter_set = DiffpyStructureParSet("nacl", nacl_structure) expected_msg = ( "'diffpy.srfit.structure.srrealparset.SrRealParSet.restrainBVS' is "