From 64cd3dea3c4b8501ddf78fd1371dc699ebe41124 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 26 Jul 2024 04:03:24 -0400 Subject: [PATCH 1/5] DOC: Bump minimum Sphinx to 5.1.0 We depend on `pydata-sphinx-theme` 0.15.0, which requires Sphinx 5, and `sphinx-tags`, which requires Sphinx 5.1, so we really shouldn't create an environment with Sphinx older than that. --- doc/conf.py | 4 ++-- requirements/doc/doc-requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 6e736e16844f..882370b7e255 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -360,8 +360,8 @@ def gallery_image_warning_filter(record): # This is the default encoding, but it doesn't hurt to be explicit source_encoding = "utf-8" -# The toplevel toctree document (renamed to root_doc in Sphinx 4.0) -root_doc = master_doc = 'index' +# The toplevel toctree document. +root_doc = 'index' # General substitutions. try: diff --git a/requirements/doc/doc-requirements.txt b/requirements/doc/doc-requirements.txt index 0666af1d49e8..1a009f5854fc 100644 --- a/requirements/doc/doc-requirements.txt +++ b/requirements/doc/doc-requirements.txt @@ -7,7 +7,7 @@ # Install the documentation requirements with: # pip install -r requirements/doc/doc-requirements.txt # -sphinx>=3.0.0,!=6.1.2 +sphinx>=5.1.0,!=6.1.2 colorspacious ipython ipywidgets From 1f339e88f4d8f66048a893728269f4ad2c443ffb Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 26 Jul 2024 20:32:26 -0400 Subject: [PATCH 2/5] DOC: Remove unused template Its use was removed in #11451. --- doc/_templates/autofunctions.rst | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 doc/_templates/autofunctions.rst diff --git a/doc/_templates/autofunctions.rst b/doc/_templates/autofunctions.rst deleted file mode 100644 index 291b8eee2ede..000000000000 --- a/doc/_templates/autofunctions.rst +++ /dev/null @@ -1,22 +0,0 @@ - -{{ fullname | escape | underline }} - - -.. automodule:: {{ fullname }} - :no-members: - -{% block functions %} -{% if functions %} - -Functions ---------- - -.. autosummary:: - :template: autosummary.rst - :toctree: - -{% for item in functions %}{% if item not in ['plotting', 'colormaps'] %} - {{ item }}{% endif %}{% endfor %} - -{% endif %} -{% endblock %} From 350ed268ba6f7687d5c17209433f55b471e88135 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 29 Jul 2024 18:50:54 -0400 Subject: [PATCH 3/5] DOC: Fix some broken references --- doc/missing-references.json | 18 ------------------ doc/users/next_whats_new/README.rst | 3 ++- lib/matplotlib/axes/_base.py | 2 +- lib/matplotlib/backend_bases.py | 2 +- lib/matplotlib/backends/backend_template.py | 4 ++-- lib/matplotlib/testing/decorators.py | 2 +- 6 files changed, 7 insertions(+), 24 deletions(-) diff --git a/doc/missing-references.json b/doc/missing-references.json index 1b0a6f9ef226..b04a729772eb 100644 --- a/doc/missing-references.json +++ b/doc/missing-references.json @@ -337,9 +337,6 @@ "Artist.stale_callback": [ "doc/users/explain/figure/interactive_guide.rst:323" ], - "Artist.sticky_edges": [ - "doc/api/axes_api.rst:356::1" - ], "Axes.dataLim": [ "doc/api/axes_api.rst:293::1", "lib/matplotlib/axes/_base.py:docstring of matplotlib.axes._base._AxesBase.update_datalim:2" @@ -357,9 +354,6 @@ "Image": [ "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.gci:4" ], - "ImageComparisonFailure": [ - "lib/matplotlib/testing/decorators.py:docstring of matplotlib.testing.decorators.image_comparison:2" - ], "Line2D.pick": [ "doc/users/explain/figure/event_handling.rst:568" ], @@ -665,29 +659,17 @@ "mpl_toolkits.axislines.Axes": [ "lib/mpl_toolkits/axisartist/axis_artist.py:docstring of mpl_toolkits.axisartist.axis_artist:7" ], - "next_whats_new": [ - "doc/users/next_whats_new/README.rst:6" - ], "option_scale_image": [ "lib/matplotlib/backends/backend_cairo.py:docstring of matplotlib.backends.backend_cairo.RendererCairo.draw_image:22", "lib/matplotlib/backends/backend_pdf.py:docstring of matplotlib.backends.backend_pdf.RendererPdf.draw_image:22", "lib/matplotlib/backends/backend_ps.py:docstring of matplotlib.backends.backend_ps.RendererPS.draw_image:22", "lib/matplotlib/backends/backend_template.py:docstring of matplotlib.backends.backend_template.RendererTemplate.draw_image:22" ], - "print_xyz": [ - "lib/matplotlib/backends/backend_template.py:docstring of matplotlib.backends.backend_template:22" - ], "toggled": [ "lib/matplotlib/backend_tools.py:docstring of matplotlib.backend_tools.AxisScaleBase.disable:4", "lib/matplotlib/backend_tools.py:docstring of matplotlib.backend_tools.AxisScaleBase.enable:4", "lib/matplotlib/backend_tools.py:docstring of matplotlib.backend_tools.AxisScaleBase.trigger:2", "lib/matplotlib/backend_tools.py:docstring of matplotlib.backend_tools.ZoomPanBase.trigger:2" - ], - "tool_removed_event": [ - "lib/matplotlib/backend_bases.py:docstring of matplotlib.backend_bases.ToolContainerBase.remove_toolitem:6" - ], - "whats_new.rst": [ - "doc/users/next_whats_new/README.rst:6" ] } } diff --git a/doc/users/next_whats_new/README.rst b/doc/users/next_whats_new/README.rst index 98b601ee32d8..dabe676afaaf 100644 --- a/doc/users/next_whats_new/README.rst +++ b/doc/users/next_whats_new/README.rst @@ -3,7 +3,8 @@ Instructions for writing "What's new" entries ============================================= -Please place new portions of `whats_new.rst` in the `next_whats_new` directory. +Please place new portions of :file:`whats_new.rst` in the :file:`next_whats_new` +directory. When adding an entry please look at the currently existing files to see if you can extend any of them. If you create a file, name it diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 688b8d78b601..a0e588569465 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2635,7 +2635,7 @@ def set_autoscale_on(self, b): @property def use_sticky_edges(self): """ - When autoscaling, whether to obey all `Artist.sticky_edges`. + When autoscaling, whether to obey all `.Artist.sticky_edges`. Default is ``True``. diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 4b818d7fcdbd..788dd42ce917 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -3419,7 +3419,7 @@ def remove_toolitem(self, name): This hook must be implemented in each backend and contains the backend-specific code to remove an element from the toolbar; it is - called when `.ToolManager` emits a `tool_removed_event`. + called when `.ToolManager` emits a ``tool_removed_event``. Because some tools are present only on the `.ToolManager` but not on the `ToolContainer`, this method must be a no-op when called on a tool diff --git a/lib/matplotlib/backends/backend_template.py b/lib/matplotlib/backends/backend_template.py index d997ec160a53..83aa6bb567c1 100644 --- a/lib/matplotlib/backends/backend_template.py +++ b/lib/matplotlib/backends/backend_template.py @@ -20,8 +20,8 @@ import matplotlib matplotlib.use("module://my.backend") -If your backend implements support for saving figures (i.e. has a `print_xyz` -method), you can register it as the default handler for a given file type:: +If your backend implements support for saving figures (i.e. has a ``print_xyz`` method), +you can register it as the default handler for a given file type:: from matplotlib.backend_bases import register_backend register_backend('xyz', 'my_backend', 'XYZ File Format') diff --git a/lib/matplotlib/testing/decorators.py b/lib/matplotlib/testing/decorators.py index 49ac4a1506f8..6f1af7debdb3 100644 --- a/lib/matplotlib/testing/decorators.py +++ b/lib/matplotlib/testing/decorators.py @@ -263,7 +263,7 @@ def image_comparison(baseline_images, extensions=None, tol=0, style=("classic", "_classic_test_patch")): """ Compare images generated by the test with those specified in - *baseline_images*, which must correspond, else an `ImageComparisonFailure` + *baseline_images*, which must correspond, else an `.ImageComparisonFailure` exception will be raised. Parameters From 42bfa268429efffb04c0712ea7d9d4dd773ae886 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 29 Jul 2024 19:22:27 -0400 Subject: [PATCH 4/5] DOC: Fix inclusion of next API/what's new instructions --- doc/api/next_api_changes/README.rst | 16 +++++++++++----- doc/devel/api_changes.rst | 8 ++++---- doc/users/next_whats_new/README.rst | 17 ++++++++++++----- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/doc/api/next_api_changes/README.rst b/doc/api/next_api_changes/README.rst index 75e70b456eb9..030a2644cdd4 100644 --- a/doc/api/next_api_changes/README.rst +++ b/doc/api/next_api_changes/README.rst @@ -1,10 +1,18 @@ :orphan: +.. NOTE TO EDITORS OF THIS FILE + This file serves as the README directly available in the file system next to the + next_api_changes entries. The content between the ``api-change-guide-*`` markers is + additionally included in the documentation page ``doc/devel/api_changes.rst``. Please + check that the page builds correctly after changing this file. + Adding API change notes ======================= -API change notes for future releases are collected in -:file:`next_api_changes`. They are divided into four subdirectories: +.. api-change-guide-start + +API change notes for future releases are collected in :file:`doc/api/next_api_changes/`. +They are divided into four subdirectories: - **Deprecations**: Announcements of future changes. Typically, these will raise a deprecation warning and users of this API should change their code @@ -33,6 +41,4 @@ Please avoid using references in section titles, as it causes links to be confusing in the table of contents. Instead, ensure that a reference is included in the descriptive text. -.. NOTE - Lines 5-30 of this file are include in :ref:`api_whats_new`; - therefore, please check the doc build after changing this file. +.. api-change-guide-end diff --git a/doc/devel/api_changes.rst b/doc/devel/api_changes.rst index b7d0a4b063ce..0e86f11a3694 100644 --- a/doc/devel/api_changes.rst +++ b/doc/devel/api_changes.rst @@ -216,8 +216,8 @@ API change notes """""""""""""""" .. include:: ../api/next_api_changes/README.rst - :start-line: 5 - :end-line: 31 + :start-after: api-change-guide-start + :end-before: api-change-guide-end .. _whats-new-notes: @@ -225,5 +225,5 @@ What's new notes """""""""""""""" .. include:: ../users/next_whats_new/README.rst - :start-line: 5 - :end-line: 24 + :start-after: whats-new-guide-start + :end-before: whats-new-guide-end diff --git a/doc/users/next_whats_new/README.rst b/doc/users/next_whats_new/README.rst index dabe676afaaf..362feda65271 100644 --- a/doc/users/next_whats_new/README.rst +++ b/doc/users/next_whats_new/README.rst @@ -1,10 +1,19 @@ :orphan: +.. NOTE TO EDITORS OF THIS FILE + This file serves as the README directly available in the file system next to the + next_whats_new entries. The content between the ``whats-new-guide-*`` markers is + additionally included in the documentation page ``doc/devel/api_changes.rst``. Please + check that the page builds correctly after changing this file. + + Instructions for writing "What's new" entries ============================================= -Please place new portions of :file:`whats_new.rst` in the :file:`next_whats_new` -directory. +.. whats-new-guide-start + +Please place new portions of :file:`whats_new.rst` in the +:file:`doc/users/next_whats_new/` directory. When adding an entry please look at the currently existing files to see if you can extend any of them. If you create a file, name it @@ -27,6 +36,4 @@ Please avoid using references in section titles, as it causes links to be confusing in the table of contents. Instead, ensure that a reference is included in the descriptive text. -.. NOTE - Lines 5-24 of this file are include in :ref:`api_whats_new`; - therefore, please check the doc build after changing this file. +.. whats-new-guide-end From cda437289b0cf41a01571904b6a13bedf8f037a4 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 30 Jul 2024 01:01:52 -0400 Subject: [PATCH 5/5] DOC: Simplify missing references extension Sphinx 3.4 added a `warn-missing-reference` event, from which we can: 1. record the missing reference, avoiding any of the messing about with logging, and; 2. suppress the warning, avoiding any messing about with the `nitpicky_ignore` settings and their changing defaults. Also, simplify some of the callbacks by simply not connect the events if not necessary, instead of checking in every one. --- doc/missing-references.json | 151 +++++++++++++------------- doc/sphinxext/missing_references.py | 162 ++++++++-------------------- 2 files changed, 119 insertions(+), 194 deletions(-) diff --git a/doc/missing-references.json b/doc/missing-references.json index b04a729772eb..7eb45863589d 100644 --- a/doc/missing-references.json +++ b/doc/missing-references.json @@ -36,11 +36,11 @@ "lib/matplotlib/colorbar.py:docstring of matplotlib.colorbar.Colorbar.add_lines:4" ], "matplotlib.axes.Axes.patch": [ - "doc/tutorials/artists.rst:188", - "doc/tutorials/artists.rst:427" + "doc/tutorials/artists.rst:185", + "doc/tutorials/artists.rst:424" ], "matplotlib.axes.Axes.patches": [ - "doc/tutorials/artists.rst:465" + "doc/tutorials/artists.rst:462" ], "matplotlib.axes.Axes.transAxes": [ "lib/mpl_toolkits/axes_grid1/anchored_artists.py:docstring of mpl_toolkits.axes_grid1.anchored_artists.AnchoredDirectionArrows:8" @@ -51,25 +51,22 @@ "lib/mpl_toolkits/axes_grid1/anchored_artists.py:docstring of mpl_toolkits.axes_grid1.anchored_artists.AnchoredSizeBar:8" ], "matplotlib.axes.Axes.xaxis": [ - "doc/tutorials/artists.rst:611", + "doc/tutorials/artists.rst:608", "doc/users/explain/axes/axes_intro.rst:133" ], "matplotlib.axes.Axes.yaxis": [ - "doc/tutorials/artists.rst:611", + "doc/tutorials/artists.rst:608", "doc/users/explain/axes/axes_intro.rst:133" ], "matplotlib.axis.Axis.label": [ - "doc/tutorials/artists.rst:658" - ], - "matplotlib.colors.Colormap.name": [ - "lib/matplotlib/cm.py:docstring of matplotlib.cm.register_cmap:14" + "doc/tutorials/artists.rst:655" ], "matplotlib.figure.Figure.patch": [ - "doc/tutorials/artists.rst:188", - "doc/tutorials/artists.rst:321" + "doc/tutorials/artists.rst:185", + "doc/tutorials/artists.rst:318" ], "matplotlib.figure.Figure.transFigure": [ - "doc/tutorials/artists.rst:370" + "doc/tutorials/artists.rst:367" ], "max": [ "lib/matplotlib/transforms.py:docstring of matplotlib.transforms.Bbox.p1:4" @@ -105,7 +102,7 @@ "lib/matplotlib/tri/_trirefine.py:docstring of matplotlib.tri._trirefine.UniformTriRefiner.refine_triangulation:2" ], "use_sticky_edges": [ - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.margins:53" + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.margins:57" ], "width": [ "lib/matplotlib/transforms.py:docstring of matplotlib.transforms.Bbox.bounds:2" @@ -125,19 +122,19 @@ }, "py:class": { "HashableList[_HT]": [ - "doc/docstring of builtins.list:17" + ":1" ], "matplotlib.axes._base._AxesBase": [ "doc/api/artist_api.rst:202" ], "matplotlib.backend_bases.FigureCanvas": [ - "doc/tutorials/artists.rst:36", - "doc/tutorials/artists.rst:38", - "doc/tutorials/artists.rst:43" + "doc/tutorials/artists.rst:33", + "doc/tutorials/artists.rst:35", + "doc/tutorials/artists.rst:40" ], "matplotlib.backend_bases.Renderer": [ - "doc/tutorials/artists.rst:38", - "doc/tutorials/artists.rst:43" + "doc/tutorials/artists.rst:35", + "doc/tutorials/artists.rst:40" ], "matplotlib.backend_bases._Backend": [ "lib/matplotlib/backend_bases.py:docstring of matplotlib.backend_bases.ShowBase:1" @@ -238,36 +235,41 @@ "lib/mpl_toolkits/axes_grid1/axes_size.py:docstring of mpl_toolkits.axes_grid1.axes_size.Scaled:1" ], "mpl_toolkits.axes_grid1.parasite_axes.AxesHostAxes": [ - "doc/api/_as_gen/mpl_toolkits.axes_grid1.parasite_axes.rst:32::1" + ":1", + "doc/api/_as_gen/mpl_toolkits.axes_grid1.parasite_axes.rst:30::1" ], "mpl_toolkits.axes_grid1.parasite_axes.AxesParasite": [ - "doc/api/_as_gen/mpl_toolkits.axes_grid1.parasite_axes.rst:32::1" + ":1", + "doc/api/_as_gen/mpl_toolkits.axes_grid1.parasite_axes.rst:30::1" ], "mpl_toolkits.axisartist.Axes": [ "doc/api/toolkits/axisartist.rst:6" ], "mpl_toolkits.axisartist.axisline_style.AxislineStyle._Base": [ - "lib/mpl_toolkits/axisartist/axisline_style.py:docstring of mpl_toolkits.axisartist.axisline_style.AxislineStyle:1" + "lib/mpl_toolkits/axisartist/axisline_style.py:docstring of mpl_toolkits.axisartist.axisline_style.AxislineStyle.SimpleArrow:1" ], "mpl_toolkits.axisartist.axisline_style._FancyAxislineStyle.FilledArrow": [ - "lib/mpl_toolkits/axisartist/axisline_style.py:docstring of mpl_toolkits.axisartist.axisline_style.AxislineStyle:1" + ":1" ], "mpl_toolkits.axisartist.axisline_style._FancyAxislineStyle.SimpleArrow": [ - "lib/mpl_toolkits/axisartist/axisline_style.py:docstring of mpl_toolkits.axisartist.axisline_style.AxislineStyle:1" + ":1" ], "mpl_toolkits.axisartist.axislines._FixedAxisArtistHelperBase": [ + ":1", "lib/mpl_toolkits/axisartist/axislines.py:docstring of mpl_toolkits.axisartist.axislines.FixedAxisArtistHelperRectilinear:1", "lib/mpl_toolkits/axisartist/grid_helper_curvelinear.py:docstring of mpl_toolkits.axisartist.grid_helper_curvelinear.FixedAxisArtistHelper:1" ], "mpl_toolkits.axisartist.axislines._FloatingAxisArtistHelperBase": [ + ":1", "lib/mpl_toolkits/axisartist/axislines.py:docstring of mpl_toolkits.axisartist.axislines.FloatingAxisArtistHelperRectilinear:1", "lib/mpl_toolkits/axisartist/grid_helper_curvelinear.py:docstring of mpl_toolkits.axisartist.grid_helper_curvelinear.FloatingAxisArtistHelper:1" ], "mpl_toolkits.axisartist.floating_axes.FloatingAxesHostAxes": [ - "doc/api/_as_gen/mpl_toolkits.axisartist.floating_axes.rst:34::1" + ":1", + "doc/api/_as_gen/mpl_toolkits.axisartist.floating_axes.rst:32::1" ], "numpy.uint8": [ - "lib/matplotlib/path.py:docstring of matplotlib.path:1" + ":1" ] }, "py:data": { @@ -297,40 +299,39 @@ "lib/matplotlib/quiver.py:docstring of matplotlib.quiver.Barbs:9" ], "matplotlib.collections._CollectionWithSizes.set_sizes": [ - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.barbs:176", + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.barbs:177", "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.broken_barh:82", "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.fill_between:118", "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.fill_betweenx:118", - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.hexbin:206", - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.pcolor:178", - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.quiver:212", + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.hexbin:211", + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.pcolor:180", + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.quiver:213", "lib/matplotlib/collections.py:docstring of matplotlib.artist.AsteriskPolygonCollection.set:44", - "lib/matplotlib/collections.py:docstring of matplotlib.artist.BrokenBarHCollection.set:44", "lib/matplotlib/collections.py:docstring of matplotlib.artist.CircleCollection.set:44", "lib/matplotlib/collections.py:docstring of matplotlib.artist.PathCollection.set:44", "lib/matplotlib/collections.py:docstring of matplotlib.artist.PolyCollection.set:44", "lib/matplotlib/collections.py:docstring of matplotlib.artist.PolyQuadMesh.set:44", "lib/matplotlib/collections.py:docstring of matplotlib.artist.RegularPolyCollection.set:44", "lib/matplotlib/collections.py:docstring of matplotlib.artist.StarPolygonCollection.set:44", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.barbs:176", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.barbs:177", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.broken_barh:82", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.fill_between:118", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.fill_betweenx:118", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hexbin:206", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pcolor:178", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.quiver:212", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hexbin:211", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pcolor:180", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.quiver:213", "lib/matplotlib/quiver.py:docstring of matplotlib.artist.Barbs.set:45", "lib/matplotlib/quiver.py:docstring of matplotlib.artist.Quiver.set:45", - "lib/matplotlib/quiver.py:docstring of matplotlib.quiver.Barbs:209", - "lib/matplotlib/quiver.py:docstring of matplotlib.quiver.Quiver:248", + "lib/matplotlib/quiver.py:docstring of matplotlib.quiver.Barbs:210", + "lib/matplotlib/quiver.py:docstring of matplotlib.quiver.Quiver:249", "lib/mpl_toolkits/mplot3d/art3d.py:docstring of matplotlib.artist.Path3DCollection.set:46", "lib/mpl_toolkits/mplot3d/art3d.py:docstring of matplotlib.artist.Poly3DCollection.set:44" ], "matplotlib.collections._MeshData.set_array": [ - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.pcolormesh:160", + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.pcolormesh:162", "lib/matplotlib/collections.py:docstring of matplotlib.artist.PolyQuadMesh.set:17", "lib/matplotlib/collections.py:docstring of matplotlib.artist.QuadMesh.set:17", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pcolormesh:160" + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pcolormesh:162" ] }, "py:obj": { @@ -349,7 +350,7 @@ "doc/users/explain/figure/interactive_guide.rst:333" ], "Glyph": [ - "doc/gallery/misc/ftface_props.rst:28" + "doc/gallery/misc/ftface_props.rst:25" ], "Image": [ "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.gci:4" @@ -358,24 +359,24 @@ "doc/users/explain/figure/event_handling.rst:568" ], "QuadContourSet.changed()": [ - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.contour:152", - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.contourf:152", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.contour:152", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.contourf:152" + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.contour:154", + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.contourf:154", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.contour:154", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.contourf:154" ], "Rectangle.contains": [ "doc/users/explain/figure/event_handling.rst:280" ], "Size.from_any": [ - "lib/mpl_toolkits/axes_grid1/axes_grid.py:docstring of mpl_toolkits.axes_grid1.axes_grid.ImageGrid:84", - "lib/mpl_toolkits/axisartist/axes_grid.py:docstring of mpl_toolkits.axisartist.axes_grid.ImageGrid:84" + "lib/mpl_toolkits/axes_grid1/axes_grid.py:docstring of mpl_toolkits.axes_grid1.axes_grid.ImageGrid:87", + "lib/mpl_toolkits/axisartist/axes_grid.py:docstring of mpl_toolkits.axisartist.axes_grid.ImageGrid:87" ], "Timer": [ "lib/matplotlib/backend_bases.py:docstring of matplotlib.backend_bases.FigureCanvasBase.new_timer:2", "lib/matplotlib/backend_bases.py:docstring of matplotlib.backend_bases.TimerBase:14" ], "ToolContainer": [ - "lib/matplotlib/backend_bases.py:docstring of matplotlib.backend_bases.ToolContainerBase.remove_toolitem:2", + "lib/matplotlib/backend_bases.py:docstring of matplotlib.backend_bases.ToolContainerBase.remove_toolitem:8", "lib/matplotlib/backend_bases.py:docstring of matplotlib.backend_bases.ToolContainerBase:20" ], "_iter_collection": [ @@ -396,7 +397,7 @@ "lib/matplotlib/dviread.py:docstring of matplotlib.dviread.Vf:20" ], "active": [ - "lib/matplotlib/widgets.py:docstring of matplotlib.widgets.AxesWidget:34" + "lib/matplotlib/widgets.py:docstring of matplotlib.widgets.AxesWidget:32" ], "ax.transAxes": [ "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.indicate_inset:19", @@ -435,43 +436,40 @@ "lib/mpl_toolkits/axes_grid1/axes_size.py:docstring of mpl_toolkits.axes_grid1.axes_size:1" ], "ipykernel.pylab.backend_inline": [ - "doc/users/explain/figure/interactive.rst:340" + "doc/users/explain/figure/interactive.rst:361" ], "kde.covariance_factor": [ - "lib/matplotlib/mlab.py:docstring of matplotlib.mlab.GaussianKDE:41" + "lib/matplotlib/mlab.py:docstring of matplotlib.mlab.GaussianKDE:40" ], "kde.factor": [ - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.violinplot:46", + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.violinplot:58", "lib/matplotlib/mlab.py:docstring of matplotlib.mlab.GaussianKDE:12", - "lib/matplotlib/mlab.py:docstring of matplotlib.mlab.GaussianKDE:45", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.violinplot:46" + "lib/matplotlib/mlab.py:docstring of matplotlib.mlab.GaussianKDE:44", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.violinplot:58" ], "make_image": [ "lib/matplotlib/image.py:docstring of matplotlib.image.composite_images:9" ], "matplotlib.animation.ArtistAnimation.new_frame_seq": [ - "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:23::1" ], "matplotlib.animation.ArtistAnimation.new_saved_frame_seq": [ - "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:23::1" ], "matplotlib.animation.ArtistAnimation.pause": [ - "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:28::1" - ], - "matplotlib.animation.ArtistAnimation.repeat": [ - "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:33::1" + "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:23::1" ], "matplotlib.animation.ArtistAnimation.resume": [ - "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:23::1" ], "matplotlib.animation.ArtistAnimation.save": [ - "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:23::1" ], "matplotlib.animation.ArtistAnimation.to_html5_video": [ - "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:23::1" ], "matplotlib.animation.ArtistAnimation.to_jshtml": [ - "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.ArtistAnimation.rst:23::1" ], "matplotlib.animation.FFMpegFileWriter.bin_path": [ "doc/api/_as_gen/matplotlib.animation.FFMpegFileWriter.rst:27::1" @@ -543,22 +541,19 @@ "lib/matplotlib/animation.py:docstring of matplotlib.animation.FileMovieWriter.finish:1::1" ], "matplotlib.animation.FuncAnimation.pause": [ - "doc/api/_as_gen/matplotlib.animation.FuncAnimation.rst:28::1" - ], - "matplotlib.animation.FuncAnimation.repeat": [ "lib/matplotlib/animation.py:docstring of matplotlib.animation.FuncAnimation.new_frame_seq:1::1" ], "matplotlib.animation.FuncAnimation.resume": [ - "doc/api/_as_gen/matplotlib.animation.FuncAnimation.rst:28::1" + "lib/matplotlib/animation.py:docstring of matplotlib.animation.FuncAnimation.new_frame_seq:1::1" ], "matplotlib.animation.FuncAnimation.save": [ - "doc/api/_as_gen/matplotlib.animation.FuncAnimation.rst:28::1" + "lib/matplotlib/animation.py:docstring of matplotlib.animation.FuncAnimation.new_frame_seq:1::1" ], "matplotlib.animation.FuncAnimation.to_html5_video": [ - "doc/api/_as_gen/matplotlib.animation.FuncAnimation.rst:28::1" + "lib/matplotlib/animation.py:docstring of matplotlib.animation.FuncAnimation.new_frame_seq:1::1" ], "matplotlib.animation.FuncAnimation.to_jshtml": [ - "doc/api/_as_gen/matplotlib.animation.FuncAnimation.rst:28::1" + "lib/matplotlib/animation.py:docstring of matplotlib.animation.FuncAnimation.new_frame_seq:1::1" ], "matplotlib.animation.HTMLWriter.bin_path": [ "doc/api/_as_gen/matplotlib.animation.HTMLWriter.rst:27::1" @@ -633,28 +628,28 @@ "doc/api/_as_gen/matplotlib.animation.PillowWriter.rst:26::1" ], "matplotlib.animation.TimedAnimation.new_frame_seq": [ - "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:23::1" ], "matplotlib.animation.TimedAnimation.new_saved_frame_seq": [ - "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:23::1" ], "matplotlib.animation.TimedAnimation.pause": [ - "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:23::1" ], "matplotlib.animation.TimedAnimation.resume": [ - "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:23::1" ], "matplotlib.animation.TimedAnimation.save": [ - "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:23::1" ], "matplotlib.animation.TimedAnimation.to_html5_video": [ - "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:23::1" ], "matplotlib.animation.TimedAnimation.to_jshtml": [ - "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:28::1" + "doc/api/_as_gen/matplotlib.animation.TimedAnimation.rst:23::1" ], "matplotlib.typing._HT": [ - "doc/docstring of builtins.list:17" + ":1" ], "mpl_toolkits.axislines.Axes": [ "lib/mpl_toolkits/axisartist/axis_artist.py:docstring of mpl_toolkits.axisartist.axis_artist:7" diff --git a/doc/sphinxext/missing_references.py b/doc/sphinxext/missing_references.py index c621adb2c945..9c3b8256cd91 100644 --- a/doc/sphinxext/missing_references.py +++ b/doc/sphinxext/missing_references.py @@ -17,11 +17,9 @@ from collections import defaultdict import json -import logging from pathlib import Path from docutils.utils import get_source_line -from docutils import nodes from sphinx.util import logging as sphinx_logging import matplotlib @@ -29,59 +27,6 @@ logger = sphinx_logging.getLogger(__name__) -class MissingReferenceFilter(logging.Filter): - """ - A logging filter designed to record missing reference warning messages - for use by this extension - """ - def __init__(self, app): - self.app = app - super().__init__() - - def _record_reference(self, record): - if not (getattr(record, 'type', '') == 'ref' and - isinstance(getattr(record, 'location', None), nodes.Node)): - return - - if not hasattr(self.app.env, "missing_references_warnings"): - self.app.env.missing_references_warnings = defaultdict(set) - - record_missing_reference(self.app, - self.app.env.missing_references_warnings, - record.location) - - def filter(self, record): - self._record_reference(record) - return True - - -def record_missing_reference(app, record, node): - domain = node["refdomain"] - typ = node["reftype"] - target = node["reftarget"] - location = get_location(node, app) - - domain_type = f"{domain}:{typ}" - - record[(domain_type, target)].add(location) - - -def record_missing_reference_handler(app, env, node, contnode): - """ - When the sphinx app notices a missing reference, it emits an - event which calls this function. This function records the missing - references for analysis at the end of the sphinx build. - """ - if not app.config.missing_references_enabled: - # no-op when we are disabled. - return - - if not hasattr(env, "missing_references_events"): - env.missing_references_events = defaultdict(set) - - record_missing_reference(app, env.missing_references_events, node) - - def get_location(node, app): """ Given a docutils node and a sphinx application, return a string @@ -146,10 +91,34 @@ def _truncate_location(location): return location.split(":", 1)[0] -def _warn_unused_missing_references(app): - if not app.config.missing_references_warn_unused_ignores: - return +def handle_missing_reference(app, domain, node): + """ + Handle the warn-missing-reference Sphinx event. + + This function will: + #. record missing references for saving/comparing with ignored list. + #. prevent Sphinx from raising a warning on ignored references. + """ + typ = node["reftype"] + target = node["reftarget"] + location = get_location(node, app) + domain_type = f"{domain.name}:{typ}" + + app.env.missing_references_events[(domain_type, target)].add(location) + + # If we're ignoring this event, return True so that Sphinx thinks we handled it, + # even though we didn't print or warn. If we aren't ignoring it, Sphinx will print a + # warning about the missing reference. + if location in app.env.missing_references_ignored_references.get( + (domain_type, target), []): + return True + + +def warn_unused_missing_references(app, exc): + """ + Check that all lines of the existing JSON file are still necessary. + """ # We can only warn if we are building from a source install # otherwise, we just have to skip this step. basepath = Path(matplotlib.__file__).parent.parent.parent.resolve() @@ -159,9 +128,8 @@ def _warn_unused_missing_references(app): return # This is a dictionary of {(domain_type, target): locations} - references_ignored = getattr( - app.env, 'missing_references_ignored_references', {}) - references_events = getattr(app.env, 'missing_references_events', {}) + references_ignored = app.env.missing_references_ignored_references + references_events = app.env.missing_references_events # Warn about any reference which is no longer missing. for (domain_type, target), locations in references_ignored.items(): @@ -184,26 +152,13 @@ def _warn_unused_missing_references(app): subtype=domain_type) -def save_missing_references_handler(app, exc): +def save_missing_references(app, exc): """ - At the end of the sphinx build, check that all lines of the existing JSON - file are still necessary. - - If the configuration value ``missing_references_write_json`` is set - then write a new JSON file containing missing references. + Write a new JSON file containing missing references. """ - if not app.config.missing_references_enabled: - # no-op when we are disabled. - return - - _warn_unused_missing_references(app) - json_path = Path(app.confdir) / app.config.missing_references_filename - - references_warnings = getattr(app.env, 'missing_references_warnings', {}) - - if app.config.missing_references_write_json: - _write_missing_references_json(references_warnings, json_path) + references_warnings = app.env.missing_references_events + _write_missing_references_json(references_warnings, json_path) def _write_missing_references_json(records, json_path): @@ -220,6 +175,7 @@ def _write_missing_references_json(records, json_path): transformed_records[domain_type][target] = sorted(paths) with json_path.open("w") as stream: json.dump(transformed_records, stream, sort_keys=True, indent=2) + stream.write("\n") # Silence pre-commit no-newline-at-end-of-file warning. def _read_missing_references_json(json_path): @@ -242,49 +198,25 @@ def _read_missing_references_json(json_path): return ignored_references -def prepare_missing_references_handler(app): +def prepare_missing_references_setup(app): """ - Handler called to initialize this extension once the configuration - is ready. - - Reads the missing references file and populates ``nitpick_ignore`` if - appropriate. + Initialize this extension once the configuration is ready. """ if not app.config.missing_references_enabled: # no-op when we are disabled. return - sphinx_logger = logging.getLogger('sphinx') - missing_reference_filter = MissingReferenceFilter(app) - for handler in sphinx_logger.handlers: - if (isinstance(handler, sphinx_logging.WarningStreamHandler) - and missing_reference_filter not in handler.filters): - - # This *must* be the first filter, because subsequent filters - # throw away the node information and then we can't identify - # the reference uniquely. - handler.filters.insert(0, missing_reference_filter) - - app.env.missing_references_ignored_references = {} + app.connect("warn-missing-reference", handle_missing_reference) + if app.config.missing_references_warn_unused_ignores: + app.connect("build-finished", warn_unused_missing_references) + if app.config.missing_references_write_json: + app.connect("build-finished", save_missing_references) json_path = Path(app.confdir) / app.config.missing_references_filename - if not json_path.exists(): - return - - ignored_references = _read_missing_references_json(json_path) - - app.env.missing_references_ignored_references = ignored_references - - # If we are going to re-write the JSON file, then don't suppress missing - # reference warnings. We want to record a full list of missing references - # for use later. Otherwise, add all known missing references to - # ``nitpick_ignore``` - if not app.config.missing_references_write_json: - # Since Sphinx v6.2, nitpick_ignore may be a list, set or tuple, and - # defaults to set. Previously it was always a list. Cast to list for - # consistency across versions. - app.config.nitpick_ignore = list(app.config.nitpick_ignore) - app.config.nitpick_ignore.extend(ignored_references.keys()) + app.env.missing_references_ignored_references = ( + _read_missing_references_json(json_path) if json_path.exists() else {} + ) + app.env.missing_references_events = defaultdict(set) def setup(app): @@ -294,8 +226,6 @@ def setup(app): app.add_config_value("missing_references_filename", "missing-references.json", "env") - app.connect("builder-inited", prepare_missing_references_handler) - app.connect("missing-reference", record_missing_reference_handler) - app.connect("build-finished", save_missing_references_handler) + app.connect("builder-inited", prepare_missing_references_setup) return {'parallel_read_safe': True}