8000 make deprecration warnings consistent (as FutureWarning) · python-control/python-control@8fcf0b7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8fcf0b7

Browse files
committed
make deprecration warnings consistent (as FutureWarning)
1 parent 7f48535 commit 8fcf0b7

26 files changed

+124
-65
lines changed

control/bdalg.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,8 @@ def connect(sys, Q, inputv, outputv):
412412
"""Index-based interconnection of an LTI system.
413413
414414
.. deprecated:: 0.10.0
415-
`connect` will be removed in a future version of python-control in
416-
favor of `interconnect`, which works with named signals.
415+
`connect` will be removed in a future version of python-control.
416+
Use :func:`interconnect` instead, which works with named signals.
417417
418418
The system `sys` is a system typically constructed with `append`, with
419419
multiple inputs and outputs. The inputs and outputs are connected
@@ -465,7 +465,7 @@ def connect(sys, Q, inputv, outputv):
465465
466466
"""
467467
# TODO: maintain `connect` for use in MATLAB submodule (?)
468-
warn("`connect` is deprecated; use `interconnect`", DeprecationWarning)
468+
warn("connect() is deprecated; use interconnect()", FutureWarning)
469469

470470
inputv, outputv, Q = \
471471
np.atleast_1d(inputv), np.atleast_1d(outputv), np.atleast_1d(Q)

control/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ def _process_legacy_keyword(kwargs, oldkey, newkey, newval):
362362
if kwargs.get(oldkey) is not None:
363363
warnings.warn(
364364
f"keyword '{oldkey}' is deprecated; use '{newkey}'",
365-
DeprecationWarning)
365+
FutureWarning)
366366
if newval is not None:
367367
raise ControlArgument(
368368
f"duplicate keywords '{oldkey}' and '{newkey}'")

control/ctrlplot.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def suptitle(
212212
213213
"""
214214
warnings.warn(
215-
"suptitle is deprecated; use cplt.set_plot_title", FutureWarning)
215+
"suptitle() is deprecated; use cplt.set_plot_title()", FutureWarning)
216216
_update_plot_title(
217217
title, fig=fig, frame=frame, use_existing=False, **kwargs)
218218

@@ -247,7 +247,8 @@ def get_plot_axes(line_array):
247247
Only the first element of each array entry is used to determine the axes.
248248
249249
"""
250-
warnings.warn("get_plot_axes is deprecated; use cplt.axes", FutureWarning)
250+
warnings.warn(
251+
"get_plot_axes() is deprecated; use cplt.axes()", FutureWarning)
251252
_get_axes = np.vectorize(lambda lines: lines[0].axes)
252253
if isinstance(line_array, ControlPlot):
253254
return _get_axes(line_array.lines)

control/frdata.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,12 +597,13 @@ def freqresp(self, omega):
597597
Method has been given the more pythonic name
598598
:meth:`FrequencyResponseData.frequency_response`. Or use
599599
:func:`freqresp` in the MATLAB compatibility module.
600+
600601
"""
601602
warn("FrequencyResponseData.freqresp(omega) will be removed in a "
602603
"future release of python-control; use "
603604
"FrequencyResponseData.frequency_response(omega), or "
604605
"freqresp(sys, omega) in the MATLAB compatibility module "
605-
"instead", DeprecationWarning)
606+
"instead", FutureWarning)
606607
return self.frequency_response(omega)
607608

608609
def feedback(self, other=1, sign=-1):

control/freqplot.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,8 @@ def bode_plot(
432432

433433
if plot is not None:
434434
warnings.warn(
435-
"`bode_plot` return values of mag, phase, omega is deprecated; "
436-
"use frequency_response()", DeprecationWarning)
435+
"bode_plot() return value of mag, phase, omega is deprecated; "
436+
"use frequency_response()", FutureWarning)
437437

438438
if plot is False:
439439
# Process the data to match what we were sent
@@ -1796,8 +1796,8 @@ def _parse_linestyle(style_name, allow_false=False):
17961796
# Legacy return value processing
17971797
if plot is not None or return_contour is not None:
17981798
warnings.warn(
1799-
"`nyquist_plot` return values of count[, contour] is deprecated; "
1800-
"use nyquist_response()", DeprecationWarning)
1799+
"nyquist_plot() return value of count[, contour] is deprecated; "
1800+
"use nyquist_response()", FutureWarning)
18011801

18021802
# Extract out the values that we will eventually return
18031803
counts = [response.count for response in nyquist_responses]
@@ -2456,7 +2456,7 @@ def singular_values_plot(
24562456
if plot is not None:
24572457
warnings.warn(
24582458
"`singular_values_plot` return values of sigma, omega is "
2459-
"deprecated; use singular_values_response()", DeprecationWarning)
2459+
"deprecated; use singular_values_response()", FutureWarning)
24602460

24612461
# Warn the user if we got past something that is not real-valued
24622462
if any([not np.allclose(np.imag(response.fresp[:, 0, :]), 0)

control/lti.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ def freqresp(sys, omega):
521521
Use `frequency_response` instead.
522522
523523
"""
524-
warn("freqresp is deprecated; use frequency_response", DeprecationWarning)
524+
warn("freqresp() is deprecated; use frequency_response()", FutureWarning)
525525
return frequency_response(sys, omega)
526526

527527

control/optimal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,14 +1111,14 @@ def solve_ocp(
11111111
raise ValueError("'minimize_method' specified more than once")
11121112
warnings.warn(
11131113
"'method' parameter is deprecated; assuming minimize_method",
1114-
DeprecationWarning)
1114+
FutureWarning)
11151115
kwargs['minimize_method'] = method
11161116
else:
11171117
if kwargs.get('trajectory_method'):
11181118
raise ValueError("'trajectory_method' specified more than once")
11191119
warnings.warn(
11201120
"'method' parameter is deprecated; assuming trajectory_method",
1121-
DeprecationWarning)
1121+
FutureWarning)
11221122
kwargs['trajectory_method'] = method
11231123

