Skip to content

Move cbook.deprecation to _api.deprecation #18657

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 6 commits into from
Oct 26, 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
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ per-file-ignores =
lib/matplotlib/backends/backend_*.py: F401
lib/matplotlib/backends/qt_editor/formlayout.py: F401, F403
lib/matplotlib/cbook/__init__.py: F401
lib/matplotlib/cbook/deprecation.py: F401
lib/matplotlib/font_manager.py: E221, E251, E501
lib/matplotlib/image.py: F401, F403
lib/matplotlib/lines.py: F401
Expand Down
13 changes: 13 additions & 0 deletions doc/api/_api_api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
*******************
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused why we are making a documentation page for something we are making private?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This targets contributors. It may be easier to read this in HTML than in plaintext.

Pandas does something similar. See the warning note at https://pandas.pydata.org/docs/reference/index.html?highlight=private.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need similar warnings at the beginning of _api.deprecation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes makes sense. I'll also extend the warning to explicitly mention that these Functions are only for developers/contributors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We read the docs too!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sigh, had a stale browser and only saw the first comment when I posted, sorry for the noise.

``matplotlib._api``
*******************

.. automodule:: matplotlib._api
:members:
:undoc-members:
:show-inheritance:

.. automodule:: matplotlib._api.deprecation
:members:
:undoc-members:
:show-inheritance:
5 changes: 0 additions & 5 deletions doc/api/cbook_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,3 @@
:members:
:undoc-members:
:show-inheritance:

.. automodule:: matplotlib.cbook.deprecation
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ Matplotlib consists of the following submodules:
type1font.rst
units_api.rst
widgets_api.rst
_api_api.rst

Toolkits
--------
Expand Down
3 changes: 3 additions & 0 deletions doc/api/next_api_changes/deprecations/18657-TH.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
``matplotlib.cbook.deprecation`` is deprecated
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The module is considered internal and will be removed from the public API.
2 changes: 1 addition & 1 deletion doc/api/prev_api_changes/api_changes_3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ The following classes, methods, functions, and attributes are deprecated:
- ``textpath.TextToPath.tex_font_map``
- ``matplotlib.cbook.deprecation.mplDeprecation`` will be removed
in future versions. It is just an alias for
:class:`matplotlib.cbook.deprecation.MatplotlibDeprecationWarning`. Please
``matplotlib.cbook.deprecation.MatplotlibDeprecationWarning``. Please
use ``matplotlib.cbook.MatplotlibDeprecationWarning`` directly if necessary.
- The ``matplotlib.cbook.Bunch`` class has been deprecated. Instead, use
`types.SimpleNamespace` from the standard library which provides the same
Expand Down
16 changes: 8 additions & 8 deletions doc/api/prev_api_changes/api_changes_3.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -767,12 +767,12 @@ The following signature related behaviours are deprecated:
keyword.
- The *interp_at_native* parameter to `.BboxImage`, which has had no effect
since Matplotlib 2.0, is deprecated.
- All arguments to the `~.cbook.deprecation.deprecated` decorator and
`~.cbook.deprecation.warn_deprecated` function, except the first one (the
version where the deprecation occurred), are now keyword-only. The goal is
to avoid accidentally setting the "message" argument when the "name" (or
"alternative") argument was intended, as this has repeatedly occurred in the
past.
- All arguments to the ``matplotlib.cbook.deprecation.deprecated`` decorator
and ``matplotlib.cbook.deprecation.warn_deprecated`` function, except the
first one (the version where the deprecation occurred), are now keyword-only.
The goal is to avoid accidentally setting the "message" argument when the
"name" (or "alternative") argument was intended, as this has repeatedly
occurred in the past.
- The arguments of `matplotlib.testing.compare.calculate_rms` have been renamed
from ``expectedImage, actualImage``, to ``expected_image, actual_image``.
- Passing positional arguments to `.Axis.set_ticklabels` beyond *ticklabels*
Expand Down Expand Up @@ -1076,8 +1076,8 @@ Undeprecations
--------------
The following API elements have been un-deprecated:

