Skip to content

[Bug]: unavoidable DeprecationWarning when using Patch3D #21740

Closed
@jakelishman

Description

@jakelishman

Bug summary

There's currently no nice way to avoid having a deprecation warning issued when using a custom subclass of Patch3D during drawing, caused by this helper function:

def do_3d_projection(artist):
"""
Call `do_3d_projection` on an *artist*, and warn if passing
*renderer*.
For our Artists, never pass *renderer*. For external Artists,
in lieu of more complicated signature parsing, always pass
*renderer* and raise a warning.
"""
if artist.__module__ == 'mpl_toolkits.mplot3d.art3d':
# Our 3D Artists have deprecated the renderer parameter, so
# avoid passing it to them; call this directly once the
# deprecation has expired.
return artist.do_3d_projection()
_api.warn_deprecated(
"3.4",
message="The 'renderer' parameter of "
"do_3d_projection() was deprecated in Matplotlib "
"%(since)s and will be removed %(removal)s.")
return artist.do_3d_projection(renderer)

added in #18302.

The deprecation is only triggered when axes are drawn, so within library code we can't locally suppress the warning, and have to modify global filters (or lie about our patches' __module__) to suppress the warning, even if we comply with the new calling convention (see for example Qiskit/qiskit#7301).

Code for reproduction

from matplotlib import pyplot
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Patch3D


class DummyPatch(Patch3D):
    def do_3d_projection(self, renderer=None):
        # This supports both 3.4 and 3.5 calling conventions.
        return 0

    def draw(self, renderer):
        pass

figure = pyplot.figure()
axes = Axes3D(figure, auto_add_to_figure=False)
figure.add_axes(axes)
axes.add_artist(DummyPatch())
axes.add_artist(DummyPatch())

pyplot.show()

Actual outcome

Running causes this warning to be emitted:

/Users/jake/tmp.py:20: MatplotlibDeprecationWarning: The 'renderer' parameter of do_3d_projection() was deprecated in Matplotlib 3.4 and will be removed two minor releases later.
  pyplot.show()

Expected outcome

It would be good to have a way to indicate that we support the new calling convention, so we can avoid triggering the warning - since it only happens when the figure is drawn, we can't reliably suppress the warning in library code without overriding the user's warning filters, which we very much don't want to do.

At the moment we're lying about our __module__ to avoid leaking this to users, but that's not ideal for us. Perhaps matplotlib could check for some other "magic" attribute on the class (like _matplotlib_new_do_3d_projection), or provide a "registration" function in mplot3d which we can call to add our class to, so the z-order sorting knows it can call us with the new convention?

Additional information

This appeared on our CI, so runs the gamut of OSs, Python versions, etc.

Operating system

No response

Matplotlib Version

3.5.0

Matplotlib Backend

No response

Python version

No response

Jupyter version

No response

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions