Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions news/util-standards.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
**Added:**

* Add ``add_observer``, ``remove_observer`` and ``has_observer`` to
``Observable``, and ``has_tags`` and ``verify_tags`` to ``TagManager``.
* Add ``is_identifier`` and ``validate_name`` to ``diffpy.srfit.util.nameutils``,
``convert_input_to_string`` to ``diffpy.srfit.util.inpututils``, and
``sort_key_for_numeric_string`` to ``diffpy.srfit.util``.

**Changed:**

* The error raised for an invalid name now says how to fix it.

**Deprecated:**

* ``Observable.addObserver``, ``removeObserver`` and ``hasObserver``,
``TagManager.hasTags`` and ``verifyTags``, ``isIdentifier``,
``validateName``, ``inputToString`` and ``sortKeyForNumericString`` are
deprecated in favour of their snake_case replacements. The old names still
work and warn, and will be removed in version 4.0.0.

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
4 changes: 2 additions & 2 deletions src/diffpy/srfit/equation/equationmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,11 @@ def setRoot(self, root):

# Stop observing the old root
if self.root is not None:
self.root.removeObserver(self._flush)
self.root.remove_observer(self._flush)

# Add the new root
self.root = root
self.root.addObserver(self._flush)
self.root.add_observer(self._flush)
self._flush(other=(self,))

# Get the args
Expand Down
2 changes: 1 addition & 1 deletion src/diffpy/srfit/equation/literals/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def addLiteral(self, literal):
# Make sure we don't have self-reference
self._loop_check(literal)
self.args.append(literal)
literal.addObserver(self._flush)
literal.add_observer(self._flush)
self._flush(other=(self,))
return

Expand Down
6 changes: 3 additions & 3 deletions src/diffpy/srfit/equation/visitors/swapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def onOperator(self, op):
# attempt to remove the same observer more than once, which
# might happen if the oldlit appears multiple times in op.args.
try:
oldlit.removeObserver(op._flush)
oldlit.remove_observer(op._flush)
except KeyError:
pass

Expand All @@ -108,12 +108,12 @@ def onOperator(self, op):
except ValueError:
# Restore the old literal
op.args.insert(idx, oldlit)
oldlit.addObserver(op._flush)
oldlit.add_observer(op._flush)
raise

# If we got here, then go on with replacing the literal
op.args.insert(idx, newlit)
newlit.addObserver(op._flush)
newlit.add_observer(op._flush)
op._flush(other=())

self._swap = False
Expand Down
4 changes: 2 additions & 2 deletions src/diffpy/srfit/fitbase/fithook.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

import numpy

from diffpy.srfit.util import sortKeyForNumericString
from diffpy.srfit.util import sort_key_for_numeric_string


class FitHook(object):
Expand Down Expand Up @@ -178,7 +178,7 @@ def postcall(self, recipe, chiv):


def _byname(nv):
return sortKeyForNumericString(nv[0])
return sort_key_for_numeric_string(nv[0])


# End class PrintFitHook
Expand Down
2 changes: 1 addition & 1 deletion src/diffpy/srfit/fitbase/fitrecipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,7 @@ def is_free(self, var):
bool
True if the variable is free (not fixed), False otherwise.
"""
return not self._tagmanager.hasTags(var, self._fixedtag)
return not self._tagmanager.has_tags(var, self._fixedtag)

@deprecated(isFree_dep_msg)
def isFree(self, var):
Expand Down
6 changes: 3 additions & 3 deletions src/diffpy/srfit/fitbase/fitresults.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
import numpy

from diffpy.srfit.util import _DASHEDLINE
from diffpy.srfit.util import sortKeyForNumericString as numstr
from diffpy.srfit.util.inpututils import inputToString
from diffpy.srfit.util import sort_key_for_numeric_string as numstr
from diffpy.srfit.util.inpututils import convert_input_to_string
from diffpy.utils._deprecator import build_deprecation_message, deprecated

fitresults_base = "diffpy.srfit.fitbase.FitResults"
Expand Down Expand Up @@ -855,7 +855,7 @@ def resultsDictionary(results):
def _parse_results_dictionary(results):
"""Remove this function when when resultsDictionary and
initializeRecipe are removed in 4.0.0."""
resstr = inputToString(results)
resstr = convert_input_to_string(results)
rx = {
"f": r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?",
"n": r"[a-zA-Z_]\w*",
Expand Down
6 changes: 3 additions & 3 deletions src/diffpy/srfit/fitbase/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from diffpy.srfit.fitbase.validatable import Validatable
from diffpy.srfit.interface import _parameter_interface
from diffpy.srfit.util.argbinders import bind2nd
from diffpy.srfit.util.nameutils import validateName
from diffpy.srfit.util.nameutils import validate_name
from diffpy.utils._deprecator import build_deprecation_message, deprecated

parameter_base = "diffpy.srfit.fitbase.Parameter"
Expand Down Expand Up @@ -102,7 +102,7 @@ def __init__(self, name, value=None, const=False):
"""
self.constrained = False
self.bounds = [-numpy.inf, +numpy.inf]
validateName(name)
validate_name(name)
Argument.__init__(self, name, value, const)
return