11241124
# Set up the optimal control problem

control/phaseplot.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,9 @@ def phase_plot(odefun, X=None, Y=None, scale=1, X0=None, T=None,
10131013

10141014
"""(legacy) Phase plot for 2D dynamical systems.
10151015
1016+
.. deprecated:: 0.10.1
1017+
This function is deprecated; use `phase_plane_plot` instead.
1018+
10161019
Produces a vector field or stream line plot for a planar system. This
10171020
function has been replaced by the :func:`~control.phase_plane_map` and
10181021
:func:`~control.phase_plane_plot` functions.
@@ -1072,7 +1075,7 @@ def phase_plot(odefun, X=None, Y=None, scale=1, X0=None, T=None,
10721075
"""
10731076
# Generate a deprecation warning
10741077
warnings.warn(
1075-
"phase_plot is deprecated; use phase_plot_plot instead",
1078+
"phase_plot() is deprecated; use phase_plane_plot() instead",
10761079
FutureWarning)
10771080

10781081
#
@@ -1272,7 +1275,7 @@ def box_grid(xlimp, ylimp):
12721275
"""box_grid generate list of points on edge of box
12731276
12741277
.. deprecated:: 0.10.0
1275-
Use `phaseplot.boxgrid` instead.
1278+
Use :func:`phaseplot.boxgrid` instead.
12761279
12771280
list = box_grid([xmin xmax xnum], [ymin ymax ynum]) generates a
12781281
list of points that correspond to a uniform grid at the end of the
@@ -1282,7 +1285,7 @@ def box_grid(xlimp, ylimp):
12821285

12831286
# Generate a deprecation warning
12841287
warnings.warn(
1285-
"box_grid is deprecated; use phaseplot.boxgrid instead",
1288+
"box_grid() is deprecated; use phaseplot.boxgrid() instead",
12861289
FutureWarning)
12871290

12881291
return boxgrid(

control/pzmap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,8 @@ def pole_zero_plot(
316316
# Legacy return value processing
317317
if plot is not None:
318318
warnings.warn(
319-
"`pole_zero_plot` return values of poles, zeros is deprecated; "
320-
"use pole_zero_map()", DeprecationWarning)
319+
"pole_zero_plot() return value of poles, zeros is deprecated; "
320+
"use pole_zero_map()", FutureWarning)
321321

322322
# Extract out the values that we will eventually return
323323
poles = [response.poles for response in pzmap_responses]

control/rlocus.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@ def root_locus_plot(
208208
#
209209
if plot is not None:
210210
warnings.warn(
211-
"`root_locus` return values of roots, gains is deprecated; "
212-
"use root_locus_map()", DeprecationWarning)
211+
"root_locus() return value of roots, gains is deprecated; "
212+
"use root_locus_map()", FutureWarning)
213213

214214
if plot is False:
215215
return responses.loci, responses.gains

control/statesp.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -355,13 +355,13 @@ def __init__(self, *args, **kwargs):
355355
def _get_states(self):
356356
warn("The StateSpace `states` attribute will be deprecated in a "
357357
"future release. Use `nstates` instead.",
358-
DeprecationWarning, stacklevel=2)
358+
FutureWarning, stacklevel=2)
359359
return self.nstates
360360

361361
def _set_states(self, value):
362362
warn("The StateSpace `states` attribute will be deprecated in a "
363363
"future release. Use `nstates` instead.",
364-
DeprecationWarning, stacklevel=2)
364+
FutureWarning, stacklevel=2)
365365
self.nstates = value
366366

367367
#: Deprecated attribute; use :attr:`nstates` instead.
@@ -906,7 +906,7 @@ def freqresp(self, omega):
906906
warn("StateSpace.freqresp(omega) will be removed in a "
907907
"future release of python-control; use "
908908
"sys.frequency_response(omega), or freqresp(sys, omega) in the "
909-
"MATLAB compatibility module instead", DeprecationWarning)
909+
"MATLAB compatibility module instead", FutureWarning)
910910
return self.frequency_response(omega)
911911

912912
# Compute poles and zeros
@@ -1618,8 +1618,8 @@ def ss(*args, **kwargs):
16181618
if len(args) > 0 and (hasattr(args[0], '__call__') or args[0] is None) \
16191619
and not isinstance(args[0], (InputOutputSystem, LTI)):
16201620
# Function as first (or second) argument => assume nonlinear IO system
1621-
warn("using ss to create nonlinear I/O systems is deprecated; "
1622-
"use nlsys()", DeprecationWarning)
1621+
warn("using ss() to create nonlinear I/O systems is deprecated; "
1622+
"use nlsys()", FutureWarning)
16231623
return NonlinearIOSystem(*args, **kwargs)
16241624

16251625
elif len(args) == 4 or len(args) == 5:
@@ -1667,7 +1667,7 @@ def ss2io(*args, **kwargs):
16671667
Create an :class:`~control.StateSpace` system with the given signal
16681668
and system names. See :func:`~control.ss` for more details.
16691669
"""
1670-
warn("ss2io is deprecated; use ss()", DeprecationWarning)
1670+
warn("ss2io() is deprecated; use ss()", FutureWarning)
16711671
return StateSpace(*args, **kwargs)
16721672

16731673

@@ -1743,7 +1743,7 @@ def tf2io(*args, **kwargs):
17431743
(2, 2, 8)
17441744
17451745
"""
1746-
warn("tf2io is deprecated; use tf2ss() or tf()", DeprecationWarning)
1746+
warn("tf2io() is deprecated; use tf2ss() or tf()", FutureWarning)
17471747
return tf2ss(*args, **kwargs)
17481748

17491749

control/tests/bdalg_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def test_feedback_args(self, tsys):
269269
def testConnect(self, tsys):
270270
sys = append(tsys.sys2, tsys.sys3) # two siso systems
271271

272-
with pytest.warns(DeprecationWarning, match="use `interconnect`"):
272+
with pytest.warns(FutureWarning, match="use interconnect()"):
273273
# should not raise error
274274
connect(sys, [[1, 2], [2, -2]], [2], [1, 2])
275275
connect(sys, [[1, 2], [2, 0]], [2], [1, 2])

control/tests/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ def legacy_plot_signature():
6565
import warnings
6666
warnings.filterwarnings(
6767
'ignore', message='passing systems .* is deprecated',
68-
category=DeprecationWarning)
68+
category=FutureWarning)
6969
warnings.filterwarnings(
70-
'ignore', message='.* return values of .* is deprecated',
71-
category=DeprecationWarning)
70+
'ignore', message='.* return value of .* is deprecated',
71+
category=FutureWarning)
7272
yield
7373
warnings.resetwarnings()
7474

control/tests/docstrings_test.py

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
(control, ""), (control.flatsys, "flatsys."),
6161
(control.optimal, "optimal."), (control.phaseplot, "phaseplot.")
6262
])
63-
def test_docstrings(module, prefix):
63+
def test_parameter_docs(module, prefix):
6464
checked = set() # Keep track of functions we have checked
6565

6666
# Look through every object in the package
@@ -78,7 +78,7 @@ def test_docstrings(module, prefix):
7878
if verbose > 1:
7979
print(f" Checking class {name}")
8080
# Check member functions within the class
81-
test_docstrings(obj, prefix + name + '.')
81+
test_parameter_docs(obj, prefix + name + '.')
8282

8383
if inspect.isfunction(obj):
8484
# Skip anything that is inherited, hidden, deprecated, or checked
@@ -105,7 +105,7 @@ def test_docstrings(module, prefix):
105105
if verbose > 1:
106106
print(" [deprecated]")
107107
continue
108-
elif f"{name} is deprecated" in docstring or \
108+
elif re.search(name + r"(\(\))? is deprecated", docstring) or \
109109
"function is deprecated" in docstring:
110110
if verbose > 1:
111111
print(" [deprecated, but not numpydoc compliant]")
@@ -114,7 +114,7 @@ def test_docstrings(module, prefix):
114114
warnings.warn(f"{name} deprecated, but not numpydoc compliant")
115115
continue
116 10000 116

117-
elif f"{name} is deprecated" in source:
117+
elif re.search(name + r"(\(\))? is deprecated", source):
118118
if verbose:
119119
print(f" {name} is deprecated, but not documented")
120120
warnings.warn(f"{name} deprecated, but not documented")
@@ -189,20 +189,71 @@ def test_docstrings(module, prefix):
189189
continue
190190
if verbose > 3:
191191
print(f" Checking keyword argument {kwargname}")
192-
assert _check_docstring(
192+
assert _check_parameter_docs(
193193
name, kwargname, inspect.getdoc(obj),
194194
prefix=prefix)
195195

196196
# Make sure this argument is documented properly in docstring
197197
else:
198198
if verbose > 3:
199199
print(f" Checking argument {argname}")
200-
assert _check_docstring(
200+
assert _check_parameter_docs(
201201
name, argname, docstring, prefix=prefix)
202202

203203

204+
@pytest.mark.parametrize("module, prefix", [
205+
(control, ""), (control.flatsys, "flatsys."),
206+
(control.optimal, "optimal."), (control.phaseplot, "phaseplot.")
207+
])
208+
def test_deprecated_functions(module, prefix):
209+
checked = set() # Keep track of functions we have checked
210+
211+
# Look through every object in the package
212+
for name, obj in inspect.getmembers(module):
213+
# Skip anything that is outside of this module
214+
if inspect.getmodule(obj) is not None and (
215+
not inspect.getmodule(obj).__name__.startswith('control')
216+
or prefix != "" and inspect.getmodule(obj) != module):
217+
# Skip anything that isn't part of the control package
218+
continue
219+
220+
if inspect.isclass(obj):
221+
# Check member functions within the class
222+
test_deprecated_functions(obj, prefix + name + '.')
223+
224+
if inspect.isfunction(obj):
225+
# Skip anything that is inherited, hidden, or checked
226+
if inspect.isclass(module) and name not in module.__dict__ \
227+
or name[0] == '_' or obj in checked:
228+
continue
229+
else:
230+
checked.add(obj)
231+
232+
# Get the docstring (skip w/ warning if there isn't one)
233+
if obj.__doc__ is None:
234+
warnings.warn(
235+
f"{module.__name__}.{name} is missing docstring")
236+
continue
237+
else:
238+
docstring = inspect.getdoc(obj)
239+
source = inspect.getsource(obj)
240+
241+
# Look for functions marked as deprecated in doc string
242+
if ".. deprecated::" in docstring:
243+
# Make sure a FutureWarning is issued
244+
if not re.search("FutureWarning", source):
245+
pytest.fail(
246+
f"{name} deprecated but does not issue FutureWarning")
247+
else:
248+
if re.search(name + r"(\(\))? is deprecated", docstring) or \
249+
re.search(name + r"(\(\))? is deprecated", source):
250+
pytest.fail(
251+
f"{name} deprecated but w/ non-standard docs/warnings")
252+
assert name != 'ss2io'
253+
254+
204255
# Utility function to check for an argument in a docstring
205-
def _check_docstring(funcname, argname, docstring, prefix=""):
256+
def _check_parameter_docs(funcname, argname, docstring, prefix=""):
206257
funcname = prefix + funcname
207258
if re.search(
208259
"\n" + r"((\w+|\.{3}), )*" + argname + r"(, (\w+|\.{3}))*:",

control/tests/frd_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ def test_eval(self):
454454
def test_freqresp_deprecated(self):
455455
sys_tf = ct.tf([1], [1, 2, 1])
456456
frd_tf = frd(sys_tf, np.logspace(-1, 1, 3))
457-
with pytest.warns(DeprecationWarning):
457+
with pytest.warns(FutureWarning):
458458
frd_tf.freqresp(1.)
459459

460460
def test_repr_str(self):

control/tests/freqresp_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def test_freqresp_siso(ss_siso):
6060
ctrl.frequency_response(ss_siso, omega)
6161

6262

63-
@pytest.mark.filterwarnings("ignore:freqresp is deprecated")
63+
@pytest.mark.filterwarnings(r"ignore:freqresp\(\) is deprecated")
6464
@slycotonly
6565
def test_freqresp_mimo_legacy(ss_mimo):
6666
"""Test MIMO frequency response calls"""
@@ -112,7 +112,7 @@ def test_nyquist_basic(ss_siso):
112112
# Check known warnings happened as expected
113113
assert len(record) == 2
114114
assert re.search("encirclements was a non-integer", str(record[0].message))
115-
assert re.search("return values .* deprecated", str(record[1].message))
115+
assert re.search("return value .* deprecated", str(record[1].message))
116116

117117
response = nyquist_response(tf_siso, omega=np.logspace(-1, 1, 10))
118118
assert len(response.contour) == 10

0 commit comments

Comments
 (0)
0