Skip to content

Deprecate BoxStyle._Base. #17737

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 2 commits into from
Oct 11, 2020
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
6 changes: 6 additions & 0 deletions doc/api/next_api_changes/deprecations/17737-AL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BoxStyles are now called without passing the *mutation_aspect* parameter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mutation aspect is now handled by the artist itself. Hence the
*mutation_aspect* parameter of ``BoxStyle._Base.__call__`` is deprecated, and
custom boxstyles should be implemented to not require this parameter (it can be
left as a parameter defaulting to 1 for back-compatibility).
28 changes: 7 additions & 21 deletions examples/userdemo/custom_boxstyle01.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# ``bbox=dict(boxstyle=custom_box_style, ...)`` to `.Axes.text`.


def custom_box_style(x0, y0, width, height, mutation_size, mutation_aspect=1):
def custom_box_style(x0, y0, width, height, mutation_size):
"""
Given the location and size of the box, return the path of the box around
it.
Expand All @@ -38,11 +38,7 @@ def custom_box_style(x0, y0, width, height, mutation_size, mutation_aspect=1):
Box location and size.
mutation_size : float
Mutation reference scale, typically the text font size.
mutation_aspect
Mutation aspect ratio.
"""
# We ignore mutation_aspect. This is okay in general.

# padding
mypad = 0.3
pad = mutation_size * mypad
Expand All @@ -66,19 +62,17 @@ def custom_box_style(x0, y0, width, height, mutation_size, mutation_aspect=1):


###############################################################################
# Alternatively, custom box styles can be implemented as subclasses of
# ``matplotlib.patches.BoxStyle._Base``, by overriding the ``transmute``
# method, as demonstrated below.
# Likewise, custom box styles can be implemented as classes that implement
# ``__call__``.
#
# The subclass can then be registered into the ``BoxStyle._style_list`` dict,
# The classes can then be registered into the ``BoxStyle._style_list`` dict,
# which allows specifying the box style as a string,
# ``bbox=dict(boxstyle="registered_name,param=value,...", ...)``.
#
# Note that this approach relies on internal APIs and is therefore not
# Note that this registration relies on internal APIs and is therefore not
# officially supported.


class MyStyle(BoxStyle._Base):
class MyStyle:
"""A simple box."""

def __init__(self, pad=0.3):
Expand All @@ -93,7 +87,7 @@ def __init__(self, pad=0.3):
self.pad = pad
super().__init__()

def transmute(self, x0, y0, width, height, mutation_size):
def __call__(self, x0, y0, width, height, mutation_size):
"""
Given the location and size of the box, return the path of the box
around it.
Expand All @@ -106,14 +100,6 @@ def transmute(self, x0, y0, width, height, mutation_size):
Box location and size.
mutation_size : float
Reference scale for the mutation, typically the text font size.
Notes
-----
Unlike when defining the box style as a function (as in
`custom_box_style`), here there is no *mutation_aspect* parameter.
Matplotlib will first squeeze the box's y-axis by *mutation_aspect*
before calling the `transmute` method, and then later reexpand the
y-axis by the same amount.
"""
# padding
pad = mutation_size * self.pad
Expand Down
15 changes: 10 additions & 5 deletions lib/matplotlib/cbook/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,8 @@ def _deprecate_method_override(method, obj, *, allow_empty=False, **kwargs):
can always use ``__class__`` to refer to the class that is currently
being defined.
obj
An object of the class where *method* is defined.
Either an object of the class where *method* is defined, or a subclass
of that class.
allow_empty : bool, default: False
Whether to allow overrides by "empty" methods without emitting a
warning.
Expand All @@ -478,15 +479,19 @@ def empty(): pass
def empty_with_docstring(): """doc"""

name = method.__name__
bound_method = getattr(obj, name)
if (bound_method != method.__get__(obj)
bound_child = getattr(obj, name)
bound_base = (
method # If obj is a class, then we need to use unbound methods.
if isinstance(bound_child, type(empty)) and isinstance(obj, type)
else method.__get__(obj))
if (bound_child != bound_base
and (not allow_empty
or (getattr(getattr(bound_method, "__code__", None),
or (getattr(getattr(bound_child, "__code__", None),
"co_code", None)
not in [empty.__code__.co_code,
empty_with_docstring.__code__.co_code]))):
warn_deprecated(**{"name": name, "obj_type": "method", **kwargs})
return bound_method
return bound_child
return None


Expand Down
Loading