Expand Down Expand Up @@ -287,7 +287,7 @@ def __init__(self, name, par):
ValueError
If the name is not a valid attribute identifier.
"""
validateName(name)
validate_name(name)

self.name = name
self.par = par
Expand Down
6 changes: 3 additions & 3 deletions src/diffpy/srfit/fitbase/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ def __init__(self):
self.meta = {}

# Observable
self.xpar.addObserver(self._flush)
self.ypar.addObserver(self._flush)
self.dypar.addObserver(self._flush)
self.xpar.add_observer(self._flush)
self.ypar.add_observer(self._flush)
self.dypar.add_observer(self._flush)
return

# We want x, y, ycalc and dy to stay in-sync with xpar, ypar and dypar
Expand Down
4 changes: 2 additions & 2 deletions src/diffpy/srfit/fitbase/profilegenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@ def set_profile(self, profile):
will store the calculated signal.
"""
if self.profile is not None:
self.profile.removeObserver(self._on_profile_update)
self.profile.remove_observer(self._on_profile_update)

self.profile = profile
self.profile.addObserver(self._on_profile_update)
self.profile.add_observer(self._on_profile_update)
self._on_profile_update(other=(self,))
return

Expand Down
12 changes: 6 additions & 6 deletions src/diffpy/srfit/fitbase/recipeorganizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
from diffpy.srfit.fitbase.validatable import Validatable
from diffpy.srfit.interface import _recipeorganizer_interface
from diffpy.srfit.util import _DASHEDLINE
from diffpy.srfit.util import sortKeyForNumericString as numstr
from diffpy.srfit.util.nameutils import validateName
from diffpy.srfit.util import sort_key_for_numeric_string as numstr
from diffpy.srfit.util.nameutils import validate_name
from diffpy.srfit.util.observable import Observable
from diffpy.utils._deprecator import build_deprecation_message, deprecated

Expand Down Expand Up @@ -218,7 +218,7 @@ class RecipeContainer(Observable, Configurable, Validatable):
def __init__(self, name):
Observable.__init__(self)
Configurable.__init__(self)
validateName(name)
validate_name(name)
self.name = name
self._parameters = OrderedDict()

Expand Down Expand Up @@ -615,13 +615,13 @@ def _add_object(self, obj, d, check=True):

# Detach the old object, if there is one
if oldobj is not None:
oldobj.removeObserver(self._flush)
oldobj.remove_observer(self._flush)

# Add the object
d[obj.name] = obj

# Observe the object
obj.addObserver(self._flush)
obj.add_observer(self._flush)

# Store this as a configurable object
self._store_configurable(obj)
Expand All @@ -640,7 +640,7 @@ def _remove_object(self, obj, d):
raise ValueError(m)

del d[obj.name]
obj.removeObserver(self._flush)
obj.remove_observer(self._flush)

return

Expand Down
24 changes: 12 additions & 12 deletions src/diffpy/srfit/structure/objcrystparset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1220,9 +1220,9 @@ def addAtoms(self, atomlist):
self.matoms.update(atomlist)
# Make sure we're observing these atoms
for a in atomlist:
a.x.addObserver(self._flush)
a.y.addObserver(self._flush)
a.z.addObserver(self._flush)
a.x.add_observer(self._flush)
a.y.add_observer(self._flush)
a.z.add_observer(self._flush)

