8000 MNT: Registered 3rd party scales do not need an axis parameter anymore by timhoffm · Pull Request #29358 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

MNT: Registered 3rd party scales do not need an axis parameter anymore #29358

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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
10 changes: 10 additions & 0 deletions doc/api/next_api_changes/deprecations/29358-TH.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
3rd party scales do not need to have an *axis* parameter anymore
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Since matplotlib 3.1 `PR 12831 <https://github.com/matplotlib/matplotlib/pull/12831>`_
scales should be reusable and therefore independent of the Axis. Therefore the use of
of the *axis* parameter in the ``__init__`` had been discouraged. However, that
parameter was still necessary for API compatibility. This is no longer the case.

`.register_scale` now accepts scale classes with and without this parameter.
3rd party scales can and should remove that parameter.
17 changes: 16 additions & 1 deletion lib/matplotlib/scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,9 @@ def limit_range_for_scale(self, vmin, vmax, minpos):
'functionlog': FuncScaleLog,
}

# caching of signature info
_scale_has_axis_parameter = {}


def get_scale_names():
"""Return the names of the available scales."""
Expand All @@ -706,7 +709,19 @@ def scale_factory(scale, axis, **kwargs):
axis : `~matplotlib.axis.Axis`
"""
scale_cls = _api.check_getitem(_scale_mapping, scale=scale)
return scale_cls(axis, **kwargs)

# We support scales that may or may not have an initial *axis* parameter.
# This information is cached, so that we do not need to inspect the signature
# on every time we create a scale.
if scale not in _scale_has_axis_parameter:
_scale_has_axis_parameter[scale] = (
"axis" in inspect.signature(scale_cls).parameters
)

if _scale_has_axis_parameter[scale]:
return scale_cls(axis, **kwargs)
else:
return scale_cls(**kwargs)


if scale_factory.__doc__:
Expand Down
38 changes: 37 additions & 1 deletion lib/matplotlib/tests/test_scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
LogTransform, InvertedLogTransform,
SymmetricalLogTransform)
import matplotlib.scale as mscale
from matplotlib.ticker import AsinhLocator, LogFormatterSciNotation
from matplotlib.ticker import (
AsinhLocator, AutoLocator, LogFormatterSciNotation,
NullFormatter, NullLocator, ScalarFormatter
)
from matplotlib.testing.decorators import check_figures_equal, image_comparison
from matplotlib.transforms import IdentityTransform

import numpy as np
from numpy.testing import assert_allclose
Expand Down Expand Up @@ -293,3 +297,35 @@ def test_bad_scale(self):
AsinhScale(axis=None, linear_width=-1)
s0 = AsinhScale(axis=None, )
s1 = AsinhScale(axis=None, linear_width=3.0)


def test_custom_scale_without_axis():
"""
Test that one can register and use custom scales that don't take an *axis* param.
"""
class CustomTransform(IdentityTransform):
pass

class CustomScale(mscale.ScaleBase):
name = "custom"

def __init__(self):
self._transform = CustomTransform()

def get_transform(self):
return self._transform

def set_default_locators_and_formatters(self, axis):
axis.set_major_locator(AutoLocator())
axis.set_major_formatter(ScalarFormatter())
axis.set_minor_locator(NullLocator())
axis.set_minor_formatter(NullFormatter())

try:
mscale.register_scale(CustomScale)
fig, ax = plt.subplots()
ax.set_xscale('custom')
assert isinstance(ax.xaxis.get_transform(), CustomTransform)
finally:
# cleanup - there's no public unregister_scale()
del mscale._scale_mapping["custom"]
Loading
0