Skip to content

Commit 488d435

Browse files
committed
Make Scale axis parameter handling more flexible
Instead of checking the types ourselves, try to bind the old signature, and if possible, use it. Otherwise, try to use the new signature. This is similar to `_api.select_matching_signature` without needing to write a callable for each signature.
1 parent f4cc437 commit 488d435

2 files changed

Lines changed: 59 additions & 6 deletions

File tree

lib/matplotlib/scale.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def _make_axis_parameter_optional(init_func):
138138
139139
This decorator ensures backward compatibility for scale classes that
140140
previously required an *axis* parameter. It allows constructors to be
141-
callerd with or without the *axis* parameter.
141+
called with or without the *axis* parameter.
142142
143143
For simplicity, this does not handle the case when *axis*
144144
is passed as a keyword. However,
@@ -170,12 +170,16 @@ def _make_axis_parameter_optional(init_func):
170170
"""
171171
@wraps(init_func)
172172
def wrapper(self, *args, **kwargs):
173-
if args and isinstance(args[0], mpl.axis.Axis):
174-
return init_func(self, *args, **kwargs)
173+
sig = inspect.signature(init_func)
174+
try:
175+
# Try old signature.
176+
sig.bind(self, *args, **kwargs)
177+
except TypeError:
178+
# Use the new signature and pass in an unused axis=None.
179+
init_func(self, None, *args, **kwargs)
175180
else:
176-
# Remove 'axis' from kwargs to avoid double assignment
177-
axis = kwargs.pop('axis', None)
178-
return init_func(self, axis, *args, **kwargs)
181+
# Use the old signature.
182+
init_func(self, *args, **kwargs)
179183
return wrapper
180184

181185

@@ -449,6 +453,11 @@ def __init__(self, axis, functions, base=10):
449453
----------
450454
axis : `~matplotlib.axis.Axis`
451455
The axis for the scale.
456+
457+
.. note::
458+
This parameter is unused and about to be removed in the future.
459+
It can already now be left out because of special preprocessing,
460+
so that ``FuncScaleLog(functions=(forward, inverse))`` is valid.
452461
functions : (callable, callable)
453462
two-tuple of the forward and inverse functions for the scale.
454463
The forward function must be monotonic.

lib/matplotlib/tests/test_scale.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import matplotlib.pyplot as plt
44
from matplotlib.scale import (
55
AsinhScale, AsinhTransform,
6+
FuncScale, LogitScale,
67
LogTransform, InvertedLogTransform,
78
SymmetricalLogTransform)
89
import matplotlib.scale as mscale
@@ -19,6 +20,49 @@
1920
import pytest
2021

2122

23+
def test_optional_axis_signature():
24+
# There are three types of original signatures possible, and this only tests one
25+
# example class of each:
26+
# 1. `axis` without default: LinearScale, FuncScale, FuncScaleLog
27+
# 2. `axis` with default and more positional parameters: LogitScale
28+
# 3. `axis` with default and only keyword-only parameters: LogScale, AsinhScale,
29+
# SymmetricalLogScale
30+
# Testing with None is sufficient as detection is purely based on the
31+
# signature structure; no type information is involved.
32+
axis = None
33+
34+
# Old signature with axis positionally.
35+
FuncScale(axis, (lambda x: x, lambda x: x))
36+
FuncScale(axis, functions=(lambda x: x, lambda x: x))
37+
LogitScale(axis)
38+
LogitScale(axis, 'clip')
39+
LogitScale(axis, nonpositive='clip')
40+
LogitScale(axis, use_overline=True)
41+
AsinhScale(axis)
42+
AsinhScale(axis, linear_width=2)
43+
AsinhScale(axis, base=3)
44+
AsinhScale(axis, subs=[2, 6])
45+
# Old signature with axis as keyword.
46+
FuncScale(axis=axis, functions=(lambda x: x, lambda x: x))
47+
LogitScale(axis=axis)
48+
LogitScale(axis=axis, nonpositive='clip')
49+
LogitScale(axis=axis, use_overline=True)
50+
AsinhScale(axis=axis)
51+
AsinhScale(axis=axis, linear_width=2)
52+
AsinhScale(axis=axis, base=3)
53+
AsinhScale(axis=axis, subs=[2, 6])
54+
# New signature without axis.
55+
FuncScale((lambda x: x, lambda x: x))
56+
FuncScale(functions=(lambda x: x, lambda x: x))
57+
LogitScale()
58+
LogitScale(nonpositive='clip')
59+
LogitScale(use_overline=True)
60+
AsinhScale()
61+
AsinhScale(linear_width=2)
62+
AsinhScale(base=3)
63+
AsinhScale(subs=[2, 6])
64+
65+
2266
@check_figures_equal()
2367
def test_log_scales(fig_test, fig_ref):
2468
ax_test = fig_test.add_subplot(122, yscale='log', xscale='symlog')

0 commit comments

Comments
 (0)