# Record the added atoms in the StretchMode
scatlist = [a.scat for a in atomlist]
Expand Down Expand Up @@ -1349,9 +1349,9 @@ def __init__(self, name, atom1, atom2, value=None, const=False, mode=None):

# Observe the atom positions
for a in [atom1, atom2]:
a.x.addObserver(self._flush)
a.y.addObserver(self._flush)
a.z.addObserver(self._flush)
a.x.add_observer(self._flush)
a.y.add_observer(self._flush)
a.z.add_observer(self._flush)

self.atom1 = atom1
self.atom2 = atom2
Expand Down Expand Up @@ -1510,9 +1510,9 @@ def __init__(

# Observe the atom positions
for a in [atom1, atom2, atom3]:
a.x.addObserver(self._flush)
a.y.addObserver(self._flush)
a.z.addObserver(self._flush)
a.x.add_observer(self._flush)
a.y.add_observer(self._flush)
a.z.add_observer(self._flush)

self.atom1 = atom1
self.atom2 = atom2
Expand Down Expand Up @@ -1688,9 +1688,9 @@ def __init__(

# Observe the atom positions
for a in [atom1, atom2, atom3, atom4]:
a.x.addObserver(self._flush)
a.y.addObserver(self._flush)
a.z.addObserver(self._flush)
a.x.add_observer(self._flush)
a.y.add_observer(self._flush)
a.z.add_observer(self._flush)

self.atom1 = atom1
self.atom2 = atom2
Expand Down
52 changes: 35 additions & 17 deletions src/diffpy/srfit/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,55 @@
##############################################################################
"""Utilities and constants used throughout SrFit."""

import re

from diffpy.utils._deprecator import build_deprecation_message, deprecated

_DASHEDLINE = 78 * "-"

sortKeyForNumericString_dep_msg = build_deprecation_message(
"diffpy.srfit.util",
"sortKeyForNumericString",
"sort_key_for_numeric_string",
"4.0.0",
)

def sortKeyForNumericString(s):
"""Compute key for sorting strings according to their integer
numeric value.

Each string gets split to string and integer segments to create keys
for comparison. Signs, decimal points and exponents are ignored.
This function is intended as the ``key`` argument for the ``sorted``
or ``list.sort`` function.
def sort_key_for_numeric_string(string):
"""Return a sort key that orders the numbers in a string by value.

The string is split into text and integer segments, so ``"a2"`` sorts
before ``"a10"``. Signs, decimal points and exponents are ignored. Use it
as the ``key`` argument of ``sorted`` or ``list.sort``.

Parameters
----------
s : str
String which may have numeric components, e.g., "a12b".
string : str
The string to build a key for, which may contain numbers, e.g.
``"a12b"``.

Returns
-------
tuple
Tuple of non-numeric segments intermixed with integer values.
The text segments of ``string`` with integer values in between,
e.g. ``("a", 12, "b")``.
"""
if sortKeyForNumericString._rx is None:
import re
segments = re.split(r"(\d+)", string)
sort_key = tuple(
int(segment) if segment.isdecimal() else segment
for segment in segments
)
return sort_key

sortKeyForNumericString._rx = re.compile(r"(\d+)")
rx = sortKeyForNumericString._rx
rv = tuple((int(w) if i % 2 else w) for i, w in enumerate(rx.split(s)))
return rv

@deprecated(sortKeyForNumericString_dep_msg)
def sortKeyForNumericString(s):
"""This function has been deprecated and will be removed in version
4.0.0.

Please use diffpy.srfit.util.sort_key_for_numeric_string instead.
"""
return sort_key_for_numeric_string(s)

sortKeyForNumericString._rx = None

# End of file
15 changes: 12 additions & 3 deletions src/diffpy/srfit/util/argbinders.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@


class bind2nd(object):
"""Freeze second argument of a callable object to a given
constant."""
"""Freeze the second argument of a callable to a constant.

Calling the instance as ``bound(a, *args, **kwargs)`` calls
``func(a, arg1, *args, **kwargs)``.

Parameters
----------
func : callable
The callable whose second argument is frozen.
arg1
The value passed as the second argument of ``func``.
"""

def __init__(self, func, arg1):
"""Freeze the second argument of function func to arg1."""
self.func = func
self.arg1 = arg1
return
Expand Down
Loading
Loading