Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Uniform processing of time response and optimization parameters #1125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 12, 2025
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
151 changes: 149 additions & 2 deletions control/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# config.py - package defaults
# RMM, 4 Nov 2012
#
# TODO: add ability to read/write configuration files (ala matplotlib)
# TODO: add ability to read/write configuration files (a la matplotlib)

"""Functions to access default parameter values.

Expand Down Expand Up @@ -384,10 +384,13 @@ def use_legacy_defaults(version):
def _process_legacy_keyword(kwargs, oldkey, newkey, newval, warn_oldkey=True):
"""Utility function for processing legacy keywords.

.. deprecated:: 0.10.2
Replace with `_process_param` or `_process_kwargs`.

Use this function to handle a legacy keyword that has been renamed.
This function pops the old keyword off of the kwargs dictionary and
issues a warning. If both the old and new keyword are present, a
ControlArgument exception is raised.
`ControlArgument` exception is raised.

Parameters
----------
Expand All @@ -412,6 +415,10 @@ def _process_legacy_keyword(kwargs, oldkey, newkey, newval, warn_oldkey=True):
Value of the (new) keyword.

"""
# TODO: turn on this warning when ready to deprecate
# warnings.warn(
# "replace `_process_legacy_keyword` with `_process_param` "
# "or `_process_kwargs`", PendingDeprecationWarning)
if oldkey in kwargs:
if warn_oldkey:
warnings.warn(
Expand All @@ -424,3 +431,143 @@ def _process_legacy_keyword(kwargs, oldkey, newkey, newval, warn_oldkey=True):
return kwargs.pop(oldkey)
else:
return newval


def _process_param(name, defval, kwargs, alias_mapping, sigval=None):
"""Process named parameter, checking aliases and legacy usage.

Helper function to process function arguments by mapping aliases to
either their default keywords or to a named argument. The alias
mapping is a dictionary that returns a tuple consisting of valid
aliases and legacy aliases::

alias_mapping = {
'argument_name_1': (['alias', ...], ['legacy', ...]),
...}

If `param` is a named keyword in the function signature with default
value `defval`, a typical calling sequence at the start of a function
is::

param = _process_param('param', defval, kwargs, function_aliases)

If `param` is a variable keyword argument (in `kwargs`), `defval` can
be passed as either None or the default value to use if `param` is not
present in `kwargs`.

Parameters
----------
name : str
Name of the parameter to be checked.
defval : object or dict
Default value for the parameter.
kwargs : dict
Dictionary of variable keyword arguments.
alias_mapping : dict
Dictionary providing aliases and legacy names.
sigval : object, optional
Default value specified in the function signature (default = None).
If specified, an error will be generated if `defval` is different
than `sigval` and an alias or legacy keyword is given.

Returns
-------
newval : object
New value of the named parameter.

Raises
------
TypeError
If multiple keyword aliases are used for the same parameter.

Warns
-----
PendingDeprecationWarning
If legacy name is used to set the value for the variable.

"""
# Check to see if the parameter is in the keyword list
if name in kwargs:
if defval != sigval:
raise TypeError(f"multiple values for parameter {name}")
newval = kwargs.pop(name)
else:
newval = defval

# Get the list of aliases and legacy names
aliases, legacy = alias_mapping[name]

for kw in legacy:
if kw in kwargs:
warnings.warn(
f"alias `{kw}` is legacy name; use `{name}` instead",
PendingDeprecationWarning)
kwval = kwargs.pop(kw)
if newval != defval and kwval != newval:
raise TypeError(
f"multiple values for parameter `{name}` (via {kw})")
newval = kwval

for kw in aliases:
if kw in kwargs:
kwval = kwargs.pop(kw)
if newval != defval and kwval != newval:
raise TypeError(
f"multiple values for parameter `{name}` (via {kw})")
newval = kwval

return newval


def _process_kwargs(kwargs, alias_mapping):
"""Process aliases and legacy keywords.

Helper function to process function arguments by mapping aliases to
their default keywords. The alias mapping is a dictionary that returns
a tuple consisting of valid aliases and legacy aliases::

alias_mapping = {
'argument_name_1': (['alias', ...], ['legacy', ...]),
...}

If an alias is present in the dictionary of keywords, it will be used
to set the value of the argument. If a legacy keyword is used, a
warning is issued.

Parameters
----------
kwargs : dict
Dictionary of variable keyword arguments.
alias_mapping : dict
Dictionary providing aliases and legacy names.

Raises
------
TypeError
If multiple keyword aliased are used for the same parameter.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If multiple keyword aliased are used for the same parameter.
If multiple keyword aliases are used for the same parameter.


Warns
-----
PendingDeprecationWarning
If legacy name is used to set the value for the variable.

"""
for name in alias_mapping or []:
aliases, legacy = alias_mapping[name]

for kw in legacy:
if kw in kwargs:
warnings.warn(
f"alias `{kw}` is legacy name; use `{name}` instead",
PendingDeprecationWarning)
if name in kwargs:
raise TypeError(
f"multiple values for parameter `{name}` (via {kw})")
kwargs[name] = kwargs.pop(kw)

for kw in aliases:
if kw in kwargs:
if name in kwargs:
raise TypeError(
f"multiple values for parameter `{name}` (via {kw})")
kwargs[name] = kwargs.pop(kw)
Loading
Loading