Source code for apstools.utils.override_parameters
"""
OverrideParameters
+++++++++++++++++++++++++++++++++++++++
Define parameters that can be overridden from a user configuration file.
EXAMPLE:
Create an ``overrides`` object in a new file ``override_params.py``::
import apstools.utils
overrides = apstools.utils.OverrideParameters()
When code supports a parameter for which a user can provide
a local override, the code should import the ``overrides``
object (from the ``override_params`` module),
and then register the parameter name, such as this example::
from override_params import overrides
overrides.register("minimum_step")
Then later::
minstep = overrides.pick("minimum_step", 45e-6)
In the user's configuration file that will override
the value of ``45e-6`` (such as can be loaded via
``%run -i user.py``), import the `overrides``
object (from the ``override_params`` module)::
from override_params import overrides
and then override the attribute(s) as desired::
overrides.set("minimum_step", 1.0e-5)
With this override in place, the ``minstep`` value
(from :meth:`~apstools.utils.OverrideParameters.pick()`)
will be ``1e-5``.
Get a pandas DataFrame object with all the overrides::
overrides.summary()
which returns this table::
parameter value
0 minimum_step 0.00001
----
.. autosummary::
~OverrideParameters
"""
import pandas as pd
[docs]class OverrideParameters:
"""
Define parameters that can be overridden from a user configuration file.
NOTE: This is a pure Python object, not using ophyd.
.. autosummary::
~pick
~register
~reset
~reset_all
~set
~summary
(new in apstools 1.5.2)
"""
def __init__(self):
# ALWAYS use ``overrides.undefined`` for comparisons and resets.
self.undefined = object()
self._parameters = {}
[docs] def register(self, parameter_name):
"""
Register a new parameter name to be supported by user overrides.
"""
if parameter_name not in self._parameters:
self._parameters[parameter_name] = self.undefined
def _check_known(self, parameter_name):
if parameter_name not in self._parameters:
raise KeyError(
f"Unknown parameter {parameter_name}. First call register()."
)
[docs] def set(self, parameter_name, value):
"""
Define an override value for a known parameter.
"""
self._check_known(parameter_name)
self._parameters[parameter_name] = value
[docs] def reset(self, parameter_name):
"""
Remove an override value for a known parameter. (sets it to undefined)
"""
self._check_known(parameter_name)
self._parameters[parameter_name] = self.undefined
[docs] def reset_all(self):
"""
Remove override values for all known parameters. (sets all to undefined)
"""
for parm in self._parameters.keys():
self.reset(parm)
[docs] def pick(self, parameter, default):
"""
Return either the override parameter value if defined, or the default.
"""
value = self._parameters.get(parameter, default)
if value == self.undefined:
value = default
return value
[docs] def summary(self):
"""
Return a pandas DataFrame with all overrides.
Parameter names that have no override value will be reported
as ``--undefined--``.
"""
parameters = []
values = []
for parm in sorted(self._parameters.keys()):
parameters.append(parm)
values.append(self.pick(parm, "--undefined--"))
return pd.DataFrame(dict(parameter=parameters, value=values))
# -----------------------------------------------------------------------------
# :author: Pete R. Jemian
# :email: jemian@anl.gov
# :copyright: (c) 2017-2023, UChicago Argonne, LLC
#
# Distributed under the terms of the Argonne National Laboratory Open Source License.
#
# The full license is in the file LICENSE.txt, distributed with this software.
# -----------------------------------------------------------------------------