- The *obj_type* keyword argument to the `~.cbook.deprecation.deprecated`
decorator.
- The *obj_type* keyword argument to the
``matplotlib.cbook.deprecation.deprecated`` decorator.
- *xmin*, *xmax* keyword arguments to `.Axes.set_xlim` and *ymin*, *ymax*
keyword arguments to `.Axes.set_ylim`

Expand Down
16 changes: 8 additions & 8 deletions doc/devel/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ There are five levels at which you can emit messages.

- `logging.critical` and `logging.error` are really only there for errors that
will end the use of the library but not kill the interpreter.
- `logging.warning` and `.cbook._warn_external` are used to warn the user,
- `logging.warning` and `._api.warn_external` are used to warn the user,
see below.
- `logging.info` is for information that the user may want to know if the
program behaves oddly. They are not displayed by default. For instance, if
Expand All @@ -527,16 +527,16 @@ By default, `logging` displays all log messages at levels higher than
``logging.WARNING`` to `sys.stderr`.

The `logging tutorial`_ suggests that the difference between `logging.warning`
and `.cbook._warn_external` (which uses `warnings.warn`) is that
`.cbook._warn_external` should be used for things the user must change to stop
and `._api.warn_external` (which uses `warnings.warn`) is that
`._api.warn_external` should be used for things the user must change to stop
the warning (typically in the source), whereas `logging.warning` can be more
persistent. Moreover, note that `.cbook._warn_external` will by default only
persistent. Moreover, note that `._api.warn_external` will by default only
emit a given warning *once* for each line of user code, whereas
`logging.warning` will display the message every time it is called.

By default, `warnings.warn` displays the line of code that has the ``warn``
call. This usually isn't more informative than the warning message itself.
Therefore, Matplotlib uses `.cbook._warn_external` which uses `warnings.warn`,
Therefore, Matplotlib uses `._api.warn_external` which uses `warnings.warn`,
but goes up the stack and displays the first line of code outside of
Matplotlib. For example, for the module::

Expand All @@ -559,13 +559,13 @@ will display::
UserWarning: Attempting to set identical bottom==top
warnings.warn('Attempting to set identical bottom==top')

Modifying the module to use `.cbook._warn_external`::
Modifying the module to use `._api.warn_external`::

from matplotlib import cbook
from matplotlib import _api

def set_range(bottom, top):
if bottom == top:
cbook._warn_external('Attempting to set identical bottom==top')
_api.warn_external('Attempting to set identical bottom==top')

and running the same script will display::

Expand Down
37 changes: 37 additions & 0 deletions lib/matplotlib/_api.py → lib/matplotlib/_api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
"""
Helper functions for managing the Matplotlib API.

This documentation is only relevant for Matplotlib developers, not for users.

.. warning:

This module and its submodules are for internal use only. Do not use them
in your own code. We may change the API at any time with no warning.

"""

import itertools
import re
import sys
import warnings


def check_in_list(_values, *, _print_supported_values=True, **kwargs):
Expand Down Expand Up @@ -93,3 +108,25 @@ def check_getitem(_mapping, **kwargs):
raise ValueError(
"{!r} is not a valid value for {}; supported values are {}"
.format(v, k, ', '.join(map(repr, mapping)))) from None


def warn_external(message, category=None):
"""
`warnings.warn` wrapper that sets *stacklevel* to "outside Matplotlib".

The original emitter of the warning can be obtained by patching this
function back to `warnings.warn`, i.e. ``_api.warn_external =
warnings.warn`` (or ``functools.partial(warnings.warn, stacklevel=2)``,
etc.).
"""
frame = sys._getframe()
for stacklevel in itertools.count(1): # lgtm[py/unused-loop-variable]
if frame is None:
# when called in embedded context may hit frame is None
break
if not re.match(r"\A(matplotlib|mpl_toolkits)(\Z|\.(?!tests\.))",
# Work around sphinx-gallery not setting __name__.
frame.f_globals.get("__name__", "")):
break
frame = frame.f_back
warnings.warn(message, category, stacklevel)
Loading