From e26db6d6e358ae89a2999c448fdc8175c0ca8be9 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Thu, 8 Oct 2026 12:12:47 -0400 Subject: [PATCH] fix: clean up core srfit before the subpackage split Fix the SASProfile set_observed_profile override that core no longer called, remove the undeclared six dependency and its Python 2 branches, and load test_fitrecipe data with ProfileParser instead of PDFParser. Co-Authored-By: Claude Opus 5.5 --- news/core-cleanup.rst | 28 ++++++++++++++++++++++++ src/diffpy/srfit/equation/builder.py | 14 +++--------- src/diffpy/srfit/fitbase/profile.py | 3 +-- src/diffpy/srfit/interface/interface.py | 6 ++--- src/diffpy/srfit/sas/sasprofile.py | 8 +++---- src/diffpy/srfit/util/weakrefcallable.py | 9 +------- tests/conftest.py | 4 ++-- tests/test_fitrecipe.py | 16 +++++++------- 8 files changed, 49 insertions(+), 39 deletions(-) create mode 100644 news/core-cleanup.rst diff --git a/news/core-cleanup.rst b/news/core-cleanup.rst new file mode 100644 index 00000000..a0a45ea7 --- /dev/null +++ b/news/core-cleanup.rst @@ -0,0 +1,28 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* Removed the undeclared ``six`` dependency and the leftover Python 2 + compatibility code that used it. + +**Fixed:** + +* ``SASProfile`` now updates its wrapped SAS ``DataInfo`` object when the + observed profile is set through ``set_observed_profile`` or + ``load_parsed_data``. Previously only the deprecated ``setObservedProfile`` + did this. +* ``FitRecipe`` tests no longer depend on the ``diffpy.srfit.pdf`` package. + +**Security:** + +* diff --git a/src/diffpy/srfit/equation/builder.py b/src/diffpy/srfit/equation/builder.py index 1bc187ec..764b0d98 100644 --- a/src/diffpy/srfit/equation/builder.py +++ b/src/diffpy/srfit/equation/builder.py @@ -77,12 +77,12 @@ """ import inspect +import io import numbers import token import tokenize import numpy -import six import diffpy.srfit.equation.literals as literals from diffpy.srfit.equation.equationmod import Equation @@ -275,7 +275,7 @@ def registerBuilder(self, name, builder): Raises ValueError if the new builder's literal causes a self- reference in an existing equation. """ - if not isinstance(name, six.string_types): + if not isinstance(name, str): raise TypeError("Name must be a string") if not isinstance(builder, BaseBuilder): raise TypeError("builder must be a BaseBuilder instance") @@ -389,7 +389,7 @@ def _get_undefined_args(self, eqstr): Raises SyntaxError if the equation string uses invalid syntax. """ - interface = six.StringIO(eqstr).readline + interface = io.StringIO(eqstr).readline # output is an iterator. Each entry (token) is a 5-tuple # token[0] = token type # token[1] = token string @@ -560,14 +560,6 @@ def __truediv__(self, other): def __rtruediv__(self, other): return self.__eval_binary(other, literals.DivisionOperator, False) - # Python 2 Compatibility ------------------------------------------------- - - if six.PY2: - __div__ = __truediv__ - __rdiv__ = __rtruediv__ - - # ------------------------------------------------------------------------ - def __pow__(self, other): return self.__eval_binary(other, literals.ExponentiationOperator) diff --git a/src/diffpy/srfit/fitbase/profile.py b/src/diffpy/srfit/fitbase/profile.py index d92d76f5..c9b6f931 100644 --- a/src/diffpy/srfit/fitbase/profile.py +++ b/src/diffpy/srfit/fitbase/profile.py @@ -23,7 +23,6 @@ __all__ = ["Parameter", "Profile"] import numpy -import six from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.fitbase.parameter import Parameter @@ -272,7 +271,7 @@ def set_calculation_range(self, xmin=None, xmax=None, dx=None): # local helper function def _isobs(a): - if not isinstance(a, six.string_types): + if not isinstance(a, str): return False if a != "obs": raise ValueError('Must be either float or "obs".') diff --git a/src/diffpy/srfit/interface/interface.py b/src/diffpy/srfit/interface/interface.py index fc0b78e9..cf0bcdce 100644 --- a/src/diffpy/srfit/interface/interface.py +++ b/src/diffpy/srfit/interface/interface.py @@ -27,8 +27,6 @@ "RecipeOrganizerInterface", ] -import six - from diffpy.srfit.equation.literals.abcs import ArgumentABC @@ -124,7 +122,7 @@ def __iadd__(self, args): # Want to detect _add_parameter or _new_parameter def f(*args): - if isinstance(args[0], six.string_types): + if isinstance(args[0], str): self._new_parameter(*args) else: self._add_parameter(*args) @@ -182,7 +180,7 @@ def __iadd__(self, args): # Want to detect add_variable or create_new_variable def f(*args): - if isinstance(args[0], six.string_types): + if isinstance(args[0], str): self.create_new_variable(*args) else: self.add_variable(*args) diff --git a/src/diffpy/srfit/sas/sasprofile.py b/src/diffpy/srfit/sas/sasprofile.py index a0761fb8..5e8bd7d0 100644 --- a/src/diffpy/srfit/sas/sasprofile.py +++ b/src/diffpy/srfit/sas/sasprofile.py @@ -92,7 +92,7 @@ def __init__(self, datainfo): self._dyobs = self._datainfo.dy return - def setObservedProfile(self, xobs, yobs, dyobs=None): + def set_observed_profile(self, xobs, yobs, dyobs=None): """Set the observed profile. This is overloaded to change the value within the datainfo object. @@ -105,8 +105,8 @@ def setObservedProfile(self, xobs, yobs, dyobs=None): Numpy array of the observed signal. dyobs Numpy array of the uncertainty in the observed signal. If - ``dyobs`` is ``None`` (default), it will be set to 1 at each - observed ``xobs``. + ``dyobs`` is ``None`` (default), it stays ``None`` to indicate + no uncertainty was observed. Raises ------ @@ -115,7 +115,7 @@ def setObservedProfile(self, xobs, yobs, dyobs=None): ValueError If ``dyobs is not None`` and ``len(dyobs) != len(xobs)``. """ - Profile.setObservedProfile(self, xobs, yobs, dyobs) + Profile.set_observed_profile(self, xobs, yobs, dyobs) # Copy the arrays to the _datainfo attribute. self._datainfo.x = self._xobs self._datainfo.y = self._yobs diff --git a/src/diffpy/srfit/util/weakrefcallable.py b/src/diffpy/srfit/util/weakrefcallable.py index 1cbb87aa..9a30ac72 100644 --- a/src/diffpy/srfit/util/weakrefcallable.py +++ b/src/diffpy/srfit/util/weakrefcallable.py @@ -17,8 +17,6 @@ import types import weakref -import six - class WeakBoundMethod(object): """Callable wrapper to a bound method stored as a weak reference. @@ -60,8 +58,6 @@ def __init__(self, f, fallback=None): # This does not handle builtin methods, but that can be added # if necessary. self.function = f.__func__ - if six.PY2: - self.function = f.__func__.__get__(None, f.im_class) self.fallback = fallback self._class = type(f.__self__) self._wref = weakref.ref(f.__self__) @@ -114,10 +110,7 @@ def __getstate__(self): mobj = self._wref() nm = self.function.__name__ amsg = "Unable to pickle this unbound function by name." - if six.PY2: - assert self.function == getattr(self._class, nm), amsg - if six.PY3: - assert self.function is getattr(self._class, nm), amsg + assert self.function is getattr(self._class, nm), amsg state = (self._class, nm, self.fallback, mobj) return state diff --git a/tests/conftest.py b/tests/conftest.py index b0859d0d..41d9146e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,10 +1,10 @@ import importlib.resources +import io import logging import sys from functools import lru_cache import pytest -import six from numpy import linspace, pi, sin import diffpy.srfit.equation.literals as literals @@ -131,7 +131,7 @@ def capturestdout(): def _capturestdout(f, *args, **kwargs): """Capture the standard output from a call of function f.""" savestdout = sys.stdout - fp = six.StringIO() + fp = io.StringIO() try: sys.stdout = fp f(*args, **kwargs) diff --git a/tests/test_fitrecipe.py b/tests/test_fitrecipe.py index 0bd91169..228ae928 100644 --- a/tests/test_fitrecipe.py +++ b/tests/test_fitrecipe.py @@ -28,7 +28,7 @@ from diffpy.srfit.fitbase.fitrecipe import FitRecipe from diffpy.srfit.fitbase.parameter import Parameter from diffpy.srfit.fitbase.profile import Profile -from diffpy.srfit.pdf import PDFParser +from diffpy.srfit.fitbase.profileparser import ProfileParser matplotlib.use("Agg") @@ -595,10 +595,10 @@ def get_labels_and_linecount(ax): def build_recipe_from_datafile(datafile): - """Helper to build a FitRecipe from a datafile using PDFParser and - PDFGenerator.""" + """Helper to build a FitRecipe from a datafile using + ProfileParser.""" profile = Profile() - parser = PDFParser() + parser = ProfileParser() parser.parse_file(str(datafile)) profile.load_parsed_data(parser) @@ -1137,9 +1137,9 @@ def test_residual_is_weighted_by_uncertainty( # ---------------------------------------------------------------------------- # addContribution, addParameterSet/removeParameterSet, and -# PDFParser.parseFile/Profile.loadParsedData are deprecated in favor of +# ProfileParser.parseFile/Profile.loadParsedData are deprecated in favor of # add_contribution, add_parameter_set/remove_parameter_set, and -# PDFParser.parse_file/Profile.load_parsed_data. The old names must still +# ProfileParser.parse_file/Profile.load_parsed_data. The old names must still # work and forward to the new implementation. @@ -1208,12 +1208,12 @@ def test_add_and_remove_parameter_set_deprecated(): def build_recipe_from_datafile_deprecated(datafile): """Duplicate of build_recipe_from_datafile to use the deprecated - PDFParser.parseFile and Profile.loadParsedData methods. + ProfileParser.parseFile and Profile.loadParsedData methods. Remove in version 4.0.0. """ profile = Profile() - parser = PDFParser() + parser = ProfileParser() parser.parseFile(str(datafile)) profile.loadParsedData(parser)