diff --git a/.coveragerc b/.coveragerc index 6ba8e5752785..f8d90f93e600 100644 --- a/.coveragerc +++ b/.coveragerc @@ -12,3 +12,5 @@ exclude_lines = def __str__ def __repr__ if __name__ == .__main__.: + if TYPE_CHECKING: + if typing.TYPE_CHECKING: diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 659eedb8d383..703ebd4c8b9d 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -38,6 +38,40 @@ jobs: flake8 --docstring-convention=all | \ reviewdog -f=pep8 -name=flake8 \ -tee -reporter=github-check -filter-mode nofilter + mypy: + name: mypy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Python 3 + uses: actions/setup-python@v4 + with: + python-version: 3.8 + + - name: Install mypy + run: pip3 install -r requirements/testing/mypy.txt -r requirements/testing/all.txt + + - name: Set up reviewdog + run: | + mkdir -p "$HOME/bin" + curl -sfL \ + https://github.com/reviewdog/reviewdog/raw/master/install.sh | \ + sh -s -- -b "$HOME/bin" + echo "$HOME/bin" >> $GITHUB_PATH + + - name: Run mypy + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -o pipefail + # the ignore missing imports can be removed when typed cycler is released and used + mypy --config pyproject.toml lib/matplotlib \ + --ignore-missing-imports \ + --follow-imports silent | \ + reviewdog -f=mypy -name=mypy \ + -tee -reporter=github-check -filter-mode nofilter + eslint: name: eslint diff --git a/doc/api/colors_api.rst b/doc/api/colors_api.rst index 970986ff4438..19980b14223b 100644 --- a/doc/api/colors_api.rst +++ b/doc/api/colors_api.rst @@ -52,6 +52,7 @@ Other classes ColorSequenceRegistry LightSource + Color Functions --------- diff --git a/doc/api/lines_api.rst b/doc/api/lines_api.rst index 4cde67c7e656..483475e7adf7 100644 --- a/doc/api/lines_api.rst +++ b/doc/api/lines_api.rst @@ -17,6 +17,9 @@ Classes Line2D VertexSelector + LineStyleType + DrawStyleType + MarkEveryType Functions --------- diff --git a/doc/api/markers_api.rst b/doc/api/markers_api.rst index 5193d2dd90c9..5f41a663693d 100644 --- a/doc/api/markers_api.rst +++ b/doc/api/markers_api.rst @@ -16,3 +16,5 @@ Classes :template: autosummary.rst MarkerStyle + MarkerType + FillStyleType diff --git a/doc/api/next_api_changes/behavior/24912-AL.rst b/doc/api/next_api_changes/behavior/24912-AL.rst new file mode 100644 index 000000000000..3a87ed217f9f --- /dev/null +++ b/doc/api/next_api_changes/behavior/24912-AL.rst @@ -0,0 +1,4 @@ +``contour`` no longer warns if no contour lines are drawn. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This can occur if the user explicitly passes a ``levels`` array with no values +between ``z.min()`` and ``z.max()``; or if ``z`` has the same value everywhere. diff --git a/doc/api/next_api_changes/deprecations/24254-OG.rst b/doc/api/next_api_changes/deprecations/24254-OG.rst new file mode 100644 index 000000000000..d6e4882a774b --- /dev/null +++ b/doc/api/next_api_changes/deprecations/24254-OG.rst @@ -0,0 +1,6 @@ +Most arguments to widgets have been made keyword-only +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Passing all but the very few first arguments positionally in the constructors +of Widgets is deprecated. Most arguments will become keyword-only in a future +version. diff --git a/doc/api/next_api_changes/removals/24254-OG.rst b/doc/api/next_api_changes/removals/24254-OG.rst new file mode 100644 index 000000000000..f29d1e0662cd --- /dev/null +++ b/doc/api/next_api_changes/removals/24254-OG.rst @@ -0,0 +1,64 @@ +Removal of deprecations in the Selector widget API +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +RectangleSelector and EllipseSelector +..................................... + +The *drawtype* keyword argument to `~matplotlib.widgets.RectangleSelector` is +removed. From now on, the only behaviour will be ``drawtype='box'``. + +Support for ``drawtype=line`` is removed altogether. As a +result, the *lineprops* keyword argument to +`~matplotlib.widgets.RectangleSelector` is also removed. + +To retain the behaviour of ``drawtype='none'``, use ``rectprops={'visible': +False}`` to make the drawn `~matplotlib.patches.Rectangle` invisible. + +Cleaned up attributes and arguments are: + +- The ``active_handle`` attribute has been privatized and removed. +- The ``drawtype`` attribute has been privatized and removed. +- The ``eventpress`` attribute has been privatized and removed. +- The ``eventrelease`` attribute has been privatized and removed. +- The ``interactive`` attribute has been privatized and removed. +- The *marker_props* argument is removed, use *handle_props* instead. +- The *maxdist* argument is removed, use *grab_range* instead. +- The *rectprops* argument is removed, use *props* instead. +- The ``rectprops`` attribute has been privatized and removed. +- The ``state`` attribute has been privatized and removed. +- The ``to_draw`` attribute has been privatized and removed. + +PolygonSelector +............... + +- The *line* attribute is removed. If you want to change the selector artist + properties, use the ``set_props`` or ``set_handle_props`` methods. +- The *lineprops* argument is removed, use *props* instead. +- The *markerprops* argument is removed, use *handle_props* instead. +- The *maxdist* argument and attribute is removed, use *grab_range* instead. +- The *vertex_select_radius* argument and attribute is removed, use + *grab_range* instead. + +SpanSelector +............ + +- The ``active_handle`` attribute has been privatized and removed. +- The ``eventpress`` attribute has been privatized and removed. +- The ``eventrelease`` attribute has been privatized and removed. +- The ``pressv`` attribute has been privatized and removed. +- The ``prev`` attribute has been privatized and removed. +- The ``rect`` attribute has been privatized and removed. +- The *rectprops* parameter has been renamed to *props*. +- The ``rectprops`` attribute has been privatized and removed. +- The *span_stays* parameter has been renamed to *interactive*. +- The ``span_stays`` attribute has been privatized and removed. +- The ``state`` attribute has been privatized and removed. + +LassoSelector +............. + +- The *lineprops* argument is removed, use *props* instead. +- The ``onpress`` and ``onrelease`` methods are removed. They are straight + aliases for ``press`` and ``release``. +- The ``matplotlib.widgets.TextBox.DIST_FROM_LEFT`` attribute has been + removed. It was marked as private in 3.5. diff --git a/doc/api/next_api_changes/removals/24948-ES.rst b/doc/api/next_api_changes/removals/24948-ES.rst new file mode 100644 index 000000000000..38ed70792f26 --- /dev/null +++ b/doc/api/next_api_changes/removals/24948-ES.rst @@ -0,0 +1,115 @@ + +Testing support +~~~~~~~~~~~~~~~ + +``matplotlib.test()`` has been removed +...................................... + +Run tests using ``pytest`` from the commandline instead. The variable +``matplotlib.default_test_modules`` was only used for ``matplotlib.test()`` and +is thus removed as well. + +To test an installed copy, be sure to specify both ``matplotlib`` and +``mpl_toolkits`` with ``--pyargs``:: + + python -m pytest --pyargs matplotlib.tests mpl_toolkits.tests + +See :ref:`testing` for more details. + + + +Auto-removal of grids by `~.Axes.pcolor` and `~.Axes.pcolormesh` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`~.Axes.pcolor` and `~.Axes.pcolormesh` previously remove any visible axes +major grid. This behavior is removed; please explicitly call ``ax.grid(False)`` +to remove the grid. + + + +Modification of ``Axes`` children sublists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See :ref:`Behavioural API Changes 3.5 - Axes children combined` for more +information; modification of the following sublists is no longer supported: + +* ``Axes.artists`` +* ``Axes.collections`` +* ``Axes.images`` +* ``Axes.lines`` +* ``Axes.patches`` +* ``Axes.tables`` +* ``Axes.texts`` + +To remove an Artist, use its `.Artist.remove` method. To add an Artist, use the +corresponding ``Axes.add_*`` method. + +Passing incorrect types to ``Axes.add_*`` methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``Axes.add_*`` methods will now raise if passed an unexpected +type. See their documentation for the types they expect. + +- `.Axes.add_collection` +- `.Axes.add_image` +- `.Axes.add_line` +- `.Axes.add_patch` +- `.Axes.add_table` + + +``ConversionInterface.convert`` no longer accepts unitless values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Previously, custom subclasses of `.units.ConversionInterface` needed to +implement a ``convert`` method that not only accepted instances of the unit, +but also unitless values (which are passed through as is). This is no longer +the case (``convert`` is never called with a unitless value), and such support +in ``.StrCategoryConverter`` is removed. Likewise, the +``.ConversionInterface.is_numlike`` helper is removed. + +Consider calling `.Axis.convert_units` instead, which still supports unitless +values. + + +Normal list of `.Artist` objects now returned by `.HandlerLine2D.create_artists` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For Matplotlib 3.5 and 3.6 a proxy list was returned that simulated the return +of `.HandlerLine2DCompound.create_artists`. Now a list containing only the +single artist is return. + + +rcParams will no longer cast inputs to str +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +rcParams that expect a (non-pathlike) str no longer cast non-str inputs using +`str`. This will avoid confusing errors in subsequent code if e.g. a list input +gets implicitly cast to a str. + + + +Case-insensitive scales +~~~~~~~~~~~~~~~~~~~~~~~ + +Previously, scales could be set case-insensitively (e.g., +``set_xscale("LoG")``). Now all builtin scales use lowercase names. + + + +Support for ``nx1 = None`` or ``ny1 = None`` in ``AxesLocator`` and ``Divider.locate`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In `.axes_grid1.axes_divider`, various internal APIs no longer supports +passing ``nx1 = None`` or ``ny1 = None`` to mean ``nx + 1`` or ``ny + 1``, in +preparation for a possible future API which allows indexing and slicing of +dividers (possibly ``divider[a:b] == divider.new_locator(a, b)``, but also +``divider[a:] == divider.new_locator(a, )``). The user-facing +`.Divider.new_locator` API is unaffected -- it correctly normalizes ``nx1 = +None`` and ``ny1 = None`` as needed. + + +change signature of ``.FigureCanvasBase.enter_notify_event`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The *xy* parameter is now required and keyword only. This was deprecated in +3.0 and originally slated to be removed in 3.5. diff --git a/doc/api/next_api_changes/removals/24965-ES.rst b/doc/api/next_api_changes/removals/24965-ES.rst new file mode 100644 index 000000000000..96089f463e64 --- /dev/null +++ b/doc/api/next_api_changes/removals/24965-ES.rst @@ -0,0 +1,5 @@ +``Colorbar`` tick update parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The *update_ticks* parameter of `.Colorbar.set_ticks` and +`.Colorbar.set_ticklabels` was ignored since 3.5 and has been removed. diff --git a/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst index 7ce5132bc7fa..7bb9009fbe77 100644 --- a/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst +++ b/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst @@ -162,7 +162,7 @@ implement a ``convert`` method that not only accepted instances of the unit, but also unitless values (which are passed through as is). This is no longer the case (``convert`` is never called with a unitless value), and such support in `.StrCategoryConverter` is deprecated. Likewise, the -`.ConversionInterface.is_numlike` helper is deprecated. +``.ConversionInterface.is_numlike`` helper is deprecated. Consider calling `.Axis.convert_units` instead, which still supports unitless values. diff --git a/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst index ce9ddef5ba5f..45b574e04cf5 100644 --- a/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst +++ b/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst @@ -282,7 +282,7 @@ Arguments - The *dummy* parameter of `.RendererPgf` has been removed. - The *props* parameter of `.Shadow` has been removed; use keyword arguments instead. -- The *recursionlimit* parameter of `matplotlib.test` has been removed. +- The *recursionlimit* parameter of ``matplotlib.test`` has been removed. - The *label* parameter of `.Tick` has no effect and has been removed. - `~.ticker.MaxNLocator` no longer accepts a positional parameter and the keyword argument *nbins* simultaneously because they specify the same diff --git a/doc/api/testing_api.rst b/doc/api/testing_api.rst index 808d2b870109..7731d4510b27 100644 --- a/doc/api/testing_api.rst +++ b/doc/api/testing_api.rst @@ -3,11 +3,6 @@ ********************** -:func:`matplotlib.test` -======================= - -.. autofunction:: matplotlib.test - :mod:`matplotlib.testing` ========================= diff --git a/doc/conf.py b/doc/conf.py index dd7ba1cebf9e..2b5bc9f2bb6f 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -458,7 +458,7 @@ def js_tag_with_cache_busting(js): # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. -html_use_opensearch = 'False' +html_use_opensearch = 'https://matplotlib.org/stable' # Output file base name for HTML help builder. htmlhelp_basename = 'Matplotlibdoc' diff --git a/doc/missing-references.json b/doc/missing-references.json index d9a64ae39c2a..18b844036b7d 100644 --- a/doc/missing-references.json +++ b/doc/missing-references.json @@ -97,10 +97,81 @@ ] }, "py:class": { + "ArrayLike": [ + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.acorr:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.angle_spectrum:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.bar:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.bar_label:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.barh:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.boxplot:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.clabel:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.csd:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.errorbar:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.eventplot:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.figimage:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.fill_between:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.fill_betweenx:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hist2d:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hist:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hlines:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.imsave:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.imshow:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.magnitude_spectrum:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.matshow:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pcolor:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pcolormesh:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.phase_spectrum:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pie:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.plot:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.plot_date:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.psd:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.rgrids:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.scatter:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.specgram:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.spy:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.stairs:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.step:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.subplot_mosaic:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.thetagrids:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.violinplot:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.vlines:1" + ], + "Axes": [ + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.axes:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.colorbar:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.delaxes:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.subplot2grid:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.subplot_mosaic:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.subplots:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.twinx:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.twiny:1" + ], + "Color": [ + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.errorbar:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.eventplot:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hist:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hlines:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pie:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.scatter:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.vlines:1" + ], + "LineStyleType": [ + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.eventplot:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hlines:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.vlines:1" + ], + "MarkerType": [ + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.scatter:1" + ], + "SubplotBase": [ + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.subplots:1" + ], + "_AxesBase": [ + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.twinx:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.twiny:1" + ], "matplotlib.axes._base._AxesBase": [ - "doc/api/artist_api.rst:202", - "doc/api/axes_api.rst:603", - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes:1" + "doc/api/artist_api.rst:202" ], "matplotlib.backend_bases.FigureCanvas": [ "doc/tutorials/intermediate/artists.rst:32", @@ -210,6 +281,23 @@ "doc/api/_as_gen/mpl_toolkits.axisartist.floating_axes.rst:32::1", "lib/mpl_toolkits/axisartist/floating_axes.py:docstring of mpl_toolkits.axisartist.floating_axes.FloatingAxesHostAxes:1" ], + "np.ndarray": [ + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.acorr:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.angle_spectrum:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.cohere:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.csd:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hist2d:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hist:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.imread:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.magnitude_spectrum:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.phase_spectrum:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.psd:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.specgram:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.subplots:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.xcorr:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.xticks:1", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.yticks:1" + ], "numpy.uint8": [ "lib/matplotlib/path.py:docstring of matplotlib.path:1" ], @@ -219,11 +307,11 @@ }, "py:data": { "matplotlib.axes.Axes.transAxes": [ - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.legend:234", - "lib/matplotlib/figure.py:docstring of matplotlib.figure.FigureBase.add_axes:2", - "lib/matplotlib/legend.py:docstring of matplotlib.legend.Legend:91", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.figlegend:233", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.legend:234" + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.legend:240", + "lib/matplotlib/figure.py:docstring of matplotlib.figure.FigureBase.add_axes:18", + "lib/matplotlib/legend.py:docstring of matplotlib.legend.Legend:107", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.figlegend:249", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.legend:240" ] }, "py:meth": { @@ -248,7 +336,7 @@ ], "matplotlib.collections._CollectionWithSizes.set_sizes": [ "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.barbs:171", - "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.broken_barh:81", + "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.broken_barh:77", "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.fill_between:113", "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.fill_betweenx:113", "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.hexbin:201", @@ -256,7 +344,7 @@ "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.quiver:207", "lib/matplotlib/collections.py:docstring of matplotlib.collections.AsteriskPolygonCollection:22", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.barbs:171", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.broken_barh:81", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.broken_barh:77", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.fill_between:113", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.fill_betweenx:113", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hexbin:201", @@ -275,15 +363,15 @@ "doc/users/explain/interactive_guide.rst:323" ], "Artist.sticky_edges": [ - "doc/api/axes_api.rst:352::1", + "doc/api/axes_api.rst:353::1", "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes.Axes.use_sticky_edges:1" ], "Axes.dataLim": [ - "doc/api/axes_api.rst:291::1", + "doc/api/axes_api.rst:292::1", "lib/matplotlib/axes/_base.py:docstring of matplotlib.axes._base._AxesBase.update_datalim:1" ], "AxesBase": [ - "doc/api/axes_api.rst:444::1", + "doc/api/axes_api.rst:445::1", "lib/matplotlib/axes/_base.py:docstring of matplotlib.axes._base._AxesBase.add_child_axes:1" ], "Figure.stale_callback": [ @@ -299,7 +387,7 @@ "lib/matplotlib/testing/decorators.py:docstring of matplotlib.testing.decorators:1" ], "Line2D.pick": [ - "doc/users/explain/event_handling.rst:468" + "doc/users/explain/event_handling.rst:567" ], "QuadContourSet.changed()": [ "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.contour:147", @@ -308,7 +396,7 @@ "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.contourf:147" ], "Rectangle.contains": [ - "doc/users/explain/event_handling.rst:180" + "doc/users/explain/event_handling.rst:279" ], "Size.from_any": [ "lib/mpl_toolkits/axes_grid1/axes_grid.py:docstring of mpl_toolkits.axes_grid1.axes_grid.ImageGrid:53", @@ -348,18 +436,14 @@ ], "axes.bbox": [ "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.legend:137", - "lib/matplotlib/figure.py:docstring of matplotlib.figure.Figure:116", - "lib/matplotlib/legend.py:docstring of matplotlib.legend.DraggableLegend.finalize_offset:20", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.figlegend:136", + "lib/matplotlib/figure.py:docstring of matplotlib.figure.Figure:126", + "lib/matplotlib/legend.py:docstring of matplotlib.legend.Legend:4", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.figlegend:146", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.legend:137" ], "can_composite": [ "lib/matplotlib/image.py:docstring of matplotlib.image:5" ], - "cleanup": [ - "lib/matplotlib/animation.py:docstring of matplotlib.animation.FileMovieWriter:13", - "lib/matplotlib/animation.py:docstring of matplotlib.animation.HTMLWriter:13" - ], "converter": [ "lib/matplotlib/testing/compare.py:docstring of matplotlib.testing.compare:1" ], @@ -368,9 +452,9 @@ ], "figure.bbox": [ "lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.legend:137", - "lib/matplotlib/figure.py:docstring of matplotlib.figure.Figure:116", - "lib/matplotlib/legend.py:docstring of matplotlib.legend.DraggableLegend.finalize_offset:20", - "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.figlegend:136", + "lib/matplotlib/figure.py:docstring of matplotlib.figure.Figure:126", + "lib/matplotlib/legend.py:docstring of matplotlib.legend.Legend:4", + "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.figlegend:146", "lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.legend:137" ], "fmt_xdata": [ diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 4289eb1702eb..7fb9e1745b39 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -103,6 +103,37 @@ """ +__all_ignore__ = [ + "__bibtex__", + "__version__", + "__version_info__", + "set_loglevel", + "ExecutableNotFoundError", + "get_configdir", + "get_cachedir", + "get_data_path", + "matplotlib_fname", + "RcParams", + "rc_params", + "rc_params_from_file", + "rcParamsDefault", + "rcParams", + "rcParamsOrig", + "defaultParams", + "rc", + "rcdefaults", + "rc_file_defaults", + "rc_file", + "rc_context", + "use", + "get_backend", + "interactive", + "is_interactive", + "colormaps", + "color_sequences", +] + + import atexit from collections import namedtuple from collections.abc import MutableMapping @@ -1278,12 +1309,6 @@ def is_interactive(): return rcParams['interactive'] -default_test_modules = [ - 'matplotlib.tests', - 'mpl_toolkits.tests', -] - - def _init_tests(): # The version of FreeType to install locally for running the # tests. This must match the value in `setupext.py` @@ -1302,58 +1327,6 @@ def _init_tests(): "" if ft2font.__freetype_build_type__ == 'local' else "not ")) -@_api.deprecated("3.5", alternative='pytest') -def test(verbosity=None, coverage=False, **kwargs): - """Run the matplotlib test suite.""" - - try: - import pytest - except ImportError: - print("matplotlib.test requires pytest to run.") - return -1 - - if not os.path.isdir(os.path.join(os.path.dirname(__file__), 'tests')): - print("Matplotlib test data is not installed") - return -1 - - old_backend = get_backend() - try: - use('agg') - - args = kwargs.pop('argv', []) - provide_default_modules = True - use_pyargs = True - for arg in args: - if any(arg.startswith(module_path) - for module_path in default_test_modules): - provide_default_modules = False - break - if os.path.exists(arg): - provide_default_modules = False - use_pyargs = False - break - if use_pyargs: - args += ['--pyargs'] - if provide_default_modules: - args += default_test_modules - - if coverage: - args += ['--cov'] - - if verbosity: - args += ['-' + 'v' * verbosity] - - retcode = pytest.main(args, **kwargs) - finally: - if old_backend.lower() != 'agg': - use(old_backend) - - return retcode - - -test.__test__ = False # pytest: this function is not a test - - def _replacer(data, value): """ Either returns ``data[value]`` or passes ``data`` back, converts either to diff --git a/lib/matplotlib/__init__.pyi b/lib/matplotlib/__init__.pyi new file mode 100644 index 000000000000..f19af276bb95 --- /dev/null +++ b/lib/matplotlib/__init__.pyi @@ -0,0 +1,116 @@ +__all__ = [ + "__bibtex__", + "__version__", + "__version_info__", + "set_loglevel", + "ExecutableNotFoundError", + "get_configdir", + "get_cachedir", + "get_data_path", + "matplotlib_fname", + "RcParams", + "rc_params", + "rc_params_from_file", + "rcParamsDefault", + "rcParams", + "rcParamsOrig", + "defaultParams", + "rc", + "rcdefaults", + "rc_file_defaults", + "rc_file", + "rc_context", + "use", + "get_backend", + "interactive", + "is_interactive", + "colormaps", + "color_sequences", +] + +import os +from pathlib import Path + +from . import cbook, rcsetup +from collections.abc import Generator, MutableMapping +import contextlib +from packaging.version import Version + +from matplotlib._api import MatplotlibDeprecationWarning +from matplotlib.cbook import sanitize_sequence +from matplotlib.rcsetup import cycler, validate_backend +from typing import Any, Callable, NamedTuple + +__bibtex__: str + +class _VersionInfo(NamedTuple): + major: int + minor: int + micro: int + releaselevel: str + serial: int + +__version__: str +__version_info__: _VersionInfo + +def set_loglevel(level: str) -> None: ... + +class _ExecInfo(NamedTuple): + executable: str + raw_version: str + version: Version + +class ExecutableNotFoundError(FileNotFoundError): ... + +def _get_executable_info(name: str) -> _ExecInfo: ... +def get_configdir() -> str: ... +def get_cachedir() -> str: ... +def get_data_path() -> str: ... +def matplotlib_fname() -> str: ... + +class RcParams(dict[str, Any]): + validate: dict[str, Callable] + def __init__(self, *args, **kwargs) -> None: ... + def __setitem__(self, key: str, val: Any) -> None: ... + def __getitem__(self, key: str) -> Any: ... + def __iter__(self) -> Generator[str, None, None]: ... + def __len__(self) -> int: ... + def find_all(self, pattern: str): ... + def copy(self) -> RcParams: ... + +def rc_params(fail_on_error: bool = ...) -> RcParams: ... +def rc_params_from_file( + fname: str | Path | os.PathLike, + fail_on_error: bool = ..., + use_default_template: bool = ..., +) -> RcParams: ... + +rcParamsDefault: RcParams +rcParams: RcParams +rcParamsOrig: RcParams +defaultParams: dict[str, Any] + +def rc(group: str, **kwargs) -> None: ... +def rcdefaults() -> None: ... +def rc_file_defaults() -> None: ... +def rc_file( + fname: str | Path | os.PathLike, *, use_default_template: bool = ... +) -> None: ... +@contextlib.contextmanager +def rc_context( + rc: dict[str, Any] | None = ..., fname: str | Path | os.PathLike | None = ... +): ... +def use(backend: str, *, force: bool = ...) -> None: ... +def get_backend() -> str: ... +def interactive(b: bool) -> None: ... +def is_interactive() -> bool: ... + +def _preprocess_data( + func: Callable | None = ..., + *, + replace_names: list[str] | None = ..., + label_namer: str | None = ... +) -> Callable: ... + +from matplotlib.cm import _colormaps as colormaps +from matplotlib.colors import _color_sequences as color_sequences diff --git a/lib/matplotlib/_c_internal_utils.pyi b/lib/matplotlib/_c_internal_utils.pyi new file mode 100644 index 000000000000..3a211223be80 --- /dev/null +++ b/lib/matplotlib/_c_internal_utils.pyi @@ -0,0 +1 @@ +def display_is_valid() -> bool: ... diff --git a/lib/matplotlib/_color_data.pyi b/lib/matplotlib/_color_data.pyi new file mode 100644 index 000000000000..9dd2e85c44e5 --- /dev/null +++ b/lib/matplotlib/_color_data.pyi @@ -0,0 +1,6 @@ +from .colors import Color + +BASE_COLORS: dict[str, Color] +TABLEAU_COLORS: dict[str, Color] +XKCD_COLORS: dict[str, Color] +CSS4_COLORS: dict[str, Color] diff --git a/lib/matplotlib/_enums.pyi b/lib/matplotlib/_enums.pyi new file mode 100644 index 000000000000..3dc8329135ff --- /dev/null +++ b/lib/matplotlib/_enums.pyi @@ -0,0 +1,18 @@ +from enum import Enum + +class _AutoStringNameEnum(Enum): + def __hash__(self): ... + +class JoinStyle(str, _AutoStringNameEnum): + miter: str + round: str + bevel: str + @staticmethod + def demo() -> None: ... + +class CapStyle(str, _AutoStringNameEnum): + butt: str + projecting: str + round: str + @staticmethod + def demo() -> None: ... diff --git a/lib/matplotlib/_image.pyi b/lib/matplotlib/_image.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 3a934c21fd50..904a84afa031 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -1344,7 +1344,7 @@ def __init__(self, state): _GlueSpec = namedtuple( "_GlueSpec", "width stretch stretch_order shrink shrink_order") -_GlueSpec._named = { +_GlueSpec._named = { # type: ignore[attr-defined] 'fil': _GlueSpec(0., 1., 1, 0., 0), 'fill': _GlueSpec(0., 1., 2, 0., 0), 'filll': _GlueSpec(0., 1., 3, 0., 0), diff --git a/lib/matplotlib/_path.pyi b/lib/matplotlib/_path.pyi new file mode 100644 index 000000000000..968d0380bb0b --- /dev/null +++ b/lib/matplotlib/_path.pyi @@ -0,0 +1,7 @@ +from typing import Sequence +import numpy as np +from .transforms import BboxBase + +def affine_transform(points: np.ndarray, matrix: np.ndarray) -> np.ndarray: ... +def count_bboxes_overlapping_bbox(a: BboxBase, bboxes: Sequence[BboxBase]) -> int: ... +def update_path_extents(*args, **kwargs): ... diff --git a/lib/matplotlib/_pylab_helpers.pyi b/lib/matplotlib/_pylab_helpers.pyi new file mode 100644 index 000000000000..6e1c8889833f --- /dev/null +++ b/lib/matplotlib/_pylab_helpers.pyi @@ -0,0 +1,27 @@ +from collections import OrderedDict + +from matplotlib.backend_bases import FigureManagerBase +from matplotlib.figure import Figure + +class Gcf: + figs: OrderedDict[int, FigureManagerBase] + @classmethod + def get_fig_manager(cls, num: int) -> FigureManagerBase: ... + @classmethod + def destroy(cls, num: int | FigureManagerBase) -> None: ... + @classmethod + def destroy_fig(cls, fig: Figure) -> None: ... + @classmethod + def destroy_all(cls) -> None: ... + @classmethod + def has_fignum(cls, num: int) -> bool: ... + @classmethod + def get_all_fig_managers(cls) -> list[FigureManagerBase]: ... + @classmethod + def get_num_fig_managers(cls) -> int: ... + @classmethod + def get_active(cls) -> FigureManagerBase: ... + @classmethod + def set_active(cls, manager: FigureManagerBase) -> None: ... + @classmethod + def draw_all(cls, force: bool = ...) -> None: ... diff --git a/lib/matplotlib/_qhull.pyi b/lib/matplotlib/_qhull.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/matplotlib/_tight_bbox.py b/lib/matplotlib/_tight_bbox.py index b2147b960735..e0fba389d120 100644 --- a/lib/matplotlib/_tight_bbox.py +++ b/lib/matplotlib/_tight_bbox.py @@ -17,8 +17,6 @@ def adjust_bbox(fig, bbox_inches, fixed_dpi=None): """ origBbox = fig.bbox origBboxInches = fig.bbox_inches - orig_layout = fig.get_layout_engine() - fig.set_layout_engine(None) _boxout = fig.transFigure._boxout old_aspect = [] @@ -46,7 +44,6 @@ def restore_bbox(): fig.bbox = origBbox fig.bbox_inches = origBboxInches - fig.set_layout_engine(orig_layout) fig.transFigure._boxout = _boxout fig.transFigure.invalidate() fig.patch.set_bounds(0, 0, 1, 1) diff --git a/lib/matplotlib/_tri.pyi b/lib/matplotlib/_tri.pyi new file mode 100644 index 000000000000..cab7fcf2bc70 --- /dev/null +++ b/lib/matplotlib/_tri.pyi @@ -0,0 +1,23 @@ +# This is a private module implemented in C++ +# As such these type stubs are overly generic, but here to allow these types +# as return types for public methods +from typing import Any + +class TrapezoidMapTriFinder: + def __init__(self, *args, **kwargs) -> None: ... + def find_many(self, *args, **kwargs) -> Any: ... + def get_tree_stats(self, *args, **kwargs) -> Any: ... + def initialize(self, *args, **kwargs) -> Any: ... + def print_tree(self, *args, **kwargs) -> Any: ... + +class TriContourGenerator: + def __init__(self, *args, **kwargs) -> None: ... + def create_contour(self, *args, **kwargs) -> Any: ... + def create_filled_contour(self, *args, **kwargs) -> Any: ... + +class Triangulation: + def __init__(self, *args, **kwargs) -> None: ... + def calculate_plane_coefficients(self, *args, **kwargs) -> Any: ... + def get_edges(self, *args, **kwargs) -> Any: ... + def get_neighbors(self, *args, **kwargs) -> Any: ... + def set_mask(self, *args, **kwargs) -> Any: ... diff --git a/lib/matplotlib/_ttconv.pyi b/lib/matplotlib/_ttconv.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/matplotlib/animation.pyi b/lib/matplotlib/animation.pyi new file mode 100644 index 000000000000..fc9fed105853 --- /dev/null +++ b/lib/matplotlib/animation.pyi @@ -0,0 +1,225 @@ +import abc +from collections.abc import Generator +import contextlib +from pathlib import Path +from matplotlib import cbook +from matplotlib._animation_data import ( + DISPLAY_TEMPLATE, + INCLUDED_FRAMES, + JS_INCLUDE, + STYLE_INCLUDE, +) +from matplotlib.artist import Artist +from matplotlib.backend_bases import TimerBase +from matplotlib.figure import Figure + +from typing import Any, Callable, Iterable, Generator, Type + +subprocess_creation_flags: int + +def adjusted_figsize(w: float, h: float, dpi: float, n: int) -> tuple[float, float]: ... + +class MovieWriterRegistry: + def __init__(self) -> None: ... + def register( + self, name: str + ) -> Callable[[Type[AbstractMovieWriter]], Type[AbstractMovieWriter]]: ... + def is_available(self, name: str) -> bool: ... + def __iter__(self) -> Generator[str, None, None]: ... + def list(self) -> list[str]: ... + def __getitem__(self, name: str) -> Type[AbstractMovieWriter]: ... + +writers: MovieWriterRegistry + +class AbstractMovieWriter(abc.ABC, metaclass=abc.ABCMeta): + fps: int + metadata: dict[str, str] + codec: str + bitrate: int + def __init__( + self, + fps: int = ..., + metadata: dict[str, str] | None = ..., + codec: str | None = ..., + bitrate: int | None = ..., + ) -> None: ... + outfile: str | Path + fig: Figure + dpi: float + + @abc.abstractmethod + def setup(self, fig: Figure, outfile: str | Path, dpi: float | None = ...): ... + @property + def frame_size(self) -> tuple[int, int]: ... + @abc.abstractmethod + def grab_frame(self, **savefig_kwargs) -> None: ... + @abc.abstractmethod + def finish(self) -> None: ... + @contextlib.contextmanager + def saving( + self, fig: Figure, outfile: str | Path, dpi: float | None, *args, **kwargs + ) -> Generator[AbstractMovieWriter, None, None]: ... + +class MovieWriter(AbstractMovieWriter): + supported_formats: list[str] + frame_format: str + extra_args: list[str] | None + def __init__( + self, + fps: int = ..., + codec: str | None = ..., + bitrate: int | None = ..., + extra_args: list[str] | None = ..., + metadata: dict[str, str] | None = ..., + ) -> None: ... + def setup(self, fig: Figure, outfile: str | Path, dpi: float | None = ...): ... + def grab_frame(self, **savefig_kwargs) -> None: ... + def finish(self) -> None: ... + @classmethod + def bin_path(cls) -> str: ... + @classmethod + def isAvailable(cls) -> bool: ... + +class FileMovieWriter(MovieWriter): + fig: Figure + outfile: str | Path + dpi: float + temp_prefix: str + fname_format_str: str + def setup( + self, + fig: Figure, + outfile: str | Path, + dpi: float | None = ..., + frame_prefix: str | Path | None = ..., + ) -> None: ... + def __del__(self) -> None: ... + @property + def frame_format(self) -> str: ... + @frame_format.setter + def frame_format(self, frame_format: str) -> None: ... + +class PillowWriter(AbstractMovieWriter): + @classmethod + def isAvailable(cls) -> bool: ... + def setup( + self, fig: Figure, outfile: str | Path, dpi: float | None = ... + ) -> None: ... + def grab_frame(self, **savefig_kwargs) -> None: ... + def finish(self) -> None: ... + +class FFMpegBase: + codec: str + @property + def output_args(self) -> list[str]: ... + +class FFMpegWriter(FFMpegBase, MovieWriter): ... + +class FFMpegFileWriter(FFMpegBase, FileMovieWriter): + supported_formats: list[str] + +class ImageMagickBase: + @classmethod + def bin_path(cls) -> str: ... + @classmethod + def isAvailable(cls) -> bool: ... + +class ImageMagickWriter(ImageMagickBase, MovieWriter): + input_names: str + +class ImageMagickFileWriter(ImageMagickBase, FileMovieWriter): + supported_formats: list[str] + @property + def input_names(self) -> str: ... + +class HTMLWriter(FileMovieWriter): + supported_formats: list[str] + @classmethod + def isAvailable(cls) -> bool: ... + embed_frames: bool + default_mode: str + def __init__( + self, + fps: int = ..., + codec: str | None = ..., + bitrate: int | None = ..., + extra_args: list[str] | None = ..., + metadata: dict[str, str] | None = ..., + embed_frames: bool = ..., + default_mode: str = ..., + embed_limit: float | None = ..., + ) -> None: ... + def setup( + self, + fig: Figure, + outfile: str | Path, + dpi: float | None = ..., + frame_dir: str | Path | None = ..., + ) -> None: ... + def grab_frame(self, **savefig_kwargs): ... + def finish(self) -> None: ... + +class Animation: + frame_seq: Iterable[Artist] + event_source: Any + def __init__( + self, fig: Figure, event_source: Any | None = ..., blit: bool = ... + ) -> None: ... + def __del__(self) -> None: ... + def save( + self, + filename: str | Path, + writer: MovieWriter | str | None = ..., + fps: int | None = ..., + dpi: float | None = ..., + codec: str | None = ..., + bitrate: int | None = ..., + extra_args: list[str] | None = ..., + metadata: dict[str, str] | None = ..., + extra_anim: list[Animation] | None = ..., + savefig_kwargs: dict[str, Any] | None = ..., + *, + progress_callback: Callable[[int, int], Any] | None = ... + ) -> None: ... + def new_frame_seq(self) -> Iterable[Artist]: ... + def new_saved_frame_seq(self) -> Iterable[Artist]: ... + def to_html5_video(self, embed_limit: float | None = ...) -> str: ... + def to_jshtml( + self, + fps: int | None = ..., + embed_frames: bool = ..., + default_mode: str | None = ..., + ) -> str: ... + def pause(self) -> None: ... + def resume(self) -> None: ... + +class TimedAnimation(Animation): + repeat: bool + def __init__( + self, + fig: Figure, + interval: int = ..., + repeat_delay: int = ..., + repeat: bool = ..., + event_source: TimerBase | None = ..., + *args, + **kwargs + ) -> None: ... + +class ArtistAnimation(TimedAnimation): + def __init__(self, fig: Figure, artists: list[Artist], *args, **kwargs) -> None: ... + +class FuncAnimation(TimedAnimation): + save_count: int + def __init__( + self, + fig: Figure, + func: Callable[..., Iterable[Artist]], + frames: Iterable[Artist] | int | Generator[Artist, None, None] | None = ..., + init_func: Callable[[], Iterable[Artist]] | None = ..., + fargs: tuple[Any, ...] | None = ..., + save_count: int | None = ..., + *, + cache_frame_data: bool = ..., + **kwargs + ) -> None: ... diff --git a/lib/matplotlib/artist.pyi b/lib/matplotlib/artist.pyi new file mode 100644 index 000000000000..0176cca49b9b --- /dev/null +++ b/lib/matplotlib/artist.pyi @@ -0,0 +1,180 @@ +from . import cbook as cbook +from .axes import Axes +from .axes._base import _AxesBase +from .backend_bases import RendererBase, MouseEvent +from .cm import ScalarMappable +from .colors import BoundaryNorm +from .figure import Figure, FigureBase +from .path import Path +from .patches import Patch +from .patheffects import AbstractPathEffect +from .transforms import ( + Bbox, + IdentityTransform, + Transform, + TransformedBbox, + TransformedPatchPath, + TransformedPath, +) + +import numpy as np + +from typing import Any, NamedTuple, Callable, TextIO, Type, TypeVar, overload +from numpy.typing import ArrayLike + +def allow_rasterization(draw): ... + +class _XYPair(NamedTuple): + x: ArrayLike + y: ArrayLike + +class _Unset: ... + +class Artist: + zorder: float + def __init_subclass__(cls): ... + stale_callback: Callable[[Artist, bool], None] | None + figure: FigureBase | None + clipbox: Bbox | None + def __init__(self) -> None: ... + def remove(self) -> None: ... + def have_units(self) -> bool: ... + # TODO units + def convert_xunits(self, x): ... + def convert_yunits(self, y): ... + @property + def axes(self) -> _AxesBase | None: ... + @axes.setter + def axes(self, new_axes: _AxesBase | None) -> None: ... + @property + def stale(self) -> bool: ... + @stale.setter + def stale(self, val: bool) -> None: ... + def get_window_extent(self, renderer: RendererBase | None = ...) -> Bbox: ... + def get_tightbbox(self, renderer: RendererBase | None = ...) -> Bbox | None: ... + def add_callback(self, func: Callable[[Artist], Any]) -> int: ... + def remove_callback(self, oid: int) -> None: ... + def pchanged(self) -> None: ... + def is_transform_set(self) -> bool: ... + def set_transform(self, t: Transform) -> None: ... + def get_transform(self) -> Transform: ... + def get_children(self) -> list[Artist]: ... + # TODO can these dicts be type narrowed? e.g. str keys + def contains(self, mouseevent: MouseEvent) -> tuple[bool, dict[Any, Any]]: ... + def pickable(self) -> bool: ... + def pick(self, mouseevent: MouseEvent) -> None: ... + def set_picker( + self, + picker: None + | bool + | float + | Callable[[Artist, MouseEvent], tuple[bool, dict[Any, Any]]], + ) -> None: ... + def get_picker( + self, + ) -> None | bool | float | Callable[ + [Artist, MouseEvent], tuple[bool, dict[Any, Any]] + ]: ... + def get_url(self) -> str | None: ... + def set_url(self, url: str | None) -> None: ... + def get_gid(self) -> str | None: ... + def set_gid(self, gid: str | None) -> None: ... + def get_snap(self) -> bool | None: ... + def set_snap(self, snap: bool | None) -> None: ... + def get_sketch_params(self) -> tuple[float, float, float] | None: ... + def set_sketch_params( + self, + scale: float | None = ..., + length: float | None = ..., + randomness: float | None = ..., + ) -> None: ... + def set_path_effects(self, path_effects: AbstractPathEffect) -> None: ... + def get_path_effects(self) -> AbstractPathEffect: ... + def get_figure(self) -> Figure | None: ... + def set_figure(self, fig: Figure) -> None: ... + def set_clip_box(self, clipbox: Bbox) -> None: ... + def set_clip_path( + self, + path: Patch | Path | TransformedPath | TransformedPatchPath | None, + transform: Transform | None = ..., + ) -> None: ... + def get_alpha(self) -> float | None: ... + def get_visible(self) -> bool: ... + def get_animated(self) -> bool: ... + def get_in_layout(self) -> bool: ... + def get_clip_on(self) -> bool: ... + def get_clip_box(self) -> Bbox | None: ... + def get_clip_path( + self, + ) -> Patch | Path | TransformedPath | TransformedPatchPath | None: ... + def get_transformed_clip_path_and_affine( + self, + ) -> tuple[None, None] | tuple[Path, Transform]: ... + def set_clip_on(self, b: bool) -> None: ... + def get_rasterized(self) -> bool: ... + def set_rasterized(self, rasterized: bool) -> None: ... + def get_agg_filter(self): ... + def set_agg_filter( + self, filter_func: Callable[[ArrayLike, float], tuple[np.ndarray, float, float]] + ) -> None: ... + def draw(self, renderer: RendererBase) -> None: ... + def set_alpha(self, alpha: float | None) -> None: ... + def set_visible(self, b: bool) -> None: ... + def set_animated(self, b: bool) -> None: ... + def set_in_layout(self, in_layout: bool) -> None: ... + def get_label(self) -> object: ... + def set_label(self, s: object) -> None: ... + def get_zorder(self) -> float: ... + def set_zorder(self, level: float) -> None: ... + @property + def sticky_edges(self) -> ArrayLike: ... + def update_from(self, other: Artist) -> None: ... + def properties(self) -> dict[str, Any]: ... + def update(self, props: dict[str, Any]) -> Any: ... + def _internal_update(self, kwargs): ... + def set(self, **kwargs: Any): ... + def findobj( + self, + match: None | Callable[[Artist], bool] | Type[Artist] = ..., + include_self: bool = ..., + ) -> list[Artist]: ... + def get_cursor_data(self, event: MouseEvent) -> Any: ... + def format_cursor_data(self, data: Any) -> str: ... + def get_mouseover(self) -> bool: ... + def set_mouseover(self, mouseover: bool) -> None: ... + +class ArtistInspector: + oorig: Artist | Type[Artist] + o: Type[Artist] + aliasd: dict[str, set[str]] + def __init__(self, o) -> None: ... + def get_aliases(self) -> dict[str, set[str]]: ... + def get_valid_values(self, attr: str) -> str | None: ... + def get_setters(self) -> list[str]: ... + @staticmethod + def number_of_parameters(func: Callable) -> int: ... + @staticmethod + def is_alias(method: Callable) -> bool: ... + def aliased_name(self, s: str) -> str: ... + def aliased_name_rest(self, s: str, target: str) -> str: ... + @overload + def pprint_setters( + self, prop: None = ..., leadingspace: int = ... + ) -> list[str]: ... + @overload + def pprint_setters(self, prop: str, leadingspace: int = ...) -> str: ... + @overload + def pprint_setters_rest( + self, prop: None = ..., leadingspace: int = ... + ) -> list[str]: ... + @overload + def pprint_setters_rest(self, prop: str, leadingspace: int = ...) -> str: ... + def properties(self) -> dict[str, Any]: ... + def pprint_getters(self) -> list[str]: ... + +def getp(obj: Artist, property: str | None = ...) -> Any: ... + +get = getp + +def setp(obj: Artist, *args, file: TextIO | None = ..., **kwargs): ... +def kwdoc(artist: Artist) -> str: ... diff --git a/lib/matplotlib/axes/__init__.pyi b/lib/matplotlib/axes/__init__.pyi new file mode 100644 index 000000000000..0b10c3b0f648 --- /dev/null +++ b/lib/matplotlib/axes/__init__.pyi @@ -0,0 +1,10 @@ +from ._axes import * + +from ._axes import Axes as Subplot + +class _SubplotBaseMeta(type): + def __instancecheck__(self, obj) -> bool: ... + +class SubplotBase(metaclass=_SubplotBaseMeta): ... + +def subplot_class_factory(cls): ... diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index a6fecd374fba..a3ec2914a777 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -5792,18 +5792,6 @@ def _interp_grid(X): C = cbook.safe_masked_invalid(C) return X, Y, C, shading - def _pcolor_grid_deprecation_helper(self): - grid_active = any(axis._major_tick_kw["gridOn"] - for axis in self._axis_map.values()) - # explicit is-True check because get_axisbelow() can also be 'line' - grid_hidden_by_pcolor = self.get_axisbelow() is True - if grid_active and not grid_hidden_by_pcolor: - _api.warn_deprecated( - "3.5", message="Auto-removal of grids by pcolor() and " - "pcolormesh() is deprecated since %(since)s and will be " - "removed %(removal)s; please call grid(False) first.") - self.grid(False) - @_preprocess_data() @_docstring.dedent_interpd def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, @@ -6008,7 +5996,6 @@ def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, collection = mcoll.PolyCollection( verts, array=C, cmap=cmap, norm=norm, alpha=alpha, **kwargs) collection._scale_norm(norm, vmin, vmax) - self._pcolor_grid_deprecation_helper() x = X.compressed() y = Y.compressed() @@ -6242,7 +6229,6 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None, coords, antialiased=antialiased, shading=shading, array=C, cmap=cmap, norm=norm, alpha=alpha, **kwargs) collection._scale_norm(norm, vmin, vmax) - self._pcolor_grid_deprecation_helper() coords = coords.reshape(-1, 2) # flatten the grid structure; keep x, y diff --git a/lib/matplotlib/axes/_axes.pyi b/lib/matplotlib/axes/_axes.pyi new file mode 100644 index 000000000000..d75f40903115 --- /dev/null +++ b/lib/matplotlib/axes/_axes.pyi @@ -0,0 +1,701 @@ +from matplotlib.axes._base import _AxesBase +from matplotlib.axes._secondary_axes import SecondaryAxis + +from matplotlib.artist import Artist +from matplotlib.backend_bases import RendererBase +from matplotlib.collections import ( + Collection, + LineCollection, + BrokenBarHCollection, + PathCollection, + PolyCollection, + EventCollection, + QuadMesh, +) +from matplotlib.colors import Color, Colormap, Normalize +from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer +from matplotlib.contour import ContourSet, QuadContourSet +from matplotlib.image import AxesImage, PcolorImage +from matplotlib.legend import Legend +from matplotlib.legend_handler import HandlerBase +from matplotlib.lines import Line2D, LineStyleType +from matplotlib.markers import MarkerType +from matplotlib.mlab import GaussianKDE +from matplotlib.patches import Rectangle, FancyArrow, Polygon, StepPatch +from matplotlib.quiver import Quiver, QuiverKey, Barbs +from matplotlib.text import Annotation, Text +from matplotlib.transforms import Transform, Bbox +import matplotlib.tri as mtri +import matplotlib.table as mtable +import matplotlib.stackplot as mstack +import matplotlib.streamplot as mstream + +import datetime +import PIL +from typing import Any, Callable, Literal, Sequence, Type, overload +import numpy as np +from numpy.typing import ArrayLike + +class Axes(_AxesBase): + def get_title(self, loc: Literal["left", "center", "right"] = ...) -> str: ... + def set_title( + self, + label: str, + fontdict: dict[str, Any] | None = ..., + loc: Literal["left", "center", "right"] | None = ..., + pad: float | None = ..., + *, + y: float | None = ..., + **kwargs + ) -> Text: ... + def get_legend_handles_labels( + self, legend_handler_map: dict[Type, HandlerBase] | None = ... + ) -> tuple[list[Artist], list[Any]]: ... + legend_: Legend + + @overload + def legend(self) -> Legend: ... + @overload + def legend(self, handles: Sequence[Artist], labels: Sequence[str]) -> Legend: ... + @overload + def legend(self, *, handles: Sequence[Artist]) -> Legend: ... + @overload + def legend(self, labels: Sequence[str]) -> Legend: ... + + def inset_axes( + self, + bounds: tuple[float, float, float, float], + *, + transform: Transform | None = ..., + zorder: float = ..., + **kwargs + ) -> Axes: ... + def indicate_inset( + self, + bounds: tuple[float, float, float, float], + inset_ax: Axes | None = ..., + *, + transform: Transform | None = ..., + facecolor: Color = ..., + edgecolor: Color = ..., + alpha: float = ..., + zorder: float = ..., + **kwargs + ) -> Rectangle: ... + def indicate_inset_zoom(self, inset_ax: Axes, **kwargs) -> Rectangle: ... + def secondary_xaxis( + self, + location: Literal["top", "bottom"] | float, + *, + functions: tuple[ + Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike] + ] + | Transform + | None = ..., + **kwargs + ) -> SecondaryAxis: ... + def secondary_yaxis( + self, + location: Literal["left", "right"] | float, + *, + functions: tuple[ + Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike] + ] + | Transform + | None = ..., + **kwargs + ) -> SecondaryAxis: ... + def text( + self, + x: float, + y: float, + s: str, + fontdict: dict[str, Any] | None = ..., + **kwargs + ) -> Text: ... + def annotate( + self, + text: str, + xy: tuple[float, float], + xytext: tuple[float, float] | None = ..., + xycoords: str + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | tuple[float, float] = ..., + textcoords: str + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | tuple[float, float] + | None = ..., + arrowprops: dict[str, Any] | None = ..., + annotation_clip: bool | None = ..., + **kwargs + ) -> Annotation: ... + def axhline( + self, y: float = ..., xmin: float = ..., xmax: float = ..., **kwargs + ) -> Line2D: ... + def axvline( + self, x: float = ..., ymin: float = ..., ymax: float = ..., **kwargs + ) -> Line2D: ... + + # TODO: Could separate the xy2 and slope signatures + def axline( + self, + xy1: tuple[float, float], + xy2: tuple[float, float] | None = ..., + *, + slope: float | None = ..., + **kwargs + ) -> Line2D: ... + def axhspan( + self, ymin: float, ymax: float, xmin: float = ..., xmax: float = ..., **kwargs + ) -> Polygon: ... + def axvspan( + self, xmin: float, xmax: float, ymin: float = ..., ymax: float = ..., **kwargs + ) -> Polygon: ... + def hlines( + self, + y: float | ArrayLike, + xmin: float | ArrayLike, + xmax: float | ArrayLike, + colors: Sequence[Color] | None = ..., + linestyles: LineStyleType = ..., + label: str = ..., + **kwargs + ) -> LineCollection: ... + def vlines( + self, + x: float | ArrayLike, + ymin: float | ArrayLike, + ymax: float | ArrayLike, + colors: Sequence[Color] | None = ..., + linestyles: LineStyleType = ..., + label: str = ..., + **kwargs + ) -> LineCollection: ... + def eventplot( + self, + positions: ArrayLike | Sequence[ArrayLike], + orientation: Literal["horizontal", "vertical"] = ..., + lineoffsets: float | Sequence[float] = ..., + linelengths: float | Sequence[float] = ..., + linewidths: float | Sequence[float] | None = ..., + colors: Color | Sequence[Color] | None = ..., + alpha: float | Sequence[float] | None = ..., + linestyles: LineStyleType | Sequence[LineStyleType] = ..., + **kwargs + ) -> EventCollection: ... + def plot( + self, + *args: float | ArrayLike | str, + scalex: bool = ..., + scaley: bool = ..., + data: Any | None = ..., + **kwargs + ) -> list[Line2D]: ... + def plot_date( + self, + x: ArrayLike, + y: ArrayLike, + fmt: str = ..., + tz: str | datetime.tzinfo | None = ..., + xdate: bool = ..., + ydate: bool = ..., + **kwargs + ) -> list[Line2D]: ... + def loglog(self, *args, **kwargs) -> list[Line2D]: ... + def semilogx(self, *args, **kwargs) -> list[Line2D]: ... + def semilogy(self, *args, **kwargs) -> list[Line2D]: ... + def acorr( + self, x: ArrayLike, **kwargs + ) -> tuple[np.ndarray, np.ndarray, LineCollection | Line2D, Line2D | None]: ... + def xcorr( + self, + x: ArrayLike, + y: ArrayLike, + normed: bool = ..., + detrend: Callable[[ArrayLike], ArrayLike] = ..., + usevlines: bool = ..., + maxlags: int = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray, LineCollection | Line2D, Line2D | None]: ... + def step( + self, + x: ArrayLike, + y: ArrayLike, + *args, + where: Literal["pre", "post", "mid"] = ..., + data: Any | None = ..., + **kwargs + ) -> list[Line2D]: ... + def bar( + self, + x: float | ArrayLike, + height: float | ArrayLike, + width: float | ArrayLike = ..., + bottom: float | ArrayLike | None = ..., + *, + align: Literal["center", "edge"] = ..., + **kwargs + ) -> BarContainer: ... + def barh( + self, + y: float | ArrayLike, + width: float | ArrayLike, + height: float | ArrayLike = ..., + left: float | ArrayLike | None = ..., + *, + align: Literal["center", "edge"] = ..., + data: Any | None = ..., + **kwargs + ) -> BarContainer: ... + def bar_label( + self, + container: BarContainer, + labels: ArrayLike | None = ..., + *, + fmt: str | Callable[[float], str] = ..., + label_type: Literal["center", "edge"] = ..., + padding: float = ..., + **kwargs + ) -> list[Text]: ... + def broken_barh( + self, + xranges: Sequence[tuple[float, float]], + yrange: tuple[float, float], + **kwargs + ) -> BrokenBarHCollection: ... + def stem( + self, + *args: ArrayLike | str, + linefmt: str | None = ..., + markerfmt: str | None = ..., + basefmt: str | None = ..., + bottom: float = ..., + label: str | None = ..., + use_line_collection: Any = ..., + orientation: Literal["vertical", "horizontal"] = ... + ) -> StemContainer: ... + + # TODO: data kwarg preprocessor? + def pie( + self, + x: ArrayLike, + explode: ArrayLike | None = ..., + labels: Sequence[str] | None = ..., + colors: Sequence[Color] | None = ..., + autopct: str | Callable[[float], str] | None = ..., + pctdistance: float = ..., + shadow: bool = ..., + labeldistance: float = ..., + startangle: float = ..., + radius: float = ..., + counterclock: bool = ..., + wedgeprops: dict[str, Any] | None = ..., + textprops: dict[str, Any] | None = ..., + center: tuple[float, float] = ..., + frame: bool = ..., + rotatelabels: bool = ..., + *, + normalize: bool = ..., + hatch: str | Sequence[str] | None = ... + ): ... + def errorbar( + self, + x: float | ArrayLike, + y: float | ArrayLike, + yerr: float | ArrayLike | None = ..., + xerr: float | ArrayLike | None = ..., + fmt: str = ..., + ecolor: Color | None = ..., + elinewidth: float | None = ..., + capsize: float | None = ..., + barsabove: bool = ..., + lolims: bool = ..., + uplims: bool = ..., + xlolims: bool = ..., + xuplims: bool = ..., + errorevery: int | tuple[int, int] = ..., + capthick: float | None = ..., + **kwargs + ) -> ErrorbarContainer: ... + def boxplot( + self, + x: ArrayLike | Sequence[ArrayLike], + notch: bool | None = ..., + sym: str | None = ..., + vert: bool | None = ..., + whis: float | tuple[float, float] | None = ..., + positions: ArrayLike | None = ..., + widths: float | ArrayLike | None = ..., + patch_artist: bool | None = ..., + bootstrap: int | None = ..., + usermedians: ArrayLike | None = ..., + conf_intervals: ArrayLike | None = ..., + meanline: bool | None = ..., + showmeans: bool | None = ..., + showcaps: bool | None = ..., + showbox: bool | None = ..., + showfliers: bool | None = ..., + boxprops: dict[str, Any] | None = ..., + labels: Sequence[str] | None = ..., + flierprops: dict[str, Any] | None = ..., + medianprops: dict[str, Any] | None = ..., + meanprops: dict[str, Any] | None = ..., + capprops: dict[str, Any] | None = ..., + whiskerprops: dict[str, Any] | None = ..., + manage_ticks: bool = ..., + autorange: bool = ..., + zorder: float | None = ..., + capwidths: float | ArrayLike | None = ..., + ) -> dict[str, Any]: ... + def bxp( + self, + bxpstats: Sequence[dict[str, Any]], + positions: ArrayLike | None = ..., + widths: float | ArrayLike | None = ..., + vert: bool = ..., + patch_artist: bool = ..., + shownotches: bool = ..., + showmeans: bool = ..., + showcaps: bool = ..., + showbox: bool = ..., + showfliers: bool = ..., + boxprops: dict[str, Any] | None = ..., + whiskerprops: dict[str, Any] | None = ..., + flierprops: dict[str, Any] | None = ..., + medianprops: dict[str, Any] | None = ..., + capprops: dict[str, Any] | None = ..., + meanprops: dict[str, Any] | None = ..., + meanline: bool = ..., + manage_ticks: bool = ..., + zorder: float | None = ..., + capwidths: float | ArrayLike | None = ..., + ) -> dict[str, Any]: ... + def scatter( + self, + x: float | ArrayLike, + y: float | ArrayLike, + s: float | ArrayLike | None = ..., + c: Sequence[Color] | Color | None = ..., + marker: MarkerType | None = ..., + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + alpha: float | None = ..., + linewidths: float | Sequence[float] | None = ..., + *, + edgecolors: Literal["face", "none"] | Color | Sequence[Color] | None = ..., + plotnonfinite: bool = ..., + **kwargs + ) -> PathCollection: ... + def hexbin( + self, + x: ArrayLike, + y: ArrayLike, + C: ArrayLike | None = ..., + gridsize: int | tuple[int, int] = ..., + bins: Literal["log"] | int | Sequence[float] | None = ..., + xscale: Literal["linear", "log"] = ..., + yscale: Literal["linear", "log"] = ..., + extent: tuple[float, float, float, float] | None = ..., + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + alpha: float | None = ..., + linewidths: float | None = ..., + edgecolors: Literal["face", "none"] | Color = ..., + reduce_C_function: Callable[[np.ndarray], float] = ..., + mincnt: int | None = ..., + marginals: bool = ..., + **kwargs + ) -> PolyCollection: ... + def arrow( + self, x: float, y: float, dx: float, dy: float, **kwargs + ) -> FancyArrow: ... + def quiverkey( + self, Q: Quiver, X: float, Y: float, U: float, label: str, **kwargs + ) -> QuiverKey: ... + def quiver(self, *args, **kwargs) -> Quiver: ... + def barbs(self, *args, **kwargs) -> Barbs: ... + def fill(self, *args, data: Any | None = ..., **kwargs) -> list[Polygon]: ... + def fill_between( + self, + x: ArrayLike, + y1: ArrayLike | float, + y2: ArrayLike | float = ..., + where: Sequence[bool] | None = ..., + interpolate: bool = ..., + step: Literal["pre", "post", "mid"] | None = ..., + **kwargs + ) -> PolyCollection: ... + def fill_betweenx( + self, + y: ArrayLike, + x1: ArrayLike | float, + x2: ArrayLike | float = ..., + where: Sequence[bool] | None = ..., + step: Literal["pre", "post", "mid"] | None = ..., + interpolate: bool = ..., + **kwargs + ) -> PolyCollection: ... + def imshow( + self, + X: ArrayLike | PIL.Image.Image, + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + *, + aspect: Literal["equal", "auto"] | float | None = ..., + interpolation: str | None = ..., + alpha: float | ArrayLike | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + origin: Literal["upper", "lower"] | None = ..., + extent: tuple[float, float, float, float] | None = ..., + interpolation_stage: Literal["data", "rgba"] | None = ..., + filternorm: bool = ..., + filterrad: float = ..., + resample: bool | None = ..., + url: str | None = ..., + **kwargs + ) -> AxesImage: ... + def pcolor( + self, + *args: ArrayLike, + shading: Literal["flat", "nearest", "auto"] | None = ..., + alpha: float | None = ..., + norm: str | Normalize | None = ..., + cmap: str | Colormap | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + **kwargs + ) -> Collection: ... + def pcolormesh( + self, + *args: ArrayLike, + alpha: float | None = ..., + norm: str | Normalize | None = ..., + cmap: str | Colormap | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + shading: Literal["flat", "nearest", "gouraud", "auto"] | None = ..., + antialiased: bool = ..., + **kwargs + ) -> QuadMesh: ... + def pcolorfast( + self, + *args: ArrayLike | tuple[float, float], + alpha: float | None = ..., + norm: str | Normalize | None = ..., + cmap: str | Colormap | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + **kwargs + ) -> AxesImage | PcolorImage | QuadMesh: ... + def contour(self, *args, **kwargs) -> QuadContourSet: ... + def contourf(self, *args, **kwargs) -> QuadContourSet: ... + def clabel( + self, CS: ContourSet, levels: ArrayLike | None = ..., **kwargs + ) -> list[Text]: ... + def hist( + self, + x: ArrayLike | Sequence[ArrayLike], + bins: int | Sequence[float] | str | None = ..., + range: tuple[float, float] | None = ..., + density: bool = ..., + weights: ArrayLike | None = ..., + cumulative: bool | float = ..., + bottom: ArrayLike | float | None = ..., + histtype: Literal["bar", "barstacked", "step", "stepfilled"] = ..., + align: Literal["left", "mid", "right"] = ..., + orientation: Literal["vertical", "horizontal"] = ..., + rwidth: float | None = ..., + log: bool = ..., + color: Color | Sequence[Color] | None = ..., + label: str | Sequence[str] | None = ..., + stacked: bool = ..., + **kwargs + ) -> tuple[ + np.ndarray | list[np.ndarray], + np.ndarray, + BarContainer | Polygon | list[BarContainer | Polygon], + ]: ... + def stairs( + self, + values: ArrayLike, + edges: ArrayLike | None = ..., + *, + orientation: Literal["vertical", "horizontal"] = ..., + baseline: float | ArrayLike = ..., + fill: bool = ..., + **kwargs + ) -> StepPatch: ... + def hist2d( + self, + x: ArrayLike, + y: ArrayLike, + bins: None + | int + | tuple[int, int] + | ArrayLike + | tuple[ArrayLike, ArrayLike] = ..., + range: ArrayLike | None = ..., + density: bool = ..., + weights: ArrayLike | None = ..., + cmin: float | None = ..., + cmax: float | None = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray, np.ndarray, QuadMesh]: ... + def psd( + self, + x: ArrayLike, + NFFT: int | None = ..., + Fs: float | None = ..., + Fc: int | None = ..., + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike], ArrayLike] + | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + noverlap: int | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + scale_by_freq: bool | None = ..., + return_line: bool | None = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray] | tuple[np.ndarray, np.ndarray, Line2D]: ... + def csd( + self, + x: ArrayLike, + y: ArrayLike, + NFFT: int | None = ..., + Fs: float | None = ..., + Fc: int | None = ..., + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike], ArrayLike] + | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + noverlap: int | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + scale_by_freq: bool | None = ..., + return_line: bool | None = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray] | tuple[np.ndarray, np.ndarray, Line2D]: ... + def magnitude_spectrum( + self, + x: ArrayLike, + Fs: float | None = ..., + Fc: int | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + scale: Literal["default", "linear", "dB"] | None = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray, Line2D]: ... + def angle_spectrum( + self, + x: ArrayLike, + Fs: float | None = ..., + Fc: int | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray, Line2D]: ... + def phase_spectrum( + self, + x: ArrayLike, + Fs: float | None = ..., + Fc: int | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray, Line2D]: ... + def cohere( + self, + x: ArrayLike, + y: ArrayLike, + NFFT: int = ..., + Fs: float = ..., + Fc: int = ..., + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike], ArrayLike] = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike = ..., + noverlap: int = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] = ..., + scale_by_freq: bool | None = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray]: ... + def specgram( + self, + x: ArrayLike, + NFFT: int | None = ..., + Fs: float | None = ..., + Fc: int | None = ..., + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike], ArrayLike] + | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + noverlap: int | None = ..., + cmap: str | Colormap | None = ..., + xextent: tuple[float, float] | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + scale_by_freq: bool | None = ..., + mode: Literal["default", "psd", "magnitude", "angle", "phase"] | None = ..., + scale: Literal["default", "linear", "dB"] | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + **kwargs + ) -> tuple[np.ndarray, np.ndarray, np.ndarray, AxesImage]: ... + def spy( + self, + Z: ArrayLike, + precision: float | Literal["present"] = ..., + marker: str | None = ..., + markersize: float | None = ..., + aspect: Literal["equal", "auto"] | float | None = ..., + origin: Literal["upper", "lower"] = ..., + **kwargs + ) -> AxesImage: ... + def matshow(self, Z: ArrayLike, **kwargs) -> AxesImage: ... + def violinplot( + self, + dataset: ArrayLike | Sequence[ArrayLike], + positions: ArrayLike | None = ..., + vert: bool = ..., + widths: float | ArrayLike = ..., + showmeans: bool = ..., + showextrema: bool = ..., + showmedians: bool = ..., + quantiles: Sequence[float] | None = ..., + points: int = ..., + bw_method: Literal["scott", "silverman"] + | float + | Callable[[GaussianKDE], float] + | None = ..., + ) -> dict[str, Collection]: ... + def violin( + self, + vpstats: Sequence[dict[str, Any]], + positions: ArrayLike | None = ..., + vert: bool = ..., + widths: float | ArrayLike = ..., + showmeans: bool = ..., + showextrema: bool = ..., + showmedians: bool = ..., + ) -> dict[str, Collection]: ... + + table = mtable.table + stackplot = mstack.stackplot + streamplot = mstream.streamplot + tricontour = mtri.tricontour + tricontourf = mtri.tricontourf + tripcolor = mtri.tripcolor + triplot = mtri.triplot diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 53f5607f41d1..d10b4e020056 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1,4 +1,4 @@ -from collections.abc import Iterable, MutableSequence +from collections.abc import Iterable, Sequence from contextlib import ExitStack import functools import inspect @@ -1403,18 +1403,15 @@ def cla(self): else: self.clear() - class ArtistList(MutableSequence): + class ArtistList(Sequence): """ A sublist of Axes children based on their type. - The type-specific children sublists will become immutable in - Matplotlib 3.7. Then, these artist lists will likely be replaced by - tuples. Use as if this is a tuple already. - - This class exists only for the transition period to warn on the - deprecated modification of artist lists. + The type-specific children sublists were made immutable in Matplotlib + 3.7. In the future these artist lists may be replaced by tuples. Use + as if this is a tuple already. """ - def __init__(self, axes, prop_name, add_name, + def __init__(self, axes, prop_name, valid_types=None, invalid_types=None): """ Parameters @@ -1425,9 +1422,6 @@ def __init__(self, axes, prop_name, add_name, prop_name : str The property name used to access this sublist from the Axes; used to generate deprecation warnings. - add_name : str - The method name used to add Artists of this sublist's type to - the Axes; used to generate deprecation warnings. valid_types : list of type, optional A list of types that determine which children will be returned by this sublist. If specified, then the Artists in the sublist @@ -1442,7 +1436,6 @@ def __init__(self, axes, prop_name, add_name, """ self._axes = axes self._prop_name = prop_name - self._add_name = add_name self._type_check = lambda artist: ( (not valid_types or isinstance(artist, valid_types)) and (not invalid_types or not isinstance(artist, invalid_types)) @@ -1468,103 +1461,47 @@ def __getitem__(self, key): def __add__(self, other): if isinstance(other, (list, _AxesBase.ArtistList)): return [*self, *other] + if isinstance(other, (tuple, _AxesBase.ArtistList)): + return (*self, *other) return NotImplemented def __radd__(self, other): if isinstance(other, list): return other + list(self) + if isinstance(other, tuple): + return other + tuple(self) return NotImplemented - def insert(self, index, item): - _api.warn_deprecated( - '3.5', - name=f'modification of the Axes.{self._prop_name}', - obj_type='property', - alternative=f'Axes.{self._add_name}') - try: - index = self._axes._children.index(self[index]) - except IndexError: - index = None - getattr(self._axes, self._add_name)(item) - if index is not None: - # Move new item to the specified index, if there's something to - # put it before. - self._axes._children[index:index] = self._axes._children[-1:] - del self._axes._children[-1] - - def __setitem__(self, key, item): - _api.warn_deprecated( - '3.5', - name=f'modification of the Axes.{self._prop_name}', - obj_type='property', - alternative=f'Artist.remove() and Axes.f{self._add_name}') - del self[key] - if isinstance(key, slice): - key = key.start - if not np.iterable(item): - self.insert(key, item) - return - - try: - index = self._axes._children.index(self[key]) - except IndexError: - index = None - for i, artist in enumerate(item): - getattr(self._axes, self._add_name)(artist) - if index is not None: - # Move new items to the specified index, if there's something - # to put it before. - i = -(i + 1) - self._axes._children[index:index] = self._axes._children[i:] - del self._axes._children[i:] - - def __delitem__(self, key): - _api.warn_deprecated( - '3.5', - name=f'modification of the Axes.{self._prop_name}', - obj_type='property', - alternative='Artist.remove()') - if isinstance(key, slice): - for artist in self[key]: - artist.remove() - else: - self[key].remove() - @property def artists(self): - return self.ArtistList(self, 'artists', 'add_artist', invalid_types=( + return self.ArtistList(self, 'artists', invalid_types=( mcoll.Collection, mimage.AxesImage, mlines.Line2D, mpatches.Patch, mtable.Table, mtext.Text)) @property def collections(self): - return self.ArtistList(self, 'collections', 'add_collection', + return self.ArtistList(self, 'collections', valid_types=mcoll.Collection) @property def images(self): - return self.ArtistList(self, 'images', 'add_image', - valid_types=mimage.AxesImage) + return self.ArtistList(self, 'images', valid_types=mimage.AxesImage) @property def lines(self): - return self.ArtistList(self, 'lines', 'add_line', - valid_types=mlines.Line2D) + return self.ArtistList(self, 'lines', valid_types=mlines.Line2D) @property def patches(self): - return self.ArtistList(self, 'patches', 'add_patch', - valid_types=mpatches.Patch) + return self.ArtistList(self, 'patches', valid_types=mpatches.Patch) @property def tables(self): - return self.ArtistList(self, 'tables', 'add_table', - valid_types=mtable.Table) + return self.ArtistList(self, 'tables', valid_types=mtable.Table) @property def texts(self): - return self.ArtistList(self, 'texts', 'add_artist', - valid_types=mtext.Text) + return self.ArtistList(self, 'texts', valid_types=mtext.Text) def get_facecolor(self): """Get the facecolor of the Axes.""" @@ -2266,20 +2203,6 @@ def has_data(self): mlines.Line2D, mpatches.Patch)) for a in self._children) - def _deprecate_noninstance(self, _name, _types, **kwargs): - """ - For each *key, value* pair in *kwargs*, check that *value* is an - instance of one of *_types*; if not, raise an appropriate deprecation. - """ - for key, value in kwargs.items(): - if not isinstance(value, _types): - _api.warn_deprecated( - '3.5', name=_name, - message=f'Passing argument *{key}* of unexpected type ' - f'{type(value).__qualname__} to %(name)s which only ' - f'accepts {_types} is deprecated since %(since)s and will ' - 'become an error %(removal)s.') - def add_artist(self, a): """ Add an `.Artist` to the Axes; return the artist. @@ -2323,8 +2246,7 @@ def add_collection(self, collection, autolim=True): """ Add a `.Collection` to the Axes; return the collection. """ - self._deprecate_noninstance('add_collection', mcoll.Collection, - collection=collection) + _api.check_isinstance(mcoll.Collection, collection=collection) label = collection.get_label() if not label: collection.set_label(f'_child{len(self._children)}') @@ -2357,7 +2279,7 @@ def add_image(self, image): """ Add an `.AxesImage` to the Axes; return the image. """ - self._deprecate_noninstance('add_image', mimage.AxesImage, image=image) + _api.check_isinstance(mimage.AxesImage, image=image) self._set_artist_props(image) if not image.get_label(): image.set_label(f'_child{len(self._children)}') @@ -2374,7 +2296,7 @@ def add_line(self, line): """ Add a `.Line2D` to the Axes; return the line. """ - self._deprecate_noninstance('add_line', mlines.Line2D, line=line) + _api.check_isinstance(mlines.Line2D, line=line) self._set_artist_props(line) if line.get_clip_path() is None: line.set_clip_path(self.patch) @@ -2391,7 +2313,7 @@ def _add_text(self, txt): """ Add a `.Text` to the Axes; return the text. """ - self._deprecate_noninstance('_add_text', mtext.Text, txt=txt) + _api.check_isinstance(mtext.Text, txt=txt) self._set_artist_props(txt) self._children.append(txt) txt._remove_method = self._children.remove @@ -2450,7 +2372,7 @@ def add_patch(self, p): """ Add a `.Patch` to the Axes; return the patch. """ - self._deprecate_noninstance('add_patch', mpatches.Patch, p=p) + _api.check_isinstance(mpatches.Patch, p=p) self._set_artist_props(p) if p.get_clip_path() is None: p.set_clip_path(self.patch) @@ -2503,7 +2425,7 @@ def add_table(self, tab): """ Add a `.Table` to the Axes; return the table. """ - self._deprecate_noninstance('add_table', mtable.Table, tab=tab) + _api.check_isinstance(mtable.Table, tab=tab) self._set_artist_props(tab) self._children.append(tab) tab.set_clip_path(self.patch) diff --git a/lib/matplotlib/axes/_base.pyi b/lib/matplotlib/axes/_base.pyi new file mode 100644 index 000000000000..8f9509f219b2 --- /dev/null +++ b/lib/matplotlib/axes/_base.pyi @@ -0,0 +1,443 @@ +import matplotlib.artist as martist + +import datetime +from collections.abc import MutableSequence +from matplotlib import cbook, offsetbox +from matplotlib.artist import Artist +from matplotlib.axis import XAxis, YAxis, Tick +from matplotlib.backend_bases import RendererBase, MouseButton, MouseEvent +from matplotlib.cbook import index_of +from matplotlib.container import Container +from matplotlib.collections import Collection +from matplotlib.colors import Color +from matplotlib.cm import ScalarMappable +from matplotlib.legend import Legend +from matplotlib.lines import Line2D +from matplotlib.gridspec import SubplotSpec, GridSpec +from matplotlib.figure import Figure +from matplotlib.image import AxesImage +from matplotlib.patches import Patch +from matplotlib.scale import ScaleBase +from matplotlib.spines import Spines +from matplotlib.table import Table +from matplotlib.text import Text +from matplotlib.rcsetup import cycler, validate_axisbelow +from matplotlib.transforms import Transform, BboxBase, Bbox + +from cycler import Cycler + +import numpy as np +from numpy.typing import ArrayLike +from typing import Any, Callable, Literal, Iterable, Iterator, Sequence, Type, overload + +class _axis_method_wrapper: + attr_name: str + method_name: str + __doc__: str + def __init__( + self, attr_name: str, method_name: str, *, doc_sub: dict[str, str] | None = ... + ) -> None: ... + def __set_name__(self, owner: Any, name: str) -> None: ... + +class _AxesBase(martist.Artist): + name: str + spines: Spines + fmt_xdata: Callable[[float], str] | None + fmt_ydata: Callable[[float], str] | None + xaxis: XAxis + yaxis: YAxis + bbox: Bbox + dataLim: Bbox + transScale: Transform + ignore_existing_data_limits: bool + axison: bool + _projection_init: Any + + def __init__( + self, + fig: Figure, + *args: tuple[float, float, float, float] | Bbox | int, + facecolor: Color | None = ..., + frameon: bool = ..., + sharex: _AxesBase | None = ..., + sharey: _AxesBase | None = ..., + label: Any = ..., + xscale: str | ScaleBase | None = ..., + yscale: str | ScaleBase | None = ..., + box_aspect: float | None = ..., + **kwargs + ) -> None: ... + def get_subplotspec(self) -> SubplotSpec | None: ... + def set_subplotspec(self, subplotspec: SubplotSpec) -> None: ... + def get_gridspec(self) -> GridSpec | None: ... + def set_figure(self, fig: Figure) -> None: ... + @property + def viewLim(self) -> Bbox: ... + def get_xaxis_transform( + self, which: Literal["grid", "tick1", "tick2"] = ... + ) -> Transform: ... + def get_xaxis_text1_transform( + self, pad_points: float + ) -> tuple[ + Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_xaxis_text2_transform( + self, pad_points + ) -> tuple[ + Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_yaxis_transform( + self, which: Literal["grid", "tick1", "tick2"] = ... + ) -> Transform: ... + def get_yaxis_text1_transform( + self, pad_points + ) -> tuple[ + Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_yaxis_text2_transform( + self, pad_points + ) -> tuple[ + Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_position(self, original: bool = ...) -> Bbox: ... + def set_position( + self, + pos: Bbox | tuple[float, float, float, float], + which: Literal["both", "active", "original"] = ..., + ) -> None: ... + def reset_position(self) -> None: ... + def set_axes_locator( + self, locator: Callable[[_AxesBase, RendererBase], Bbox] + ) -> None: ... + def get_axes_locator(self) -> Callable[[_AxesBase, RendererBase], Bbox]: ... + def sharex(self, other: _AxesBase) -> None: ... + def sharey(self, other: _AxesBase) -> None: ... + def clear(self) -> None: ... + def cla(self) -> None: ... + + # Could be made generic, but comments indicate it may be temporary anyway + class ArtistList(Sequence[Artist]): + def __init__( + self, + axes: _AxesBase, + prop_name: str, + valid_types: list[Type] | None = ..., + invalid_types: tuple[Type] | None = ..., + ) -> None: ... + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[Artist]: ... + @overload + def __getitem__(self, key: int) -> Artist: ... + @overload + def __getitem__(self, key: slice) -> list[Artist]: ... + + @overload + def __add__(self, other: _AxesBase.ArtistList) -> list[Artist]: ... + @overload + def __add__(self, other: list[Any]) -> list[Any]: ... + @overload + def __add__(self, other: tuple[Any]) -> tuple[Any]: ... + + @overload + def __radd__(self, other: _AxesBase.ArtistList) -> list[Artist]: ... + @overload + def __radd__(self, other: list[Any]) -> list[Any]: ... + @overload + def __radd__(self, other: tuple[Any]) -> tuple[Any]: ... + + @property + def artists(self) -> _AxesBase.ArtistList: ... + @property + def collections(self) -> _AxesBase.ArtistList: ... + @property + def images(self) -> _AxesBase.ArtistList: ... + @property + def lines(self) -> _AxesBase.ArtistList: ... + @property + def patches(self) -> _AxesBase.ArtistList: ... + @property + def tables(self) -> _AxesBase.ArtistList: ... + @property + def texts(self) -> _AxesBase.ArtistList: ... + def get_facecolor(self) -> Color: ... + def set_facecolor(self, color: Color | None) -> None: ... + @overload + def set_prop_cycle(self, cycler: Cycler) -> None: ... + @overload + def set_prop_cycle(self, label: str, values: Iterable[Any]) -> None: ... + @overload + def set_prop_cycle(self, **kwargs: Iterable[Any]) -> None: ... + def get_aspect(self) -> float | Literal["auto"]: ... + def set_aspect( + self, + aspect: float | Literal["auto", "equal"], + adjustable: Literal["box", "datalim"] | None = ..., + anchor: str | tuple[float, float] | None = ..., + share: bool = ..., + ) -> None: ... + def get_adjustable(self) -> Literal["box", "datalim"]: ... + def set_adjustable( + self, adjustable: Literal["box", "datalim"], share: bool = ... + ) -> None: ... + def get_box_aspect(self) -> float | None: ... + def set_box_aspect(self, aspect: float | None = ...) -> None: ... + def get_anchor(self) -> str | tuple[float, float]: ... + def set_anchor( + self, anchor: str | tuple[float, float], share: bool = ... + ) -> None: ... + def get_data_ratio(self) -> float: ... + def apply_aspect(self, position: Bbox | None = ...) -> None: ... + @overload + def axis( + self, + arg: tuple[float, float, float, float] | bool | str | None = ..., + *, + emit: bool = ... + ) -> tuple[float, float, float, float]: ... + @overload + def axis( + self, + *, + emit: bool = ..., + xmin: float | None = ..., + xmax: float | None = ..., + ymin: float | None = ..., + ymax: float | None = ... + ) -> tuple[float, float, float, float]: ... + def get_legend(self) -> Legend: ... + def get_images(self) -> list[AxesImage]: ... + def get_lines(self) -> list[Line2D]: ... + def get_xaxis(self) -> XAxis: ... + def get_yaxis(self) -> YAxis: ... + def has_data(self) -> bool: ... + def add_artist(self, a: Artist) -> Artist: ... + def add_child_axes(self, ax: _AxesBase) -> _AxesBase: ... + def add_collection( + self, collection: Collection, autolim: bool = ... + ) -> Collection: ... + def add_image(self, image: AxesImage) -> AxesImage: ... + def add_line(self, line: Line2D) -> Line2D: ... + def add_patch(self, p: Patch) -> Patch: ... + def add_table(self, tab: Table) -> Table: ... + def add_container(self, container: Container) -> Container: ... + def relim(self, visible_only: bool = ...) -> None: ... + def update_datalim( + self, xys: ArrayLike, updatex: bool = ..., updatey: bool = ... + ) -> None: ... + def in_axes(self, mouseevent: MouseEvent) -> bool: ... + def get_autoscale_on(self) -> bool: ... + def set_autoscale_on(self, b: bool) -> None: ... + @property + def use_sticky_edges(self) -> bool: ... + @use_sticky_edges.setter + def use_sticky_edges(self, b: bool) -> None: ... + def set_xmargin(self, m: float) -> None: ... + def set_ymargin(self, m: float) -> None: ... + + # Probably could be made better with overloads + def margins( + self, + *margins: float, + x: float | None = ..., + y: float | None = ..., + tight: bool | None = ... + ) -> tuple[float, float] | None: ... + def set_rasterization_zorder(self, z: float | None) -> None: ... + def get_rasterization_zorder(self) -> float | None: ... + def autoscale( + self, + enable: bool = ..., + axis: Literal["both", "x", "y"] = ..., + tight: bool | None = ..., + ) -> None: ... + def autoscale_view( + self, tight: bool | None = ..., scalex: bool = ..., scaley: bool = ... + ) -> None: ... + def draw_artist(self, a: Artist) -> None: ... + def redraw_in_frame(self) -> None: ... + def get_frame_on(self) -> bool: ... + def set_frame_on(self, b: bool) -> None: ... + def get_axisbelow(self) -> bool | Literal["line"]: ... + def set_axisbelow(self, b: bool | Literal["line"]) -> None: ... + def grid( + self, + visible: bool | None = ..., + which: Literal["major", "minor", "both"] = ..., + axis: Literal["both", "x", "y"] = ..., + **kwargs + ) -> None: ... + def ticklabel_format( + self, + *, + axis: Literal["both", "x", "y"] = ..., + style: Literal["", "sci", "scientific", "plain"] = ..., + scilimits: tuple[int, int] | None = ..., + useOffset: bool | float | None = ..., + useLocale: bool | None = ..., + useMathText: bool | None = ... + ) -> None: ... + def locator_params( + self, axis: Literal["both", "x", "y"] = ..., tight: bool | None = ..., **kwargs + ) -> None: ... + def tick_params(self, axis: Literal["both", "x", "y"] = ..., **kwargs) -> None: ... + def set_axis_off(self) -> None: ... + def set_axis_on(self) -> None: ... + def get_xlabel(self) -> str: ... + def set_xlabel( + self, + xlabel: str, + fontdict: dict[str, Any] | None = ..., + labelpad: float | None = ..., + *, + loc: Literal["left", "center", "right"] | None = ..., + **kwargs + ) -> Text: ... + def invert_xaxis(self) -> None: ... + def get_xbound(self) -> tuple[float, float]: ... + def set_xbound( + self, lower: float | None = ..., upper: float | None = ... + ) -> None: ... + def get_xlim(self) -> tuple[float, float]: ... + def set_xlim( + self, + left: float | None = ..., + right: float | None = ..., + emit: bool = ..., + auto: bool | None = ..., + *, + xmin: float | None = ..., + xmax: float | None = ... + ) -> tuple[float, float]: ... + def get_ylabel(self) -> str: ... + def set_ylabel( + self, + ylabel: str, + fontdict: dict[str, Any] | None = ..., + labelpad: float | None = ..., + *, + loc: Literal["bottom", "center", "top"] | None = ..., + **kwargs + ) -> Text: ... + def invert_yaxis(self) -> None: ... + def get_ybound(self) -> tuple[float, float]: ... + def set_ybound( + self, lower: float | None = ..., upper: float | None = ... + ) -> None: ... + def get_ylim(self) -> tuple[float, float]: ... + def set_ylim( + self, + bottom: float | None = ..., + top: float | None = ..., + emit: bool = ..., + auto: bool | None = ..., + *, + ymin: float | None = ..., + ymax: float | None = ... + ) -> tuple[float, float]: ... + def format_xdata(self, x: float) -> str: ... + def format_ydata(self, y: float) -> str: ... + def format_coord(self, x: float, y: float) -> str: ... + def minorticks_on(self) -> None: ... + def minorticks_off(self) -> None: ... + def can_zoom(self) -> bool: ... + def can_pan(self) -> bool: ... + def get_navigate(self) -> bool: ... + def set_navigate(self, b: bool) -> None: ... + def get_navigate_mode(self) -> Literal["PAN", "ZOOM"] | None: ... + def set_navigate_mode(self, b: Literal["PAN", "ZOOM"] | None) -> None: ... + def start_pan(self, x: float, y: float, button: MouseButton) -> None: ... + def end_pan(self) -> None: ... + def drag_pan( + self, button: MouseButton, key: str | None, x: float, y: float + ) -> None: ... + def get_children(self) -> list[Artist]: ... + def contains_point(self, point: tuple[int, int]) -> bool: ... + def get_default_bbox_extra_artists(self) -> list[Artist]: ... + def get_tightbbox( + self, + renderer: RendererBase | None = ..., + call_axes_locator: bool = ..., + bbox_extra_artists: Sequence[Artist] | None = ..., + *, + for_layout_only: bool = ... + ) -> Bbox | None: ... + def twinx(self) -> _AxesBase: ... + def twiny(self) -> _AxesBase: ... + def get_shared_x_axes(self) -> cbook.GrouperView: ... + def get_shared_y_axes(self) -> cbook.GrouperView: ... + def label_outer(self) -> None: ... + + # The methods underneath this line are added via the `_axis_method_wrapper` class + # Initially they are set to an object, but that object uses `__set_name__` to override + # itself with a method modified from the Axis methods for the x or y Axis. + # As such, they are typed according to the resultant method rather than as that object. + + def get_xgridlines(self) -> list[Line2D]: ... + def get_xticklines(self, minor: bool = ...) -> list[Line2D]: ... + def get_ygridlines(self) -> list[Line2D]: ... + def get_yticklines(self, minor: bool = ...) -> list[Line2D]: ... + def _sci(self, im: ScalarMappable) -> None: ... + def get_autoscalex_on(self) -> bool: ... + def get_autoscaley_on(self) -> bool: ... + def set_autoscalex_on(self, b: bool) -> None: ... + def set_autoscaley_on(self, b: bool) -> None: ... + def xaxis_inverted(self) -> bool: ... + def get_xscale(self) -> str: ... + def set_xscale(self, value: str | ScaleBase, **kwargs) -> None: ... + def get_xticks(self, *, minor: bool = ...) -> np.ndarray: ... + def set_xticks( + self, + ticks: Iterable[float], + labels: Iterable[str] | None = ..., + *, + minor: bool = ..., + **kwargs + ) -> list[Tick]: ... + def get_xmajorticklabels(self) -> list[Text]: ... + def get_xminorticklabels(self) -> list[Text]: ... + def get_xticklabels( + self, minor: bool = ..., which: Literal["major", "minor", "both"] | None = ... + ) -> list[Text]: ... + def set_xticklabels( + self, + labels: Iterable[str | Text], + *, + minor: bool = ..., + fontdict: dict[str, Any] | None = ..., + **kwargs + ) -> list[Text]: ... + def yaxis_inverted(self) -> bool: ... + def get_yscale(self) -> str: ... + def set_yscale(self, value: str | ScaleBase, **kwargs) -> None: ... + def get_yticks(self, *, minor: bool = ...) -> np.ndarray: ... + def set_yticks( + self, + ticks: Iterable[float], + labels: Iterable[str] | None = ..., + *, + minor: bool = ..., + **kwargs + ) -> list[Tick]: ... + def get_ymajorticklabels(self) -> list[Text]: ... + def get_yminorticklabels(self) -> list[Text]: ... + def get_yticklabels( + self, minor: bool = ..., which: Literal["major", "minor", "both"] | None = ... + ) -> list[Text]: ... + def set_yticklabels( + self, + labels: Iterable[str | Text], + *, + minor: bool = ..., + fontdict: dict[str, Any] | None = ..., + **kwargs + ) -> list[Text]: ... + def xaxis_date(self, tz: str | datetime.tzinfo | None = ...) -> None: ... + def yaxis_date(self, tz: str | datetime.tzinfo | None = ...) -> None: ... diff --git a/lib/matplotlib/axes/_secondary_axes.pyi b/lib/matplotlib/axes/_secondary_axes.pyi new file mode 100644 index 000000000000..386ef1d930ad --- /dev/null +++ b/lib/matplotlib/axes/_secondary_axes.pyi @@ -0,0 +1,44 @@ +from matplotlib.axes._base import _AxesBase +from matplotlib.axis import Axis, Tick + +from matplotlib.colors import Color +from matplotlib.transforms import Transform + +from typing import Literal, Callable, Iterable +from numpy.typing import ArrayLike + +class SecondaryAxis(_AxesBase): + def __init__( + self, + parent: _AxesBase, + orientation: Literal["x", "y"], + location: Literal["top", "bottom", "right", "left"] | float, + functions: tuple[ + Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike] + ] + | Transform, + **kwargs + ) -> None: ... + def set_alignment( + self, align: Literal["top", "bottom", "right", "left"] + ) -> None: ... + def set_location( + self, location: Literal["top", "bottom", "right", "left"] | float + ) -> None: ... + def set_ticks( + self, + ticks: Iterable[float], + labels: Iterable[str] | None = ..., + *, + minor: bool = ..., + **kwargs + ) -> list[Tick]: ... + def set_functions( + self, + functions: tuple[ + Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike] + ] + | Transform, + ): ... + def set_aspect(self, *args, **kwargs) -> None: ... + def set_color(self, color: Color) -> None: ... diff --git a/lib/matplotlib/axis.pyi b/lib/matplotlib/axis.pyi new file mode 100644 index 000000000000..7aea224a0587 --- /dev/null +++ b/lib/matplotlib/axis.pyi @@ -0,0 +1,276 @@ +import matplotlib.artist as martist +from matplotlib import cbook +from matplotlib.axes import Axes +from matplotlib.backend_bases import RendererBase +from matplotlib.colors import Color +from matplotlib.lines import Line2D +from matplotlib.text import Text +from matplotlib.ticker import Locator, Formatter +from matplotlib.transforms import Transform, Bbox + +import datetime +from typing import Any, Literal, Type, Iterable, Callable +import numpy as np +from numpy.typing import ArrayLike + + +GRIDLINE_INTERPOLATION_STEPS: int + +class Tick(martist.Artist): + axes: Axes + tick1line: Line2D + tick2line: Line2D + gridline: Line2D + label1: Text + label2: Text + def __init__( + self, + axes: Axes, + loc: float, + *, + size: float | None = ..., + width: float | None = ..., + color: Color | None = ..., + tickdir: Literal["in", "inout", "out"] | None = ..., + pad: float | None = ..., + labelsize: float | None = ..., + labelcolor: Color | None = ..., + zorder: float | None = ..., + gridOn: bool | None = ..., + tick1On: bool = ..., + tick2On: bool = ..., + label1On: bool = ..., + label2On: bool = ..., + major: bool = ..., + labelrotation: float = ..., + grid_color: Color | None = ..., + grid_linestyle: str | None = ..., + grid_linewidth: float | None = ..., + grid_alpha: float | None = ..., + **kwargs + ) -> None: ... + @property + def label(self) -> Text: ... + def get_tickdir(self) -> Literal["in", "inout", "out"]: ... + def get_tick_padding(self) -> float: ... + def get_children(self) -> list[martist.Artist]: ... + stale: bool + def get_pad_pixels(self) -> float: ... + def set_pad(self, val: float) -> None: ... + def get_pad(self) -> None: ... + def get_loc(self) -> float: ... + def set_label1(self, s: object) -> None: ... + def set_label(self, s: object) -> None: ... + def set_label2(self, s: object) -> None: ... + def set_url(self, url: str | None) -> None: ... + def get_view_interval(self) -> ArrayLike: ... + def update_position(self, loc: float) -> None: ... + +class XTick(Tick): + __name__: str + def __init__(self, *args, **kwargs) -> None: ... + stale: bool + def update_position(self, loc: float) -> None: ... + def get_view_interval(self) -> np.ndarray: ... + +class YTick(Tick): + __name__: str + def __init__(self, *args, **kwargs) -> None: ... + stale: bool + def update_position(self, loc: float) -> None: ... + def get_view_interval(self) -> np.ndarray: ... + +class Ticker: + def __init__(self) -> None: ... + @property + def locator(self) -> Locator | None: ... + @locator.setter + def locator(self, locator: Locator) -> None: ... + @property + def formatter(self) -> Formatter | None: ... + @formatter.setter + def formatter(self, formatter: Formatter) -> None: ... + +class _LazyTickList: + def __init__(self, major: bool) -> None: ... + def __get__(self, instance: Axis, cls: Type): ... + +class Axis(martist.Artist): + OFFSETTEXTPAD: int + isDefault_label: bool + axes: Axes + major: Ticker + minor: Ticker + callbacks: cbook.CallbackRegistry + label: Text + offsetText: Text + labelpad: float + pickradius: float + def __init__(self, axes, *, pickradius: float = ...) -> None: ... + @property + def isDefault_majloc(self) -> bool: ... + @isDefault_majloc.setter + def isDefault_majloc(self, value: bool) -> None: ... + @property + def isDefault_majfmt(self) -> bool: ... + @isDefault_majfmt.setter + def isDefault_majfmt(self, value: bool) -> None: ... + @property + def isDefault_minloc(self) -> bool: ... + @isDefault_minloc.setter + def isDefault_minloc(self, value: bool) -> None: ... + @property + def isDefault_minfmt(self) -> bool: ... + @isDefault_minfmt.setter + def isDefault_minfmt(self, value: bool) -> None: ... + majorTicks: _LazyTickList + minorTicks: _LazyTickList + def get_remove_overlapping_locs(self) -> bool: ... + def set_remove_overlapping_locs(self, val: bool) -> None: ... + @property + def remove_overlapping_locs(self) -> bool: ... + @remove_overlapping_locs.setter + def remove_overlapping_locs(self, val: bool) -> None: ... + stale: bool + def set_label_coords( + self, x: float, y: float, transform: Transform | None = ... + ) -> None: ... + def get_transform(self) -> Transform: ... + def get_scale(self) -> str: ... + def limit_range_for_scale( + self, vmin: float, vmax: float + ) -> tuple[float, float]: ... + def get_children(self) -> list[martist.Artist]: ... + # TODO units + converter: Any + units: Any + def clear(self) -> None: ... + def reset_ticks(self) -> None: ... + def set_tick_params( + self, + which: Literal["major", "minor", "both"] = ..., + reset: bool = ..., + **kwargs + ) -> None: ... + def get_tick_params( + self, which: Literal["major", "minor"] = ... + ) -> dict[str, Any]: ... + def get_view_interval(self) -> tuple[float, float]: ... + def set_view_interval( + self, vmin: float, vmax: float, ignore: bool = ... + ) -> None: ... + def get_data_interval(self) -> tuple[float, float]: ... + def set_data_interval( + self, vmin: float, vmax: float, ignore: bool = ... + ) -> None: ... + def get_inverted(self) -> bool: ... + def set_inverted(self, inverted: bool) -> None: ... + def set_default_intervals(self) -> None: ... + def get_ticklabel_extents(self, renderer: RendererBase) -> tuple[Bbox, Bbox]: ... + def get_tightbbox( + self, renderer: RendererBase | None = ..., *, for_layout_only: bool = ... + ) -> Bbox | None: ... + def get_tick_padding(self) -> float: ... + def get_gridlines(self) -> list[Line2D]: ... + def get_label(self) -> Text: ... + def get_offset_text(self) -> Text: ... + def get_pickradius(self) -> float: ... + def get_majorticklabels(self) -> list[Text]: ... + def get_minorticklabels(self) -> list[Text]: ... + def get_ticklabels( + self, minor: bool = ..., which: Literal["major", "minor", "both"] | None = ... + ) -> list[Text]: ... + def get_majorticklines(self) -> list[Line2D]: ... + def get_minorticklines(self) -> list[Line2D]: ... + def get_ticklines(self, minor: bool = ...) -> list[Line2D]: ... + def get_majorticklocs(self) -> np.ndarray: ... + def get_minorticklocs(self) -> np.ndarray: ... + def get_ticklocs(self, *, minor: bool = ...) -> np.ndarray: ... + def get_ticks_direction(self, minor: bool = ...) -> np.ndarray: ... + def get_label_text(self) -> str: ... + def get_major_locator(self) -> Locator: ... + def get_minor_locator(self) -> Locator: ... + def get_major_formatter(self) -> Formatter: ... + def get_minor_formatter(self) -> Formatter: ... + def get_major_ticks(self, numticks: int | None = ...) -> list[Tick]: ... + def get_minor_ticks(self, numticks: int | None = ...) -> list[Tick]: ... + def grid( + self, + visible: bool | None = ..., + which: Literal["major", "minor", "both"] = ..., + **kwargs + ) -> None: ... + # TODO units + def update_units(self, data): ... + def have_units(self) -> bool: ... + def convert_units(self, x): ... + def set_units(self, u) -> None: ... + def get_units(self): ... + def set_label_text( + self, label: str, fontdict: dict[str, Any] | None = ..., **kwargs + ) -> Text: ... + def set_major_formatter( + self, formatter: Formatter | str | Callable[[float, float], str] + ) -> None: ... + def set_minor_formatter( + self, formatter: Formatter | str | Callable[[float, float], str] + ) -> None: ... + def set_major_locator(self, locator: Locator) -> None: ... + def set_minor_locator(self, locator: Locator) -> None: ... + def set_pickradius(self, pickradius: float) -> None: ... + def set_ticklabels( + self, + labels: Iterable[str | Text], + *, + minor: bool = ..., + fontdict: dict[str, Any] | None = ..., + **kwargs + ) -> list[Text]: ... + def set_ticks( + self, + ticks: Iterable[float], + labels: Iterable[str] | None = ..., + *, + minor: bool = ..., + **kwargs + ) -> list[Tick]: ... + def axis_date(self, tz: str | datetime.tzinfo | None = ...) -> None: ... + def get_tick_space(self) -> int: ... + def get_label_position(self) -> Literal["top", "bottom"]: ... + def set_label_position( + self, position: Literal["top", "bottom", "left", "right"] + ) -> None: ... + def get_minpos(self) -> float: ... + +class XAxis(Axis): + __name__: str + axis_name: str + def __init__(self, *args, **kwargs) -> None: ... + label_position: Literal["bottom", "top"] + stale: bool + def set_label_position(self, position: Literal["bottom", "top"]) -> None: ... # type: ignore[override] + def get_text_heights(self, renderer: RendererBase) -> tuple[float, float]: ... + def set_ticks_position( + self, position: Literal["top", "bottom", "both", "default", "none"] + ) -> None: ... + def tick_top(self) -> None: ... + def tick_bottom(self) -> None: ... + def get_ticks_position(self) -> Literal["top", "bottom", "default", "unkown"]: ... + def get_tick_space(self) -> int: ... + +class YAxis(Axis): + __name__: str + axis_name: str + def __init__(self, *args, **kwargs) -> None: ... + label_position: Literal["left", "right"] + stale: bool + def set_label_position(self, position: Literal["left", "right"]) -> None: ... # type: ignore[override] + def set_offset_position(self, position: Literal["left", "right"]) -> None: ... + def get_text_widths(self, renderer: RendererBase) -> tuple[float, float]: ... + def set_ticks_position( + self, position: Literal["left", "right", "both", "default", "none"] + ) -> None: ... + def tick_right(self) -> None: ... + def tick_left(self) -> None: ... + def get_ticks_position(self) -> Literal["left", "right", "default", "unkown"]: ... + def get_tick_space(self) -> int: ... diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 16ce51cd600e..c573c369e9e3 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1969,7 +1969,7 @@ def leave_notify_event(self, guiEvent=None): @_api.deprecated("3.6", alternative=( "callbacks.process('enter_notify_event', LocationEvent(...))")) - def enter_notify_event(self, guiEvent=None, xy=None): + def enter_notify_event(self, guiEvent=None, *, xy): """ Callback processing for the mouse cursor entering the canvas. @@ -1983,18 +1983,7 @@ def enter_notify_event(self, guiEvent=None, xy=None): xy : (float, float) The coordinate location of the pointer when the canvas is entered. """ - if xy is not None: - x, y = xy - self._lastx, self._lasty = x, y - else: - x = None - y = None - _api.warn_deprecated( - '3.0', removal='3.5', name='enter_notify_event', - message='Since %(since)s, %(name)s expects a location but ' - 'your backend did not pass one. This will become an error ' - '%(removal)s.') - + self._lastx, self._lasty = x, y = xy event = LocationEvent('figure_enter_event', self, x, y, guiEvent) self.callbacks.process('figure_enter_event', event) diff --git a/lib/matplotlib/backend_bases.pyi b/lib/matplotlib/backend_bases.pyi new file mode 100644 index 000000000000..391cfe2e54f2 --- /dev/null +++ b/lib/matplotlib/backend_bases.pyi @@ -0,0 +1,493 @@ +from enum import Enum, IntEnum +import os +import io +from matplotlib import ( + cbook, + colors, + get_backend, + is_interactive, + rcParams, + textpath, + transforms, + widgets, + _api, +) +from matplotlib._enums import CapStyle, JoinStyle +from matplotlib._pylab_helpers import Gcf +from matplotlib.artist import Artist +from matplotlib.axes import Axes +from matplotlib.backend_managers import ToolManager +from matplotlib.backend_tools import Cursors, ToolBase +from matplotlib.colorbar import Colorbar +from matplotlib.colors import Color +from matplotlib.figure import Figure +from matplotlib.font_manager import FontProperties +from matplotlib.lines import LineStyleType +from matplotlib.path import Path +from matplotlib.texmanager import TexManager +from matplotlib.text import Text +from matplotlib.transforms import Affine2D, Transform, TransformedPath, Bbox + +from typing import Any, Callable, Literal, NamedTuple, Sequence, Type, TypeVar +from numpy.typing import ArrayLike + +def register_backend( + format: str, backend: str | Type[FigureCanvasBase], description: str | None = ... +) -> None: ... +def get_registered_canvas_class(format: str) -> Type[FigureCanvasBase]: ... + +class RendererBase: + def __init__(self) -> None: ... + def open_group(self, s: str, gid: int | None = ...) -> None: ... + def close_group(self, s: str) -> None: ... + def draw_path( + self, + gc: GraphicsContextBase, + path: Path, + transform: Transform, + rgbFace: Color | None = ..., + ) -> None: ... + def draw_markers( + self, + gc: GraphicsContextBase, + marker_path: Path, + marker_trans: Transform, + path: Path, + trans: Transform, + rgbFace: Color | None = ..., + ) -> None: ... + def draw_path_collection( + self, + gc: GraphicsContextBase, + master_transform: Transform, + paths: Sequence[Path], + all_transforms: Sequence[ArrayLike], + offsets: ArrayLike | Sequence[ArrayLike], + offset_trans: Transform, + facecolors: Color | Sequence[Color], + edgecolors: Color | Sequence[Color], + linewidths: float | Sequence[float], + linestyles: LineStyleType | Sequence[LineStyleType], + antialiaseds: bool | Sequence[bool], + urls: str | Sequence[str], + offset_position: Any, + ) -> None: ... + def draw_quad_mesh( + self, + gc: GraphicsContextBase, + master_transform: Transform, + meshWidth, + meshHeight, + coordinates: ArrayLike, + offsets: ArrayLike | Sequence[ArrayLike], + offsetTrans: Transform, + facecolors: Sequence[Color], + antialiased: bool, + edgecolors: Sequence[Color] | Color | None, + ): ... + def draw_gouraud_triangle( + self, + gc: GraphicsContextBase, + points: ArrayLike, + colors: ArrayLike, + transform: Transform, + ) -> None: ... + def draw_gouraud_triangles( + self, + gc: GraphicsContextBase, + triangles_array: ArrayLike, + colors_array: ArrayLike, + transform: Transform, + ) -> None: ... + def get_image_magnification(self) -> float: ... + def draw_image( + self, + gc: GraphicsContextBase, + x: float, + y: float, + im: ArrayLike, + transform: transforms.Affine2DBase | None = ..., + ) -> None: ... + def option_image_nocomposite(self) -> bool: ... + def option_scale_image(self) -> bool: ... + def draw_tex( + self, + gc: GraphicsContextBase, + x: float, + y: float, + s: str, + prop: FontProperties, + angle: float, + *, + mtext: Text | None = ... + ) -> None: ... + def draw_text( + self, + gc: GraphicsContextBase, + x: float, + y: float, + s: str, + prop: FontProperties, + angle: float, + ismath: bool | Literal["TeX"] = ..., + mtext: Text | None = ..., + ) -> None: ... + def get_text_width_height_descent( + self, s: str, prop: FontProperties, ismath: bool | Literal["TeX"] + ) -> tuple[float, float, float]: ... + def flipy(self) -> bool: ... + def get_canvas_width_height(self) -> tuple[float, float]: ... + def get_texmanager(self) -> TexManager: ... + def new_gc(self) -> GraphicsContextBase: ... + def points_to_pixels(self, points: ArrayLike) -> ArrayLike: ... + def start_rasterizing(self) -> None: ... + def stop_rasterizing(self) -> None: ... + def start_filter(self) -> None: ... + def stop_filter(self, filter_func) -> None: ... + +class GraphicsContextBase: + def __init__(self) -> None: ... + def copy_properties(self, gc: GraphicsContextBase) -> None: ... + def restore(self) -> None: ... + def get_alpha(self) -> float: ... + def get_antialiased(self) -> int: ... + def get_capstyle(self) -> CapStyle: ... + def get_clip_rectangle(self) -> Bbox | None: ... + def get_clip_path( + self, + ) -> tuple[TransformedPath, Transform] | tuple[None, None]: ... + def get_dashes(self) -> tuple[float, ArrayLike | None]: ... + def get_forced_alpha(self) -> bool: ... + def get_joinstyle(self) -> JoinStyle: ... + def get_linewidth(self) -> float: ... + def get_rgb(self) -> tuple[float, float, float, float]: ... + def get_url(self) -> str | None: ... + def get_gid(self) -> int | None: ... + def get_snap(self) -> bool | None: ... + def set_alpha(self, alpha: float) -> None: ... + def set_antialiased(self, b: bool) -> None: ... + def set_capstyle(self, cs: CapStyle) -> None: ... + def set_clip_rectangle(self, rectangle: Bbox | None) -> None: ... + def set_clip_path(self, path: TransformedPath | None) -> None: ... + def set_dashes(self, dash_offset: float, dash_list: ArrayLike | None) -> None: ... + def set_foreground(self, fg: Color, isRGBA: bool = ...) -> None: ... + def set_joinstyle(self, js: JoinStyle) -> None: ... + def set_linewidth(self, w: float) -> None: ... + def set_url(self, url: str | None) -> None: ... + def set_gid(self, id: int | None) -> None: ... + def set_snap(self, snap: bool | None) -> None: ... + def set_hatch(self, hatch: str) -> None: ... + def get_hatch(self) -> str | None: ... + def get_hatch_path(self, density: float = ...) -> Path: ... + def get_hatch_color(self) -> Color: ... + def set_hatch_color(self, hatch_color: Color) -> None: ... + def get_hatch_linewidth(self) -> float: ... + def get_sketch_params(self) -> tuple[float, float, float] | None: ... + def set_sketch_params( + self, + scale: float | None = ..., + length: float | None = ..., + randomness: float | None = ..., + ) -> None: ... + +class TimerBase: + callbacks: list[tuple[Callable, tuple, dict[str, Any]]] + def __init__( + self, + interval: int | None = ..., + callbacks: list[tuple[Callable, tuple, dict[str, Any]]] | None = ..., + ) -> None: ... + def __del__(self) -> None: ... + def start(self, interval: int | None = ...) -> None: ... + def stop(self) -> None: ... + @property + def interval(self) -> int: ... + @interval.setter + def interval(self, interval: int) -> None: ... + @property + def single_shot(self) -> bool: ... + @single_shot.setter + def single_shot(self, ss: bool) -> None: ... + def add_callback(self, func: Callable, *args, **kwargs) -> Callable: ... + def remove_callback(self, func: Callable, *args, **kwargs) -> None: ... + +class Event: + name: str + canvas: FigureCanvasBase + guiEvent: Any + def __init__( + self, name: str, canvas: FigureCanvasBase, guiEvent: Any | None = ... + ) -> None: ... + +class DrawEvent(Event): + renderer: RendererBase + def __init__( + self, name: str, canvas: FigureCanvasBase, renderer: RendererBase + ) -> None: ... + +class ResizeEvent(Event): + width: int + height: int + def __init__(self, name: str, canvas: FigureCanvasBase) -> None: ... + +class CloseEvent(Event): ... + +class LocationEvent(Event): + lastevent: Event | None + x: int + y: int + inaxes: Axes | None + xdata: float | None + ydata: float | None + def __init__( + self, + name: str, + canvas: FigureCanvasBase, + x: int, + y: int, + guiEvent: Any | None = ..., + ) -> None: ... + +class MouseButton(IntEnum): + LEFT: int + MIDDLE: int + RIGHT: int + BACK: int + FORWARD: int + +class MouseEvent(LocationEvent): + button: MouseButton | Literal["up", "down"] | None + key: str | None + step: float + dblclick: bool + def __init__( + self, + name: str, + canvas: FigureCanvasBase, + x: int, + y: int, + button: MouseButton | Literal["up", "down"] | None = ..., + key: str | None = ..., + step: float = ..., + dblclick: bool = ..., + guiEvent: Any | None = ..., + ) -> None: ... + +class PickEvent(Event): + mouseevent: MouseEvent + artist: Artist + def __init__( + self, + name: str, + canvas: FigureCanvasBase, + mouseevent: MouseEvent, + artist: Artist, + guiEvent: Any | None = ..., + **kwargs + ) -> None: ... + +class KeyEvent(LocationEvent): + key: str | None + def __init__( + self, + name: str, + canvas: FigureCanvasBase, + key: str | None, + x: int = ..., + y: int = ..., + guiEvent: Any | None = ..., + ) -> None: ... + +class FigureCanvasBase: + required_interactive_framework: str | None + + @_api.classproperty + def manager_class(cls) -> Type[FigureManagerBase]: ... + events: list[str] + fixed_dpi: None | float + filetypes: dict[str, str] + + @_api.classproperty + def supports_blit(cls) -> bool: ... + + figure: Figure + manager: None | FigureManagerBase + widgetlock: widgets.LockDraw + mouse_grabber: None | Axes + toolbar: None | NavigationToolbar2 + def __init__(self, figure: Figure | None = ...) -> None: ... + @property + def callbacks(self) -> cbook.CallbackRegistry: ... + @property + def button_pick_id(self) -> int: ... + @property + def scroll_pick_id(self) -> int: ... + @classmethod + def new_manager(cls, figure: Figure, num: int | str): ... + def is_saving(self) -> bool: ... + def pick(self, mouseevent: MouseEvent) -> None: ... + def blit(self, bbox: Bbox | None = ...) -> None: ... + def inaxes(self, xy: tuple[float, float]) -> Axes | None: ... + def grab_mouse(self, ax: Axes) -> None: ... + def release_mouse(self, ax: Axes) -> None: ... + def set_cursor(self, cursor: Cursors) -> None: ... + def draw(self, *args, **kwargs) -> None: ... + def draw_idle(self, *args, **kwargs) -> None: ... + @property + def device_pixel_ratio(self) -> float: ... + def get_width_height(self, *, physical: bool = ...) -> tuple[int, int]: ... + @classmethod + def get_supported_filetypes(cls) -> dict[str, str]: ... + @classmethod + def get_supported_filetypes_grouped(cls) -> dict[str, list[str]]: ... + def print_figure( + self, + filename: str | os.PathLike | io.FileIO, + dpi: float | None = ..., + facecolor: Color | Literal["auto"] | None = ..., + edgecolor: Color | Literal["auto"] | None = ..., + orientation: str = ..., + format: str | None = ..., + *, + bbox_inches: Literal["tight"] | Bbox | None = ..., + pad_inches: float | None = ..., + bbox_extra_artists: list[Artist] | None = ..., + backend: str | None = ..., + **kwargs + ): ... + @classmethod + def get_default_filetype(cls) -> str: ... + def get_default_filename(self) -> str: ... + T = TypeVar("T", bound=FigureCanvasBase) + def switch_backends(self, FigureCanvasClass: Type[T]) -> T: ... + def mpl_connect(self, s: str, func: Callable[[Event], Any]) -> int: ... + def mpl_disconnect(self, cid: int) -> None: ... + def new_timer( + self, + interval: int | None = ..., + callbacks: list[tuple[Callable, tuple, dict[str, Any]]] | None = ..., + ): ... + def flush_events(self) -> None: ... + def start_event_loop(self, timeout: float = ...) -> None: ... + def stop_event_loop(self) -> None: ... + +def key_press_handler( + event: KeyEvent, + canvas: FigureCanvasBase | None = ..., + toolbar: NavigationToolbar2 | None = ..., +): ... +def button_press_handler( + event: MouseEvent, + canvas: FigureCanvasBase | None = ..., + toolbar: NavigationToolbar2 | None = ..., +) -> None: ... + +class NonGuiException(Exception): ... + +class FigureManagerBase: + canvas: FigureCanvasBase + num: int | str + key_press_handler_id: int | None + button_press_handler_id: int | None + toolmanager: ToolManager + toolbar: NavigationToolbar2 + def __init__(self, canvas: FigureCanvasBase, num: int | str) -> None: ... + @classmethod + def create_with_canvas( + cls, canvas_class: Type[FigureCanvasBase], figure: Figure, num: int | str + ): ... + @classmethod + def start_main_loop(cls) -> None: ... + @classmethod + def pyplot_show(cls, *, block: bool | None = ...) -> None: ... + def show(self) -> None: ... + def destroy(self) -> None: ... + def full_screen_toggle(self) -> None: ... + def resize(self, w: int, h: int) -> None: ... + def get_window_title(self) -> str: ... + def set_window_title(self, title: str) -> None: ... + +cursors: Cursors + +class _Mode(str, Enum): + NONE: str + PAN: str + ZOOM: str + +class NavigationToolbar2: + toolitems: tuple[tuple[str, ...] | tuple[None, ...], ...] + canvas: FigureCanvasBase + mode: _Mode + def __init__(self, canvas: FigureCanvasBase) -> None: ... + def set_message(self, s: str) -> None: ... + def draw_rubberband( + self, event: Event, x0: float, y0: float, x1: float, y1: float + ) -> None: ... + def remove_rubberband(self) -> None: ... + def home(self, *args) -> None: ... + def back(self, *args) -> None: ... + def forward(self, *args) -> None: ... + def mouse_move(self, event: MouseEvent) -> None: ... + def pan(self, *args) -> None: ... + + class _PanInfo(NamedTuple): + button: MouseButton + axes: Axes + cid: int + def press_pan(self, event: Event) -> None: ... + def drag_pan(self, event: Event) -> None: ... + def release_pan(self, event: Event) -> None: ... + def zoom(self, *args) -> None: ... + + class _ZoomInfo(NamedTuple): + direction: Literal["in", "out"] + start_xy: tuple[float, float] + axes: Axes + cid: int + cbar: Colorbar + def press_zoom(self, event: Event) -> None: ... + def drag_zoom(self, event: Event) -> None: ... + def release_zoom(self, event: Event) -> None: ... + def push_current(self) -> None: ... + subplot_tool: widgets.SubplotTool + def configure_subplots(self, *args): ... + def save_figure(self, *args) -> None: ... + def update(self) -> None: ... + def set_history_buttons(self) -> None: ... + +class ToolContainerBase: + toolmanager: ToolManager + def __init__(self, toolmanager: ToolManager) -> None: ... + def add_tool(self, tool: ToolBase, group: str, position: int = ...) -> None: ... + def trigger_tool(self, name: str) -> None: ... + def add_toolitem( + self, + name: str, + group: str, + position: int, + image: str, + description: str, + toggle: bool, + ) -> None: ... + def toggle_toolitem(self, name: str, toggled: bool) -> None: ... + def remove_toolitem(self, name: str) -> None: ... + def set_message(self, s: str) -> None: ... + +class _Backend: + backend_version: str + FigureCanvas: Type[FigureCanvasBase] + FigureManager: Type[FigureManagerBase] + mainloop: None | Callable[[], Any] + @classmethod + def new_figure_manager(cls, num: int | str, *args, **kwargs): ... + @classmethod + def new_figure_manager_given_figure(cls, num: int | str, figure: Figure): ... + @classmethod + def draw_if_interactive(cls) -> None: ... + @classmethod + def show(cls, *, block: bool | None = ...) -> None: ... + @staticmethod + def export(cls) -> Type[_Backend]: ... + +class ShowBase(_Backend): + def __call__(self, block: bool | None = ...): ... diff --git a/lib/matplotlib/backend_managers.pyi b/lib/matplotlib/backend_managers.pyi new file mode 100644 index 000000000000..e5356be29ac5 --- /dev/null +++ b/lib/matplotlib/backend_managers.pyi @@ -0,0 +1,63 @@ +from matplotlib import backend_tools, cbook, widgets +from matplotlib.backend_bases import FigureCanvasBase +from matplotlib.figure import Figure + +from typing import Any, Callable, Iterable, TypeVar, Type + +class ToolEvent: + name: str + sender: Any + tool: backend_tools.ToolBase + data: Any + def __init__(self, name, sender, tool, data: Any | None = ...) -> None: ... + +class ToolTriggerEvent(ToolEvent): + canvasevent: ToolEvent + def __init__( + self, + name, + sender, + tool, + canvasevent: ToolEvent | None = ..., + data: Any | None = ..., + ) -> None: ... + +class ToolManagerMessageEvent: + name: str + sender: Any + message: str + def __init__(self, name: str, sender: Any, message: str) -> None: ... + +class ToolManager: + keypresslock: widgets.LockDraw + messagelock: widgets.LockDraw + def __init__(self, figure: Figure | None = ...) -> None: ... + @property + def canvas(self) -> FigureCanvasBase | None: ... + @property + def figure(self) -> Figure | None: ... + @figure.setter + def figure(self, figure: Figure) -> None: ... + def set_figure(self, figure: Figure, update_tools: bool = ...) -> None: ... + def toolmanager_connect(self, s: str, func: Callable[[ToolEvent], Any]) -> int: ... + def toolmanager_disconnect(self, cid: int): ... + def message_event(self, message: str, sender: Any | None = ...) -> None: ... + @property + def active_toggle(self) -> dict[str | None, list[str] | str]: ... + def get_tool_keymap(self, name: str) -> list[str]: ... + def update_keymap(self, name: str, key: str | Iterable[str]) -> None: ... + def remove_tool(self, name: str) -> None: ... + T = TypeVar("T", bound=backend_tools.ToolBase) + def add_tool(self, name: str, tool: Type[T], *args, **kwargs) -> T: ... + def trigger_tool( + self, + name: str, + sender: Any | None = ..., + canvasevent: ToolEvent | None = ..., + data: Any | None = ..., + ) -> None: ... + @property + def tools(self) -> dict[str, backend_tools.ToolBase]: ... + def get_tool( + self, name: str, warn: bool = ... + ) -> backend_tools.ToolBase | None: ... diff --git a/lib/matplotlib/backend_tools.pyi b/lib/matplotlib/backend_tools.pyi new file mode 100644 index 000000000000..9af8b630cafa --- /dev/null +++ b/lib/matplotlib/backend_tools.pyi @@ -0,0 +1,124 @@ +import enum +from matplotlib import cbook +from matplotlib.axes import Axes +from matplotlib.backend_bases import ToolContainerBase, FigureCanvasBase +from matplotlib.backend_managers import ToolManager, ToolEvent +from matplotlib.figure import Figure +from matplotlib.scale import ScaleBase +from matplotlib._pylab_helpers import Gcf + +from typing import Any, Type + +class Cursors(enum.IntEnum): + POINTER: int + HAND: int + SELECT_REGION: int + MOVE: int + WAIT: int + RESIZE_HORIZONTAL: int + RESIZE_VERTICAL: int + +cursors = Cursors + +class ToolBase: + default_keymap: list[str] | None + description: str | None + image: str | None + def __init__(self, toolmanager: ToolManager, name: str) -> None: ... + @property + def name(self) -> str: ... + @property + def toolmanger(self) -> ToolManager: ... + @property + def canvas(self) -> FigureCanvasBase | None: ... + @property + def figure(self) -> Figure | None: ... + @figure.setter + def figure(self, figure: Figure | None) -> None: ... + def set_figure(self, figure: Figure | None) -> None: ... + def trigger(self, sender: Any, event: ToolEvent, data: Any = ...) -> None: ... + def destroy(self) -> None: ... + +class ToolToggleBase(ToolBase): + radio_group: str | None + cursor: Cursors | None + default_toggled: bool + def __init__( + self, toolmanager: ToolManager, name: str, *, toggled: bool = ... + ) -> None: ... + def enable(self, event: ToolEvent | None = ...) -> None: ... + def disable(self, event: ToolEvent | None = ...) -> None: ... + @property + def toggled(self) -> bool: ... + def set_figure(self, figure: Figure | None) -> None: ... + +class ToolSetCursor(ToolBase): ... + +class ToolCursorPosition(ToolBase): + def send_message(self, event: ToolEvent) -> None: ... + +class RubberbandBase(ToolBase): + def draw_rubberband(self, *data) -> None: ... + def remove_rubberband(self) -> None: ... + +class ToolQuit(ToolBase): ... +class ToolQuitAll(ToolBase): ... +class ToolGrid(ToolBase): ... +class ToolMinorGrid(ToolBase): ... +class ToolFullScreen(ToolBase): ... + +class AxisScaleBase(ToolToggleBase): + def enable(self, event: ToolEvent | None = ...) -> None: ... + def disable(self, event: ToolEvent | None = ...) -> None: ... + +class ToolYScale(AxisScaleBase): + def set_scale(self, ax: Axes, scale: str | ScaleBase) -> None: ... + +class ToolXScale(AxisScaleBase): + def set_scale(self, ax, scale: str | ScaleBase) -> None: ... + +class ToolViewsPositions(ToolBase): + views: dict[Figure | Axes, cbook.Stack] + positions: dict[Figure | Axes, cbook.Stack] + home_views: dict[Figure, dict[Axes, tuple[float, float, float, float]]] + def add_figure(self, figure: Figure) -> None: ... + def clear(self, figure: Figure) -> None: ... + def update_view(self) -> None: ... + def push_current(self, figure: Figure | None = ...) -> None: ... + def update_home_views(self, figure: Figure | None = ...) -> None: ... + def home(self) -> None: ... + def back(self) -> None: ... + def forward(self) -> None: ... + +class ViewsPositionsBase(ToolBase): ... +class ToolHome(ViewsPositionsBase): ... +class ToolBack(ViewsPositionsBase): ... +class ToolForward(ViewsPositionsBase): ... +class ConfigureSubplotsBase(ToolBase): ... +class SaveFigureBase(ToolBase): ... + +class ZoomPanBase(ToolToggleBase): + base_scale: float + scrollthresh: float + lastscroll: float + def __init__(self, *args) -> None: ... + def enable(self, event: ToolEvent | None = ...) -> None: ... + def disable(self, event: ToolEvent | None = ...) -> None: ... + def scroll_zoom(self, event: ToolEvent) -> None: ... + +class ToolZoom(ZoomPanBase): ... +class ToolPan(ZoomPanBase): ... + +class ToolHelpBase(ToolBase): + @staticmethod + def format_shortcut(key_sequence: str) -> str: ... + +class ToolCopyToClipboardBase(ToolBase): ... + +default_tools: dict[str, ToolBase] +default_toolbar_tools: list[list[str | list[str]]] + +def add_tools_to_manager( + toolmanager: ToolManager, tools: dict[str, Type[ToolBase]] = ... +) -> None: ... +def add_tools_to_container(container: ToolContainerBase, tools: list[Any]) -> None: ... diff --git a/lib/matplotlib/backends/_backend_agg.pyi b/lib/matplotlib/backends/_backend_agg.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/matplotlib/backends/_macosx.pyi b/lib/matplotlib/backends/_macosx.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/matplotlib/backends/_tkagg.pyi b/lib/matplotlib/backends/_tkagg.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/matplotlib/backends/backend_webagg_core.py b/lib/matplotlib/backends/backend_webagg_core.py index 232fa10616b4..57cfa311b8f7 100644 --- a/lib/matplotlib/backends/backend_webagg_core.py +++ b/lib/matplotlib/backends/backend_webagg_core.py @@ -390,11 +390,8 @@ class NavigationToolbar2WebAgg(backend_bases.NavigationToolbar2): if name_of_method in _ALLOWED_TOOL_ITEMS ] - cursor = _api.deprecate_privatize_attribute("3.5") - def __init__(self, canvas): self.message = '' - self._cursor = None # Remove with deprecation. super().__init__(canvas) def set_message(self, message): diff --git a/lib/matplotlib/bezier.pyi b/lib/matplotlib/bezier.pyi new file mode 100644 index 000000000000..e600c2ef3644 --- /dev/null +++ b/lib/matplotlib/bezier.pyi @@ -0,0 +1,73 @@ +from typing import Any, Callable, Literal + +import numpy as np +from numpy.typing import ArrayLike + +from .path import Path + +class NonIntersectingPathException(ValueError): ... + +def get_intersection( + cx1: float, + cy1: float, + cos_t1: float, + sin_t1: float, + cx2: float, + cy2: float, + cos_t2: float, + sin_t2: float, +) -> tuple[float, float]: ... +def get_normal_points( + cx: float, cy: float, cos_t: float, sin_t: float, length: float +) -> tuple[float, float, float, float]: ... +def split_de_casteljau(beta: ArrayLike, t: float) -> tuple[np.ndarray, np.ndarray]: ... +def find_bezier_t_intersecting_with_closedpath( + bezier_point_at_t: Callable[[float], tuple[float, float]], + inside_closedpath: Callable[[tuple[float, float]], bool], + t0: float = ..., + t1: float = ..., + tolerance: float = ..., +) -> tuple[float, float]: ... + +# TODO make generic over d, the dimension? ndarraydim +class BezierSegment: + def __init__(self, control_points: ArrayLike) -> None: ... + def __call__(self, t: ArrayLike) -> np.ndarray: ... + def point_at_t(self, t: float) -> tuple[float, ...]: ... + @property + def control_points(self) -> np.ndarray: ... + @property + def dimension(self) -> int: ... + @property + def degree(self) -> int: ... + @property + def polynomial_coefficients(self) -> np.ndarray: ... + def axis_aligned_extrema(self) -> tuple[np.ndarray, np.ndarray]: ... + +def split_bezier_intersecting_with_closedpath( + bezier: ArrayLike, + inside_closedpath: Callable[[tuple[float, float]], bool], + tolerance: float = ..., +) -> tuple[np.ndarray, np.ndarray]: ... +def split_path_inout( + path: Path, + inside: Callable[[tuple[float, float]], bool], + tolerance: float = ..., + reorder_inout: bool = ..., +) -> tuple[Path, Path]: ... +def inside_circle( + cx: float, cy: float, r: float +) -> Callable[[tuple[float, float]], bool]: ... +def get_cos_sin(x0: float, y0: float, x1: float, y1: float) -> tuple[float, float]: ... +def check_if_parallel( + dx1: float, dy1: float, dx2: float, dy2: float, tolerance: float = ... +) -> Literal[-1, False, 1]: ... +def get_parallels( + bezier2: ArrayLike, width: float +) -> tuple[list[tuple[float, float]], list[tuple[float, float]]]: ... +def find_control_points( + c1x: float, c1y: float, mmx: float, mmy: float, c2x: float, c2y: float +) -> list[tuple[float, float]]: ... +def make_wedged_bezier2( + bezier2: ArrayLike, width: float, w1: float = ..., wm: float = ..., w2: float = ... +) -> tuple[list[tuple[float, float]], list[tuple[float, float]]]: ... diff --git a/lib/matplotlib/category.py b/lib/matplotlib/category.py index 280a9802f2fb..4ac2379ea5f5 100644 --- a/lib/matplotlib/category.py +++ b/lib/matplotlib/category.py @@ -53,17 +53,6 @@ def convert(value, unit, axis): StrCategoryConverter._validate_unit(unit) # dtype = object preserves numerical pass throughs values = np.atleast_1d(np.array(value, dtype=object)) - # pass through sequence of non binary numbers - with _api.suppress_matplotlib_deprecation_warning(): - is_numlike = all(units.ConversionInterface.is_numlike(v) - and not isinstance(v, (str, bytes)) - for v in values) - if values.size and is_numlike: - _api.warn_deprecated( - "3.5", message="Support for passing numbers through unit " - "converters is deprecated since %(since)s and support will be " - "removed %(removal)s; use Axis.convert_units instead.") - return np.asarray(values, dtype=float) # force an update so it also does type checking unit.update(values) return np.vectorize(unit._mapping.__getitem__, otypes=[float])(values) diff --git a/lib/matplotlib/cbook.pyi b/lib/matplotlib/cbook.pyi new file mode 100644 index 000000000000..0eb46314f8da --- /dev/null +++ b/lib/matplotlib/cbook.pyi @@ -0,0 +1,156 @@ +import collections.abc +from collections.abc import Collection, Generator +import contextlib +import io +import os +from pathlib import Path + +from matplotlib.artist import Artist + +import numpy as np +from numpy.typing import ArrayLike + +from typing import ( + Any, + Callable, + Iterable, + Iterator, + Generic, + Literal, + TypeVar, + Type, + overload, +) + +T = TypeVar("T") + +class CallbackRegistry: + exception_handler: Callable[[Exception], Any] + callbacks: dict[Any, dict[int, Any]] + def __init__( + self, + exception_handler: Callable[[Exception], Any] | None = ..., + *, + signals: Iterable[Any] | None = ... + ) -> None: ... + def connect(self, signal: Any, func: Callable) -> int: ... + def disconnect(self, cid: int) -> None: ... + def process(self, s: Any, *args, **kwargs) -> None: ... + @contextlib.contextmanager + def blocked(self, *, signal: Any | None = ...): ... + +class silent_list(list[T]): + type: str | None + def __init__(self, type, seq: Iterable[T] | None = ...) -> None: ... + +def strip_math(s: str) -> str: ... +def is_writable_file_like(obj: Any) -> bool: ... +def file_requires_unicode(x: Any) -> bool: ... +def to_filehandle( + fname: str | os.PathLike | io.FileIO, + flag: str = ..., + return_opened: bool = ..., + encoding: str | None = ..., +) -> io.FileIO: ... +def open_file_cm( + path_or_file: str | os.PathLike | io.FileIO, + mode: str = ..., + encoding: str | None = ..., +): ... +def is_scalar_or_string(val: Any) -> bool: ... +@overload +def get_sample_data( + fname: str | os.PathLike | io.FileIO, + asfileobj: Literal[True] = ..., + *, + np_load: bool = ... +) -> io.FileIO: ... +@overload +def get_sample_data( + fname: str | os.PathLike | io.FileIO, + asfileobj: Literal[False], + *, + np_load: bool = ... +) -> str: ... +def _get_data_path(*args: Path | str) -> Path: ... +def flatten( + seq: Iterable[Any], scalarp: Callable[[Any], bool] = ... +) -> Generator[Any, None, None]: ... + +class Stack(Generic[T]): + def __init__(self, default: T | None = ...) -> None: ... + def __call__(self) -> T: ... + def __len__(self) -> int: ... + def __getitem__(self, ind: int) -> T: ... + def forward(self) -> T: ... + def back(self) -> T: ... + def push(self, o: T) -> T: ... + def home(self) -> T: ... + def empty(self) -> bool: ... + def clear(self) -> None: ... + def bubble(self, o: T) -> T: ... + def remove(self, o: T) -> None: ... + +def safe_masked_invalid(x: ArrayLike, copy: bool = ...) -> np.ndarray: ... +def print_cycles( + objects: Iterable[Any], outstream: io.FileIO = ..., show_progress: bool = ... +) -> None: ... + +class Grouper(Generic[T]): + def __init__(self, init: Iterable[T] = ...) -> None: ... + def __contains__(self, item: T) -> bool: ... + def clean(self) -> None: ... + def join(self, a: T, *args: T) -> None: ... + def joined(self, a: T, b: T) -> bool: ... + def remove(self, a: T) -> None: ... + def __iter__(self) -> Iterator[list[T]]: ... + def get_siblings(self, a: T) -> list[T]: ... + +class GrouperView(Generic[T]): + def __init__(self, grouper: Grouper[T]) -> None: ... + def __contains__(self, item: T) -> bool: ... + def __iter__(self) -> Iterator[list[T]]: ... + def joined(self, a: T, b: T) -> bool: ... + def get_siblings(self, a: T) -> list[T]: ... + +def simple_linear_interpolation(a: ArrayLike, steps: int) -> np.ndarray: ... +def delete_masked_points(*args): ... +def boxplot_stats( + X: ArrayLike, + whis: float | tuple[float, float] = ..., + bootstrap: int | None = ..., + labels: ArrayLike | None = ..., + autorange: bool = ..., +) -> list[dict[str, Any]]: ... + +ls_mapper: dict[str, str] +ls_mapper_r: dict[str, str] + +def contiguous_regions(mask: ArrayLike) -> list[np.ndarray]: ... +def is_math_text(s: str) -> bool: ... +def violin_stats( + X: ArrayLike, method: Callable, points: int = ..., quantiles: ArrayLike | None = ... +) -> list[dict[str, Any]]: ... +def pts_to_prestep(x: ArrayLike, *args: ArrayLike) -> np.ndarray: ... +def pts_to_poststep(x: ArrayLike, *args: ArrayLike) -> np.ndarray: ... +def pts_to_midstep(x: np.ndarray, *args: np.ndarray) -> np.ndarray: ... + +STEP_LOOKUP_MAP: dict[str, Callable] + +def index_of(y: float | ArrayLike) -> tuple[np.ndarray, np.ndarray]: ... +def safe_first_element(obj: Collection[T]) -> T: ... +def sanitize_sequence(data): ... +def normalize_kwargs( + kw: dict[str, Any], + alias_mapping: dict[str, list[str]] | Type[Artist] | Artist | None = ..., +) -> dict[str, Any]: ... + +class _OrderedSet(collections.abc.MutableSet): + def __init__(self) -> None: ... + def __contains__(self, key) -> bool: ... + def __iter__(self): ... + def __len__(self) -> int: ... + def add(self, key) -> None: ... + def discard(self, key) -> None: ... + +def _format_approx(number: float, precision: int) -> str: ... diff --git a/lib/matplotlib/cm.pyi b/lib/matplotlib/cm.pyi new file mode 100644 index 000000000000..2c77f1cf45ed --- /dev/null +++ b/lib/matplotlib/cm.pyi @@ -0,0 +1,54 @@ +from collections.abc import Mapping +from matplotlib import cbook, colors, scale +from matplotlib.colorbar import Colorbar +from matplotlib._cm import datad + +import numpy as np +from numpy.typing import ArrayLike +from typing import Iterator + +class ColormapRegistry(Mapping[str, colors.Colormap]): + def __init__(self, cmaps: Mapping[str, colors.Colormap]) -> None: ... + def __getitem__(self, item: str) -> colors.Colormap: ... + def __iter__(self) -> Iterator[str]: ... + def __len__(self) -> int: ... + def __call__(self) -> list[str]: ... + def register( + self, cmap: colors.Colormap, *, name: str | None = ..., force: bool = ... + ) -> None: ... + def unregister(self, name: str) -> None: ... + def get_cmap(self, cmap: str | colors.Colormap): ... + +_colormaps: ColormapRegistry = ... + +class ScalarMappable: + cmap: colors.Colormap | None + colorbar: Colorbar | None + callbacks: cbook.CallbackRegistry + def __init__( + self, + norm: colors.Normalize | None = ..., + cmap: str | colors.Colormap | None = ..., + ) -> None: ... + def to_rgba( + self, + x: np.ndarray, + alpha: float | ArrayLike | None = ..., + bytes: bool = ..., + norm: bool = ..., + ) -> np.ndarray: ... + def set_array(self, A: ArrayLike | None) -> None: ... + def get_array(self) -> np.ndarray | None: ... + def get_cmap(self) -> colors.Colormap: ... + def get_clim(self) -> tuple[float, float]: ... + def set_clim(self, vmin: float | None = ..., vmax: float | None = ...) -> None: ... + def get_alpha(self) -> float | None: ... + def set_cmap(self, cmap: str | colors.Colormap) -> None: ... + @property + def norm(self) -> colors.Normalize: ... + @norm.setter + def norm(self, norm: colors.Normalize | str | None) -> None: ... + def set_norm(self, norm: colors.Normalize | str | None) -> None: ... + def autoscale(self) -> None: ... + def autoscale_None(self) -> None: ... + def changed(self) -> None: ... diff --git a/lib/matplotlib/collections.pyi b/lib/matplotlib/collections.pyi new file mode 100644 index 000000000000..4536e2d3cd2f --- /dev/null +++ b/lib/matplotlib/collections.pyi @@ -0,0 +1,216 @@ +from . import artist, cbook, cm, transforms +from .backend_bases import MouseEvent +from .artist import Artist +from .colors import Color, Normalize, Colormap +from .lines import LineStyleType +from .path import Path +from .patches import Patch +from .ticker import Locator, Formatter +from .tri import Triangulation +from ._enums import CapStyle, JoinStyle + +import numpy as np +from numpy.typing import ArrayLike +from typing import Callable, Iterable, Literal, Sequence + +class Collection(artist.Artist, cm.ScalarMappable): + def __init__( + self, + edgecolors: Color | Sequence[Color] | None = ..., + facecolors: Color | Sequence[Color] | None = ..., + linewidths: float | Sequence[float] | None = ..., + linestyles: LineStyleType | Sequence[LineStyleType] = ..., + capstyle: CapStyle | None = ..., + joinstyle: JoinStyle | None = ..., + antialiaseds: bool | Sequence[bool] | None = ..., + offsets: tuple[float, float] | Sequence[tuple[float, float]] | None = ..., + offset_transform: transforms.Transform | None = ..., + norm: Normalize | None = ..., + cmap: Colormap | None = ..., + pickradius: float = ..., + hatch: str | None = ..., + urls: Sequence[str] | None = ..., + *, + zorder: float = ..., + **kwargs + ) -> None: ... + def get_paths(self) -> Sequence[Path]: ... + def set_paths(self, paths: Sequence[Path]) -> None: ... + def get_transforms(self) -> Sequence[transforms.Transform]: ... + def get_offset_transform(self) -> transforms.Transform: ... + def set_offset_transform(self, offset_transform: transforms.Transform) -> None: ... + def get_datalim(self, transData: transforms.Transform) -> transforms.Bbox: ... + def set_pickradius(self, pickradius: float) -> None: ... + def get_pickradius(self) -> float: ... + def set_urls(self, urls: Sequence[str]) -> None: ... + def get_urls(self) -> Sequence[str | None]: ... + def set_hatch(self, hatch: str) -> None: ... + def get_hatch(self) -> str: ... + def set_offsets(self, offsets: ArrayLike) -> None: ... + def get_offsets(self) -> ArrayLike: ... + def set_linewidth(self, lw: float | Sequence[float]) -> None: ... + def set_linestyle(self, ls: LineStyleType | Sequence[LineStyleType]) -> None: ... + def set_capstyle(self, cs: CapStyle | Sequence[CapStyle]) -> None: ... + def get_capstyle(self) -> CapStyle | Sequence[CapStyle]: ... + def set_joinstyle(self, js: JoinStyle | Sequence[JoinStyle]) -> None: ... + def get_joinstyle(self) -> JoinStyle | Sequence[JoinStyle]: ... + def set_antialiased(self, aa: bool | Sequence[bool]) -> None: ... + def set_color(self, c: Color | Sequence[Color]) -> None: ... + def set_facecolor(self, c: Color | Sequence[Color]) -> None: ... + def get_facecolor(self) -> Color | Sequence[Color]: ... + def get_edgecolor(self) -> Color | Sequence[Color]: ... + def set_edgecolor(self, c: Color | Sequence[Color]) -> None: ... + def set_alpha(self, alpha: float | Sequence[float] | None) -> None: ... + def get_linewidth(self) -> float | Sequence[float]: ... + def get_linestyle(self) -> LineStyleType | Sequence[LineStyleType]: ... + def update_scalarmappable(self) -> None: ... + def get_fill(self) -> bool: ... + def update_from(self, other: Artist) -> None: ... + +class _CollectionWithSizes(Collection): + def get_sizes(self) -> np.ndarray: ... + def set_sizes(self, sizes: ArrayLike | None, dpi: float = ...) -> None: ... + +class PathCollection(_CollectionWithSizes): + def __init__( + self, paths: Sequence[Path], sizes: ArrayLike | None = ..., **kwargs + ) -> None: ... + def set_paths(self, paths: Sequence[Path]) -> None: ... + def get_paths(self) -> Sequence[Path]: ... + def legend_elements( + self, + prop: Literal["colors", "sizes"] = ..., + num: int | Literal["auto"] | ArrayLike | Locator = ..., + fmt: str | Formatter | None = ..., + func: Callable[[ArrayLike], ArrayLike] = ..., + **kwargs + ): ... + +class PolyCollection(_CollectionWithSizes): + def __init__( + self, + verts: Sequence[ArrayLike], + sizes: ArrayLike | None = ..., + closed: bool = ..., + **kwargs + ) -> None: ... + def set_verts( + self, verts: Sequence[ArrayLike | Path], closed: bool = ... + ) -> None: ... + def set_paths(self, verts: Sequence[Path], closed: bool = ...) -> None: ... + def set_verts_and_codes( + self, verts: Sequence[ArrayLike | Path], codes: Sequence[int] + ) -> None: ... + +class BrokenBarHCollection(PolyCollection): + def __init__( + self, + xranges: Iterable[tuple[float, float]], + yrange: tuple[float, float], + **kwargs + ) -> None: ... + @classmethod + def span_where( + cls, x: ArrayLike, ymin: float, ymax: float, where: ArrayLike, **kwargs + ) -> BrokenBarHCollection: ... + +class RegularPolyCollection(_CollectionWithSizes): + def __init__( + self, numsides: int, rotation: float = ..., sizes: ArrayLike = ..., **kwargs + ) -> None: ... + def get_numsides(self) -> int: ... + def get_rotation(self) -> float: ... + +class StarPolygonCollection(RegularPolyCollection): ... +class AsteriskPolygonCollection(RegularPolyCollection): ... + +class LineCollection(Collection): + def __init__( + self, segments: Sequence[ArrayLike], *, zorder: float = ..., **kwargs + ) -> None: ... + def set_segments(self, segments: Sequence[ArrayLike] | None) -> None: ... + def set_verts(self, segments: Sequence[ArrayLike] | None) -> None: ... + def set_paths(self, segments: Sequence[ArrayLike] | None) -> None: ... # type: ignore[override] + def get_segments(self) -> list[np.ndarray]: ... + def set_color(self, c: Color | Sequence[Color]) -> None: ... + def set_colors(self, c: Color | Sequence[Color]) -> None: ... + def get_color(self) -> Color | Sequence[Color]: ... + def get_colors(self) -> Color | Sequence[Color]: ... + +class EventCollection(LineCollection): + def __init__( + self, + positions: ArrayLike, + orientation: Literal["horizontal", "vertical"] = ..., + lineoffset: float = ..., + linelength: float = ..., + linewidth: float | Sequence[float] | None = ..., + color: Color | Sequence[Color] | None = ..., + linestyle: LineStyleType | Sequence[LineStyleType] = ..., + antialiased: bool | Sequence[bool] | None = ..., + **kwargs + ) -> None: ... + def get_positions(self) -> list[float]: ... + def set_positions(self, positions: Sequence[float] | None) -> None: ... + def add_positions(self, position: Sequence[float] | None) -> None: ... + def extend_positions(self, position: Sequence[float] | None) -> None: ... + def append_positions(self, position: Sequence[float] | None) -> None: ... + def is_horizontal(self) -> bool: ... + def get_orientation(self) -> Literal["horizontal", "vertical"]: ... + def switch_orientation(self) -> None: ... + def set_orientation( + self, orientation: Literal["horizontal", "vertical"] + ) -> None: ... + def get_linelength(self) -> float | Sequence[float]: ... + def set_linelength(self, linelength: float | Sequence[float]) -> None: ... + def get_lineoffset(self) -> float: ... + def set_lineoffset(self, lineoffset: float) -> None: ... + def get_linewidth(self) -> float: ... + def get_linewidths(self) -> Sequence[float]: ... + def get_color(self) -> Color: ... + +class CircleCollection(_CollectionWithSizes): + def __init__(self, sizes: float | ArrayLike, **kwargs) -> None: ... + +class EllipseCollection(Collection): + def __init__( + self, + widths: ArrayLike, + heights: ArrayLike, + angles: ArrayLike, + units: Literal[ + "points", "inches", "dots", "width", "height", "x", "y", "xy" + ] = ..., + **kwargs + ) -> None: ... + +class PatchCollection(Collection): + def __init__( + self, patches: Iterable[Patch], match_original: bool = ..., **kwargs + ) -> None: ... + def set_paths(self, patches: Iterable[Patch]) -> None: ... # type: ignore[override] + +class TriMesh(Collection): + def __init__(self, triangulation: Triangulation, **kwargs) -> None: ... + def get_paths(self) -> list[Path]: ... + # Parent class has an argument, perhaps add a noop arg? + def set_paths(self) -> None: ... # type: ignore[override] + @staticmethod + def convert_mesh_to_paths(tri: Triangulation) -> list[Path]: ... + +class QuadMesh(Collection): + def __init__( + self, + coordinates: ArrayLike, + *, + antialiased: bool = ..., + shading: Literal["flat", "gouraud"] = ..., + **kwargs + ) -> None: ... + def get_paths(self) -> list[Path]: ... + # Parent class has an argument, perhaps add a noop arg? + def set_paths(self) -> None: ... # type: ignore[override] + def set_array(self, A: ArrayLike | None) -> None: ... + def get_datalim(self, transData: transforms.Transform) -> transforms.Bbox: ... + def get_coordinates(self) -> ArrayLike: ... + def get_cursor_data(self, event: MouseEvent) -> float: ... diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 0a8b23251e6a..966eb0760b47 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -875,9 +875,7 @@ def _get_ticker_locator_formatter(self): self._minorlocator = minorlocator _log.debug('locator: %r', locator) - @_api.delete_parameter("3.5", "update_ticks") - def set_ticks(self, ticks, update_ticks=True, labels=None, *, - minor=False, **kwargs): + def set_ticks(self, ticks, *, labels=None, minor=False, **kwargs): """ Set tick locations. @@ -916,9 +914,7 @@ def get_ticks(self, minor=False): else: return self._long_axis().get_majorticklocs() - @_api.delete_parameter("3.5", "update_ticks") - def set_ticklabels(self, ticklabels, update_ticks=True, *, minor=False, - **kwargs): + def set_ticklabels(self, ticklabels, *, minor=False, **kwargs): """ [*Discouraged*] Set tick labels. diff --git a/lib/matplotlib/colorbar.pyi b/lib/matplotlib/colorbar.pyi new file mode 100644 index 000000000000..1460c387f960 --- /dev/null +++ b/lib/matplotlib/colorbar.pyi @@ -0,0 +1,129 @@ +import matplotlib.spines as mspines +from matplotlib import cbook, cm, collections, colors, contour, ticker +from matplotlib.axes import Axes +from matplotlib.patches import Patch +from matplotlib.ticker import Locator, Formatter + +import numpy as np +from numpy.typing import ArrayLike +from typing import Any, Literal, Sequence, overload + +class _ColorbarSpine(mspines.Spines): + def __init__(self, axes: Axes): ... + +class Colorbar: + n_rasterize: int + mappable: cm.ScalarMappable + ax: Axes + alpha: float + cmap: colors.Colormap + norm: colors.Normalize + values: Sequence[float] | None + boundaries: Sequence[float] | None + extend: Literal["neither", "both", "min", "max"] + spacing: Literal["uniform", "proportional"] + orientation: Literal["vertical", "horizontal"] + drawedges: bool + extendfrac: Literal["auto"] | float | Sequence[float] | None + extendrect: bool + solids: None | collections.QuadMesh + solids_patches: list[Patch] + lines: list[collections.LineCollection] + outline: _ColorbarSpine + dividers: collections.LineCollection + ticklocation: Literal["left", "right", "top", "bottom"] + def __init__( + self, + ax: Axes, + mappable: cm.ScalarMappable | None = ..., + *, + cmap: str | colors.Colormap | None = ..., + norm: colors.Normalize | None = ..., + alpha: float | None = ..., + values: Sequence[float] | None = ..., + boundaries: Sequence[float] | None = ..., + orientation: Literal["vertical", "horizontal"] | None = ..., + ticklocation: Literal["auto", "left", "right", "top", "bottom"] = ..., + extend: Literal["neither", "both", "min", "max"] | None = ..., + spacing: Literal["uniform", "proportional"] = ..., + ticks: Sequence[float] | Locator | None = ..., + format: str | Formatter | None = ..., + drawedges: bool = ..., + filled: bool = ..., + extendfrac: Literal["auto"] | float | Sequence[float] | None = ..., + extendrect: bool = ..., + label: str = ..., + location: Literal["left", "right", "top", "bottom"] | None = ... + ) -> None: ... + @property + def locator(self) -> Locator: ... + @locator.setter + def locator(self, loc: Locator) -> None: ... + @property + def minorlocator(self) -> Locator: ... + @minorlocator.setter + def minorlocator(self, loc: Locator) -> None: ... + @property + def formatter(self) -> Formatter: ... + @formatter.setter + def formatter(self, fmt: Formatter) -> None: ... + @property + def minorformatter(self) -> Formatter: ... + @minorformatter.setter + def minorformatter(self, fmt: Formatter) -> None: ... + def update_normal(self, mappable: cm.ScalarMappable) -> None: ... + @overload + def add_lines(self, CS: contour.ContourSet, erase: bool = ...) -> None: ... + @overload + def add_lines( + self, + levels: ArrayLike, + colors: colors.Color | Sequence[colors.Color], + linewidths: float | ArrayLike, + erase: bool = ..., + ) -> None: ... + def update_ticks(self) -> None: ... + def set_ticks( + self, + ticks: Sequence[float] | Locator, + *, + labels: Sequence[str] | None = ..., + minor: bool = ..., + **kwargs + ) -> None: ... + def get_ticks(self, minor: bool = ...) -> np.ndarray: ... + def set_ticklabels( + self, + ticklabels: Sequence[str], + *, + minor: bool = ..., + **kwargs + ) -> None: ... + def minorticks_on(self) -> None: ... + def minorticks_off(self) -> None: ... + def set_label(self, label: str, *, loc: str | None = ..., **kwargs) -> None: ... + def set_alpha(self, alpha: float | np.ndarray) -> None: ... + def remove(self) -> None: ... + def drag_pan(self, button: Any, key: Any, x: float, y: float) -> None: ... + +ColorbarBase = Colorbar + +def make_axes( + parents: Axes | list[Axes] | np.ndarray, + location: Literal["left", "right", "top", "bottom"] | None = ..., + orientation: Literal["vertical", "horizontal"] | None = ..., + fraction: float = ..., + shrink: float = ..., + aspect: float = ..., + **kwargs +): ... +def make_axes_gridspec( + parent: Axes, + *, + location: Literal["left", "right", "top", "bottom"] | None = ..., + orientation: Literal["vertical", "horizontal"] | None = ..., + fraction: float = ..., + shrink: float = ..., + aspect: float = ..., + **kwargs +): ... diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 2d3072da04de..c1fea37902b7 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -48,6 +48,8 @@ import itertools from numbers import Number import re +from typing import Union + from PIL import Image from PIL.PngImagePlugin import PngInfo @@ -56,6 +58,12 @@ from matplotlib import _api, _cm, cbook, scale from ._color_data import BASE_COLORS, TABLEAU_COLORS, CSS4_COLORS, XKCD_COLORS +Color = Union[ + tuple[float, float, float], + tuple[float, float, float, float], + str, +] + class _ColorMapping(dict): def __init__(self, mapping): diff --git a/lib/matplotlib/colors.pyi b/lib/matplotlib/colors.pyi new file mode 100644 index 000000000000..d42f2ac1a164 --- /dev/null +++ b/lib/matplotlib/colors.pyi @@ -0,0 +1,313 @@ +from ._color_data import BASE_COLORS, CSS4_COLORS, TABLEAU_COLORS, XKCD_COLORS +from collections.abc import Mapping +from matplotlib import cbook, scale +import re + +from typing import Any, Callable, Sequence, Iterable, Iterator, Literal, Type, Union, overload + +import numpy as np +from numpy.typing import ArrayLike + +Color = Union[tuple[float, float, float], tuple[float, float, float, float], str] + +class _ColorMapping(dict[str, Color]): + cache: dict[tuple[Color, float | None], tuple[float, float, float, float]] + def __init__(self, mapping) -> None: ... + def __setitem__(self, key, value) -> None: ... + def __delitem__(self, key) -> None: ... + +def get_named_colors_mapping() -> _ColorMapping: ... + +class ColorSequenceRegistry(Mapping): + def __init__(self) -> None: ... + def __getitem__(self, item: str) -> list[Color]: ... + def __iter__(self) -> Iterator[str]: ... + def __len__(self) -> int: ... + def register(self, name: str, color_list: Iterable[Color]) -> None: ... + def unregister(self, name: str) -> None: ... + +_color_sequences: ColorSequenceRegistry = ... + +def is_color_like(c: Any) -> bool: ... +def same_color(c1: Color, c2: Color) -> bool: ... +def to_rgba( + c: Color, alpha: float | None = ... +) -> tuple[float, float, float, float]: ... +def to_rgba_array( + c: Color | ArrayLike, alpha: float | ArrayLike | None = ... +) -> np.ndarray: ... +def to_rgb(c: Color) -> tuple[float, float, float]: ... +def to_hex(c: Color, keep_alpha: bool = ...) -> str: ... + +cnames: dict[str, Color] = CSS4_COLORS +hexColorPattern: re.Pattern +rgb2hex = to_hex +hex2color = to_rgb + +class ColorConverter: + colors: _ColorMapping + cache: dict[tuple[Color, float | None], tuple[float, float, float, float]] + @staticmethod + def to_rgb(c: Color) -> tuple[float, float, float]: ... + @staticmethod + def to_rgba( + c: Color, alpha: float | None = ... + ) -> tuple[float, float, float, float]: ... + @staticmethod + def to_rgba_array( + c: Color | ArrayLike, alpha: float | ArrayLike | None = ... + ) -> np.ndarray: ... + +colorConverter: ColorConverter + +class Colormap: + name: str + N: int + colorbar_extend: bool + def __init__(self, name: str, N: int = ...) -> None: ... + def __call__( + self, X: ArrayLike, alpha: ArrayLike | None = ..., bytes: bool = ... + ) -> tuple[float, float, float, float] | np.ndarray: ... + def __copy__(self) -> Colormap: ... + def __eq__(self, other: Any) -> bool: ... + def get_bad(self) -> np.ndarray: ... + def set_bad(self, color: Color = ..., alpha: float | None = ...) -> None: ... + def get_under(self) -> np.ndarray: ... + def set_under(self, color: Color = ..., alpha: float | None = ...) -> None: ... + def get_over(self) -> np.ndarray: ... + def set_over(self, color: Color = ..., alpha: float | None = ...) -> None: ... + def set_extremes( + self, + *, + bad: Color | None = ..., + under: Color | None = ..., + over: Color | None = ... + ) -> None: ... + def with_extremes( + self, + *, + bad: Color | None = ..., + under: Color | None = ..., + over: Color | None = ... + ) -> Colormap: ... + def is_gray(self) -> bool: ... + def resampled(self, lutsize: int) -> Colormap: ... + def reversed(self, name: str | None = ...) -> Colormap: ... + def copy(self) -> Colormap: ... + +class LinearSegmentedColormap(Colormap): + monochrome: bool + def __init__( + self, + name: str, + segmentdata: dict[ + Literal["red", "green", "blue", "alpha"], Sequence[tuple[float, ...]] + ], + N: int = ..., + gamma: float = ..., + ) -> None: ... + def set_gamma(self, gamma: float) -> None: ... + @staticmethod + def from_list( + name: str, colors: ArrayLike, N: int = ..., gamma: float = ... + ) -> LinearSegmentedColormap: ... + def resampled(self, lutsize: int) -> LinearSegmentedColormap: ... + def reversed(self, name: str | None = ...) -> LinearSegmentedColormap: ... + +class ListedColormap(Colormap): + monochrome: bool + colors: ArrayLike | Color + def __init__( + self, colors: ArrayLike | Color, name: str = ..., N: int | None = ... + ) -> None: ... + def resampled(self, lutsize: int) -> ListedColormap: ... + def reversed(self, name: str | None = ...) -> ListedColormap: ... + +class Normalize: + callbacks: cbook.CallbackRegistry + def __init__( + self, vmin: float | None = ..., vmax: float | None = ..., clip: bool = ... + ) -> None: ... + @property + def vmin(self) -> float | None: ... + @vmin.setter + def vmin(self, value: float | None) -> None: ... + @property + def vmax(self) -> float | None: ... + @vmax.setter + def vmax(self, value: float | None) -> None: ... + @property + def clip(self) -> bool: ... + @clip.setter + def clip(self, value: bool) -> None: ... + @staticmethod + def process_value(value: ArrayLike) -> tuple[np.ma.MaskedArray, bool]: ... + def __call__(self, value: ArrayLike, clip: bool | None = ...) -> ArrayLike: ... + def inverse(self, value: ArrayLike) -> ArrayLike: ... + def autoscale(self, A: ArrayLike) -> None: ... + def autoscale_None(self, A: ArrayLike) -> None: ... + def scaled(self) -> bool: ... + +class TwoSlopeNorm(Normalize): + def __init__( + self, vcenter: float, vmin: float | None = ..., vmax: float | None = ... + ) -> None: ... + @property + def vcenter(self) -> float: ... + @vcenter.setter + def vcenter(self, value: float) -> None: ... + def autoscale_None(self, A: ArrayLike) -> None: ... + def __call__(self, value: ArrayLike, clip: bool | None = ...) -> ArrayLike: ... + def inverse(self, value: ArrayLike) -> ArrayLike: ... + +class CenteredNorm(Normalize): + def __init__( + self, vcenter: float = ..., halfrange: float | None = ..., clip: bool = ... + ) -> None: ... + @property + def vcenter(self) -> float: ... + @vcenter.setter + def vcenter(self, vcenter: float) -> None: ... + @property + def halfrange(self) -> float: ... + @halfrange.setter + def halfrange(self, halfrange: float) -> None: ... + +@overload +def make_norm_from_scale( + scale_cls: Type[scale.ScaleBase], + base_norm_cls: Type[Normalize], + *, + init: Callable | None = ... +) -> Type[Normalize]: ... +@overload +def make_norm_from_scale( + scale_cls: Type[scale.ScaleBase], + base_norm_cls: None = ..., + *, + init: Callable | None = ... +) -> Callable[[Type[Normalize]], Type[Normalize]]: ... + +class FuncNorm(Normalize): ... +class LogNorm(Normalize): ... + +class SymLogNorm(Normalize): + @property + def linthresh(self) -> float: ... + @linthresh.setter + def linthresh(self, value: float) -> None: ... + +class AsinhNorm(Normalize): + @property + def linear_width(self) -> float: ... + @linear_width.setter + def linear_width(self, value: float) -> None: ... + +class PowerNorm(Normalize): + gamma: float + def __init__( + self, + gamma: float, + vmin: float | None = ..., + vmax: float | None = ..., + clip: bool = ..., + ) -> None: ... + def __call__(self, value: ArrayLike, clip: bool | None = ...) -> ArrayLike: ... + def inverse(self, value: ArrayLike) -> ArrayLike: ... + +class BoundaryNorm(Normalize): + boundaries: np.ndarray + N: int + Ncmap: int + extend: Literal["neither", "both", "min", "max"] + def __init__( + self, + boundaries: ArrayLike, + ncolors: int, + clip: bool = ..., + *, + extend: Literal["neither", "both", "min", "max"] = ... + ) -> None: ... + def __call__(self, value: ArrayLike, clip: bool | None = ...) -> ArrayLike: ... + def inverse(self, value: ArrayLike) -> ArrayLike: ... + +class NoNorm(Normalize): + def __call__(self, value: ArrayLike, clip: bool | None = ...) -> ArrayLike: ... + def inverse(self, value: ArrayLike) -> ArrayLike: ... + +def rgb_to_hsv(arr: ArrayLike) -> np.ndarray: ... +def hsv_to_rgb(hsv: ArrayLike) -> np.ndarray: ... + +class LightSource: + azdeg: float + altdeg: float + hsv_min_val: float + hsv_max_val: float + hsv_min_sat: float + hsv_max_sat: float + def __init__( + self, + azdeg: float = ..., + altdeg: float = ..., + hsv_min_val: float = ..., + hsv_max_val: float = ..., + hsv_min_sat: float = ..., + hsv_max_sat: float = ..., + ) -> None: ... + @property + def direction(self) -> np.ndarray: ... + def hillshade( + self, + elevation: ArrayLike, + vert_exag: float = ..., + dx: float = ..., + dy: float = ..., + fraction: float = ..., + ) -> np.ndarray: ... + def shade_normals( + self, normals: np.ndarray, fraction: float = ... + ) -> np.ndarray: ... + def shade( + self, + data: ArrayLike, + cmap: Colormap, + norm: Normalize | None = ..., + blend_mode: Literal["hsv", "overlay", "soft"] | Callable = ..., + vmin: float | None = ..., + vmax: float | None = ..., + vert_exag: float = ..., + dx: float = ..., + dy: float = ..., + fraction: float = ..., + **kwargs + ) -> np.ndarray: ... + def shade_rgb( + self, + rgb: ArrayLike, + elevation: ArrayLike, + fraction: float = ..., + blend_mode: Literal["hsv", "overlay", "soft"] | Callable = ..., + vert_exag: float = ..., + dx: float = ..., + dy: float = ..., + **kwargs + ) -> np.ndarray: ... + def blend_hsv( + self, + rgb: ArrayLike, + intensity: ArrayLike, + hsv_max_sat: float | None = ..., + hsv_max_val: float | None = ..., + hsv_min_val: float | None = ..., + hsv_min_sat: float | None = ..., + ) -> ArrayLike: ... + def blend_soft_light( + self, rgb: np.ndarray, intensity: np.ndarray + ) -> np.ndarray: ... + def blend_overlay(self, rgb: np.ndarray, intensity: np.ndarray) -> np.ndarray: ... + +def from_levels_and_colors( + levels: Sequence[float], + colors: Sequence[Color], + extend: Literal["neither", "min", "max", "both"] = ..., +) -> tuple[ListedColormap, BoundaryNorm]: ... diff --git a/lib/matplotlib/container.pyi b/lib/matplotlib/container.pyi new file mode 100644 index 000000000000..e9c9a7fb8a00 --- /dev/null +++ b/lib/matplotlib/container.pyi @@ -0,0 +1,56 @@ +from matplotlib import cbook +from matplotlib.artist import Artist +from matplotlib.lines import Line2D +from matplotlib.collections import LineCollection +from matplotlib.patches import Rectangle + +from typing import Any, Callable, Literal +from numpy.typing import ArrayLike + +class Container(tuple): + def __new__(cls, *args, **kwargs): ... + def __init__(self, kl, label: Any | None = ...) -> None: ... + def remove(self): ... + def get_children(self): ... + def get_label(self) -> str | None: ... + def set_label(self, s: Any) -> None: ... + def add_callback(self, func: Callable[[Artist], Any]) -> int: ... + def remove_callback(self, oid: int) -> None: ... + def pchanged(self) -> None: ... + +class BarContainer(Container): + patches: list[Rectangle] + errorbar: None | ErrorbarContainer + datavalues: None | ArrayLike + orientation: None | Literal["vertical", "horizontal"] + def __init__( + self, + patches: list[Rectangle], + errorbar: ErrorbarContainer | None = ..., + *, + datavalues: ArrayLike | None = ..., + orientation: Literal["vertical", "horizontal"] | None = ..., + **kwargs + ) -> None: ... + +class ErrorbarContainer(Container): + lines: tuple[Line2D, Line2D, LineCollection] + has_xerr: bool + has_yerr: bool + def __init__( + self, + lines: tuple[Line2D, Line2D, LineCollection], + has_xerr: bool = ..., + has_yerr: bool = ..., + **kwargs + ) -> None: ... + +class StemContainer(Container): + markerline: Line2D + stemlines: LineCollection + baseline: Line2D + def __init__( + self, + markerline_stemlines_baseline: tuple[Line2D, LineCollection, Line2D], + **kwargs + ) -> None: ... diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index bbcc2a9ce433..42096958bb93 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1137,18 +1137,8 @@ def _process_contour_level_args(self, args, z_dtype): self.levels = self._autolev(levels_arg) else: self.levels = np.asarray(levels_arg, np.float64) - - if not self.filled: - inside = (self.levels > self.zmin) & (self.levels < self.zmax) - levels_in = self.levels[inside] - if len(levels_in) == 0: - self.levels = [self.zmin] - _api.warn_external( - "No contour levels were found within the data range.") - if self.filled and len(self.levels) < 2: raise ValueError("Filled contours require at least 2 levels.") - if len(self.levels) > 1 and np.min(np.diff(self.levels)) <= 0.0: raise ValueError("Contour levels must be increasing") diff --git a/lib/matplotlib/contour.pyi b/lib/matplotlib/contour.pyi new file mode 100644 index 000000000000..b0c6efb0883d --- /dev/null +++ b/lib/matplotlib/contour.pyi @@ -0,0 +1,153 @@ +import matplotlib.cm as cm +from matplotlib.artist import Artist +from matplotlib.axes import Axes +from matplotlib.backend_bases import MouseButton +from matplotlib.collections import Collection, PathCollection +from matplotlib.colors import Color, Colormap, Normalize +from matplotlib.font_manager import FontProperties +from matplotlib.text import Text +from matplotlib.transforms import Transform +from matplotlib.ticker import Locator, Formatter + +from numpy.typing import ArrayLike +import numpy as np +from typing import Any, Callable, Literal, Iterable, Sequence + +class ClabelText(Text): ... + +class ContourLabeler: + labelFmt: str | Formatter | Callable[[float], str] | dict[float, str] + labelManual: bool | Iterable[tuple[float, float]] + rightside_up: bool + labelLevelList: list[float] + labelIndiceList: list[int] + labelMappable: cm.ScalarMappable + labelCValueList: list[Color] + labelXYs: list[tuple[float, float]] + def clabel( + self, + levels: ArrayLike | None = ..., + *, + fontsize: str | float | None = ..., + inline: bool = ..., + inline_spacing: float = ..., + fmt: str | Formatter | Callable[[float], str] | dict[float, str] | None = ..., + colors: Color | Sequence[Color] | None = ..., + use_clabeltext: bool = ..., + manual: bool | Iterable[tuple[float, float]] = ..., + rightside_up: bool = ..., + zorder: float | None = ... + ) -> list[Text]: ... + @property + def labelFontProps(self) -> FontProperties: ... + @property + def labelFontSizeList(self) -> list[float]: ... + @property + def labelTextsList(self) -> list[Text]: ... + def print_label(self, linecontour: ArrayLike, labelwidth: float) -> bool: ... + def too_close(self, x: float, y: float, lw: float) -> bool: ... + def set_label_props(self, label: Text, text: str, color: Color) -> None: ... + def get_text( + self, + lev: float, + fmt: str | Formatter | Callable[[float], str] | dict[float, str], + ) -> str: ... + def locate_label( + self, linecontour: ArrayLike, labelwidth: float + ) -> tuple[float, float, float]: ... + def calc_label_rot_and_inline( + self, + slc: ArrayLike, + ind: int, + lw: float, + lc: ArrayLike | None = ..., + spacing: int = ..., + ) -> tuple[float, list[ArrayLike]]: ... + def add_label( + self, x: float, y: float, rotation: float, lev: float, cvalue: Color + ) -> None: ... + def add_label_clabeltext( + self, x: float, y: float, rotation: float, lev: float, cvalue: Color + ) -> None: ... + def add_label_near( + self, + x: float, + y: float, + inline: bool = ..., + inline_spacing: int = ..., + transform: Transform | Literal[False] | None = ..., + ) -> None: ... + def pop_label(self, index: int = ...) -> None: ... + def labels(self, inline: bool, inline_spacing: int) -> None: ... + def remove(self) -> None: ... + +class ContourSet(cm.ScalarMappable, ContourLabeler): + axes: Axes + levels: Iterable[float] + filled: bool + linewidths: float | ArrayLike | None + linestyles: None | Literal["solid", "dashed", "dashdot", "dotted"] | Iterable[ + Literal["solid", "dashed", "dashdot", "dotted"] + ] + hatches: Iterable[str | None] + alpha: float | None + origin: Literal["upper", "lower", "image"] | None + extent: tuple[float, float, float, float] | None + colors: Color | Sequence[Color] + extend: Literal["neither", "both", "min", "max"] + antialiased: bool | None + nchunk: int + locator: Locator | None + logscale: bool + negative_linestyles: None | Literal[ + "solid", "dashed", "dashdot", "dotted" + ] | Iterable[Literal["solid", "dashed", "dashdot", "dotted"]] + collections: list[PathCollection] + labelTexts: list[Text] + labelCValues: list[Color] + allkinds: list[np.ndarray] + tcolors: list[tuple[float, float, float, float]] + + # only for not filled + tlinewidths: list[tuple[float]] + + def __init__( + self, + ax: Axes, + *args, + levels: Iterable[float] | None = ..., + filled: bool = ..., + linewidths: float | ArrayLike | None = ..., + linestyles: Literal["solid", "dashed", "dashdot", "dotted"] + | Iterable[Literal["solid", "dashed", "dashdot", "dotted"]] + | None = ..., + hatches: Iterable[str | None] = ..., + alpha: float | None = ..., + origin: Literal["upper", "lower", "image"] | None = ..., + extent: tuple[float, float, float, float] | None = ..., + cmap: str | Colormap | None = ..., + colors: Color | Sequence[Color] | None = ..., + norm: str | Normalize | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + extend: Literal["neither", "both", "min", "max"] = ..., + antialiased: bool | None = ..., + nchunk: int = ..., + locator: Locator | None = ..., + transform: Transform | None = ..., + negative_linestyles: Literal["solid", "dashed", "dashdot", "dotted"] + | Iterable[Literal["solid", "dashed", "dashdot", "dotted"]] + | None = ..., + **kwargs + ) -> None: ... + def get_transform(self) -> Transform: ... + def legend_elements( + self, variable_name: str = ..., str_format: Callable[[float], str] = ... + ) -> tuple[list[Artist], list[str]]: ... + def get_alpha(self) -> float | None: ... + def set_alpha(self, alpha: float | None) -> None: ... + def find_nearest_contour( + self, x: float, y: float, indices: Iterable[int] | None = ..., pixel: bool = ... + ) -> tuple[Collection, int, int, float, float, float]: ... + +class QuadContourSet(ContourSet): ... diff --git a/lib/matplotlib/dviread.pyi b/lib/matplotlib/dviread.pyi new file mode 100644 index 000000000000..af4093954cbe --- /dev/null +++ b/lib/matplotlib/dviread.pyi @@ -0,0 +1,87 @@ +from matplotlib import cbook as cbook +from pathlib import Path +import io +import os +from enum import Enum +from typing import NamedTuple, Generator + +class _dvistate(Enum): + pre: int + outer: int + inpage: int + post_post: int + finale: int + +class Page(NamedTuple): + text: list[Text] + boxes: list[Box] + height: int + width: int + descent: int + +class Box(NamedTuple): + x: int + y: int + height: int + width: int + +class Text(NamedTuple): + x: int + y: int + font: DviFont + glyph: int + width: int + @property + def font_path(self) -> Path: ... + @property + def font_size(self) -> float: ... + @property + def font_effects(self) -> dict[str, float]: ... + @property + def glyph_name_or_index(self) -> int | str: ... + +class Dvi: + file: io.BufferedReader + dpi: float | None + fonts: dict[int, DviFont] + state: _dvistate + def __init__(self, filename: str | os.PathLike, dpi: float | None) -> None: ... + def __enter__(self) -> Dvi: ... + def __exit__(self, etype, evalue, etrace) -> None: ... + def __iter__(self) -> Generator[Page, None, None]: ... + def close(self) -> None: ... + +class DviFont: + texname: bytes + size: float + widths: list[int] + def __init__( + self, scale: float, tfm: Tfm, texname: bytes, vf: Vf | None + ) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + +class Vf(Dvi): + def __init__(self, filename: str | os.PathLike) -> None: ... + def __getitem__(self, code: int): ... + +class Tfm: + checksum: int + design_size: int + width: dict[int, int] + height: dict[int, int] + depth: dict[int, int] + def __init__(self, filename: str | os.PathLike) -> None: ... + +class PsFont(NamedTuple): + texname: bytes + psname: bytes + effects: dict[str, float] + encoding: None | bytes + filename: str + +class PsfontsMap: + def __new__(cls, filename: str | os.PathLike) -> PsfontsMap: ... + def __getitem__(self, texname: bytes) -> PsFont: ... + +def find_tex_file(filename: str | os.PathLike) -> str: ... diff --git a/lib/matplotlib/figure.pyi b/lib/matplotlib/figure.pyi new file mode 100644 index 000000000000..dac8b585d008 --- /dev/null +++ b/lib/matplotlib/figure.pyi @@ -0,0 +1,388 @@ +import io +import os + +from matplotlib import backend_bases, projections +from matplotlib.artist import Artist, allow_rasterization +from matplotlib.axes import Axes, SubplotBase +from matplotlib.backend_bases import ( + DrawEvent, + FigureCanvasBase, + MouseButton, + MouseEvent, + NonGuiException, + RendererBase, +) +from matplotlib.colors import Color, Colormap, Normalize +from matplotlib.colorbar import Colorbar +from matplotlib.cm import ScalarMappable +from matplotlib.gridspec import GridSpec, SubplotSpec +from matplotlib.image import _ImageBase +from matplotlib.layout_engine import ( + ConstrainedLayoutEngine, + LayoutEngine, + PlaceHolderLayoutEngine, + TightLayoutEngine, +) +from matplotlib.legend import Legend +from matplotlib.lines import Line2D +from matplotlib.patches import Rectangle, Patch +from matplotlib.text import Text +from matplotlib.transforms import ( + Affine2D, + Bbox, + BboxBase, + BboxTransformTo, + TransformedBbox, + Transform, +) + +import numpy as np +from numpy.typing import ArrayLike + +from typing import Any, Callable, Iterable, Literal, overload + +class SubplotParams: + def __init__( + self, + left: float | None = ..., + bottom: float | None = ..., + right: float | None = ..., + top: float | None = ..., + wspace: float | None = ..., + hspace: float | None = ..., + ) -> None: ... + left: float + right: float + bottom: float + top: float + wspace: float + hspace: float + def update( + self, + left: float | None = ..., + bottom: float | None = ..., + right: float | None = ..., + top: float | None = ..., + wspace: float | None = ..., + hspace: float | None = ..., + ) -> None: ... + +class FigureBase(Artist): + figure: FigureBase | None + artists: list[Artist] + lines: list[Line2D] + patches: list[Patch] + texts: list[Text] + images: list[_ImageBase] + legends: list[Legend] + subfigs: list[SubFigure] + stale: bool + suppressComposite: bool | None + def __init__(self, **kwargs) -> None: ... + def autofmt_xdate( + self, + bottom: float = ..., + rotation: int = ..., + ha: Literal["left", "center", "right"] = ..., + which: Literal["major", "minor", "both"] = ..., + ) -> None: ... + def get_children(self) -> list[Artist]: ... + def contains(self, mouseevent: MouseEvent) -> tuple[bool, dict[Any, Any]]: ... + def suptitle(self, t: str, **kwargs) -> Text: ... + def supxlabel(self, t: str, **kwargs) -> Text: ... + def supylabel(self, t: str, **kwargs) -> Text: ... + def get_edgecolor(self) -> Color: ... + def get_facecolor(self) -> Color: ... + def get_frameon(self) -> bool: ... + def set_linewidth(self, linewidth: float) -> None: ... + def get_linewidth(self) -> float: ... + def set_edgecolor(self, color: Color) -> None: ... + def set_facecolor(self, color: Color) -> None: ... + def set_frameon(self, b: bool) -> None: ... + @property + def frameon(self) -> bool: ... + @frameon.setter + def frameon(self, b: bool) -> None: ... + def add_artist(self, artist: Artist, clip: bool = ...) -> Artist: ... + @overload + def add_axes(self, ax: Axes) -> Axes: ... + @overload + def add_axes( + self, + rect: tuple[float, float, float, float], + projection: None | str = ..., + polar: bool = ..., + **kwargs + ) -> Axes: ... + + # TODO: docstring indicates SubplotSpec a valid arg, but none of the listed signatures appear to be that + @overload + def add_subplot( + self, nrows: int, ncols: int, index: int | tuple[int, int], **kwargs + ) -> Axes: ... + @overload + def add_subplot(self, pos: int, **kwargs) -> Axes: ... + @overload + def add_subplot(self, ax: Axes) -> Axes: ... + @overload + def add_subplot(self) -> Axes: ... + @overload + def subplots( + self, + nrows: int = ..., + ncols: int = ..., + *, + sharex: bool | Literal["none", "all", "row", "col"] = ..., + sharey: bool | Literal["none", "all", "row", "col"] = ..., + squeeze: Literal[False], + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + subplot_kw: dict[str, Any] | None = ..., + gridspec_kw: dict[str, Any] | None = ... + ) -> np.ndarray: ... + @overload + def subplots( + self, + nrows: int = ..., + ncols: int = ..., + *, + sharex: bool | Literal["none", "all", "row", "col"] = ..., + sharey: bool | Literal["none", "all", "row", "col"] = ..., + squeeze: Literal[True] = ..., + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + subplot_kw: dict[str, Any] | None = ..., + gridspec_kw: dict[str, Any] | None = ... + ) -> np.ndarray | SubplotBase | Axes: ... + def delaxes(self, ax: Axes) -> None: ... + def clear(self, keep_observers: bool = ...) -> None: ... + def clf(self, keep_observers: bool = ...): ... + @overload + def legend(self) -> Legend: ... + @overload + def legend(self, handles: Iterable[Artist], labels: Iterable[str]) -> Legend: ... + @overload + def legend(self, *, handles: Iterable[Artist]) -> Legend: ... + @overload + def legend(self, labels: Iterable[str]) -> Legend: ... + def text( + self, + x: float, + y: float, + s: str, + fontdict: dict[str, Any] | None = ..., + **kwargs + ) -> Text: ... + def colorbar( + self, + mappable: ScalarMappable, + cax: Axes | None = ..., + ax: Axes | Iterable[Axes] | None = ..., + use_gridspec: bool = ..., + **kwargs + ) -> Colorbar: ... + def subplots_adjust( + self, + left: str | None = ..., + bottom: str | None = ..., + right: str | None = ..., + top: str | None = ..., + wspace: str | None = ..., + hspace: str | None = ..., + ) -> None: ... + def align_xlabels(self, axs: Iterable[Axes] | None = ...) -> None: ... + def align_ylabels(self, axs: Iterable[Axes] | None = ...) -> None: ... + def align_labels(self, axs: Iterable[Axes] | None = ...) -> None: ... + def add_gridspec(self, nrows: int = ..., ncols: int = ..., **kwargs): ... + @overload + def subfigures( + self, + nrows: int = ..., + ncols: int = ..., + squeeze: Literal[False] = ..., + wspace: float | None = ..., + hspace: float | None = ..., + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + **kwargs + ) -> np.ndarray: ... + @overload + def subfigures( + self, + nrows: int = ..., + ncols: int = ..., + squeeze: Literal[True] = ..., + wspace: float | None = ..., + hspace: float | None = ..., + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + **kwargs + ) -> np.ndarray | SubFigure: ... + def add_subfigure(self, subplotspec: SubplotSpec, **kwargs) -> SubFigure: ... + def sca(self, a: Axes) -> Axes: ... + def gca(self) -> Axes: ... + def _gci(self) -> ScalarMappable | None: ... + def _process_projection_requirements( + self, *args, axes_class=None, polar=False, projection=None, **kwargs + ): ... + def get_default_bbox_extra_artists(self) -> list[Artist]: ... + def get_tightbbox( + self, + renderer: RendererBase | None = ..., + bbox_extra_artists: Iterable[Artist] | None = ..., + ) -> Bbox: ... + + # Any in list of list is recursive list[list[Hashable | list[Hashable | ...]]] but that can't really be type checked + def subplot_mosaic( + self, + mosaic: str | list[list[Any]], + *, + sharex: bool = ..., + sharey: bool = ..., + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + empty_sentinel: Any = ..., + subplot_kw: dict[str, Any] | None = ..., + per_subplot_kw: dict[Any, dict[str, Any]] | None = ..., + gridspec_kw: dict[str, Any] | None = ... + ) -> dict[Any, Axes]: ... + +class SubFigure(FigureBase): + figure: FigureBase + subplotpars: SubplotParams + dpi_scale_trans: Transform + canvas: FigureCanvasBase + transFigure: Transform + bbox_relative: Bbox + figbbox: Bbox + bbox: Bbox + transSubfigure: Transform + patch: Rectangle + def __init__( + self, + parent: Figure | SubFigure, + subplotspec: SubplotSpec, + *, + facecolor: Color | None = ..., + edgecolor: Color | None = ..., + linewidth: float = ..., + frameon: bool | None = ..., + **kwargs + ) -> None: ... + @property + def dpi(self) -> float: ... + @dpi.setter + def dpi(self, value: float) -> None: ... + def get_dpi(self) -> float: ... + def set_dpi(self, val) -> None: ... + def get_constrained_layout(self) -> bool: ... + def get_constrained_layout_pads( + self, relative: bool = ... + ) -> tuple[float, float, float, float]: ... + def get_layout_engine(self) -> LayoutEngine: ... + @property # type: ignore[misc] + def axes(self) -> list[Axes]: ... # type: ignore[override] + def get_axes(self) -> list[Axes]: ... + +class Figure(FigureBase): + bbox_inches: Bbox + dpi_scale_trans: Transform + bbox: Bbox + figbbox: Bbox + transFigure: Transform + transSubfigure: Transform + patch: Rectangle + subplotpars: SubplotParams + def __init__( + self, + figsize: tuple[float, float] | None = ..., + dpi: float | None = ..., + facecolor: Color | None = ..., + edgecolor: Color | None = ..., + linewidth: float = ..., + frameon: bool | None = ..., + subplotpars: SubplotParams | None = ..., + tight_layout: bool | dict[str, Any] | None = ..., + constrained_layout: bool | dict[str, Any] | None = ..., + *, + layout: Literal["constrained", "compressed", "tight"] + | LayoutEngine + | None = ..., + **kwargs + ) -> None: ... + def pick(self, mouseevent: MouseEvent) -> None: ... + def set_layout_engine( + self, + layout: Literal["constrained", "compressed", "tight"] + | LayoutEngine + | None = ..., + **kwargs + ) -> None: ... + def get_layout_engine(self) -> LayoutEngine | None: ... + def show(self, warn: bool = ...) -> None: ... + @property # type: ignore[misc] + def axes(self) -> list[Axes]: ... # type: ignore[override] + def get_axes(self) -> list[Axes]: ... + @property + def dpi(self) -> float: ... + @dpi.setter + def dpi(self, dpi: float) -> None: ... + def get_tight_layout(self) -> bool: ... + def get_constrained_layout(self) -> bool: ... + canvas: FigureCanvasBase + def set_canvas(self, canvas: FigureCanvasBase) -> None: ... + def figimage( + self, + X: ArrayLike, + xo: int = ..., + yo: int = ..., + alpha: float | None = ..., + norm: str | Normalize | None = ..., + cmap: str | Colormap | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + origin: Literal["upper", "lower"] | None = ..., + resize: bool = ..., + **kwargs + ): ... + def set_size_inches( + self, w: float | tuple[float, float], h: float | None = ..., forward: bool = ... + ) -> None: ... + def get_size_inches(self) -> np.ndarray: ... + def get_figwidth(self) -> float: ... + def get_figheight(self) -> float: ... + def get_dpi(self) -> float: ... + def set_dpi(self, val: float) -> None: ... + def set_figwidth(self, val: float, forward: bool = ...) -> None: ... + def set_figheight(self, val: float, forward: bool = ...) -> None: ... + def clear(self, keep_observers: bool = ...) -> None: ... + def draw_without_rendering(self) -> None: ... + def draw_artist(self, a: Artist) -> None: ... + def add_axobserver(self, func: Callable[[Figure], Any]): ... + def savefig( + self, + fname: str | os.PathLike | io.FileIO, + *, + transparent: bool | None = ..., + **kwargs + ) -> None: ... + def ginput( + self, + n: int = ..., + timeout: float = ..., + show_clicks: bool = ..., + mouse_add: MouseButton = ..., + mouse_pop: MouseButton = ..., + mouse_stop: MouseButton = ..., + ) -> list[tuple[int, int]]: ... + def waitforbuttonpress(self, timeout: float = ...): ... + def tight_layout( + self, + *, + pad: float = ..., + h_pad: float | None = ..., + w_pad: float | None = ..., + rect: tuple[float, float, float, float] | None = ... + ) -> None: ... + +def figaspect(arg: float | ArrayLike) -> tuple[float, float]: ... diff --git a/lib/matplotlib/font_manager.pyi b/lib/matplotlib/font_manager.pyi new file mode 100644 index 000000000000..a26ef0fcbc58 --- /dev/null +++ b/lib/matplotlib/font_manager.pyi @@ -0,0 +1,134 @@ +from dataclasses import dataclass +import json +import os + +from matplotlib._afm import AFM +from matplotlib import cbook, ft2font +from matplotlib._fontconfig_pattern import ( + generate_fontconfig_pattern, + parse_fontconfig_pattern, +) + +from pathlib import Path + +from typing import Any, Literal, Iterable + +font_scalings: dict[str | None, float] +stretch_dict: dict[str, int] +weight_dict: dict[str, int] +font_family_aliases: set[str] +MSFolders: str +MSFontDirectories: list[str] +MSUserFontDirectories: list[str] +X11FontDirectories: list[str] +OSXFontDirectories: list[str] + +def get_fontext_synonyms(fontext: str) -> list[str]: ... +def list_fonts(directory: str, extensions: Iterable[str]): ... +def win32FontDirectory() -> str: ... +def _get_fontconfig_fonts() -> list[Path]: ... +def findSystemFonts( + fontpaths: Iterable[str] | None = ..., fontext: str = ... +) -> list[str]: ... +@dataclass +class FontEntry: + fname: str = ... + name: str = ... + style: str = ... + variant: str = ... + weight: str = ... + tretch: str = ... + size: str = ... + +def ttfFontProperty(font: ft2font.FT2Font) -> FontEntry: ... +def afmFontProperty(fontpath: str, font: AFM) -> FontEntry: ... + +class FontProperties: + def __init__( + self, + family: str | None = ..., + style: Literal["normal", "italic", "oblique"] | None = ..., + variant: Literal["normal", "small-caps"] | None = ..., + weight: int | str | None = ..., + stretch: int | str | None = ..., + size: float | str | None = ..., + fname: str | None = ..., + math_fontfamily: str | None = ..., + ) -> None: ... + def __hash__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... + def get_family(self) -> str: ... + def get_name(self) -> str: ... + def get_style(self) -> Literal["normal", "italic", "oblique"]: ... + def get_variant(self) -> Literal["normal", "small-caps"]: ... + def get_weight(self) -> int | str: ... + def get_stretch(self) -> int | str: ... + def get_size(self) -> float: ... + def get_file(self) -> str: ... + def get_fontconfig_pattern(self) -> dict[str, list[Any]]: ... + def set_family(self, family: str | Iterable[str]) -> None: ... + def set_style(self, style: Literal["normal", "italic", "oblique"]) -> None: ... + def set_variant(self, variant: Literal["normal", "small-caps"]) -> None: ... + def set_weight(self, weight: int | str) -> None: ... + def set_stretch(self, stretch: int | str) -> None: ... + def set_size(self, size: float | str) -> None: ... + def set_file(self, file: str | os.PathLike | Path | None) -> None: ... + def set_fontconfig_pattern(self, pattern: str) -> None: ... + def get_math_fontfamily(self) -> str: ... + def set_math_fontfamily(self, fontfamily: str | None) -> None: ... + def copy(self) -> FontProperties: ... + def set_name(self, family: str) -> None: ... + def get_slant(self) -> Literal["normal", "italic", "oblique"]: ... + def set_slant(self, style: Literal["normal", "italic", "oblique"]) -> None: ... + def get_size_in_points(self) -> float: ... + +def json_dump(data: FontManager, filename: str | Path | os.PathLike) -> None: ... +def json_load(filename: str | Path | os.PathLike) -> FontManager: ... + +class FontManager: + default_size: float | None + defaultFamily: dict[str, str] + afmlist: list[FontEntry] + ttflist: list[FontEntry] + def __init__(self, size: float | None = ..., weight: str = ...) -> None: ... + def addfont(self, path: str | Path | os.PathLike) -> None: ... + @property + def defaultFont(self) -> dict[str, str]: ... + def get_default_weight(self) -> str: ... + @staticmethod + def get_default_size() -> float: ... + def set_default_weight(self, weight: str) -> None: ... + def score_family( + self, families: str | list[str] | tuple[str], family2: str + ) -> float: ... + def score_style(self, style1: str, style2: str) -> float: ... + def score_variant(self, variant1: str, variant2: str) -> float: ... + def score_stretch(self, stretch1: str | int, stretch2: str | int) -> float: ... + def score_weight(self, weight1: str | float, weight2: str | float) -> float: ... + def score_size(self, size1: str | float, size2: str | float) -> float: ... + def findfont( + self, + prop: str | FontProperties, + fontext: Literal["ttf", "afm"] = ..., + directory: str | None = ..., + fallback_to_default: bool = ..., + rebuild_if_missing: bool = ..., + ) -> str: ... + def get_font_names(self) -> list[str]: ... + +def is_opentype_cff_font(filename: str) -> bool: ... +def get_font( + font_filepaths: Iterable[str | Path | bytes] | str | Path | bytes, + hinting_factor: int | None = ..., +) -> ft2font.FT2Font: ... + +fontManager: FontManager + +def findfont( + prop: str | FontProperties, + fontext: Literal["ttf", "afm"] = ..., + directory: str | None = ..., + fallback_to_default: bool = ..., + rebuild_if_missing: bool = ..., +) -> str: ... +def get_font_names() -> list[str]: ... diff --git a/lib/matplotlib/ft2font.pyi b/lib/matplotlib/ft2font.pyi new file mode 100644 index 000000000000..b4c30ef5ad8c --- /dev/null +++ b/lib/matplotlib/ft2font.pyi @@ -0,0 +1,94 @@ +# This is generated from a compiled module, and as such is very generic +# This could be more specific. Docstrings for this module are light + +from typing import Any + +BOLD: int +EXTERNAL_STREAM: int +FAST_GLYPHS: int +FIXED_SIZES: int +FIXED_WIDTH: int +GLYPH_NAMES: int +HORIZONTAL: int +ITALIC: int +KERNING: int +KERNING_DEFAULT: int +KERNING_UNFITTED: int +KERNING_UNSCALED: int +LOAD_CROP_BITMAP: int +LOAD_DEFAULT: int +LOAD_FORCE_AUTOHINT: int +LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH: int +LOAD_IGNORE_TRANSFORM: int +LOAD_LINEAR_DESIGN: int +LOAD_MONOCHROME: int +LOAD_NO_AUTOHINT: int +LOAD_NO_BITMAP: int +LOAD_NO_HINTING: int +LOAD_NO_RECURSE: int +LOAD_NO_SCALE: int +LOAD_PEDANTIC: int +LOAD_RENDER: int +LOAD_TARGET_LCD: int +LOAD_TARGET_LCD_V: int +LOAD_TARGET_LIGHT: int +LOAD_TARGET_MONO: int +LOAD_TARGET_NORMAL: int +LOAD_VERTICAL_LAYOUT: int +MULTIPLE_MASTERS: int +SCALABLE: int +SFNT: int +VERTICAL: int + +class FT2Font: + ascender: Any + bbox: Any + descender: Any + face_flags: Any + family_name: Any + fname: Any + height: Any + max_advance_height: Any + max_advance_width: Any + num_charmaps: Any + num_faces: Any + num_fixed_sizes: Any + num_glyphs: Any + postscript_name: Any + scalable: Any + style_flags: Any + style_name: Any + underline_position: Any + underline_thickness: Any + units_per_EM: Any + def __init__(self, *args, **kwargs) -> None: ... + def _get_fontmap(self, *args, **kwargs) -> Any: ... + def clear(self, *args, **kwargs) -> Any: ... + def draw_glyph_to_bitmap(self, *args, **kwargs) -> Any: ... + def draw_glyphs_to_bitmap(self, *args, **kwargs) -> Any: ... + def get_bitmap_offset(self, *args, **kwargs) -> Any: ... + def get_char_index(self, *args, **kwargs) -> Any: ... + def get_charmap(self, *args, **kwargs) -> Any: ... + def get_descent(self, *args, **kwargs) -> Any: ... + def get_glyph_name(self, *args, **kwargs) -> Any: ... + def get_image(self, *args, **kwargs) -> Any: ... + def get_kerning(self, *args, **kwargs) -> Any: ... + def get_name_index(self, *args, **kwargs) -> Any: ... + def get_num_glyphs(self, *args, **kwargs) -> Any: ... + def get_path(self, *args, **kwargs) -> Any: ... + def get_ps_font_info(self, *args, **kwargs) -> Any: ... + def get_sfnt(self, *args, **kwargs) -> Any: ... + def get_sfnt_table(self, *args, **kwargs) -> Any: ... + def get_width_height(self, *args, **kwargs) -> Any: ... + def get_xys(self, *args, **kwargs) -> Any: ... + def load_char(self, *args, **kwargs) -> Any: ... + def load_glyph(self, *args, **kwargs) -> Any: ... + def select_charmap(self, *args, **kwargs) -> Any: ... + def set_charmap(self, *args, **kwargs) -> Any: ... + def set_size(self, *args, **kwargs) -> Any: ... + def set_text(self, *args, **kwargs) -> Any: ... + +class FT2Image: + def __init__(self, *args, **kwargs) -> None: ... + def draw_rect(self, *args, **kwargs) -> Any: ... + def draw_rect_filled(self, *args, **kwargs) -> Any: ... diff --git a/lib/matplotlib/gridspec.pyi b/lib/matplotlib/gridspec.pyi new file mode 100644 index 000000000000..6c118e58733a --- /dev/null +++ b/lib/matplotlib/gridspec.pyi @@ -0,0 +1,132 @@ +from typing import Any, Literal, overload + +from numpy.typing import ArrayLike +import numpy as np + +from matplotlib.axes import Axes, SubplotBase +from matplotlib.backend_bases import RendererBase +from matplotlib.figure import Figure, SubplotParams +from matplotlib.transforms import Bbox + +class GridSpecBase: + def __init__( + self, + nrows: int, + ncols: int, + height_ratios: ArrayLike | None = ..., + width_ratios: ArrayLike | None = ..., + ) -> None: ... + @property + def nrows(self) -> int: ... + @property + def ncols(self) -> int: ... + def get_geometry(self) -> tuple[int, int]: ... + def get_subplot_params(self, figure: Figure | None = ...) -> SubplotParams: ... + def new_subplotspec( + self, loc: tuple[int, int], rowspan: int = ..., colspan: int = ... + ) -> SubplotSpec: ... + def set_width_ratios(self, width_ratios: ArrayLike | None) -> None: ... + def get_width_ratios(self) -> ArrayLike: ... + def set_height_ratios(self, height_ratios: ArrayLike | None) -> None: ... + def get_height_ratios(self) -> ArrayLike: ... + def get_grid_positions( + self, fig: Figure, raw: bool = ... + ) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: ... + @staticmethod + def _check_gridspec_exists(figure, nrows, ncols): ... + def __getitem__(self, key: tuple[int, int] | slice | int) -> SubplotSpec: ... + @overload + def subplots( + self, + *, + sharex: bool | Literal["all", "row", "col", "none"] = ..., + sharey: bool | Literal["all", "row", "col", "none"] = ..., + squeeze: Literal[False], + subplot_kw: dict[str, Any] | None = ... + ) -> np.ndarray: ... + @overload + def subplots( + self, + *, + sharex: bool | Literal["all", "row", "col", "none"] = ..., + sharey: bool | Literal["all", "row", "col", "none"] = ..., + squeeze: Literal[True] = ..., + subplot_kw: dict[str, Any] | None = ... + ) -> np.ndarray | SubplotBase | Axes: ... + +class GridSpec(GridSpecBase): + left: float | None + bottom: float | None + right: float | None + top: float | None + wspace: float | None + hspace: float | None + figure: Figure | None + def __init__( + self, + nrows: int, + ncols: int, + figure: Figure | None = ..., + left: float | None = ..., + bottom: float | None = ..., + right: float | None = ..., + top: float | None = ..., + wspace: float | None = ..., + hspace: float | None = ..., + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + ) -> None: ... + def update(self, **kwargs: float | None) -> None: ... + def locally_modified_subplot_params(self) -> list[str]: ... + def tight_layout( + self, + figure: Figure, + renderer: RendererBase | None = ..., + pad: float = ..., + h_pad: float | None = ..., + w_pad: float | None = ..., + rect: tuple[float, float, float, float] | None = ..., + ) -> None: ... + +class GridSpecFromSubplotSpec(GridSpecBase): + figure: Figure | None + def __init__( + self, + nrows: int, + ncols: int, + subplot_spec: SubplotSpec, + wspace: float | None = ..., + hspace: float | None = ..., + height_ratios: ArrayLike | None = ..., + width_ratios: ArrayLike | None = ..., + ) -> None: ... + def get_topmost_subplotspec(self) -> SubplotSpec: ... + +class SubplotSpec: + num1: int + def __init__( + self, gridspec: GridSpec, num1: int, num2: int | None = ... + ) -> None: ... + @staticmethod + def _from_subplot_args(figure, args): ... + @property + def num2(self) -> int: ... + @num2.setter + def num2(self, value: int) -> None: ... + def get_gridspec(self) -> GridSpec: ... + def get_geometry(self) -> tuple[int, int, int, int]: ... + @property + def rowspan(self) -> range: ... + @property + def colspan(self) -> range: ... + def is_first_row(self) -> bool: ... + def is_last_row(self) -> bool: ... + def is_first_col(self) -> bool: ... + def is_last_col(self) -> bool: ... + def get_position(self, figure: Figure) -> Bbox: ... + def get_topmost_subplotspec(self) -> SubplotSpec: ... + def __eq__(self, other: object) -> bool: ... + def __hash__(self) -> int: ... + def subgridspec( + self, nrows: int, ncols: int, **kwargs + ) -> GridSpecFromSubplotSpec: ... diff --git a/lib/matplotlib/hatch.pyi b/lib/matplotlib/hatch.pyi new file mode 100644 index 000000000000..348cf5214984 --- /dev/null +++ b/lib/matplotlib/hatch.pyi @@ -0,0 +1,68 @@ +from matplotlib.path import Path + +import numpy as np +from numpy.typing import ArrayLike + +class HatchPatternBase: ... + +class HorizontalHatch(HatchPatternBase): + num_lines: int + num_vertices: int + def __init__(self, hatch: str, density: int) -> None: ... + def set_vertices_and_codes(self, vertices: ArrayLike, codes: ArrayLike) -> None: ... + +class VerticalHatch(HatchPatternBase): + num_lines: int + num_vertices: int + def __init__(self, hatch: str, density: int) -> None: ... + def set_vertices_and_codes(self, vertices: ArrayLike, codes: ArrayLike) -> None: ... + +class NorthEastHatch(HatchPatternBase): + num_lines: int + num_vertices: int + def __init__(self, hatch: str, density: int) -> None: ... + def set_vertices_and_codes(self, vertices: ArrayLike, codes: ArrayLike) -> None: ... + +class SouthEastHatch(HatchPatternBase): + num_lines: int + num_vertices: int + def __init__(self, hatch: str, density: int) -> None: ... + def set_vertices_and_codes(self, vertices: ArrayLike, codes: ArrayLike) -> None: ... + +class Shapes(HatchPatternBase): + filled: bool + num_shapes: int + num_vertices: int + def __init__(self, hatch: str, density: int) -> None: ... + def set_vertices_and_codes(self, vertices: ArrayLike, codes: ArrayLike) -> None: ... + +class Circles(Shapes): + shape_vertices: np.ndarray + shape_codes: np.ndarray + def __init__(self, hatch: str, density: int) -> None: ... + +class SmallCircles(Circles): + size: float + num_rows: int + def __init__(self, hatch: str, density: int) -> None: ... + +class LargeCircles(Circles): + size: float + num_rows: int + def __init__(self, hatch: str, density: int) -> None: ... + +class SmallFilledCircles(Circles): + size: float + filled: bool + num_rows: int + def __init__(self, hatch: str, density: int) -> None: ... + +class Stars(Shapes): + size: float + filled: bool + num_rows: int + shape_vertices: np.ndarray + shape_codes: np.ndarray + def __init__(self, hatch: str, density: int) -> None: ... + +def get_path(hatchpattern: str, density: int = ...) -> Path: ... diff --git a/lib/matplotlib/image.pyi b/lib/matplotlib/image.pyi new file mode 100644 index 000000000000..e38d4617a535 --- /dev/null +++ b/lib/matplotlib/image.pyi @@ -0,0 +1,176 @@ +import io +import os +import pathlib + +from matplotlib._image import * +import matplotlib.artist as martist +from matplotlib.axes import Axes +from matplotlib import cbook, cm +from matplotlib.backend_bases import FigureCanvasBase, RendererBase, MouseEvent +from matplotlib.colors import Colormap, Normalize +from matplotlib.figure import Figure +from matplotlib.transforms import ( + Affine2D, + Bbox, + BboxBase, + BboxTransform, + BboxTransformTo, + IdentityTransform, + TransformedBbox, + Transform, +) + +from typing import Any, Literal, Sequence +import numpy as np +from numpy.typing import ArrayLike + +import PIL # type: ignore + +interpolations_names: set[str] + +def composite_images( + images: Sequence[_ImageBase], renderer: RendererBase, magnification: float = ... +) -> tuple[np.ndarray, float, float]: ... + +class _ImageBase(martist.Artist, cm.ScalarMappable): + zorder: float + origin: Literal["upper", "lower"] + axes: Axes + def __init__( + self, + ax: Axes, + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + interpolation: str | None = ..., + origin: Literal["upper", "lower"] | None = ..., + filternorm: bool = ..., + filterrad: float = ..., + resample: bool | None = ..., + *, + interpolation_stage: Literal["data", "rgba"] | None = ..., + **kwargs + ) -> None: ... + def get_size(self) -> tuple[int, int]: ... + def set_alpha(self, alpha: float | ArrayLike | None) -> None: ... + def changed(self) -> None: ... + def make_image( + self, renderer: RendererBase, magnification: float = ..., unsampled: bool = ... + ) -> tuple[np.ndarray, float, float, Affine2D]: ... + def draw(self, renderer: RendererBase, *args, **kwargs) -> None: ... + def write_png(self, fname: str | pathlib.Path | io.FileIO) -> None: ... + def set_data(self, A: ArrayLike | None) -> None: ... + def set_array(self, A: ArrayLike | None) -> None: ... + def get_interpolation(self) -> str: ... + def set_interpolation(self, s: str) -> None: ... + def set_interpolation_stage(self, s: Literal["data", "rgba"]) -> None: ... + def can_composite(self) -> bool: ... + def set_resample(self, v: bool | None) -> None: ... + def get_resample(self) -> bool: ... + def set_filternorm(self, filternorm: bool) -> None: ... + def get_filternorm(self) -> bool: ... + def set_filterrad(self, filterrad: float) -> None: ... + def get_filterrad(self) -> float: ... + +class AxesImage(_ImageBase): + def __init__( + self, + ax: Axes, + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + interpolation: str | None = ..., + origin: Literal["upper", "lower"] | None = ..., + extent: tuple[float, float, float, float] | None = ..., + filternorm: bool = ..., + filterrad: float = ..., + resample: bool = ..., + *, + interpolation_stage: Literal["data", "rgba"] | None = ..., + **kwargs + ) -> None: ... + def get_window_extent(self, renderer: RendererBase | None = ...): ... + def make_image( + self, renderer: RendererBase, magnification: float = ..., unsampled: bool = ... + ): ... + def set_extent( + self, extent: tuple[float, float, float, float], **kwargs + ) -> None: ... + def get_extent(self) -> tuple[float, float, float, float]: ... + def get_cursor_data(self, event: MouseEvent) -> None | float: ... + +class NonUniformImage(AxesImage): + mouseover: bool + def __init__( + self, ax: Axes, *, interpolation: Literal["nearest", "bilinear"] = ..., **kwargs + ) -> None: ... + def set_data(self, x: ArrayLike, y: ArrayLike, A: ArrayLike) -> None: ... # type: ignore[override] + # more limited interpolation available here than base class + def set_interpolation(self, s: Literal["nearest", "bilinear"]) -> None: ... # type: ignore[override] + +class PcolorImage(AxesImage): + def __init__( + self, + ax: Axes, + x: ArrayLike | None = ..., + y: ArrayLike | None = ..., + A: ArrayLike | None = ..., + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + **kwargs + ) -> None: ... + def set_data(self, x: ArrayLike, y: ArrayLike, A: ArrayLike) -> None: ... # type: ignore[override] + +class FigureImage(_ImageBase): + zorder: float + figure: Figure + ox: float + oy: float + magnification: float + def __init__( + self, + fig: Figure, + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + offsetx: int = ..., + offsety: int = ..., + origin: Literal["upper", "lower"] | None = ..., + **kwargs + ) -> None: ... + +class BboxImage(_ImageBase): + bbox: Bbox + def __init__( + self, + bbox: Bbox, + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + interpolation: str | None = ..., + origin: Literal["upper", "lower"] | None = ..., + filternorm: bool = ..., + filterrad: float = ..., + resample: bool = ..., + **kwargs + ) -> None: ... + def get_window_extent(self, renderer: RendererBase | None = ...): ... + +def imread(fname: str | io.FileIO, format: str | None = ...) -> np.ndarray: ... +def imsave( + fname: str | os.PathLike | io.FileIO, + arr: ArrayLike, + vmin: float | None = ..., + vmax: float | None = ..., + cmap: str | Colormap | None = ..., + format: str | None = ..., + origin: Literal["upper", "lower"] | None = ..., + dpi: float = ..., + *, + metadata: dict[str, str] | None = ..., + pil_kwargs: dict[str, Any] | None = ... +) -> None: ... +def pil_to_array(pilImage: PIL.Image.Image) -> np.ndarray: ... +def thumbnail( + infile: str | io.FileIO, + thumbfile: str | io.FileIO, + scale: float = ..., + interpolation: str = ..., + preview: bool = ..., +) -> Figure: ... diff --git a/lib/matplotlib/layout_engine.pyi b/lib/matplotlib/layout_engine.pyi new file mode 100644 index 000000000000..81c4107d39fd --- /dev/null +++ b/lib/matplotlib/layout_engine.pyi @@ -0,0 +1,64 @@ +from matplotlib._constrained_layout import do_constrained_layout +from matplotlib._tight_layout import get_subplotspec_list, get_tight_layout_figure +from matplotlib.figure import Figure + +from typing import Any + +class LayoutEngine: + def __init__(self, **kwargs) -> None: ... + def set(self) -> None: ... + @property + def colorbar_gridspec(self) -> bool: ... + @property + def adjust_compatible(self) -> bool: ... + def get(self) -> dict[str, Any]: ... + def execute(self, fig) -> None: ... + +class PlaceHolderLayoutEngine(LayoutEngine): + def __init__( + self, adjust_compatible: bool, colorbar_gridspec: bool, **kwargs + ) -> None: ... + def execute(self, fig: Figure) -> None: ... + +class TightLayoutEngine(LayoutEngine): + def __init__( + self, + *, + pad: float = ..., + h_pad: float | None = ..., + w_pad: float | None = ..., + rect: tuple[float, float, float, float] = ..., + **kwargs + ) -> None: ... + def execute(self, fig: Figure) -> None: ... + def set( + self, + *, + pad: float | None = ..., + w_pad: float | None = ..., + h_pad: float | None = ..., + rect: tuple[float, float, float, float] | None = ... + ) -> None: ... + +class ConstrainedLayoutEngine(LayoutEngine): + def __init__( + self, + *, + h_pad: float | None = ..., + w_pad: float | None = ..., + hspace: float | None = ..., + wspace: float | None = ..., + rect: tuple[float, float, float, float] = ..., + compress: bool = ..., + **kwargs + ) -> None: ... + def execute(self, fig: Figure): ... + def set( + self, + *, + h_pad: float | None = ..., + w_pad: float | None = ..., + hspace: float | None = ..., + wspace: float | None = ..., + rect: tuple[float, float, float, float] | None = ... + ) -> None: ... diff --git a/lib/matplotlib/legend.pyi b/lib/matplotlib/legend.pyi new file mode 100644 index 000000000000..c56b0345f774 --- /dev/null +++ b/lib/matplotlib/legend.pyi @@ -0,0 +1,164 @@ +from . import legend_handler +from matplotlib import colors, offsetbox +from matplotlib.axes import Axes +from matplotlib.artist import Artist, allow_rasterization +from matplotlib.cbook import silent_list +from matplotlib.collections import ( + CircleCollection, + Collection, + LineCollection, + PathCollection, + PolyCollection, + RegularPolyCollection, +) +from matplotlib.colors import Color +from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer +from matplotlib.figure import Figure +from matplotlib.font_manager import FontProperties +from matplotlib.legend_handler import HandlerBase +from matplotlib.lines import Line2D +from matplotlib.offsetbox import ( + AnchoredOffsetbox, + DraggableOffsetBox, + DrawingArea, + HPacker, + TextArea, + VPacker, +) +from matplotlib.patches import FancyBboxPatch, Patch, Rectangle, Shadow, StepPatch +from matplotlib.text import Text +from matplotlib.transforms import ( + Bbox, + BboxBase, + BboxTransformFrom, + BboxTransformTo, + TransformedBbox, + Transform, +) + + +import pathlib +from typing import Any, Literal, Iterable, Type, overload + +class DraggableLegend(DraggableOffsetBox): + legend: Legend + def __init__( + self, legend: Legend, use_blit: bool = ..., update: Literal["loc", "bbox"] = ... + ) -> None: ... + def finalize_offset(self) -> None: ... + +class Legend(Artist): + codes: dict[str, int] + zorder: float + prop: FontProperties + texts: list[Text] + legendHandles: list[Artist | None] + numpoints: int + markerscale: float + scatterpoints: int + borderpad: float + labelspacing: float + handlelength: float + handleheight: float + handletextpad: float + borderaxespad: float + columnspacing: float + shadow: bool + isaxes: bool + axes: Axes + parent: Axes | Figure + legendPatch: FancyBboxPatch + def __init__( + self, + parent: Axes | Figure, + handles: Iterable[Artist], + labels: Iterable[str], + loc: str | tuple[float, float] | int | None = ..., + numpoints: int | None = ..., + markerscale: float | None = ..., + markerfirst: bool = ..., + reverse: bool = ..., + scatterpoints: int | None = ..., + scatteryoffsets: Iterable[float] | None = ..., + prop: FontProperties | dict[str, Any] | None = ..., + fontsize: float | str | None = ..., + labelcolor: Color + | Iterable[Color] + | Literal["linecolor", "markerfacecolor", "mfc", "markeredgecolor", "mec"] + | None = ..., + borderpad: float | None = ..., + labelspacing: float | None = ..., + handlelength: float | None = ..., + handleheight: float | None = ..., + handletextpad: float | None = ..., + borderaxespad: float | None = ..., + columnspacing: float | None = ..., + ncols: int = ..., + mode: Literal["expand"] | None = ..., + fancybox: bool | None = ..., + shadow: bool | None = ..., + title: str | None = ..., + title_fontsize: float | None = ..., + framealpha: float | None = ..., + edgecolor: Literal["inherit"] | Color | None = ..., + facecolor: Literal["inherit"] | Color | None = ..., + bbox_to_anchor: BboxBase + | tuple[float, float] + | tuple[float, float, float, float] + | None = ..., + bbox_transform: Transform | None = ..., + frameon: bool | None = ..., + handler_map: dict[Artist | Type, HandlerBase] | None = ..., + title_fontproperties: FontProperties | dict[str, Any] | None = ..., + alignment: Literal["center", "left", "right"] = ..., + *, + ncol: int = ..., + draggable: bool = ... + ) -> None: ... + def set_ncols(self, ncols: int) -> None: ... + @classmethod + def get_default_handler_map(cls) -> dict[Type, HandlerBase]: ... + @classmethod + def set_default_handler_map(cls, handler_map: dict[Type, HandlerBase]) -> None: ... + @classmethod + def update_default_handler_map( + cls, handler_map: dict[Type, HandlerBase] + ) -> None: ... + def get_legend_handler_map(self) -> dict[Type, HandlerBase]: ... + @staticmethod + def get_legend_handler( + legend_handler_map: dict[Type, HandlerBase], orig_handle: Any + ) -> HandlerBase | None: ... + def get_children(self) -> list[Artist]: ... + def get_frame(self) -> Rectangle: ... + def get_lines(self) -> list[Line2D]: ... + def get_patches(self) -> list[Patch]: ... + def get_texts(self) -> list[Text]: ... + def set_alignment(self, alignment: Literal["center", "left", "right"]) -> None: ... + def get_alignment(self) -> Literal["center", "left", "right"]: ... + def set_title( + self, title: str, prop: FontProperties | str | pathlib.Path | None = ... + ) -> None: ... + def get_title(self) -> Text: ... + def get_frame_on(self) -> bool: ... + def set_frame_on(self, b: bool) -> None: ... + draw_frame = set_frame_on + def get_bbox_to_anchor(self) -> BboxBase: ... + def set_bbox_to_anchor( + self, bbox: BboxBase, transform: Transform | None = ... + ) -> None: ... + @overload + def set_draggable( + self, + state: Literal[True], + use_blit: bool = ..., + update: Literal["loc", "bbox"] = ..., + ) -> DraggableLegend: ... + @overload + def set_draggable( + self, + state: Literal[False], + use_blit: bool = ..., + update: Literal["loc", "bbox"] = ..., + ) -> None: ... + def get_draggable(self) -> bool: ... diff --git a/lib/matplotlib/legend_handler.py b/lib/matplotlib/legend_handler.py index cc39cd39cd6d..849644145856 100644 --- a/lib/matplotlib/legend_handler.py +++ b/lib/matplotlib/legend_handler.py @@ -27,7 +27,6 @@ def legend_artist(self, legend, orig_handle, fontsize, handlebox) """ -from collections.abc import Sequence from itertools import cycle import numpy as np @@ -132,9 +131,6 @@ def legend_artist(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, handlebox.get_transform()) - if isinstance(artists, _Line2DHandleList): - artists = [artists[0]] - # create_artists will return a list of artists. for a in artists: handlebox.add_artist(a) @@ -277,24 +273,6 @@ def create_artists(self, legend, orig_handle, return [legline, legline_marker] -class _Line2DHandleList(Sequence): - def __init__(self, legline): - self._legline = legline - - def __len__(self): - return 2 - - def __getitem__(self, index): - if index != 0: - # Make HandlerLine2D return [self._legline] directly after - # deprecation elapses. - _api.warn_deprecated( - "3.5", message="Access to the second element returned by " - "HandlerLine2D is deprecated since %(since)s; it will be " - "removed %(removal)s.") - return [self._legline, self._legline][index] - - class HandlerLine2D(HandlerNpoints): """ Handler for `.Line2D` instances. @@ -331,7 +309,7 @@ def create_artists(self, legend, orig_handle, legline.set_transform(trans) - return _Line2DHandleList(legline) + return [legline] class HandlerPatch(HandlerBase): @@ -790,8 +768,6 @@ def create_artists(self, legend, orig_handle, _a_list = handler.create_artists( legend, handle1, next(xds_cycle), ydescent, width, height, fontsize, trans) - if isinstance(_a_list, _Line2DHandleList): - _a_list = [_a_list[0]] a_list.extend(_a_list) return a_list diff --git a/lib/matplotlib/legend_handler.pyi b/lib/matplotlib/legend_handler.pyi new file mode 100644 index 000000000000..eb3fc779dc59 --- /dev/null +++ b/lib/matplotlib/legend_handler.pyi @@ -0,0 +1,297 @@ +from collections.abc import Sequence +from matplotlib import cbook +from matplotlib.artist import Artist +from matplotlib.legend import Legend +from matplotlib.lines import Line2D +from matplotlib.offsetbox import OffsetBox +from matplotlib.patches import Rectangle +from matplotlib.transforms import Transform + +from typing import Callable, TypeVar + +from numpy.typing import ArrayLike + +def update_from_first_child(tgt: Artist, src: Artist) -> None: ... + +class HandlerBase: + def __init__( + self, + xpad: float = ..., + ypad: float = ..., + update_func: Callable[[Artist, Artist], None] | None = ..., + ) -> None: ... + def update_prop( + self, legend_handle: Artist, orig_handle: Artist, legend: Legend + ) -> None: ... + def adjust_drawing_area( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + ) -> tuple[float, float, float, float]: ... + def legend_artist( + self, legend: Legend, orig_handle: Artist, fontsize: float, handlebox: OffsetBox + ) -> Artist: ... + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerNpoints(HandlerBase): + def __init__( + self, marker_pad: float = ..., numpoints: int | None = ..., **kwargs + ) -> None: ... + def get_numpoints(self, legend: Legend) -> int | None: ... + def get_xdata( + self, + legend: Legend, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + ) -> tuple[ArrayLike, ArrayLike]: ... + +class HandlerNpointsYoffsets(HandlerNpoints): + def __init__( + self, + numpoints: int | None = ..., + yoffsets: Sequence[float] | None = ..., + **kwargs + ) -> None: ... + def get_ydata( + self, + legend: Legend, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + ) -> ArrayLike: ... + +class HandlerLine2DCompound(HandlerNpoints): + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerLine2D(HandlerNpoints): + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerPatch(HandlerBase): + def __init__(self, patch_func: Callable | None = ..., **kwargs) -> None: ... + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerStepPatch(HandlerBase): + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerLineCollection(HandlerLine2D): + def get_numpoints(self, legend: Legend) -> int: ... + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +T = TypeVar("T", bound=Artist) + +class HandlerRegularPolyCollection(HandlerNpointsYoffsets): + def __init__( + self, + yoffsets: Sequence[float] | None = ..., + sizes: Sequence[float] | None = ..., + **kwargs + ) -> None: ... + def get_numpoints(self, legend: Legend) -> int: ... + def get_sizes( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + ) -> Sequence[float]: ... + def update_prop( + self, legend_handle, orig_handle: Artist, legend: Legend + ) -> None: ... + def create_collection( + self, + orig_handle: T, + sizes: Sequence[float] | None, + offsets: Sequence[float] | None, + offset_transform: Transform, + ) -> T: ... + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerPathCollection(HandlerRegularPolyCollection): + def create_collection( + self, + orig_handle: T, + sizes: Sequence[float] | None, + offsets: Sequence[float] | None, + offset_transform: Transform, + ) -> T: ... + +class HandlerCircleCollection(HandlerRegularPolyCollection): + def create_collection( + self, + orig_handle: T, + sizes: Sequence[float] | None, + offsets: Sequence[float] | None, + offset_transform: Transform, + ) -> T: ... + +class HandlerErrorbar(HandlerLine2D): + def __init__( + self, + xerr_size: float = ..., + yerr_size: float | None = ..., + marker_pad: float = ..., + numpoints: int | None = ..., + **kwargs + ) -> None: ... + def get_err_size( + self, + legend: Legend, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + ) -> tuple[float, float]: ... + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerStem(HandlerNpointsYoffsets): + def __init__( + self, + marker_pad: float = ..., + numpoints: int | None = ..., + bottom: float | None = ..., + yoffsets: Sequence[float] | None = ..., + **kwargs + ) -> None: ... + def get_ydata( + self, + legend: Legend, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + ) -> ArrayLike: ... + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerTuple(HandlerBase): + def __init__( + self, ndivide: int = ..., pad: float | None = ..., **kwargs + ) -> None: ... + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... + +class HandlerPolyCollection(HandlerBase): + def create_artists( + self, + legend: Legend, + orig_handle: Artist, + xdescent: float, + ydescent: float, + width: float, + height: float, + fontsize: float, + trans: Transform, + ) -> Sequence[Artist]: ... diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index f843ccd49fee..4932c1f50920 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -6,6 +6,7 @@ from numbers import Integral, Number, Real import logging +from typing import Literal, Sequence, Union import numpy as np @@ -1590,3 +1591,18 @@ def onpick(self, event): lineMarkers = MarkerStyle.markers drawStyles = Line2D.drawStyles fillStyles = MarkerStyle.fillstyles + +LineStyleType = Union[str, tuple[float, Sequence[float]]] +DrawStyleType = Literal[ + "default", "steps", "steps-pre", "steps-mid", "steps-post" +] +MarkEveryType = Union[ + None, + int, + tuple[int, int], + slice, + list[int], + float, + tuple[float, float], + list[bool], +] diff --git a/lib/matplotlib/lines.pyi b/lib/matplotlib/lines.pyi new file mode 100644 index 000000000000..6faeacea4656 --- /dev/null +++ b/lib/matplotlib/lines.pyi @@ -0,0 +1,162 @@ +from . import cbook +from ._enums import CapStyle, JoinStyle +from .artist import Artist, allow_rasterization +from .axes import Axes +from .backend_bases import MouseEvent, FigureCanvasBase +from .cbook import STEP_LOOKUP_MAP, ls_mapper, ls_mapper_r +from .colors import Color +from .markers import ( + CARETDOWN, + CARETDOWNBASE, + CARETLEFT, + CARETLEFTBASE, + CARETRIGHT, + CARETRIGHTBASE, + CARETUP, + CARETUPBASE, + TICKDOWN, + TICKLEFT, + TICKRIGHT, + TICKUP, + MarkerStyle, + MarkerType, + FillStyleType, +) +from .path import Path +from .transforms import Bbox, BboxTransformTo, TransformedPath, Transform + +from typing import Any, Literal, Sequence, Union, Callable, overload +from numpy.typing import ArrayLike + +def segment_hits( + cx: ArrayLike, cy: ArrayLike, x: ArrayLike, y: ArrayLike, radius: ArrayLike +) -> ArrayLike: ... + +class Line2D(Artist): + lineStyles: dict[str, str] + drawStyles: dict[str, str] + drawStyleKeys: list[str] + markers: dict[str | int, str] + filled_markers: tuple[str, ...] + fillStyles: tuple[str, ...] + zorder: float + ind_offset: float + def __init__( + self, + xdata: ArrayLike, + ydata: ArrayLike, + linewidth: float | None = ..., + linestyle: LineStyleType | None = ..., + color: Color | None = ..., + gapcolor: Color | None = ..., + marker: MarkerType | None = ..., + markersize: float | None = ..., + markeredgewidth: float | None = ..., + markeredgecolor: Color | None = ..., + markerfacecolor: Color | None = ..., + markerfacecoloralt: Color = ..., + fillstyle: FillStyleType | None = ..., + antialiased: bool | None = ..., + dash_capstyle: CapStyle | None = ..., + solid_capstyle: CapStyle | None = ..., + dash_joinstyle: JoinStyle | None = ..., + solid_joinstyle: JoinStyle | None = ..., + pickradius: float = ..., + drawstyle: DrawStyleType | None = ..., + markevery: MarkEveryType | None = ..., + **kwargs + ) -> None: ... + def contains(self, mouseevent: MouseEvent) -> tuple[bool, dict]: ... + def get_pickradius(self) -> float: ... + def set_pickradius(self, pickradius: float) -> None: ... + pickradius: float + def get_fillstyle(self) -> FillStyleType: ... + stale: bool + def set_fillstyle(self, fs: FillStyleType) -> None: ... + def set_markevery(self, every: MarkEveryType) -> None: ... + def get_markevery(self) -> MarkEveryType: ... + def set_picker( + self, p: None | bool | float | Callable[[Artist, MouseEvent], tuple[bool, dict]] + ) -> None: ... + def get_bbox(self) -> Bbox: ... + @overload + def set_data(self, args: ArrayLike) -> None: ... + @overload + def set_data(self, x: ArrayLike, y: ArrayLike) -> None: ... + def recache_always(self) -> None: ... + def recache(self, always: bool = ...) -> None: ... + def set_transform(self, t: Transform) -> None: ... + def get_antialiased(self) -> bool: ... + def get_color(self) -> Color: ... + def get_drawstyle(self) -> DrawStyleType: ... + def get_gapcolor(self) -> Color: ... + def get_linestyle(self) -> LineStyleType: ... + def get_linewidth(self) -> float: ... + def get_marker(self) -> MarkerType: ... + def get_markeredgecolor(self) -> Color: ... + def get_markeredgewidth(self) -> float: ... + def get_markerfacecolor(self) -> Color: ... + def get_markerfacecoloralt(self) -> Color: ... + def get_markersize(self) -> float: ... + def get_data(self, orig: bool = ...) -> tuple[ArrayLike, ArrayLike]: ... + def get_xdata(self, orig: bool = ...) -> ArrayLike: ... + def get_ydata(self, orig: bool = ...) -> ArrayLike: ... + def get_path(self) -> Path: ... + def get_xydata(self) -> ArrayLike: ... + def set_antialiased(self, b: bool) -> None: ... + def set_color(self, color: Color) -> None: ... + def set_drawstyle(self, drawstyle: DrawStyleType | None) -> None: ... + def set_gapcolor(self, gapcolor: Color | None) -> None: ... + def set_linewidth(self, w: float) -> None: ... + def set_linestyle(self, ls: LineStyleType) -> None: ... + def set_marker(self, marker: MarkerType) -> None: ... + def set_markeredgecolor(self, ec: Color | None) -> None: ... + def set_markerfacecolor(self, fc: Color | None) -> None: ... + def set_markerfacecoloralt(self, fc: Color | None) -> None: ... + def set_markeredgewidth(self, ew: float | None) -> None: ... + def set_markersize(self, sz: float) -> None: ... + def set_xdata(self, x: ArrayLike) -> None: ... + def set_ydata(self, y: ArrayLike) -> None: ... + def set_dashes(self, seq: Sequence[float] | tuple[None, None]) -> None: ... + def update_from(self, other: Artist) -> None: ... + def set_dash_joinstyle(self, s: JoinStyle) -> None: ... + def set_solid_joinstyle(self, s: JoinStyle) -> None: ... + def get_dash_joinstyle(self) -> str: ... + def get_solid_joinstyle(self) -> str: ... + def set_dash_capstyle(self, s: CapStyle) -> None: ... + def set_solid_capstyle(self, s: CapStyle) -> None: ... + def get_dash_capstyle(self) -> str: ... + def get_solid_capstyle(self) -> str: ... + def is_dashed(self) -> bool: ... + +class _AxLine(Line2D): + def __init__( + self, + xy1: tuple[float, float], + xy2: tuple[float, float] | None, + slope: float | None, + **kwargs + ) -> None: ... + +class VertexSelector: + axes: Axes + line: Line2D + cid: int + ind: set[int] + def __init__(self, line: Line2D) -> None: ... + canvas: FigureCanvasBase + def process_selected( + self, ind: Sequence[int], xs: ArrayLike, ys: ArrayLike + ) -> None: ... + def onpick(self, event: Any) -> None: ... + +lineStyles: dict[str, str] +lineMarkers: dict[str | int, str] +drawStyles: dict[str, str] +fillStyles: tuple[FillStyleType, ...] + +LineStyleType = Union[str, tuple[float, Sequence[float]]] +DrawStyleType = Literal["default", "steps", "steps-pre", "steps-mid", "steps-post"] +MarkEveryType = Union[ + None, int, tuple[int, int], slice, list[int], float, tuple[float, float], list[bool] +] diff --git a/lib/matplotlib/markers.py b/lib/matplotlib/markers.py index c9fc0141939d..2950a367f87c 100644 --- a/lib/matplotlib/markers.py +++ b/lib/matplotlib/markers.py @@ -136,6 +136,7 @@ from collections.abc import Sized import inspect +from typing import Union, Literal import numpy as np @@ -941,3 +942,7 @@ def _set_x_filled(self): self._transform.rotate_deg( {'top': 0, 'left': 90, 'bottom': 180, 'right': 270}[fs]) self._alt_transform = self._transform.frozen().rotate_deg(180) + + +MarkerType = Union[str, Path, MarkerStyle] +FillStyleType = Literal["full", "left", "right", "bottom", "top", "none"] diff --git a/lib/matplotlib/markers.pyi b/lib/matplotlib/markers.pyi new file mode 100644 index 000000000000..11b13370c975 --- /dev/null +++ b/lib/matplotlib/markers.pyi @@ -0,0 +1,55 @@ +from . import cbook +from ._enums import CapStyle, JoinStyle +from .path import Path +from .transforms import Affine2D, IdentityTransform, Transform + +from numpy.typing import ArrayLike +from typing import Literal, Union + +TICKLEFT: int +TICKRIGHT: int +TICKUP: int +TICKDOWN: int +CARETLEFT: int +CARETRIGHT: int +CARETUP: int +CARETDOWN: int +CARETLEFTBASE: int +CARETRIGHTBASE: int +CARETUPBASE: int +CARETDOWNBASE: int + +class MarkerStyle: + markers: dict[str | int, str] + filled_markers: tuple[str, ...] + fillstyles: tuple[FillStyleType, ...] + def __init__( + self, + marker: str | ArrayLike | Path | MarkerStyle | None = ..., + fillstyle: FillStyleType | None = ..., + transform: Transform | None = ..., + capstyle: CapStyle | None = ..., + joinstyle: JoinStyle | None = ..., + ) -> None: ... + def __bool__(self) -> bool: ... + def is_filled(self) -> bool: ... + def get_fillstyle( + self, + ) -> FillStyleType: ... + def get_joinstyle(self) -> JoinStyle: ... + def get_capstyle(self) -> CapStyle: ... + def get_marker(self) -> str | ArrayLike | Path | MarkerStyle | None: ... + def get_path(self) -> Path: ... + def get_transform(self) -> Transform: ... + def get_alt_path(self) -> Path: ... + def get_alt_transform(self) -> Transform: ... + def get_snap_threshold(self) -> float | None: ... + def get_user_transform(self) -> Transform | None: ... + def transformed(self, transform: Affine2D) -> MarkerStyle: ... + def rotated( + self, *, deg: float | None = ..., rad: float | None = ... + ) -> MarkerStyle: ... + def scaled(self, sx: float, sy: float | None = ...) -> MarkerStyle: ... + +MarkerType = Union[str, Path, MarkerStyle] +FillStyleType = Literal["full", "left", "right", "bottom", "top", "none"] diff --git a/lib/matplotlib/mathtext.pyi b/lib/matplotlib/mathtext.pyi new file mode 100644 index 000000000000..78ed0d961883 --- /dev/null +++ b/lib/matplotlib/mathtext.pyi @@ -0,0 +1,22 @@ +import io +import os +from ._mathtext import RasterParse, VectorParse, get_unicode_index +from matplotlib.font_manager import FontProperties +from matplotlib.ft2font import FT2Image, LOAD_NO_HINTING +from matplotlib.colors import Color + +from typing import Literal + +class MathTextParser: + def __init__(self, output: Literal["path", "raster", "macosx"]) -> None: ... + def parse(self, s: str, dpi: float = ..., prop: FontProperties | None = ...): ... + +def math_to_image( + s: str, + filename_or_obj: str | os.PathLike | io.FileIO, + prop: FontProperties | None = ..., + dpi: float | None = ..., + format: str | None = ..., + *, + color: Color | None = ... +): ... diff --git a/lib/matplotlib/mlab.pyi b/lib/matplotlib/mlab.pyi new file mode 100644 index 000000000000..79611dee2877 --- /dev/null +++ b/lib/matplotlib/mlab.pyi @@ -0,0 +1,124 @@ +from matplotlib import cbook + +from typing import Literal, Callable +import numpy as np +from numpy.typing import ArrayLike + +def window_hanning(x: ArrayLike) -> ArrayLike: ... +def window_none(x: ArrayLike) -> ArrayLike: ... +def detrend( + x: ArrayLike, + key: Literal["default", "constant", "mean", "linear", "none"] + | Callable[[ArrayLike, int | None], ArrayLike] + | None = ..., + axis: int | None = ..., +): ... +def detrend_mean(x: ArrayLike, axis: int | None = ...) -> ArrayLike: ... +def detrend_none(x: ArrayLike, axis: int | None = ...) -> ArrayLike: ... +def detrend_linear(y: ArrayLike) -> ArrayLike: ... +def psd( + x: ArrayLike, + NFFT: int | None = ..., + Fs: float | None = ..., + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike, int | None], ArrayLike] + | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + noverlap: int | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + scale_by_freq: bool | None = ..., +) -> tuple[ArrayLike, ArrayLike]: ... +def csd( + x: ArrayLike, + y: ArrayLike | None, + NFFT: int | None = ..., + Fs: float | None = ..., + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike, int | None], ArrayLike] + | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + noverlap: int | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + scale_by_freq: bool | None = ..., +) -> tuple[ArrayLike, ArrayLike]: ... +def complex_spectrum( + x: ArrayLike, + Fs: float | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., +) -> tuple[ArrayLike, ArrayLike]: ... +def magnitude_spectrum( + x: ArrayLike, + Fs: float | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., +) -> tuple[ArrayLike, ArrayLike]: ... +def angle_spectrum( + x: ArrayLike, + Fs: float | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., +) -> tuple[ArrayLike, ArrayLike]: ... +def phase_spectrum( + x: ArrayLike, + Fs: float | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., +) -> tuple[ArrayLike, ArrayLike]: ... +def specgram( + x: ArrayLike, + NFFT: int | None = ..., + Fs: float | None = ..., + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike, int | None], ArrayLike] + | None = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = ..., + noverlap: int | None = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] | None = ..., + scale_by_freq: bool | None = ..., + mode: Literal["psd", "complex", "magnitude", "angle", "phase"] | None = ..., +): ... +def cohere( + x: ArrayLike, + y: ArrayLike, + NFFT: int = ..., + Fs: float = ..., + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike, int | None], ArrayLike] = ..., + window: Callable[[ArrayLike], ArrayLike] | ArrayLike = ..., + noverlap: int = ..., + pad_to: int | None = ..., + sides: Literal["default", "onesided", "twosided"] = ..., + scale_by_freq: bool | None = ..., +): ... + +class GaussianKDE: + dataset: ArrayLike + dim: int + num_dp: int + factor: float + data_covariance: ArrayLike + data_inv_cov: ArrayLike + covariance: ArrayLike + inv_cov: ArrayLike + norm_factor: float + def __init__( + self, + dataset: ArrayLike, + bw_method: Literal["scott", "silverman"] + | float + | Callable[[GaussianKDE], float] + | None = ..., + ) -> None: ... + def scotts_factor(self) -> float: ... + def silverman_factor(self) -> float: ... + def covariance_factor(self) -> float: ... + def evaluate(self, points: ArrayLike) -> np.ndarray: ... + def __call__(self, points: ArrayLike) -> np.ndarray: ... diff --git a/lib/matplotlib/mpl-data/matplotlibrc b/lib/matplotlib/mpl-data/matplotlibrc index 28dad0f392a5..26c78658f4e0 100644 --- a/lib/matplotlib/mpl-data/matplotlibrc +++ b/lib/matplotlib/mpl-data/matplotlibrc @@ -237,7 +237,7 @@ ## ## The font.variant property has two values: normal or small-caps. For ## TrueType fonts, which are scalable fonts, small-caps is equivalent -## to using a font size of 'smaller', or about 83%% of the current font +## to using a font size of 'smaller', or about 83 % of the current font ## size. ## ## The font.weight property has effectively 13 values: normal, bold, @@ -445,9 +445,9 @@ ## These control the default format strings used in AutoDateFormatter. ## Any valid format datetime format string can be used (see the python ## `datetime` for details). For example, by using: -## - '%%x' will use the locale date representation -## - '%%X' will use the locale time representation -## - '%%c' will use the full locale datetime representation +## - '%x' will use the locale date representation +## - '%X' will use the locale time representation +## - '%c' will use the full locale datetime representation ## These values map to the scales: ## {'year': 365, 'month': 30, 'day': 1, 'hour': 1/24, 'minute': 1 / (24 * 60)} diff --git a/lib/matplotlib/offsetbox.pyi b/lib/matplotlib/offsetbox.pyi new file mode 100644 index 000000000000..553d021cc3ac --- /dev/null +++ b/lib/matplotlib/offsetbox.pyi @@ -0,0 +1,315 @@ +import matplotlib.artist as martist +from matplotlib.axes import Axes +from matplotlib.backend_bases import RendererBase, Event, FigureCanvasBase +from matplotlib.colors import Colormap, Normalize +import matplotlib.text as mtext +from matplotlib.figure import Figure +from matplotlib.font_manager import FontProperties +from matplotlib.image import BboxImage +from matplotlib.patches import FancyArrowPatch, FancyBboxPatch +from matplotlib.transforms import Bbox, BboxBase, TransformedBbox, Transform + +import numpy as np +from numpy.typing import ArrayLike +from typing import Any, Callable, Literal, Sequence + +DEBUG: bool + +def bbox_artist(*args, **kwargs) -> None: ... +def _get_packed_offsets( + widths: Sequence[float], + total: float | None, + sep: float, + mode: Literal["fixed", "expand", "equal"] = ..., +) -> tuple[float, np.ndarray]: ... + +class OffsetBox(martist.Artist): + width: float | None + height: float | None + def __init__(self, *args, **kwargs) -> None: ... + def set_figure(self, fig: Figure) -> None: ... + def set_offset( + self, + xy: tuple[float, float] + | Callable[[float, float, float, float, RendererBase], tuple[float, float]], + ) -> None: ... + def get_offset( + self, + width: float, + height: float, + xdescent: float, + ydescent: float, + renderer: RendererBase, + ) -> tuple[float, float]: ... + def set_width(self, width: float) -> None: ... + def set_height(self, height: float) -> None: ... + def get_visible_children(self) -> list[martist.Artist]: ... + def get_children(self) -> list[martist.Artist]: ... + def get_extent_offsets( + self, renderer: RendererBase + ) -> tuple[float, float, float, float, list[tuple[float, float]]]: ... + def get_extent( + self, renderer: RendererBase + ) -> tuple[float, float, float, float]: ... + def get_window_extent(self, renderer: RendererBase | None = ...) -> Bbox: ... + +class PackerBase(OffsetBox): + height: float | None + width: float | None + sep: float | None + pad: float | None + mode: Literal["fixed", "expand", "equal"] + align: Literal["top", "bottom", "left", "right", "center", "baseline"] + def __init__( + self, + pad: float | None = ..., + sep: float | None = ..., + width: float | None = ..., + height: float | None = ..., + align: Literal["top", "bottom", "left", "right", "center", "baseline"] = ..., + mode: Literal["fixed", "expand", "equal"] = ..., + children: list[martist.Artist] | None = ..., + ) -> None: ... + +class VPacker(PackerBase): ... +class HPacker(PackerBase): ... + +class PaddedBox(OffsetBox): + pad: float | None + patch: FancyBboxPatch + def __init__( + self, + child: martist.Artist, + pad: float | None = ..., + draw_frame: bool = ..., + patch_attrs: dict[str, Any] | None = ..., + ) -> None: ... + def update_frame(self, bbox: Bbox, fontsize: float | None = ...) -> None: ... + def draw_frame(self, renderer: RendererBase) -> None: ... + +class DrawingArea(OffsetBox): + width: float + height: float + xdescent: float + ydescent: float + offset_transform: Transform + dpi_transform: Transform + def __init__( + self, + width: float, + height: float, + xdescent: float = ..., + ydescent: float = ..., + clip: bool = ..., + ) -> None: ... + @property + def clip_children(self) -> bool: ... + @clip_children.setter + def clip_children(self, val: bool) -> None: ... + def get_transform(self) -> Transform: ... + def set_transform(self, t: Transform) -> None: ... + + # does not accept all options of superclass + def set_offset(self, xy: tuple[float, float]) -> None: ... # type: ignore[override] + def get_offset(self) -> tuple[float, float]: ... # type: ignore[override] + def add_artist(self, a: martist.Artist) -> None: ... + +class TextArea(OffsetBox): + offset_transform: Transform + def __init__( + self, + s: str, + textprops: dict[str, Any] | None = ..., + multilinebaseline: bool = ..., + ) -> None: ... + def set_text(self, s: str) -> None: ... + def get_text(self) -> str: ... + def set_multilinebaseline(self, t: bool) -> None: ... + def get_multilinebaseline(self) -> bool: ... + def set_transform(self, t: Transform) -> None: ... + + # does not accept all options of superclass + def set_offset(self, xy: tuple[float, float]) -> None: ... # type: ignore[override] + def get_offset(self) -> tuple[float, float]: ... # type: ignore[override] + +class AuxTransformBox(OffsetBox): + aux_transform: Transform + offset_transform: Transform + ref_offset_transform: Transform + def __init__(self, aux_transform: Transform) -> None: ... + def add_artist(self, a: martist.Artist) -> None: ... + def get_transform(self) -> Transform: ... + def set_transform(self, t: Transform) -> None: ... + + # does not accept all options of superclass + def set_offset(self, xy: tuple[float, float]) -> None: ... # type: ignore[override] + def get_offset(self) -> tuple[float, float]: ... # type: ignore[override] + +class AnchoredOffsetbox(OffsetBox): + zorder: float + codes: dict[str, int] + loc: int + borderpad: float + pad: float + prop: FontProperties + patch: FancyBboxPatch + def __init__( + self, + loc: str, + pad: float = ..., + borderpad: float = ..., + child: OffsetBox | None = ..., + prop: FontProperties | None = ..., + frameon: bool = ..., + bbox_to_anchor: BboxBase + | tuple[float, float] + | tuple[float, float, float, float] + | None = ..., + bbox_transform: Transform | None = ..., + **kwargs + ) -> None: ... + def set_child(self, child: OffsetBox | None) -> None: ... + def get_child(self) -> OffsetBox | None: ... + def get_children(self) -> list[martist.Artist]: ... + def get_bbox_to_anchor(self) -> Bbox: ... + def set_bbox_to_anchor( + self, bbox: Bbox, transform: Transform | None = ... + ) -> None: ... + def get_offset( + self, + width: float, + height: float, + xdescent: float, + ydescent: float, + renderer: RendererBase, + ) -> tuple[float, float]: ... + def update_frame(self, bbox: Bbox, fontsize: float | None = ...) -> None: ... + +class AnchoredText(AnchoredOffsetbox): + txt: TextArea + def __init__( + self, + s: str, + loc: str, + pad: float = ..., + borderpad: float = ..., + prop: dict[str, Any] | None = ..., + **kwargs + ) -> None: ... + +class OffsetImage(OffsetBox): + image: BboxImage + def __init__( + self, + arr: ArrayLike, + zoom: float = ..., + cmap: Colormap | str | None = ..., + norm: Normalize | str | None = ..., + interpolation: str | None = ..., + origin: Literal["upper", "lower"] | None = ..., + filternorm: bool = ..., + filterrad: float = ..., + resample: bool = ..., + dpi_cor: bool = ..., + **kwargs + ) -> None: ... + stale: bool + def set_data(self, arr: ArrayLike | None) -> None: ... + def get_data(self) -> ArrayLike | None: ... + def set_zoom(self, zoom: float) -> None: ... + def get_zoom(self) -> float: ... + def get_children(self) -> list[martist.Artist]: ... + +class AnnotationBbox(martist.Artist, mtext._AnnotationBase): + zorder: float + offsetbox: OffsetBox + arrowprops: dict[str, Any] | None + xybox: tuple[float, float] + boxcoords: str | tuple[str, str] | martist.Artist | Transform | Callable[ + [RendererBase], Bbox | Transform + ] + arrow_patch: FancyArrowPatch | None + patch: FancyBboxPatch + prop: FontProperties + def __init__( + self, + offsetbox: OffsetBox, + xy: tuple[float, float], + xybox: tuple[float, float] | None = ..., + xycoords: str + | tuple[str, str] + | martist.Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] = ..., + boxcoords: str + | tuple[str, str] + | martist.Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | None = ..., + frameon: bool = ..., + pad: float = ..., + annotation_clip: bool | None = ..., + box_alignment: tuple[float, float] = ..., + bboxprops: dict[str, Any] | None = ..., + arrowprops: dict[str, Any] | None = ..., + fontsize: float | str | None = ..., + **kwargs + ) -> None: ... + @property + def xyann(self) -> tuple[float, float]: ... + @xyann.setter + def xyann(self, xyann: tuple[float, float]) -> None: ... + @property + def anncoords( + self, + ) -> str | tuple[str, str] | martist.Artist | Transform | Callable[ + [RendererBase], Bbox | Transform + ]: ... + @anncoords.setter + def anncoords( + self, + coords: str + | tuple[str, str] + | martist.Artist + | Transform + | Callable[[RendererBase], Bbox | Transform], + ) -> None: ... + def get_children(self) -> list[martist.Artist]: ... + def set_figure(self, fig: Figure) -> None: ... + def set_fontsize(self, s: str | float | None = ...) -> None: ... + def get_fontsize(self) -> float: ... + def get_tightbbox(self, renderer: RendererBase | None = ...) -> Bbox: ... + def update_positions(self, renderer: RendererBase) -> None: ... + +class DraggableBase: + ref_artist: martist.Artist + got_artist: bool + canvas: FigureCanvasBase + cids: list[int] + mouse_x: int + mouse_y: int + background: Any + def __init__(self, ref_artist: martist.Artist, use_blit: bool = ...) -> None: ... + def on_motion(self, evt: Event) -> None: ... + def on_pick(self, evt: Event) -> None: ... + def on_release(self, event: Event) -> None: ... + def disconnect(self) -> None: ... + def save_offset(self) -> None: ... + def update_offset(self, dx: float, dy: float) -> None: ... + def finalize_offset(self) -> None: ... + +class DraggableOffsetBox(DraggableBase): + offsetbox: OffsetBox + def __init__( + self, ref_artist: martist.Artist, offsetbox: OffsetBox, use_blit: bool = ... + ) -> None: ... + def save_offset(self) -> None: ... + def update_offset(self, dx: float, dy: float) -> None: ... + def get_loc_in_canvas(self) -> tuple[float, float]: ... + +class DraggableAnnotation(DraggableBase): + annotation: mtext.Annotation + def __init__(self, annotation: mtext.Annotation, use_blit: bool = ...) -> None: ... + def save_offset(self) -> None: ... + def update_offset(self, dx: float, dy: float) -> None: ... diff --git a/lib/matplotlib/patches.pyi b/lib/matplotlib/patches.pyi new file mode 100644 index 000000000000..3455069db6d4 --- /dev/null +++ b/lib/matplotlib/patches.pyi @@ -0,0 +1,740 @@ +from . import artist, cbook, colors, transforms +from .axes import Axes +from ._enums import CapStyle, JoinStyle +from .backend_bases import RendererBase +from .bezier import ( + NonIntersectingPathException, + get_cos_sin, + get_intersection, + get_parallels, + inside_circle, + make_wedged_bezier2, + split_bezier_intersecting_with_closedpath, + split_path_inout, +) +from .colors import Color +from .lines import LineStyleType +from .path import Path +from .transforms import Transform, Bbox + +from typing import Any, Literal, Type, overload + +import numpy as np +from numpy.typing import ArrayLike + +class Patch(artist.Artist): + zorder: float + def __init__( + self, + edgecolor: Color | None = ..., + facecolor: Color | None = ..., + color: Color | None = ..., + linewidth: float | None = ..., + linestyle: LineStyleType | None = ..., + antialiased: bool | None = ..., + hatch: str | None = ..., + fill: bool = ..., + capstyle: CapStyle | None = ..., + joinstyle: JoinStyle | None = ..., + **kwargs, + ) -> None: ... + def get_verts(self) -> ArrayLike: ... + def contains_point( + self, point: tuple[float, float], radius: float | None = ... + ) -> bool: ... + def contains_points( + self, points: ArrayLike, radius: float | None = ... + ) -> np.ndarray: ... + def get_extents(self) -> Bbox: ... + def get_transform(self) -> Transform: ... + def get_data_transform(self) -> Transform: ... + def get_patch_transform(self) -> Transform: ... + def get_antialiased(self) -> bool: ... + def get_edgecolor(self) -> Color: ... + def get_facecolor(self) -> Color: ... + def get_linewidth(self) -> float: ... + def get_linestyle(self) -> LineStyleType: ... + def set_antialiased(self, aa: bool | None) -> None: ... + def set_edgecolor(self, color: Color | None) -> None: ... + def set_facecolor(self, color: Color | None) -> None: ... + def set_color(self, c: Color | None) -> None: ... + def set_alpha(self, alpha: float | None) -> None: ... + def set_linewidth(self, w: float | None) -> None: ... + def set_linestyle(self, ls: LineStyleType | None) -> None: ... + def set_fill(self, b: bool) -> None: ... + def get_fill(self) -> bool: ... + fill = property(get_fill, set_fill) + def set_capstyle(self, s: CapStyle) -> None: ... + def get_capstyle(self) -> CapStyle: ... + def set_joinstyle(self, s: JoinStyle) -> None: ... + def get_joinstyle(self) -> JoinStyle: ... + def set_hatch(self, hatch: str) -> None: ... + def get_hatch(self) -> str: ... + def get_path(self) -> Path: ... + +class Shadow(Patch): + patch: Patch + def __init__(self, patch: Patch, ox: float, oy: float, **kwargs) -> None: ... + +class Rectangle(Patch): + angle: float + def __init__( + self, + xy: tuple[float, float], + width: float, + height: float, + angle: float = ..., + *, + rotation_point: Literal["xy", "center"] | tuple[float, float] = ..., + **kwargs, + ) -> None: ... + @property + def rotation_point(self) -> Literal["xy", "center"] | tuple[float, float]: ... + @rotation_point.setter + def rotation_point( + self, value: Literal["xy", "center"] | tuple[float, float] + ) -> None: ... + def get_x(self) -> float: ... + def get_y(self) -> float: ... + def get_xy(self) -> tuple[float, float]: ... + def get_corners(self) -> np.ndarray: ... + def get_center(self) -> np.ndarray: ... + def get_width(self) -> float: ... + def get_height(self) -> float: ... + def get_angle(self) -> float: ... + def set_x(self, x: float) -> None: ... + def set_y(self, y: float) -> None: ... + def set_angle(self, angle: float) -> None: ... + def set_xy(self, xy: tuple[float, float]) -> None: ... + def set_width(self, w: float) -> None: ... + def set_height(self, h: float) -> None: ... + @overload + def set_bounds(self, args: tuple[float, float, float, float], /) -> None: ... + @overload + def set_bounds( + self, left: float, bottom: float, width: float, height: float, / + ) -> None: ... + def get_bbox(self) -> Bbox: ... + xy = property(get_xy, set_xy) + +class RegularPolygon(Patch): + xy: tuple[float, float] + numvertices: int + orientation: float + radius: float + def __init__( + self, + xy: tuple[float, float], + numVertices: int, + radius: float = ..., + orientation: float = ..., + **kwargs, + ) -> None: ... + +class PathPatch(Patch): + def __init__(self, path: Path, **kwargs) -> None: ... + def set_path(self, path: Path) -> None: ... + +class StepPatch(PathPatch): + orientation: Literal["vertical", "horizontal"] + def __init__( + self, + values: ArrayLike, + edges: ArrayLike, + *, + orientation: Literal["vertical", "horizontal"] = ..., + baseline: float = ..., + **kwargs, + ) -> None: ... + + # NamedTuple StairData, defined in body of method + def get_data(self) -> tuple[np.ndarray, np.ndarray, float]: ... + def set_data( + self, + values: ArrayLike | None = ..., + edges: ArrayLike | None = ..., + baseline: float | None = ..., + ) -> None: ... + +class Polygon(Patch): + def __init__(self, xy: ArrayLike, closed: bool = ..., **kwargs) -> None: ... + def get_closed(self) -> bool: ... + def set_closed(self, closed: bool) -> None: ... + def get_xy(self) -> np.ndarray: ... + def set_xy(self, xy: ArrayLike) -> None: ... + xy = property(get_xy, set_xy, doc="The vertices of the path as (N, 2) numpy array.") + +class Wedge(Patch): + center: tuple[float, float] + r: float + theta1: float + theta2: float + width: float | None + def __init__( + self, + center: tuple[float, float], + r: float, + theta1: float, + theta2: float, + width: float | None = ..., + **kwargs, + ) -> None: ... + def set_center(self, center: tuple[float, float]) -> None: ... + def set_radius(self, radius: float) -> None: ... + def set_theta1(self, theta1: float) -> None: ... + def set_theta2(self, theta2: float) -> None: ... + def set_width(self, width: float | None) -> None: ... + +class Arrow(Patch): + def __init__( + self, x: float, y: float, dx: float, dy: float, width: float = ..., **kwargs + ) -> None: ... + +class FancyArrow(Polygon): + def __init__( + self, + x: float, + y: float, + dx: float, + dy: float, + width: float = ..., + length_includes_head: bool = ..., + head_width: float | None = ..., + head_length: float | None = ..., + shape: Literal["full", "left", "right"] = ..., + overhang: float = ..., + head_starts_at_zero: bool = ..., + **kwargs, + ) -> None: ... + def set_data( + self, + *, + x: float | None = ..., + y: float | None = ..., + dx: float | None = ..., + dy: float | None = ..., + width: float | None = ..., + head_width: float | None = ..., + head_length: float | None = ..., + ) -> None: ... + +class CirclePolygon(RegularPolygon): + def __init__( + self, + xy: tuple[float, float], + radius: float = ..., + resolution: int = ..., + **kwargs, + ) -> None: ... + +class Ellipse(Patch): + def __init__( + self, + xy: tuple[float, float], + width: float, + height: float, + angle: float = ..., + **kwargs, + ) -> None: ... + def set_center(self, xy: tuple[float, float]) -> None: ... + def get_center(self) -> float: ... + center = property(get_center, set_center) + + def set_width(self, width: float) -> None: ... + def get_width(self) -> float: ... + width = property(get_width, set_width) + + def set_height(self, height: float) -> None: ... + def get_height(self) -> float: ... + height = property(get_height, set_height) + + def set_angle(self, angle: float) -> None: ... + def get_angle(self) -> float: ... + angle = property(get_angle, set_angle) + + def get_corners(self) -> np.ndarray: ... + +class Annulus(Patch): + a: float + b: float + def __init__( + self, + xy: tuple[float, float], + r: float | tuple[float, float], + width: float, + angle: float = ..., + **kwargs, + ) -> None: ... + def set_center(self, xy: tuple[float, float]) -> None: ... + def get_center(self) -> tuple[float, float]: ... + center = property(get_center, set_center) + + def set_width(self, width: float) -> None: ... + def get_width(self) -> float: ... + width = property(get_width, set_width) + + def set_angle(self, angle: float) -> None: ... + def get_angle(self) -> float: ... + angle = property(get_angle, set_angle) + + def set_semimajor(self, a: float) -> None: ... + def set_semiminor(self, b: float) -> None: ... + def set_radii(self, r: float | tuple[float, float]) -> None: ... + def get_radii(self) -> tuple[float, float]: ... + radii = property(get_radii, set_radii) + +class Circle(Ellipse): + def __init__( + self, xy: tuple[float, float], radius: float = ..., **kwargs + ) -> None: ... + def set_radius(self, radius: float) -> None: ... + def get_radius(self): ... + radius = property(get_radius, set_radius) + +class Arc(Ellipse): + theta1: float + theta2: float + def __init__( + self, + xy: tuple[float, float], + width: float, + height: float, + angle: float = ..., + theta1: float = ..., + theta2: float = ..., + **kwargs, + ) -> None: ... + +def bbox_artist( + artist: artist.Artist, + renderer: RendererBase, + props: dict[str, Any] | None = ..., + fill: bool = ..., +) -> None: ... +def draw_bbox( + bbox: Bbox, + renderer: RendererBase, + color: Color = ..., + trans: Transform | None = ..., +) -> None: ... + +class _Style: + def __init_subclass__(cls) -> None: ... + def __new__(cls, stylename, **kwargs): ... + @classmethod + def get_styles(cls) -> dict[str, Type]: ... + @classmethod + def pprint_styles(cls) -> str: ... + @classmethod + def register(cls, name: str, style: Type) -> None: ... + +class BoxStyle(_Style): + class Square: + pad: float + def __init__(self, pad: float = ...) -> None: ... + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + + class Circle: + pad: float + def __init__(self, pad: float = ...) -> None: ... + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + + class LArrow: + pad: float + def __init__(self, pad: float = ...) -> None: ... + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + + class RArrow(LArrow): + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + + class DArrow: + pad: float + def __init__(self, pad: float = ...) -> None: ... + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + + class Round: + pad: float + rounding_size: float | None + def __init__( + self, pad: float = ..., rounding_size: float | None = ... + ) -> None: ... + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + + class Round4: + pad: float + rounding_size: float | None + def __init__( + self, pad: float = ..., rounding_size: float | None = ... + ) -> None: ... + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + + class Sawtooth: + pad: float + tooth_size: float | None + def __init__( + self, pad: float = ..., tooth_size: float | None = ... + ) -> None: ... + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + + class Roundtooth(Sawtooth): + def __call__( + self, + x0: float, + y0: float, + width: float, + height: float, + mutation_size: float, + ) -> Path: ... + +class ConnectionStyle(_Style): + class _Base: + class SimpleEvent: + def __init__(self, xy: tuple[float, float]) -> None: ... + + def __call__( + self, + posA: tuple[float, float], + posB: tuple[float, float], + shrinkA: float = ..., + shrinkB: float = ..., + patchA: Patch | None = ..., + patchB: Patch | None = ..., + ) -> Path: ... + + class Arc3(_Base): + rad: float + def __init__(self, rad: float = ...) -> None: ... + def connect( + self, posA: tuple[float, float], posB: tuple[float, float] + ) -> Path: ... + + class Angle3(_Base): + angleA: float + angleB: float + def __init__(self, angleA: float = ..., angleB: float = ...) -> None: ... + def connect( + self, posA: tuple[float, float], posB: tuple[float, float] + ) -> Path: ... + + class Angle(_Base): + angleA: float + angleB: float + rad: float + def __init__( + self, angleA: float = ..., angleB: float = ..., rad: float = ... + ) -> None: ... + def connect( + self, posA: tuple[float, float], posB: tuple[float, float] + ) -> Path: ... + + class Arc(_Base): + angleA: float + angleB: float + armA: float | None + armB: float | None + rad: float + def __init__( + self, + angleA: float = ..., + angleB: float = ..., + armA: float | None = ..., + armB: float | None = ..., + rad: float = ..., + ) -> None: ... + def connect( + self, posA: tuple[float, float], posB: tuple[float, float] + ) -> Path: ... + + class Bar(_Base): + armA: float + armB: float + fraction: float + angle: float | None + def __init__( + self, + armA: float = ..., + armB: float = ..., + fraction: float = ..., + angle: float | None = ..., + ) -> None: ... + def connect( + self, posA: tuple[float, float], posB: tuple[float, float] + ) -> Path: ... + +class ArrowStyle(_Style): + class _Base: + @staticmethod + def ensure_quadratic_bezier(path: Path) -> list[float]: ... + def transmute( + self, path: Path, mutation_size: float, linewidth: float + ) -> tuple[Path, bool]: ... + def __call__( + self, + path: Path, + mutation_size: float, + linewidth: float, + aspect_ratio: float = ..., + ) -> tuple[Path, bool]: ... + + class _Curve(_Base): + arrow: str + fillbegin: bool + fillend: bool + def __init__( + self, + head_length: float = ..., + head_width: float = ..., + widthA: float = ..., + widthB: float = ..., + lengthA: float = ..., + lengthB: float = ..., + angleA: float | None = ..., + angleB: float | None = ..., + scaleA: float | None = ..., + scaleB: float | None = ..., + ) -> None: ... + + class Curve(_Curve): + def __init__(self) -> None: ... + + class CurveA(_Curve): + arrow: str + + class CurveB(_Curve): + arrow: str + + class CurveAB(_Curve): + arrow: str + + class CurveFilledA(_Curve): + arrow: str + + class CurveFilledB(_Curve): + arrow: str + + class CurveFilledAB(_Curve): + arrow: str + + class BracketA(_Curve): + arrow: str + def __init__( + self, widthA: float = ..., lengthA: float = ..., angleA: float = ... + ) -> None: ... + + class BracketB(_Curve): + arrow: str + def __init__( + self, widthB: float = ..., lengthB: float = ..., angleB: float = ... + ) -> None: ... + + class BracketAB(_Curve): + arrow: str + def __init__( + self, + widthA: float = ..., + lengthA: float = ..., + angleA: float = ..., + widthB: float = ..., + lengthB: float = ..., + angleB: float = ..., + ) -> None: ... + + class BarAB(_Curve): + arrow: str + def __init__( + self, + widthA: float = ..., + angleA: float = ..., + widthB: float = ..., + angleB: float = ..., + ) -> None: ... + + class BracketCurve(_Curve): + arrow: str + def __init__( + self, widthA: float = ..., lengthA: float = ..., angleA: float | None = ... + ) -> None: ... + + class CurveBracket(_Curve): + arrow: str + def __init__( + self, widthB: float = ..., lengthB: float = ..., angleB: float | None = ... + ) -> None: ... + + class Simple(_Base): + def __init__( + self, + head_length: float = ..., + head_width: float = ..., + tail_width: float = ..., + ) -> None: ... + + class Fancy(_Base): + def __init__( + self, + head_length: float = ..., + head_width: float = ..., + tail_width: float = ..., + ) -> None: ... + + class Wedge(_Base): + tail_width: float + shrink_factor: float + def __init__( + self, tail_width: float = ..., shrink_factor: float = ... + ) -> None: ... + +class FancyBboxPatch(Patch): + def __init__( + self, + xy: tuple[float, float], + width: float, + height: float, + boxstyle: str | BoxStyle = ..., + *, + mutation_scale: float = ..., + mutation_aspect: float = ..., + **kwargs, + ) -> None: ... + def set_boxstyle(self, boxstyle: str | BoxStyle | None = ..., **kwargs): ... + def get_boxstyle(self) -> BoxStyle: ... + def set_mutation_scale(self, scale: float) -> None: ... + def get_mutation_scale(self) -> float: ... + def set_mutation_aspect(self, aspect: float) -> None: ... + def get_mutation_aspect(self) -> float: ... + def get_x(self) -> float: ... + def get_y(self) -> float: ... + def get_width(self) -> float: ... + def get_height(self) -> float: ... + def set_x(self, x: float) -> None: ... + def set_y(self, y: float) -> None: ... + def set_width(self, w: float) -> None: ... + def set_height(self, h: float) -> None: ... + @overload + def set_bounds(self, args: tuple[float, float, float, float], /) -> None: ... + @overload + def set_bounds( + self, left: float, bottom: float, width: float, height: float, / + ) -> None: ... + def get_bbox(self) -> Bbox: ... + +class FancyArrowPatch(Patch): + patchA: Patch + patchB: Patch + shrinkA: float + shrinkB: float + def __init__( + self, + posA: tuple[float, float] | None = ..., + posB: tuple[float, float] | None = ..., + path: Path | None = ..., + arrowstyle: str | ArrowStyle = ..., + connectionstyle: str | ConnectionStyle = ..., + patchA: Patch | None = ..., + patchB: Patch | None = ..., + shrinkA: float = ..., + shrinkB: float = ..., + mutation_scale: float = ..., + mutation_aspect: float | None = ..., + **kwargs, + ) -> None: ... + def set_positions( + self, posA: tuple[float, float], posB: tuple[float, float] + ) -> None: ... + def set_patchA(self, patchA: Patch) -> None: ... + def set_patchB(self, patchB: Patch) -> None: ... + def set_connectionstyle( + self, connectionstyle: str | ConnectionStyle | None = ..., **kwargs + ): ... + def get_connectionstyle(self) -> ConnectionStyle: ... + def set_arrowstyle(self, arrowstyle: str | ArrowStyle | None = ..., **kwargs): ... + def get_arrowstyle(self) -> ArrowStyle: ... + def set_mutation_scale(self, scale: float) -> None: ... + def get_mutation_scale(self) -> float: ... + def set_mutation_aspect(self, aspect: float | None) -> None: ... + def get_mutation_aspect(self) -> float: ... + +class ConnectionPatch(FancyArrowPatch): + xy1: tuple[float, float] + xy2: tuple[float, float] + coords1: str | Transform + coords2: str | Transform | None + axesA: Axes | None + axesB: Axes | None + def __init__( + self, + xyA: tuple[float, float], + xyB: tuple[float, float], + coordsA: str | Transform, + coordsB: str | Transform | None = ..., + axesA: Axes | None = ..., + axesB: Axes | None = ..., + arrowstyle: str | ArrowStyle = ..., + connectionstyle: str | ConnectionStyle = ..., + patchA: Patch | None = ..., + patchB: Patch | None = ..., + shrinkA: float = ..., + shrinkB: float = ..., + mutation_scale: float = ..., + mutation_aspect: float | None = ..., + clip_on: bool = ..., + **kwargs, + ) -> None: ... + def set_annotation_clip(self, b: bool | None) -> None: ... + def get_annotation_clip(self) -> bool | None: ... diff --git a/lib/matplotlib/path.pyi b/lib/matplotlib/path.pyi new file mode 100644 index 000000000000..5978fa6a6d7d --- /dev/null +++ b/lib/matplotlib/path.pyi @@ -0,0 +1,141 @@ +from .bezier import BezierSegment as BezierSegment +from .cbook import simple_linear_interpolation as simple_linear_interpolation +from .transforms import Affine2D, Transform, Bbox +from collections.abc import Generator + +import numpy as np +from numpy.typing import ArrayLike + +from typing import Any, Iterable, Sequence, Type, overload + +class Path: + code_type: Type[np.uint8] + STOP: np.uint8 + MOVETO: np.uint8 + LINETO: np.uint8 + CURVE3: np.uint8 + CURVE4: np.uint8 + CLOSEPOLY: np.uint8 + NUM_VERTICES_FOR_CODE: dict[np.uint8, int] + + def __init__( + self, + vertices: ArrayLike, + codes: ArrayLike | None = ..., + _interpolation_steps: int = ..., + closed: bool = ..., + readonly: bool = ..., + ) -> None: ... + @property + def vertices(self) -> ArrayLike: ... + @vertices.setter + def vertices(self, vertices: ArrayLike) -> None: ... + @property + def codes(self) -> ArrayLike: ... + @codes.setter + def codes(self, codes: ArrayLike) -> None: ... + @property + def simplify_threshold(self) -> float: ... + @simplify_threshold.setter + def simplify_threshold(self, threshold: float) -> None: ... + @property + def should_simplify(self) -> bool: ... + @should_simplify.setter + def should_simplify(self, should_simplify: bool) -> None: ... + @property + def readonly(self) -> bool: ... + def copy(self) -> Path: ... + def __deepcopy__(self, memo: dict[int, Any] | None = ...): ... + deepcopy = __deepcopy__ + + @classmethod + def make_compound_path_from_polys(cls, XY: ArrayLike) -> Path: ... + @classmethod + def make_compound_path(cls, *args: Path) -> Path: ... + def __len__(self) -> int: ... + def iter_segments( + self, + transform: Transform | None = ..., + remove_nans: bool = ..., + clip: tuple[float, float, float, float] | None = ..., + snap: bool | None = ..., + stroke_width: float = ..., + simplify: bool | None = ..., + curves: bool = ..., + sketch: tuple[float, float, float] | None = ..., + ) -> Generator[tuple[np.ndarray, np.uint8], None, None]: ... + def iter_bezier(self, **kwargs) -> Generator[BezierSegment, None, None]: ... + def cleaned( + self, + transform: Transform | None = ..., + remove_nans: bool = ..., + clip: tuple[float, float, float, float] | None = ..., + *, + simplify: bool | None = ..., + curves: bool = ..., + stroke_width: float = ..., + snap: bool | None = ..., + sketch: tuple[float, float, float] | None = ... + ) -> Path: ... + def transformed(self, transform: Transform) -> Path: ... + def contains_point( + self, + point: tuple[float, float], + transform: Transform | None = ..., + radius: float = ..., + ) -> bool: ... + def contains_points( + self, points: ArrayLike, transform: Transform | None = ..., radius: float = ... + ) -> np.ndarray: ... + def contains_path(self, path: Path, transform: Transform | None = ...) -> bool: ... + def get_extents(self, transform: Transform | None = ..., **kwargs) -> Bbox: ... + def intersects_path(self, other: Path, filled: bool = ...) -> bool: ... + def intersects_bbox(self, bbox: Bbox, filled: bool = ...) -> bool: ... + def interpolated(self, steps: int) -> Path: ... + def to_polygons( + self, + transform: Transform | None = ..., + width: float = ..., + height: float = ..., + closed_only: bool = ..., + ) -> list[ArrayLike]: ... + @classmethod + def unit_rectangle(cls) -> Path: ... + @classmethod + def unit_regular_polygon(cls, numVertices: int) -> Path: ... + @classmethod + def unit_regular_star(cls, numVertices: int, innerCircle: float = ...) -> Path: ... + @classmethod + def unit_regular_asterisk(cls, numVertices: int) -> Path: ... + @classmethod + def unit_circle(cls) -> Path: ... + @classmethod + def circle( + cls, + center: tuple[float, float] = ..., + radius: float = ..., + readonly: bool = ..., + ) -> Path: ... + @classmethod + def unit_circle_righthalf(cls) -> Path: ... + @classmethod + def arc( + cls, theta1: float, theta2: float, n: int | None = ..., is_wedge: bool = ... + ) -> Path: ... + @classmethod + def wedge(cls, theta1: float, theta2: float, n: int | None = ...) -> Path: ... + @overload + @staticmethod + def hatch(hatchpattern: str, density: float = ...) -> Path: ... + @overload + @staticmethod + def hatch(hatchpattern: None, density: float = ...) -> None: ... + def clip_to_bbox(self, bbox: Bbox, inside: bool = ...) -> Path: ... + +def get_path_collection_extents( + master_transform: Transform, + paths: Sequence[Path], + transforms: Iterable[Affine2D], + offsets: ArrayLike, + offset_transform: Affine2D, +) -> Bbox: ... diff --git a/lib/matplotlib/patheffects.pyi b/lib/matplotlib/patheffects.pyi new file mode 100644 index 000000000000..dbdb2fe0e145 --- /dev/null +++ b/lib/matplotlib/patheffects.pyi @@ -0,0 +1,104 @@ +from matplotlib.backend_bases import RendererBase, GraphicsContextBase +from matplotlib.colors import Color +from matplotlib.path import Path +from matplotlib.patches import Patch +from matplotlib.transforms import Transform + +from typing import Iterable, Sequence + +class AbstractPathEffect: + def __init__(self, offset: tuple[float, float] = ...) -> None: ... + def draw_path( + self, + renderer: RendererBase, + gc: GraphicsContextBase, + tpath: Path, + affine: Transform, + rgbFace: Color | None = ..., + ) -> None: ... + +class PathEffectRenderer(RendererBase): + def __init__( + self, path_effects: Iterable[AbstractPathEffect], renderer: RendererBase + ) -> None: ... + def copy_with_path_effect(self, path_effects: Iterable[AbstractPathEffect]): ... + def draw_path( + self, + gc: GraphicsContextBase, + tpath: Path, + affine: Transform, + rgbFace: Color | None = ..., + ) -> None: ... + def draw_markers( + self, + gc: GraphicsContextBase, + marker_path: Path, + marker_trans: Transform, + path: Path, + *args, + **kwargs + ) -> None: ... + def draw_path_collection( + self, + gc: GraphicsContextBase, + master_transform: Transform, + paths: Sequence[Path], + *args, + **kwargs + ) -> None: ... + def __getattribute__(self, name: str): ... + +class Normal(AbstractPathEffect): ... + +class Stroke(AbstractPathEffect): + def __init__(self, offset: tuple[float, float] = ..., **kwargs) -> None: ... + # rgbFace becomes non-optional + def draw_path(self, gc: GraphicsContextBase, tpath: Path, affine: Transform, rgbFace: Color = ...) -> None: ... # type: ignore + +class withStroke(Stroke): ... + +class SimplePatchShadow(AbstractPathEffect): + def __init__( + self, + offset: tuple[float, float] = ..., + shadow_rgbFace: Color | None = ..., + alpha: float | None = ..., + rho: float = ..., + **kwargs + ) -> None: ... + # rgbFace becomes non-optional + def draw_path(self, gc: GraphicsContextBase, tpath: Path, affine: Transform, rgbFace: Color = ...) -> None: ... # type: ignore + +class withSimplePatchShadow(SimplePatchShadow): ... + +class SimpleLineShadow(AbstractPathEffect): + def __init__( + self, + offset: tuple[float, float] = ..., + shadow_color: Color = ..., + alpha: float = ..., + rho: float = ..., + **kwargs + ) -> None: ... + # rgbFace becomes non-optional + def draw_path(self, gc: GraphicsContextBase, tpath: Path, affine: Transform, rgbFace: Color = ...) -> None: ... # type: ignore + +class PathPatchEffect(AbstractPathEffect): + patch: Patch + def __init__(self, offset: tuple[float, float] = ..., **kwargs) -> None: ... + # rgbFace becomes non-optional + def draw_path(self, gc: GraphicsContextBase, tpath: Path, affine: Transform, rgbFace: Color = ...) -> None: ... # type: ignore + +class TickedStroke(AbstractPathEffect): + def __init__( + self, + offset: tuple[float, float] = ..., + spacing: float = ..., + angle: float = ..., + length: float = ..., + **kwargs + ) -> None: ... + # rgbFace becomes non-optional + def draw_path(self, gc: GraphicsContextBase, tpath: Path, affine: Transform, rgbFace: Color = ...) -> None: ... # type: ignore + +class withTickedStroke(TickedStroke): ... diff --git a/lib/matplotlib/projections/__init__.pyi b/lib/matplotlib/projections/__init__.pyi new file mode 100644 index 000000000000..b5f6e3c5a92f --- /dev/null +++ b/lib/matplotlib/projections/__init__.pyi @@ -0,0 +1,17 @@ +from .geo import AitoffAxes, HammerAxes, LambertAxes, MollweideAxes +from .polar import PolarAxes +from ..axes import Axes + +from typing import Type + +class ProjectionRegistry: + def __init__(self) -> None: ... + def register(self, *projections: Type[Axes]) -> None: ... + def get_projection_class(self, name: str) -> Type[Axes]: ... + def get_projection_names(self) -> list[str]: ... + +projection_registry: ProjectionRegistry + +def register_projection(cls: Type[Axes]) -> None: ... +def get_projection_class(projection: str | None = ...) -> Type[Axes]: ... +def get_projection_names() -> list[str]: ... diff --git a/lib/matplotlib/projections/geo.pyi b/lib/matplotlib/projections/geo.pyi new file mode 100644 index 000000000000..0487d039b33b --- /dev/null +++ b/lib/matplotlib/projections/geo.pyi @@ -0,0 +1,123 @@ +from matplotlib.axes import Axes as Axes +from matplotlib.patches import Circle as Circle +from matplotlib.path import Path as Path +from matplotlib.ticker import ( + FixedLocator as FixedLocator, + Formatter as Formatter, + NullFormatter as NullFormatter, + NullLocator as NullLocator, +) +from matplotlib.transforms import ( + Affine2D as Affine2D, + BboxTransformTo as BboxTransformTo, + Transform as Transform, +) + +from typing import Any, Literal + +class GeoAxes(Axes): + class ThetaFormatter(Formatter): + def __init__(self, round_to: float = ...) -> None: ... + def __call__(self, x: float, pos: Any | None = ...): ... + RESOLUTION: float + def get_xaxis_transform( + self, which: Literal["tick1", "tick2", "grid"] = ... + ) -> Transform: ... + def get_xaxis_text1_transform( + self, pad: float + ) -> tuple[ + Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_xaxis_text2_transform( + self, pad: float + ) -> tuple[ + Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_yaxis_transform( + self, which: Literal["tick1", "tick2", "grid"] = ... + ) -> Transform: ... + def get_yaxis_text1_transform( + self, pad: float + ) -> tuple[ + Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_yaxis_text2_transform( + self, pad: float + ) -> tuple[ + Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def set_xlim(self, *args, **kwargs) -> tuple[float, float]: ... + def set_ylim(self, *args, **kwargs) -> tuple[float, float]: ... + def format_coord(self, lon: float, lat: float) -> str: ... + def set_longitude_grid(self, degrees: float) -> None: ... + def set_latitude_grid(self, degrees: float) -> None: ... + def set_longitude_grid_ends(self, degrees: float) -> None: ... + def get_data_ratio(self) -> float: ... + def can_zoom(self) -> bool: ... + def can_pan(self) -> bool: ... + def start_pan(self, x, y, button) -> None: ... + def end_pan(self) -> None: ... + def drag_pan(self, button, key, x, y) -> None: ... + +class _GeoTransform(Transform): + input_dims: int + output_dims: int + def __init__(self, resolution: int) -> None: ... + +class AitoffAxes(GeoAxes): + name: str + + class AitoffTransform(_GeoTransform): + def inverted(self) -> AitoffAxes.InvertedAitoffTransform: ... + + class InvertedAitoffTransform(_GeoTransform): + def inverted(self) -> AitoffAxes.AitoffTransform: ... + +class HammerAxes(GeoAxes): + name: str + + class HammerTransform(_GeoTransform): + def inverted(self) -> HammerAxes.InvertedHammerTransform: ... + + class InvertedHammerTransform(_GeoTransform): + def inverted(self) -> HammerAxes.HammerTransform: ... + +class MollweideAxes(GeoAxes): + name: str + + class MollweideTransform(_GeoTransform): + def inverted(self) -> MollweideAxes.InvertedMollweideTransform: ... + + class InvertedMollweideTransform(_GeoTransform): + def inverted(self) -> MollweideAxes.MollweideTransform: ... + +class LambertAxes(GeoAxes): + name: str + + class LambertTransform(_GeoTransform): + def __init__( + self, center_longitude: float, center_latitude: float, resolution: int + ) -> None: ... + def inverted(self) -> LambertAxes.InvertedLambertTransform: ... + + class InvertedLambertTransform(_GeoTransform): + def __init__( + self, center_longitude: float, center_latitude: float, resolution: int + ) -> None: ... + def inverted(self) -> LambertAxes.LambertTransform: ... + + def __init__( + self, + *args, + center_longitude: float = ..., + center_latitude: float = ..., + **kwargs + ) -> None: ... diff --git a/lib/matplotlib/projections/polar.py b/lib/matplotlib/projections/polar.py index 3fbb4d2b9cfd..3243c76d8661 100644 --- a/lib/matplotlib/projections/polar.py +++ b/lib/matplotlib/projections/polar.py @@ -16,13 +16,18 @@ class PolarTransform(mtransforms.Transform): - """ + r""" The base polar transform. - This transform maps polar coordinates ``(theta, r)`` into Cartesian - coordinates ``(x, y) = (r * cos(theta), r * sin(theta))`` (but does not + This transform maps polar coordinates :math:`\theta, r` into Cartesian + coordinates :math:`x, y = r \cos(\theta), r \sin(\theta)` + (but does not fully transform into Axes coordinates or handle positioning in screen space). + This transformation is designed to be applied to data after any scaling + along the radial axis (e.g. log-scaling) has been applied to the input + data. + Path segments at a fixed radius are automatically transformed to circular arcs as long as ``path._interpolation_steps > 1``. """ @@ -30,7 +35,7 @@ class PolarTransform(mtransforms.Transform): input_dims = output_dims = 2 def __init__(self, axis=None, use_rmin=True, - _apply_theta_transforms=True): + _apply_theta_transforms=True, *, scale_transform=None): """ Parameters ---------- @@ -46,12 +51,18 @@ def __init__(self, axis=None, use_rmin=True, self._axis = axis self._use_rmin = use_rmin self._apply_theta_transforms = _apply_theta_transforms + self._scale_transform = scale_transform __str__ = mtransforms._make_str_method( "_axis", use_rmin="_use_rmin", _apply_theta_transforms="_apply_theta_transforms") + def _get_rorigin(self): + # Get lower r limit after being scaled by the radial scale transform + return self._scale_transform.transform( + (0, self._axis.get_rorigin()))[1] + def transform_non_affine(self, tr): # docstring inherited theta, r = np.transpose(tr) @@ -61,7 +72,7 @@ def transform_non_affine(self, tr): theta *= self._axis.get_theta_direction() theta += self._axis.get_theta_offset() if self._use_rmin and self._axis is not None: - r = (r - self._axis.get_rorigin()) * self._axis.get_rsign() + r = (r - self._get_rorigin()) * self._axis.get_rsign() r = np.where(r >= 0, r, np.nan) return np.column_stack([r * np.cos(theta), r * np.sin(theta)]) @@ -85,7 +96,7 @@ def transform_path_non_affine(self, path): # that behavior here. last_td, td = np.rad2deg([last_t, t]) if self._use_rmin and self._axis is not None: - r = ((r - self._axis.get_rorigin()) + r = ((r - self._get_rorigin()) * self._axis.get_rsign()) if last_td <= td: while td - last_td > 360: @@ -877,7 +888,9 @@ def _set_lim_and_transforms(self): # data. This one is aware of rmin self.transProjection = self.PolarTransform( self, - _apply_theta_transforms=False) + _apply_theta_transforms=False, + scale_transform=self.transScale + ) # Add dependency on rorigin. self.transProjection.set_children(self._originViewLim) @@ -888,9 +901,25 @@ def _set_lim_and_transforms(self): # The complete data transformation stack -- from data all the # way to display coordinates + # + # 1. Remove any radial axis scaling (e.g. log scaling) + # 2. Shift data in the theta direction + # 3. Project the data from polar to cartesian values + # (with the origin in the same place) + # 4. Scale and translate the cartesian values to Axes coordinates + # (here the origin is moved to the lower left of the Axes) + # 5. Move and scale to fill the Axes + # 6. Convert from Axes coordinates to Figure coordinates self.transData = ( - self.transScale + self.transShift + self.transProjection + - (self.transProjectionAffine + self.transWedge + self.transAxes)) + self.transScale + + self.transShift + + self.transProjection + + ( + self.transProjectionAffine + + self.transWedge + + self.transAxes + ) + ) # This is the transform for theta-axis ticks. It is # equivalent to transData, except it always puts r == 0.0 and r == 1.0 diff --git a/lib/matplotlib/projections/polar.pyi b/lib/matplotlib/projections/polar.pyi new file mode 100644 index 000000000000..e8278f6bfb80 --- /dev/null +++ b/lib/matplotlib/projections/polar.pyi @@ -0,0 +1,190 @@ +import matplotlib.axis as maxis +import matplotlib.ticker as mticker +import matplotlib.transforms as mtransforms +from matplotlib import cbook +from matplotlib.axes import Axes +from matplotlib.lines import Line2D +from matplotlib.path import Path +from matplotlib.spines import Spine +from matplotlib.text import Text +from matplotlib.ticker import _DummyAxis + +import numpy as np +from numpy.typing import ArrayLike +from typing import Any, Literal, Sequence, overload + +class PolarTransform(mtransforms.Transform): + input_dims: int + output_dims: int + def __init__( + self, + axis: PolarAxes | None = ..., + use_rmin: bool = ..., + _apply_theta_transforms: bool = ..., + ) -> None: ... + def inverted(self) -> InvertedPolarTransform: ... + +class PolarAffine(mtransforms.Affine2DBase): + def __init__( + self, scale_transform: mtransforms.Transform, limits: mtransforms.BboxBase + ) -> None: ... + +class InvertedPolarTransform(mtransforms.Transform): + input_dims: int + output_dims: int + def __init__( + self, + axis: PolarAxes | None = ..., + use_rmin: bool = ..., + _apply_theta_transforms: bool = ..., + ) -> None: ... + def inverted(self) -> PolarTransform: ... + +class ThetaFormatter(mticker.Formatter): ... + +class _AxisWrapper: + def __init__(self, axis: maxis.Axis) -> None: ... + def get_view_interval(self) -> np.ndarray: ... + def set_view_interval(self, vmin: float, vmax: float) -> None: ... + def get_minpos(self) -> float: ... + def get_data_interval(self) -> np.ndarray: ... + def set_data_interval(self, vmin: float, vmax: float) -> None: ... + def get_tick_space(self) -> int: ... + +class ThetaLocator(mticker.Locator): + base: mticker.Locator + axis: _AxisWrapper | None + def __init__(self, base: mticker.Locator) -> None: ... + +class ThetaTick(maxis.XTick): + def __init__(self, axes: PolarAxes, *args, **kwargs) -> None: ... + +class ThetaAxis(maxis.XAxis): + axis_name: str + +class RadialLocator(mticker.Locator): + base: mticker.Locator + def __init__(self, base, axes: PolarAxes | None = ...) -> None: ... + +class RadialTick(maxis.YTick): ... + +class RadialAxis(maxis.YAxis): + axis_name: str + +class _WedgeBbox(mtransforms.Bbox): + def __init__( + self, + center: tuple[float, float], + viewLim: mtransforms.Bbox, + originLim: mtransforms.Bbox, + **kwargs, + ) -> None: ... + +class PolarAxes(Axes): + name: str + use_sticky_edges: bool + def __init__( + self, + *args, + theta_offset: float = ..., + theta_direction: float = ..., + rlabel_position: float = ..., + **kwargs, + ) -> None: ... + def get_xaxis_transform( + self, which: Literal["tick1", "tick2", "grid"] = ... + ) -> mtransforms.Transform: ... + def get_xaxis_text1_transform( + self, pad: float + ) -> tuple[ + mtransforms.Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_xaxis_text2_transform( + self, pad: float + ) -> tuple[ + mtransforms.Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_yaxis_transform( + self, which: Literal["tick1", "tick2", "grid"] = ... + ) -> mtransforms.Transform: ... + def get_yaxis_text1_transform( + self, pad: float + ) -> tuple[ + mtransforms.Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def get_yaxis_text2_transform( + self, pad: float + ) -> tuple[ + mtransforms.Transform, + Literal["center", "top", "bottom", "baseline", "center_baseline"], + Literal["center", "left", "right"], + ]: ... + def set_thetamax(self, thetamax: float) -> None: ... + def get_thetamax(self) -> float: ... + def set_thetamin(self, thetamin: float) -> None: ... + def get_thetamin(self) -> float: ... + @overload + def set_thetalim(self, minval: float, maxval: float, /) -> tuple[float, float]: ... + @overload + def set_thetalim( + self, *, thetamin: float, thetamax: float + ) -> tuple[float, float]: ... + def set_theta_offset(self, offset: float) -> None: ... + def get_theta_offset(self) -> float: ... + def set_theta_zero_location( + self, + loc: Literal["N", "NW", "W", "SW", "S", "SE", "E", "NE"], + offset: float = ..., + ) -> None: ... + def set_theta_direction( + self, + direction: Literal[-1, 1, "clockwise", "counterclockwise", "anticlockwise"], + ) -> None: ... + def get_theta_direction(self) -> Literal[-1, 1]: ... + def set_rmax(self, rmax: float) -> None: ... + def get_rmax(self) -> float: ... + def set_rmin(self, rmin: float) -> None: ... + def get_rmin(self) -> float: ... + def set_rorigin(self, rorigin: float) -> None: ... + def get_rorigin(self) -> float: ... + def get_rsign(self) -> float: ... + def set_rlim( + self, + bottom: float | None = ..., + top: float | None = ..., + emit: bool = ..., + auto: bool = ..., + **kwargs, + ): ... + def get_rlabel_position(self) -> float: ... + def set_rlabel_position(self, value: float) -> None: ... + def set_rscale(self, *args, **kwargs) -> None: ... + def set_rticks(self, *args, **kwargs) -> None: ... + def set_thetagrids( + self, + angles: ArrayLike, + labels: Sequence[str | Text] | None = ..., + fmt: str | None = ..., + **kwargs, + ) -> tuple[list[Line2D], list[Text]]: ... + def set_rgrids( + self, + radii: ArrayLike, + labels: Sequence[str | Text] | None = ..., + angle: float | None = ..., + fmt: str | None = ..., + **kwargs, + ) -> tuple[list[Line2D], list[Text]]: ... + def format_coord(self, theta: float, r: float) -> str: ... + def get_data_ratio(self) -> float: ... + def can_zoom(self) -> bool: ... + def can_pan(self) -> bool: ... + def start_pan(self, x: float, y: float, button: int) -> None: ... + def end_pan(self) -> None: ... + def drag_pan(self, button: Any, key: Any, x: float, y: float) -> None: ... diff --git a/lib/matplotlib/py.typed b/lib/matplotlib/py.typed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index acd187d5d1c9..c6bee1400a2a 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -35,6 +35,10 @@ implicit and explicit interfaces. """ +# fmt: off + +from __future__ import annotations + from contextlib import ExitStack from enum import Enum import functools @@ -63,17 +67,67 @@ from matplotlib import rcParams, rcParamsDefault, get_backend, rcParamsOrig from matplotlib.rcsetup import interactive_bk as _interactive_bk from matplotlib.artist import Artist -from matplotlib.axes import Axes, Subplot -from matplotlib.projections import PolarAxes +from matplotlib.axes import Axes, Subplot # type: ignore +from matplotlib.projections import PolarAxes # type: ignore from matplotlib import mlab # for detrend_none, window_hanning from matplotlib.scale import get_scale_names from matplotlib import cm -from matplotlib.cm import _colormaps as colormaps, register_cmap +from matplotlib.cm import _colormaps as colormaps +from matplotlib.cm import register_cmap # type: ignore from matplotlib.colors import _color_sequences as color_sequences import numpy as np +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + import datetime + import io + import pathlib + import os + + import PIL + + from numpy.typing import ArrayLike + from typing import ( + Any, Callable, Literal, Sequence, Iterable, Type, Generator + ) + + from matplotlib.axis import Tick + from matplotlib.axes import SubplotBase + from matplotlib.axes._base import _AxesBase + from matplotlib.backend_bases import RendererBase, Event + from matplotlib.cm import ScalarMappable + from matplotlib.contour import ContourSet, QuadContourSet + from matplotlib.collections import ( + Collection, + LineCollection, + BrokenBarHCollection, + PolyCollection, + PathCollection, + EventCollection, + QuadMesh, + ) + from matplotlib.colorbar import Colorbar + from matplotlib.colors import Color, Colormap + from matplotlib.container import ( + BarContainer, + ErrorbarContainer, + StemContainer, + ) + from matplotlib.figure import SubFigure + from matplotlib.legend import Legend + from matplotlib.lines import LineStyleType + from matplotlib.markers import MarkerType + from matplotlib.mlab import GaussianKDE + from matplotlib.image import AxesImage + from matplotlib.patches import FancyArrow, StepPatch + from matplotlib.quiver import Barbs, Quiver, QuiverKey + from matplotlib.scale import ScaleBase + from matplotlib.transforms import Transform, Bbox + from matplotlib.widgets import SubplotTool + # We may not need the following imports here: from matplotlib.colors import Normalize from matplotlib.lines import Line2D @@ -150,7 +204,7 @@ def install_repl_displayhook(): ip.events.register("post_execute", _draw_all_if_interactive) _REPL_DISPLAYHOOK = _ReplDisplayHook.IPYTHON - from IPython.core.pylabtools import backend2gui + from IPython.core.pylabtools import backend2gui # type: ignore # trigger IPython's eventloop integration, if available ipython_gui_name = backend2gui.get(get_backend()) if ipython_gui_name: @@ -161,7 +215,7 @@ def uninstall_repl_displayhook(): """Disconnect from the display hook of the current shell.""" global _REPL_DISPLAYHOOK if _REPL_DISPLAYHOOK is _ReplDisplayHook.IPYTHON: - from IPython import get_ipython + from IPython import get_ipython # type: ignore ip = get_ipython() ip.events.unregister("post_execute", _draw_all_if_interactive) _REPL_DISPLAYHOOK = _ReplDisplayHook.NONE @@ -170,13 +224,18 @@ def uninstall_repl_displayhook(): draw_all = _pylab_helpers.Gcf.draw_all +# Ensure this appears in the pyplot docs. @_copy_docstring_and_deprecators(matplotlib.set_loglevel) -def set_loglevel(*args, **kwargs): # Ensure this appears in the pyplot docs. +def set_loglevel(*args, **kwargs) -> None: return matplotlib.set_loglevel(*args, **kwargs) @_copy_docstring_and_deprecators(Artist.findobj) -def findobj(o=None, match=None, include_self=True): +def findobj( + o: Artist | None = None, + match: Callable[[Artist], bool] | Type[Artist] | None = None, + include_self: bool = True +) -> list[Artist]: if o is None: o = gcf() return o.findobj(match, include_self=include_self) @@ -445,7 +504,7 @@ def show(*args, **kwargs): return _get_backend_mod().show(*args, **kwargs) -def isinteractive(): +def isinteractive() -> bool: """ Return whether plots are updated after every plotting command. @@ -475,7 +534,7 @@ def isinteractive(): return matplotlib.is_interactive() -def ioff(): +def ioff() -> ExitStack: """ Disable interactive mode. @@ -515,7 +574,7 @@ def ioff(): return stack -def ion(): +def ion() -> ExitStack: """ Enable interactive mode. @@ -555,7 +614,7 @@ def ion(): return stack -def pause(interval): +def pause(interval: float) -> None: """ Run the GUI event loop for *interval* seconds. @@ -584,17 +643,20 @@ def pause(interval): @_copy_docstring_and_deprecators(matplotlib.rc) -def rc(group, **kwargs): +def rc(group: str, **kwargs) -> None: matplotlib.rc(group, **kwargs) @_copy_docstring_and_deprecators(matplotlib.rc_context) -def rc_context(rc=None, fname=None): +def rc_context( + rc: dict[str, Any] | None = None, + fname: str | pathlib.Path | os.PathLike | None = None, +): return matplotlib.rc_context(rc, fname) @_copy_docstring_and_deprecators(matplotlib.rcdefaults) -def rcdefaults(): +def rcdefaults() -> None: matplotlib.rcdefaults() if matplotlib.is_interactive(): draw_all() @@ -618,7 +680,9 @@ def setp(obj, *args, **kwargs): return matplotlib.artist.setp(obj, *args, **kwargs) -def xkcd(scale=1, length=100, randomness=2): +def xkcd( + scale: float = 1, length: float = 100, randomness: float = 2 +) -> ExitStack: """ Turn on `xkcd `_ sketch-style drawing mode. This will only have effect on things drawn after this function is called. @@ -659,7 +723,7 @@ def xkcd(scale=1, length=100, randomness=2): "xkcd mode is not compatible with text.usetex = True") stack = ExitStack() - stack.callback(dict.update, rcParams, rcParams.copy()) + stack.callback(dict.update, rcParams, rcParams.copy()) # type: ignore from matplotlib import patheffects rcParams.update({ @@ -688,16 +752,22 @@ def xkcd(scale=1, length=100, randomness=2): ## Figures ## @_api.make_keyword_only("3.6", "facecolor") -def figure(num=None, # autoincrement if None, else integer from 1-N - figsize=None, # defaults to rc figure.figsize - dpi=None, # defaults to rc figure.dpi - facecolor=None, # defaults to rc figure.facecolor - edgecolor=None, # defaults to rc figure.edgecolor - frameon=True, - FigureClass=Figure, - clear=False, - **kwargs - ): +def figure( + # autoincrement if None, else integer from 1-N + num: int | str | Figure | SubFigure | None = None, + # defaults to rc figure.figsize + figsize: tuple[float, float] | None = None, + # defaults to rc figure.dpi + dpi: float | None = None, + # defaults to rc figure.facecolor + facecolor: Color | None = None, + # defaults to rc figure.edgecolor + edgecolor: Color | None = None, + frameon: bool = True, + FigureClass: Type[Figure] = Figure, + clear: bool = False, + **kwargs +): """ Create a new figure, or activate an existing figure. @@ -797,7 +867,8 @@ def figure(num=None, # autoincrement if None, else integer from 1-N else: num = int(num) # crude validation of num argument - manager = _pylab_helpers.Gcf.get_fig_manager(num) + # Type of "num" has narrowed to int, but mypy can't quite see it + manager = _pylab_helpers.Gcf.get_fig_manager(num) # type: ignore[arg-type] if manager is None: max_open_warning = rcParams['figure.max_open_warning'] if len(allnums) == max_open_warning >= 1: @@ -863,7 +934,7 @@ def _auto_draw_if_interactive(fig, val): fig.canvas.draw_idle() -def gcf(): +def gcf() -> Figure: """ Get the current figure. @@ -879,24 +950,24 @@ def gcf(): return figure() -def fignum_exists(num): +def fignum_exists(num: int) -> bool: """Return whether the figure with the given id exists.""" return _pylab_helpers.Gcf.has_fignum(num) or num in get_figlabels() -def get_fignums(): +def get_fignums() -> list[int]: """Return a list of existing figure numbers.""" return sorted(_pylab_helpers.Gcf.figs) -def get_figlabels(): +def get_figlabels() -> list[Any]: """Return a list of existing figure labels.""" managers = _pylab_helpers.Gcf.get_all_fig_managers() managers.sort(key=lambda m: m.num) return [m.canvas.figure.get_label() for m in managers] -def get_current_fig_manager(): +def get_current_fig_manager() -> FigureManagerBase | None: """ Return the figure manager of the current figure. @@ -914,16 +985,16 @@ def get_current_fig_manager(): @_copy_docstring_and_deprecators(FigureCanvasBase.mpl_connect) -def connect(s, func): +def connect(s: str, func: Callable[[Event], Any]) -> int: return gcf().canvas.mpl_connect(s, func) @_copy_docstring_and_deprecators(FigureCanvasBase.mpl_disconnect) -def disconnect(cid): +def disconnect(cid: int) -> None: return gcf().canvas.mpl_disconnect(cid) -def close(fig=None): +def close(fig: None | int | str | Figure | Literal["all"] = None) -> None: """ Close a figure window. @@ -965,12 +1036,12 @@ def close(fig=None): "or None, not %s" % type(fig)) -def clf(): +def clf() -> None: """Clear the current figure.""" gcf().clear() -def draw(): +def draw() -> None: """ Redraw the current figure. @@ -991,9 +1062,11 @@ def draw(): @_copy_docstring_and_deprecators(Figure.savefig) -def savefig(*args, **kwargs): +def savefig(*args, **kwargs) -> None: fig = gcf() - res = fig.savefig(*args, **kwargs) + # savefig default implementation has no return, so mypy is unhappy + # presumably this is here because subclasses can return? + res = fig.savefig(*args, **kwargs) # type: ignore[func-returns-value] fig.canvas.draw_idle() # Need this if 'transparent=True', to reset colors. return res @@ -1001,7 +1074,7 @@ def savefig(*args, **kwargs): ## Putting things in figures ## -def figlegend(*args, **kwargs): +def figlegend(*args, **kwargs) -> Legend: return gcf().legend(*args, **kwargs) if Figure.legend.__doc__: figlegend.__doc__ = Figure.legend.__doc__ \ @@ -1013,7 +1086,10 @@ def figlegend(*args, **kwargs): ## Axes ## @_docstring.dedent_interpd -def axes(arg=None, **kwargs): +def axes( + arg: None | tuple[float, float, float, float] = None, + **kwargs +) -> Axes: """ Add an Axes to the current figure and make it the current Axes. @@ -1070,17 +1146,6 @@ def axes(arg=None, **kwargs): %(Axes:kwdoc)s - Notes - ----- - If the figure already has an Axes with key (*args*, - *kwargs*) then it will simply make that axes current and - return it. This behavior is deprecated. Meanwhile, if you do - not want this behavior (i.e., you want to force the creation of a - new axes), you must use a unique set of args and kwargs. The Axes - *label* attribute has been exposed for this purpose: if you want - two Axes that are otherwise identical to be added to the figure, - make sure you give them unique labels. - See Also -------- .Figure.add_axes @@ -1110,7 +1175,7 @@ def axes(arg=None, **kwargs): return fig.add_axes(arg, **kwargs) -def delaxes(ax=None): +def delaxes(ax: Axes | None = None) -> None: """ Remove an `~.axes.Axes` (defaulting to the current axes) from its figure. """ @@ -1119,15 +1184,17 @@ def delaxes(ax=None): ax.remove() -def sca(ax): +def sca(ax: Axes) -> None: """ Set the current Axes to *ax* and the current Figure to the parent of *ax*. """ figure(ax.figure) - ax.figure.sca(ax) + # Mypy sees ax.figure as potentially None, + # but if you are calling this, it won't be None + ax.figure.sca(ax) # type: ignore -def cla(): +def cla() -> None: """Clear the current axes.""" # Not generated via boilerplate.py to allow a different docstring. return gca().cla() @@ -1136,7 +1203,7 @@ def cla(): ## More ways of creating axes ## @_docstring.dedent_interpd -def subplot(*args, **kwargs): +def subplot(*args, **kwargs) -> Axes: """ Add an Axes to the current figure or retrieve an existing Axes. @@ -1336,9 +1403,17 @@ def subplot(*args, **kwargs): return ax -def subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, - width_ratios=None, height_ratios=None, - subplot_kw=None, gridspec_kw=None, **fig_kw): +def subplots( + nrows: int = 1, ncols: int = 1, *, + sharex: bool | Literal["none", "all", "row", "col"] = False, + sharey: bool | Literal["none", "all", "row", "col"] = False, + squeeze: bool = True, + width_ratios: Sequence[float] | None = None, + height_ratios: Sequence[float] | None = None, + subplot_kw: dict[str, Any] | None = None, + gridspec_kw: dict[str, Any] | None = None, + **fig_kw +) -> tuple[Figure, Axes | np.ndarray | SubplotBase]: """ Create a figure and a set of subplots. @@ -1490,10 +1565,19 @@ def subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, return fig, axs -def subplot_mosaic(mosaic, *, sharex=False, sharey=False, - width_ratios=None, height_ratios=None, empty_sentinel='.', - subplot_kw=None, gridspec_kw=None, - per_subplot_kw=None, **fig_kw): +def subplot_mosaic( + mosaic: str | list[list[Any]], + *, + sharex: bool = False, + sharey: bool = False, + width_ratios: ArrayLike | None = None, + height_ratios: ArrayLike | None = None, + empty_sentinel: Any = '.', + subplot_kw: dict[str, Any] | None = None, + gridspec_kw: dict[str, Any] | None = None, + per_subplot_kw: dict[Any, dict[str, Any]] | None = None, + **fig_kw +) -> tuple[Figure, dict[Any, Axes]]: """ Build a layout of Axes based on ASCII art or nested lists. @@ -1605,7 +1689,12 @@ def subplot_mosaic(mosaic, *, sharex=False, sharey=False, return fig, ax_dict -def subplot2grid(shape, loc, rowspan=1, colspan=1, fig=None, **kwargs): +def subplot2grid( + shape: tuple[int, int], loc: tuple[int, int], + rowspan: int = 1, colspan: int = 1, + fig: Figure | None = None, + **kwargs +) -> Axes: """ Create a subplot at a specific location inside a regular grid. @@ -1667,7 +1756,7 @@ def subplot2grid(shape, loc, rowspan=1, colspan=1, fig=None, **kwargs): return ax -def twinx(ax=None): +def twinx(ax: Axes | None = None) -> _AxesBase: """ Make and return a second axes that shares the *x*-axis. The new axes will overlay *ax* (or the current axes if *ax* is *None*), and its ticks will be @@ -1683,7 +1772,7 @@ def twinx(ax=None): return ax1 -def twiny(ax=None): +def twiny(ax: Axes | None = None) -> _AxesBase: """ Make and return a second axes that shares the *y*-axis. The new axes will overlay *ax* (or the current axes if *ax* is *None*), and its ticks will be @@ -1699,7 +1788,7 @@ def twiny(ax=None): return ax1 -def subplot_tool(targetfig=None): +def subplot_tool(targetfig: Figure | None = None) -> SubplotTool: """ Launch a subplot tool window for a figure. @@ -1709,7 +1798,7 @@ def subplot_tool(targetfig=None): """ if targetfig is None: targetfig = gcf() - tb = targetfig.canvas.manager.toolbar + tb = targetfig.canvas.manager.toolbar # type: ignore[union-attr] if hasattr(tb, "configure_subplots"): # toolbar2 return tb.configure_subplots() elif hasattr(tb, "trigger_tool"): # toolmanager @@ -1719,7 +1808,7 @@ def subplot_tool(targetfig=None): "an associated toolbar") -def box(on=None): +def box(on: bool | None = None) -> None: """ Turn the axes box on or off on the current axes. @@ -1742,7 +1831,7 @@ def box(on=None): ## Axis ## -def xlim(*args, **kwargs): +def xlim(*args, **kwargs) -> tuple[float, float]: """ Get or set the x limits of the current axes. @@ -1779,7 +1868,7 @@ def xlim(*args, **kwargs): return ret -def ylim(*args, **kwargs): +def ylim(*args, **kwargs) -> tuple[float, float]: """ Get or set the y-limits of the current axes. @@ -1816,7 +1905,13 @@ def ylim(*args, **kwargs): return ret -def xticks(ticks=None, labels=None, *, minor=False, **kwargs): +def xticks( + ticks: Sequence[float] | None = None, + labels: Sequence[str] | None = None, + *, + minor: bool = False, + **kwargs +) -> tuple[list[Tick] | np.ndarray, list[Text]]: """ Get or set the current tick locations and labels of the x-axis. @@ -1869,17 +1964,24 @@ def xticks(ticks=None, labels=None, *, minor=False, **kwargs): else: locs = ax.set_xticks(ticks, minor=minor) + labels_out: list[Text] = [] if labels is None: - labels = ax.get_xticklabels(minor=minor) - for l in labels: + labels_out = ax.get_xticklabels(minor=minor) + for l in labels_out: l._internal_update(kwargs) else: - labels = ax.set_xticklabels(labels, minor=minor, **kwargs) + labels_out = ax.set_xticklabels(labels, minor=minor, **kwargs) - return locs, labels + return locs, labels_out -def yticks(ticks=None, labels=None, *, minor=False, **kwargs): +def yticks( + ticks: Sequence[float] | None = None, + labels: Sequence[str] | None = None, + *, + minor: bool = False, + **kwargs +) -> tuple[list[Tick] | np.ndarray, list[Text]]: """ Get or set the current tick locations and labels of the y-axis. @@ -1932,17 +2034,24 @@ def yticks(ticks=None, labels=None, *, minor=False, **kwargs): else: locs = ax.set_yticks(ticks, minor=minor) + labels_out: list[Text] = [] if labels is None: - labels = ax.get_yticklabels(minor=minor) - for l in labels: + labels_out = ax.get_yticklabels(minor=minor) + for l in labels_out: l._internal_update(kwargs) else: - labels = ax.set_yticklabels(labels, minor=minor, **kwargs) + labels_out = ax.set_yticklabels(labels, minor=minor, **kwargs) - return locs, labels + return locs, labels_out -def rgrids(radii=None, labels=None, angle=None, fmt=None, **kwargs): +def rgrids( + radii: ArrayLike | None = None, + labels: Sequence[str | Text] | None = None, + angle: float | None = None, + fmt: str | None = None, + **kwargs +) -> tuple[list[Line2D], list[Text]]: """ Get or set the radial gridlines on the current polar plot. @@ -2005,15 +2114,20 @@ def rgrids(radii=None, labels=None, angle=None, fmt=None, **kwargs): if not isinstance(ax, PolarAxes): raise RuntimeError('rgrids only defined for polar axes') if all(p is None for p in [radii, labels, angle, fmt]) and not kwargs: - lines = ax.yaxis.get_gridlines() - labels = ax.yaxis.get_ticklabels() + lines_out: list[Line2D] = ax.yaxis.get_gridlines() + labels_out: list[Text] = ax.yaxis.get_ticklabels() else: - lines, labels = ax.set_rgrids( + lines_out, labels_out = ax.set_rgrids( radii, labels=labels, angle=angle, fmt=fmt, **kwargs) - return lines, labels + return lines_out, labels_out -def thetagrids(angles=None, labels=None, fmt=None, **kwargs): +def thetagrids( + angles: ArrayLike | None = None, + labels: Sequence[str | Text] | None = None, + fmt: str | None = None, + **kwargs +) -> tuple[list[Line2D], list[Text]]: """ Get or set the theta gridlines on the current polar plot. @@ -2073,16 +2187,17 @@ def thetagrids(angles=None, labels=None, fmt=None, **kwargs): if not isinstance(ax, PolarAxes): raise RuntimeError('thetagrids only defined for polar axes') if all(param is None for param in [angles, labels, fmt]) and not kwargs: - lines = ax.xaxis.get_ticklines() - labels = ax.xaxis.get_ticklabels() + lines_out: list[Line2D] = ax.xaxis.get_ticklines() + labels_out: list[Text] = ax.xaxis.get_ticklabels() else: - lines, labels = ax.set_thetagrids(angles, - labels=labels, fmt=fmt, **kwargs) - return lines, labels + lines_out, labels_out = ax.set_thetagrids(angles, + labels=labels, fmt=fmt, + **kwargs) + return lines_out, labels_out @_api.deprecated("3.7", pending=True) -def get_plot_commands(): +def get_plot_commands() -> Generator[str, None, None]: """ Get a sorted list of all of the plotting commands. """ @@ -2093,7 +2208,7 @@ def get_plot_commands(): if name not in NON_PLOT_COMMANDS) -def _get_pyplot_commands(): +def _get_pyplot_commands() -> list[str]: # This works by searching for all functions in this module and removing # a few hard-coded exclusions, as well as all of the colormap-setting # functions, and anything marked as private with a preceding underscore. @@ -2110,7 +2225,12 @@ def _get_pyplot_commands(): @_copy_docstring_and_deprecators(Figure.colorbar) -def colorbar(mappable=None, cax=None, ax=None, **kwargs): +def colorbar( + mappable: ScalarMappable | None = None, + cax: Axes | None = None, + ax: Axes | Iterable[Axes] | None = None, + **kwargs +) -> Colorbar: if mappable is None: mappable = gci() if mappable is None: @@ -2122,7 +2242,7 @@ def colorbar(mappable=None, cax=None, ax=None, **kwargs): return ret -def clim(vmin=None, vmax=None): +def clim(vmin: float | None = None, vmax: float | None = None) -> None: """ Set the color limits of the current image. @@ -2145,12 +2265,15 @@ def clim(vmin=None, vmax=None): # eventually this implementation should move here, use indirection for now to # avoid having two copies of the code floating around. -def get_cmap(name=None, lut=None): - return cm._get_cmap(name=name, lut=lut) -get_cmap.__doc__ = cm._get_cmap.__doc__ +def get_cmap( + name: Colormap | str | None = None, + lut: int | None = None +) -> Colormap: + return cm._get_cmap(name=name, lut=lut) # type: ignore +get_cmap.__doc__ = cm._get_cmap.__doc__ # type: ignore -def set_cmap(cmap): +def set_cmap(cmap: Colormap | str) -> None: """ Set the default colormap, and applies it to the current image if any. @@ -2175,16 +2298,18 @@ def set_cmap(cmap): @_copy_docstring_and_deprecators(matplotlib.image.imread) -def imread(fname, format=None): +def imread(fname: str | io.FileIO, format: str | None = None) -> np.ndarray: return matplotlib.image.imread(fname, format) @_copy_docstring_and_deprecators(matplotlib.image.imsave) -def imsave(fname, arr, **kwargs): +def imsave( + fname: str | os.PathLike | io.FileIO, arr: ArrayLike, **kwargs +) -> None: return matplotlib.image.imsave(fname, arr, **kwargs) -def matshow(A, fignum=None, **kwargs): +def matshow(A: ArrayLike, fignum: None | int = None, **kwargs) -> AxesImage: """ Display an array as a matrix in a new figure window. @@ -2200,7 +2325,7 @@ def matshow(A, fignum=None, **kwargs): A : 2D array-like The matrix to be displayed. - fignum : None or int or False + fignum : None or int If *None*, create a new figure window with automatic numbering. If a nonzero integer, draw into the figure with the given number @@ -2236,7 +2361,7 @@ def matshow(A, fignum=None, **kwargs): return im -def polar(*args, **kwargs): +def polar(*args, **kwargs) -> list[Line2D]: """ Make a polar plot. @@ -2262,11 +2387,12 @@ def polar(*args, **kwargs): # requested, ignore rcParams['backend'] and force selection of a backend that # is compatible with the current running interactive framework. if (rcParams["backend_fallback"] - and rcParams._get_backend_or_none() in ( + and rcParams._get_backend_or_none() in ( # type: ignore set(_interactive_bk) - {'WebAgg', 'nbAgg'}) - and cbook._get_running_interactive_framework()): - rcParams._set("backend", rcsetup._auto_backend_sentinel) + and cbook._get_running_interactive_framework()): # type: ignore + rcParams._set("backend", rcsetup._auto_backend_sentinel) # type: ignore +# fmt: on ################# REMAINING CONTENT GENERATED BY boilerplate.py ############## @@ -2274,347 +2400,711 @@ def polar(*args, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.figimage) def figimage( - X, xo=0, yo=0, alpha=None, norm=None, cmap=None, vmin=None, - vmax=None, origin=None, resize=False, **kwargs): + X: ArrayLike, + xo: int = 0, + yo: int = 0, + alpha: float | None = None, + norm: str | Normalize | None = None, + cmap: str | Colormap | None = None, + vmin: float | None = None, + vmax: float | None = None, + origin: Literal["upper", "lower"] | None = None, + resize: bool = False, + **kwargs, +): return gcf().figimage( - X, xo=xo, yo=yo, alpha=alpha, norm=norm, cmap=cmap, vmin=vmin, - vmax=vmax, origin=origin, resize=resize, **kwargs) + X, + xo=xo, + yo=yo, + alpha=alpha, + norm=norm, + cmap=cmap, + vmin=vmin, + vmax=vmax, + origin=origin, + resize=resize, + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.text) -def figtext(x, y, s, fontdict=None, **kwargs): +def figtext( + x: float, + y: float, + s: str, + fontdict: dict[str, Any] | None = None, + **kwargs, +) -> Text: return gcf().text(x, y, s, fontdict=fontdict, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.gca) -def gca(): +def gca() -> Axes: return gcf().gca() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure._gci) -def gci(): +def gci() -> ScalarMappable | None: return gcf()._gci() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.ginput) def ginput( - n=1, timeout=30, show_clicks=True, - mouse_add=MouseButton.LEFT, mouse_pop=MouseButton.RIGHT, - mouse_stop=MouseButton.MIDDLE): + n: int = 1, + timeout: float = 30, + show_clicks: bool = True, + mouse_add: MouseButton = MouseButton.LEFT, + mouse_pop: MouseButton = MouseButton.RIGHT, + mouse_stop: MouseButton = MouseButton.MIDDLE, +) -> list[tuple[int, int]]: return gcf().ginput( - n=n, timeout=timeout, show_clicks=show_clicks, - mouse_add=mouse_add, mouse_pop=mouse_pop, - mouse_stop=mouse_stop) + n=n, + timeout=timeout, + show_clicks=show_clicks, + mouse_add=mouse_add, + mouse_pop=mouse_pop, + mouse_stop=mouse_stop, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.subplots_adjust) def subplots_adjust( - left=None, bottom=None, right=None, top=None, wspace=None, - hspace=None): + left: str | None = None, + bottom: str | None = None, + right: str | None = None, + top: str | None = None, + wspace: str | None = None, + hspace: str | None = None, +) -> None: return gcf().subplots_adjust( - left=left, bottom=bottom, right=right, top=top, wspace=wspace, - hspace=hspace) + left=left, + bottom=bottom, + right=right, + top=top, + wspace=wspace, + hspace=hspace, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.suptitle) -def suptitle(t, **kwargs): +def suptitle(t: str, **kwargs) -> Text: return gcf().suptitle(t, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.tight_layout) -def tight_layout(*, pad=1.08, h_pad=None, w_pad=None, rect=None): +def tight_layout( + *, + pad: float = 1.08, + h_pad: float | None = None, + w_pad: float | None = None, + rect: tuple[float, float, float, float] | None = None, +) -> None: return gcf().tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.waitforbuttonpress) -def waitforbuttonpress(timeout=-1): +def waitforbuttonpress(timeout: float = -1): return gcf().waitforbuttonpress(timeout=timeout) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.acorr) -def acorr(x, *, data=None, **kwargs): +def acorr( + x: ArrayLike, *, data=None, **kwargs +) -> tuple[np.ndarray, np.ndarray, LineCollection | Line2D, Line2D | None]: return gca().acorr( - x, **({"data": data} if data is not None else {}), **kwargs) + x, **({"data": data} if data is not None else {}), **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.angle_spectrum) def angle_spectrum( - x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, *, - data=None, **kwargs): + x: ArrayLike, + Fs: float | None = None, + Fc: int | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, Line2D]: return gca().angle_spectrum( - x, Fs=Fs, Fc=Fc, window=window, pad_to=pad_to, sides=sides, - **({"data": data} if data is not None else {}), **kwargs) + x, + Fs=Fs, + Fc=Fc, + window=window, + pad_to=pad_to, + sides=sides, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.annotate) def annotate( - text, xy, xytext=None, xycoords='data', textcoords=None, - arrowprops=None, annotation_clip=None, **kwargs): + text: str, + xy: tuple[float, float], + xytext: tuple[float, float] | None = None, + xycoords: str + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | tuple[float, float] = "data", + textcoords: str + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | tuple[float, float] + | None = None, + arrowprops: dict[str, Any] | None = None, + annotation_clip: bool | None = None, + **kwargs, +) -> Annotation: return gca().annotate( - text, xy, xytext=xytext, xycoords=xycoords, - textcoords=textcoords, arrowprops=arrowprops, - annotation_clip=annotation_clip, **kwargs) + text, + xy, + xytext=xytext, + xycoords=xycoords, + textcoords=textcoords, + arrowprops=arrowprops, + annotation_clip=annotation_clip, + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.arrow) -def arrow(x, y, dx, dy, **kwargs): +def arrow(x: float, y: float, dx: float, dy: float, **kwargs) -> FancyArrow: return gca().arrow(x, y, dx, dy, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.autoscale) -def autoscale(enable=True, axis='both', tight=None): +def autoscale( + enable: bool = True, + axis: Literal["both", "x", "y"] = "both", + tight: bool | None = None, +) -> None: return gca().autoscale(enable=enable, axis=axis, tight=tight) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axhline) -def axhline(y=0, xmin=0, xmax=1, **kwargs): +def axhline( + y: float = 0, xmin: float = 0, xmax: float = 1, **kwargs +) -> Line2D: return gca().axhline(y=y, xmin=xmin, xmax=xmax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axhspan) -def axhspan(ymin, ymax, xmin=0, xmax=1, **kwargs): +def axhspan( + ymin: float, ymax: float, xmin: float = 0, xmax: float = 1, **kwargs +) -> Polygon: return gca().axhspan(ymin, ymax, xmin=xmin, xmax=xmax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axis) -def axis(arg=None, /, *, emit=True, **kwargs): +def axis( + arg: tuple[float, float, float, float] | bool | str | None = None, + /, + *, + emit: bool = True, + **kwargs, +) -> tuple[float, float, float, float]: return gca().axis(arg, emit=emit, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axline) -def axline(xy1, xy2=None, *, slope=None, **kwargs): +def axline( + xy1: tuple[float, float], + xy2: tuple[float, float] | None = None, + *, + slope: float | None = None, + **kwargs, +) -> Line2D: return gca().axline(xy1, xy2=xy2, slope=slope, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axvline) -def axvline(x=0, ymin=0, ymax=1, **kwargs): +def axvline( + x: float = 0, ymin: float = 0, ymax: float = 1, **kwargs +) -> Line2D: return gca().axvline(x=x, ymin=ymin, ymax=ymax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axvspan) -def axvspan(xmin, xmax, ymin=0, ymax=1, **kwargs): +def axvspan( + xmin: float, xmax: float, ymin: float = 0, ymax: float = 1, **kwargs +) -> Polygon: return gca().axvspan(xmin, xmax, ymin=ymin, ymax=ymax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.bar) def bar( - x, height, width=0.8, bottom=None, *, align='center', - data=None, **kwargs): + x: float | ArrayLike, + height: float | ArrayLike, + width: float | ArrayLike = 0.8, + bottom: float | ArrayLike | None = None, + *, + align: Literal["center", "edge"] = "center", + data=None, + **kwargs, +) -> BarContainer: return gca().bar( - x, height, width=width, bottom=bottom, align=align, - **({"data": data} if data is not None else {}), **kwargs) + x, + height, + width=width, + bottom=bottom, + align=align, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.barbs) -def barbs(*args, data=None, **kwargs): +def barbs(*args, data=None, **kwargs) -> Barbs: return gca().barbs( - *args, **({"data": data} if data is not None else {}), - **kwargs) + *args, **({"data": data} if data is not None else {}), **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.barh) def barh( - y, width, height=0.8, left=None, *, align='center', - data=None, **kwargs): + y: float | ArrayLike, + width: float | ArrayLike, + height: float | ArrayLike = 0.8, + left: float | ArrayLike | None = None, + *, + align: Literal["center", "edge"] = "center", + data: Any | None = None, + **kwargs, +) -> BarContainer: return gca().barh( - y, width, height=height, left=left, align=align, - **({"data": data} if data is not None else {}), **kwargs) + y, + width, + height=height, + left=left, + align=align, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.bar_label) def bar_label( - container, labels=None, *, fmt='%g', label_type='edge', - padding=0, **kwargs): + container: BarContainer, + labels: ArrayLike | None = None, + *, + fmt: str | Callable[[float], str] = "%g", + label_type: Literal["center", "edge"] = "edge", + padding: float = 0, + **kwargs, +) -> list[Text]: return gca().bar_label( - container, labels=labels, fmt=fmt, label_type=label_type, - padding=padding, **kwargs) + container, + labels=labels, + fmt=fmt, + label_type=label_type, + padding=padding, + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.boxplot) def boxplot( - x, notch=None, sym=None, vert=None, whis=None, - positions=None, widths=None, patch_artist=None, - bootstrap=None, usermedians=None, conf_intervals=None, - meanline=None, showmeans=None, showcaps=None, showbox=None, - showfliers=None, boxprops=None, labels=None, flierprops=None, - medianprops=None, meanprops=None, capprops=None, - whiskerprops=None, manage_ticks=True, autorange=False, - zorder=None, capwidths=None, *, data=None): + x: ArrayLike | Sequence[ArrayLike], + notch: bool | None = None, + sym: str | None = None, + vert: bool | None = None, + whis: float | tuple[float, float] | None = None, + positions: ArrayLike | None = None, + widths: float | ArrayLike | None = None, + patch_artist: bool | None = None, + bootstrap: int | None = None, + usermedians: ArrayLike | None = None, + conf_intervals: ArrayLike | None = None, + meanline: bool | None = None, + showmeans: bool | None = None, + showcaps: bool | None = None, + showbox: bool | None = None, + showfliers: bool | None = None, + boxprops: dict[str, Any] | None = None, + labels: Sequence[str] | None = None, + flierprops: dict[str, Any] | None = None, + medianprops: dict[str, Any] | None = None, + meanprops: dict[str, Any] | None = None, + capprops: dict[str, Any] | None = None, + whiskerprops: dict[str, Any] | None = None, + manage_ticks: bool = True, + autorange: bool = False, + zorder: float | None = None, + capwidths: float | ArrayLike | None = None, + *, + data=None, +) -> dict[str, Any]: return gca().boxplot( - x, notch=notch, sym=sym, vert=vert, whis=whis, - positions=positions, widths=widths, patch_artist=patch_artist, - bootstrap=bootstrap, usermedians=usermedians, - conf_intervals=conf_intervals, meanline=meanline, - showmeans=showmeans, showcaps=showcaps, showbox=showbox, - showfliers=showfliers, boxprops=boxprops, labels=labels, - flierprops=flierprops, medianprops=medianprops, - meanprops=meanprops, capprops=capprops, - whiskerprops=whiskerprops, manage_ticks=manage_ticks, - autorange=autorange, zorder=zorder, capwidths=capwidths, - **({"data": data} if data is not None else {})) + x, + notch=notch, + sym=sym, + vert=vert, + whis=whis, + positions=positions, + widths=widths, + patch_artist=patch_artist, + bootstrap=bootstrap, + usermedians=usermedians, + conf_intervals=conf_intervals, + meanline=meanline, + showmeans=showmeans, + showcaps=showcaps, + showbox=showbox, + showfliers=showfliers, + boxprops=boxprops, + labels=labels, + flierprops=flierprops, + medianprops=medianprops, + meanprops=meanprops, + capprops=capprops, + whiskerprops=whiskerprops, + manage_ticks=manage_ticks, + autorange=autorange, + zorder=zorder, + capwidths=capwidths, + **({"data": data} if data is not None else {}), + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.broken_barh) -def broken_barh(xranges, yrange, *, data=None, **kwargs): +def broken_barh( + xranges: Sequence[tuple[float, float]], + yrange: tuple[float, float], + *, + data=None, + **kwargs, +) -> BrokenBarHCollection: return gca().broken_barh( - xranges, yrange, - **({"data": data} if data is not None else {}), **kwargs) + xranges, + yrange, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.clabel) -def clabel(CS, levels=None, **kwargs): +def clabel( + CS: ContourSet, levels: ArrayLike | None = None, **kwargs +) -> list[Text]: return gca().clabel(CS, levels=levels, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.cohere) def cohere( - x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, - window=mlab.window_hanning, noverlap=0, pad_to=None, - sides='default', scale_by_freq=None, *, data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + NFFT: int = 256, + Fs: float = 2, + Fc: int = 0, + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike], ArrayLike] = mlab.detrend_none, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike = mlab.window_hanning, + noverlap: int = 0, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] = "default", + scale_by_freq: bool | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray]: return gca().cohere( - x, y, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend, window=window, - noverlap=noverlap, pad_to=pad_to, sides=sides, + x, + y, + NFFT=NFFT, + Fs=Fs, + Fc=Fc, + detrend=detrend, + window=window, + noverlap=noverlap, + pad_to=pad_to, + sides=sides, scale_by_freq=scale_by_freq, - **({"data": data} if data is not None else {}), **kwargs) + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.contour) -def contour(*args, data=None, **kwargs): +def contour(*args, data=None, **kwargs) -> QuadContourSet: __ret = gca().contour( - *args, **({"data": data} if data is not None else {}), - **kwargs) - if __ret._A is not None: sci(__ret) # noqa + *args, **({"data": data} if data is not None else {}), **kwargs + ) + if __ret._A is not None: + sci(__ret) # noqa return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.contourf) -def contourf(*args, data=None, **kwargs): +def contourf(*args, data=None, **kwargs) -> QuadContourSet: __ret = gca().contourf( - *args, **({"data": data} if data is not None else {}), - **kwargs) - if __ret._A is not None: sci(__ret) # noqa + *args, **({"data": data} if data is not None else {}), **kwargs + ) + if __ret._A is not None: + sci(__ret) # noqa return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.csd) def csd( - x, y, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, - noverlap=None, pad_to=None, sides=None, scale_by_freq=None, - return_line=None, *, data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + NFFT: int | None = None, + Fs: float | None = None, + Fc: int | None = None, + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike], ArrayLike] + | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + noverlap: int | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + scale_by_freq: bool | None = None, + return_line: bool | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray] | tuple[np.ndarray, np.ndarray, Line2D]: return gca().csd( - x, y, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend, window=window, - noverlap=noverlap, pad_to=pad_to, sides=sides, - scale_by_freq=scale_by_freq, return_line=return_line, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + NFFT=NFFT, + Fs=Fs, + Fc=Fc, + detrend=detrend, + window=window, + noverlap=noverlap, + pad_to=pad_to, + sides=sides, + scale_by_freq=scale_by_freq, + return_line=return_line, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.errorbar) def errorbar( - x, y, yerr=None, xerr=None, fmt='', ecolor=None, - elinewidth=None, capsize=None, barsabove=False, lolims=False, - uplims=False, xlolims=False, xuplims=False, errorevery=1, - capthick=None, *, data=None, **kwargs): + x: float | ArrayLike, + y: float | ArrayLike, + yerr: float | ArrayLike | None = None, + xerr: float | ArrayLike | None = None, + fmt: str = "", + ecolor: Color | None = None, + elinewidth: float | None = None, + capsize: float | None = None, + barsabove: bool = False, + lolims: bool = False, + uplims: bool = False, + xlolims: bool = False, + xuplims: bool = False, + errorevery: int | tuple[int, int] = 1, + capthick: float | None = None, + *, + data=None, + **kwargs, +) -> ErrorbarContainer: return gca().errorbar( - x, y, yerr=yerr, xerr=xerr, fmt=fmt, ecolor=ecolor, - elinewidth=elinewidth, capsize=capsize, barsabove=barsabove, - lolims=lolims, uplims=uplims, xlolims=xlolims, - xuplims=xuplims, errorevery=errorevery, capthick=capthick, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + yerr=yerr, + xerr=xerr, + fmt=fmt, + ecolor=ecolor, + elinewidth=elinewidth, + capsize=capsize, + barsabove=barsabove, + lolims=lolims, + uplims=uplims, + xlolims=xlolims, + xuplims=xuplims, + errorevery=errorevery, + capthick=capthick, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.eventplot) def eventplot( - positions, orientation='horizontal', lineoffsets=1, - linelengths=1, linewidths=None, colors=None, alpha=None, - linestyles='solid', *, data=None, **kwargs): + positions: ArrayLike | Sequence[ArrayLike], + orientation: Literal["horizontal", "vertical"] = "horizontal", + lineoffsets: float | Sequence[float] = 1, + linelengths: float | Sequence[float] = 1, + linewidths: float | Sequence[float] | None = None, + colors: Color | Sequence[Color] | None = None, + alpha: float | Sequence[float] | None = None, + linestyles: LineStyleType | Sequence[LineStyleType] = "solid", + *, + data=None, + **kwargs, +) -> EventCollection: return gca().eventplot( - positions, orientation=orientation, lineoffsets=lineoffsets, - linelengths=linelengths, linewidths=linewidths, colors=colors, - alpha=alpha, linestyles=linestyles, - **({"data": data} if data is not None else {}), **kwargs) + positions, + orientation=orientation, + lineoffsets=lineoffsets, + linelengths=linelengths, + linewidths=linewidths, + colors=colors, + alpha=alpha, + linestyles=linestyles, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.fill) -def fill(*args, data=None, **kwargs): +def fill(*args, data: Any | None = None, **kwargs) -> list[Polygon]: return gca().fill( - *args, **({"data": data} if data is not None else {}), - **kwargs) + *args, **({"data": data} if data is not None else {}), **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.fill_between) def fill_between( - x, y1, y2=0, where=None, interpolate=False, step=None, *, - data=None, **kwargs): + x: ArrayLike, + y1: ArrayLike | float, + y2: ArrayLike | float = 0, + where: Sequence[bool] | None = None, + interpolate: bool = False, + step: Literal["pre", "post", "mid"] | None = None, + *, + data=None, + **kwargs, +) -> PolyCollection: return gca().fill_between( - x, y1, y2=y2, where=where, interpolate=interpolate, step=step, - **({"data": data} if data is not None else {}), **kwargs) + x, + y1, + y2=y2, + where=where, + interpolate=interpolate, + step=step, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.fill_betweenx) def fill_betweenx( - y, x1, x2=0, where=None, step=None, interpolate=False, *, - data=None, **kwargs): + y: ArrayLike, + x1: ArrayLike | float, + x2: ArrayLike | float = 0, + where: Sequence[bool] | None = None, + step: Literal["pre", "post", "mid"] | None = None, + interpolate: bool = False, + *, + data=None, + **kwargs, +) -> PolyCollection: return gca().fill_betweenx( - y, x1, x2=x2, where=where, step=step, interpolate=interpolate, - **({"data": data} if data is not None else {}), **kwargs) + y, + x1, + x2=x2, + where=where, + step=step, + interpolate=interpolate, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.grid) -def grid(visible=None, which='major', axis='both', **kwargs): +def grid( + visible: bool | None = None, + which: Literal["major", "minor", "both"] = "major", + axis: Literal["both", "x", "y"] = "both", + **kwargs, +) -> None: return gca().grid(visible=visible, which=which, axis=axis, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.hexbin) def hexbin( - x, y, C=None, gridsize=100, bins=None, xscale='linear', - yscale='linear', extent=None, cmap=None, norm=None, vmin=None, - vmax=None, alpha=None, linewidths=None, edgecolors='face', - reduce_C_function=np.mean, mincnt=None, marginals=False, *, - data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + C: ArrayLike | None = None, + gridsize: int | tuple[int, int] = 100, + bins: Literal["log"] | int | Sequence[float] | None = None, + xscale: Literal["linear", "log"] = "linear", + yscale: Literal["linear", "log"] = "linear", + extent: tuple[float, float, float, float] | None = None, + cmap: str | Colormap | None = None, + norm: str | Normalize | None = None, + vmin: float | None = None, + vmax: float | None = None, + alpha: float | None = None, + linewidths: float | None = None, + edgecolors: Literal["face", "none"] | Color = "face", + reduce_C_function: Callable[[np.ndarray], float] = np.mean, + mincnt: int | None = None, + marginals: bool = False, + *, + data=None, + **kwargs, +) -> PolyCollection: __ret = gca().hexbin( - x, y, C=C, gridsize=gridsize, bins=bins, xscale=xscale, - yscale=yscale, extent=extent, cmap=cmap, norm=norm, vmin=vmin, - vmax=vmax, alpha=alpha, linewidths=linewidths, - edgecolors=edgecolors, reduce_C_function=reduce_C_function, - mincnt=mincnt, marginals=marginals, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + C=C, + gridsize=gridsize, + bins=bins, + xscale=xscale, + yscale=yscale, + extent=extent, + cmap=cmap, + norm=norm, + vmin=vmin, + vmax=vmax, + alpha=alpha, + linewidths=linewidths, + edgecolors=edgecolors, + reduce_C_function=reduce_C_function, + mincnt=mincnt, + marginals=marginals, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret @@ -2622,38 +3112,104 @@ def hexbin( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.hist) def hist( - x, bins=None, range=None, density=False, weights=None, - cumulative=False, bottom=None, histtype='bar', align='mid', - orientation='vertical', rwidth=None, log=False, color=None, - label=None, stacked=False, *, data=None, **kwargs): + x: ArrayLike | Sequence[ArrayLike], + bins: int | Sequence[float] | str | None = None, + range: tuple[float, float] | None = None, + density: bool = False, + weights: ArrayLike | None = None, + cumulative: bool | float = False, + bottom: ArrayLike | float | None = None, + histtype: Literal["bar", "barstacked", "step", "stepfilled"] = "bar", + align: Literal["left", "mid", "right"] = "mid", + orientation: Literal["vertical", "horizontal"] = "vertical", + rwidth: float | None = None, + log: bool = False, + color: Color | Sequence[Color] | None = None, + label: str | Sequence[str] | None = None, + stacked: bool = False, + *, + data=None, + **kwargs, +) -> tuple[ + np.ndarray | list[np.ndarray], + np.ndarray, + BarContainer | Polygon | list[BarContainer | Polygon], +]: return gca().hist( - x, bins=bins, range=range, density=density, weights=weights, - cumulative=cumulative, bottom=bottom, histtype=histtype, - align=align, orientation=orientation, rwidth=rwidth, log=log, - color=color, label=label, stacked=stacked, - **({"data": data} if data is not None else {}), **kwargs) + x, + bins=bins, + range=range, + density=density, + weights=weights, + cumulative=cumulative, + bottom=bottom, + histtype=histtype, + align=align, + orientation=orientation, + rwidth=rwidth, + log=log, + color=color, + label=label, + stacked=stacked, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.stairs) def stairs( - values, edges=None, *, orientation='vertical', baseline=0, - fill=False, data=None, **kwargs): + values: ArrayLike, + edges: ArrayLike | None = None, + *, + orientation: Literal["vertical", "horizontal"] = "vertical", + baseline: float | ArrayLike = 0, + fill: bool = False, + data=None, + **kwargs, +) -> StepPatch: return gca().stairs( - values, edges=edges, orientation=orientation, - baseline=baseline, fill=fill, - **({"data": data} if data is not None else {}), **kwargs) + values, + edges=edges, + orientation=orientation, + baseline=baseline, + fill=fill, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.hist2d) def hist2d( - x, y, bins=10, range=None, density=False, weights=None, - cmin=None, cmax=None, *, data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + bins: None + | int + | tuple[int, int] + | ArrayLike + | tuple[ArrayLike, ArrayLike] = 10, + range: ArrayLike | None = None, + density: bool = False, + weights: ArrayLike | None = None, + cmin: float | None = None, + cmax: float | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, np.ndarray, QuadMesh]: __ret = gca().hist2d( - x, y, bins=bins, range=range, density=density, - weights=weights, cmin=cmin, cmax=cmax, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + bins=bins, + range=range, + density=density, + weights=weights, + cmin=cmin, + cmax=cmax, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret[-1]) return __ret @@ -2661,89 +3217,169 @@ def hist2d( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.hlines) def hlines( - y, xmin, xmax, colors=None, linestyles='solid', label='', *, - data=None, **kwargs): + y: float | ArrayLike, + xmin: float | ArrayLike, + xmax: float | ArrayLike, + colors: Sequence[Color] | None = None, + linestyles: LineStyleType = "solid", + label: str = "", + *, + data=None, + **kwargs, +) -> LineCollection: return gca().hlines( - y, xmin, xmax, colors=colors, linestyles=linestyles, - label=label, **({"data": data} if data is not None else {}), - **kwargs) + y, + xmin, + xmax, + colors=colors, + linestyles=linestyles, + label=label, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.imshow) def imshow( - X, cmap=None, norm=None, *, aspect=None, interpolation=None, - alpha=None, vmin=None, vmax=None, origin=None, extent=None, - interpolation_stage=None, filternorm=True, filterrad=4.0, - resample=None, url=None, data=None, **kwargs): + X: ArrayLike | PIL.Image.Image, + cmap: str | Colormap | None = None, + norm: str | Normalize | None = None, + *, + aspect: Literal["equal", "auto"] | float | None = None, + interpolation: str | None = None, + alpha: float | ArrayLike | None = None, + vmin: float | None = None, + vmax: float | None = None, + origin: Literal["upper", "lower"] | None = None, + extent: tuple[float, float, float, float] | None = None, + interpolation_stage: Literal["data", "rgba"] | None = None, + filternorm: bool = True, + filterrad: float = 4.0, + resample: bool | None = None, + url: str | None = None, + data=None, + **kwargs, +) -> AxesImage: __ret = gca().imshow( - X, cmap=cmap, norm=norm, aspect=aspect, - interpolation=interpolation, alpha=alpha, vmin=vmin, - vmax=vmax, origin=origin, extent=extent, + X, + cmap=cmap, + norm=norm, + aspect=aspect, + interpolation=interpolation, + alpha=alpha, + vmin=vmin, + vmax=vmax, + origin=origin, + extent=extent, interpolation_stage=interpolation_stage, - filternorm=filternorm, filterrad=filterrad, resample=resample, - url=url, **({"data": data} if data is not None else {}), - **kwargs) + filternorm=filternorm, + filterrad=filterrad, + resample=resample, + url=url, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.legend) -def legend(*args, **kwargs): +def legend(*args, **kwargs) -> Legend: return gca().legend(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.locator_params) -def locator_params(axis='both', tight=None, **kwargs): +def locator_params( + axis: Literal["both", "x", "y"] = "both", + tight: bool | None = None, + **kwargs, +) -> None: return gca().locator_params(axis=axis, tight=tight, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.loglog) -def loglog(*args, **kwargs): +def loglog(*args, **kwargs) -> list[Line2D]: return gca().loglog(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.magnitude_spectrum) def magnitude_spectrum( - x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, - scale=None, *, data=None, **kwargs): + x: ArrayLike, + Fs: float | None = None, + Fc: int | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + scale: Literal["default", "linear", "dB"] | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, Line2D]: return gca().magnitude_spectrum( - x, Fs=Fs, Fc=Fc, window=window, pad_to=pad_to, sides=sides, - scale=scale, **({"data": data} if data is not None else {}), - **kwargs) + x, + Fs=Fs, + Fc=Fc, + window=window, + pad_to=pad_to, + sides=sides, + scale=scale, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.margins) -def margins(*margins, x=None, y=None, tight=True): +def margins( + *margins: float, + x: float | None = None, + y: float | None = None, + tight: bool | None = True, +) -> tuple[float, float] | None: return gca().margins(*margins, x=x, y=y, tight=tight) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.minorticks_off) -def minorticks_off(): +def minorticks_off() -> None: return gca().minorticks_off() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.minorticks_on) -def minorticks_on(): +def minorticks_on() -> None: return gca().minorticks_on() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.pcolor) def pcolor( - *args, shading=None, alpha=None, norm=None, cmap=None, - vmin=None, vmax=None, data=None, **kwargs): + *args: ArrayLike, + shading: Literal["flat", "nearest", "auto"] | None = None, + alpha: float | None = None, + norm: str | Normalize | None = None, + cmap: str | Colormap | None = None, + vmin: float | None = None, + vmax: float | None = None, + data=None, + **kwargs, +) -> Collection: __ret = gca().pcolor( - *args, shading=shading, alpha=alpha, norm=norm, cmap=cmap, - vmin=vmin, vmax=vmax, - **({"data": data} if data is not None else {}), **kwargs) + *args, + shading=shading, + alpha=alpha, + norm=norm, + cmap=cmap, + vmin=vmin, + vmax=vmax, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret @@ -2751,13 +3387,29 @@ def pcolor( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.pcolormesh) def pcolormesh( - *args, alpha=None, norm=None, cmap=None, vmin=None, - vmax=None, shading=None, antialiased=False, data=None, - **kwargs): + *args: ArrayLike, + alpha: float | None = None, + norm: str | Normalize | None = None, + cmap: str | Colormap | None = None, + vmin: float | None = None, + vmax: float | None = None, + shading: Literal["flat", "nearest", "gouraud", "auto"] | None = None, + antialiased: bool = False, + data=None, + **kwargs, +) -> QuadMesh: __ret = gca().pcolormesh( - *args, alpha=alpha, norm=norm, cmap=cmap, vmin=vmin, - vmax=vmax, shading=shading, antialiased=antialiased, - **({"data": data} if data is not None else {}), **kwargs) + *args, + alpha=alpha, + norm=norm, + cmap=cmap, + vmin=vmin, + vmax=vmax, + shading=shading, + antialiased=antialiased, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret @@ -2765,118 +3417,275 @@ def pcolormesh( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.phase_spectrum) def phase_spectrum( - x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, *, - data=None, **kwargs): + x: ArrayLike, + Fs: float | None = None, + Fc: int | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, Line2D]: return gca().phase_spectrum( - x, Fs=Fs, Fc=Fc, window=window, pad_to=pad_to, sides=sides, - **({"data": data} if data is not None else {}), **kwargs) + x, + Fs=Fs, + Fc=Fc, + window=window, + pad_to=pad_to, + sides=sides, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.pie) def pie( - x, explode=None, labels=None, colors=None, autopct=None, - pctdistance=0.6, shadow=False, labeldistance=1.1, - startangle=0, radius=1, counterclock=True, wedgeprops=None, - textprops=None, center=(0, 0), frame=False, - rotatelabels=False, *, normalize=True, hatch=None, data=None): + x: ArrayLike, + explode: ArrayLike | None = None, + labels: Sequence[str] | None = None, + colors: Sequence[Color] | None = None, + autopct: str | Callable[[float], str] | None = None, + pctdistance: float = 0.6, + shadow: bool = False, + labeldistance: float = 1.1, + startangle: float = 0, + radius: float = 1, + counterclock: bool = True, + wedgeprops: dict[str, Any] | None = None, + textprops: dict[str, Any] | None = None, + center: tuple[float, float] = (0, 0), + frame: bool = False, + rotatelabels: bool = False, + *, + normalize: bool = True, + hatch: str | Sequence[str] | None = None, + data=None, +): return gca().pie( - x, explode=explode, labels=labels, colors=colors, - autopct=autopct, pctdistance=pctdistance, shadow=shadow, - labeldistance=labeldistance, startangle=startangle, - radius=radius, counterclock=counterclock, - wedgeprops=wedgeprops, textprops=textprops, center=center, - frame=frame, rotatelabels=rotatelabels, normalize=normalize, - hatch=hatch, **({"data": data} if data is not None else {})) + x, + explode=explode, + labels=labels, + colors=colors, + autopct=autopct, + pctdistance=pctdistance, + shadow=shadow, + labeldistance=labeldistance, + startangle=startangle, + radius=radius, + counterclock=counterclock, + wedgeprops=wedgeprops, + textprops=textprops, + center=center, + frame=frame, + rotatelabels=rotatelabels, + normalize=normalize, + hatch=hatch, + **({"data": data} if data is not None else {}), + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.plot) -def plot(*args, scalex=True, scaley=True, data=None, **kwargs): +def plot( + *args: float | ArrayLike | str, + scalex: bool = True, + scaley: bool = True, + data: Any | None = None, + **kwargs, +) -> list[Line2D]: return gca().plot( - *args, scalex=scalex, scaley=scaley, - **({"data": data} if data is not None else {}), **kwargs) + *args, + scalex=scalex, + scaley=scaley, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.plot_date) def plot_date( - x, y, fmt='o', tz=None, xdate=True, ydate=False, *, - data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + fmt: str = "o", + tz: str | datetime.tzinfo | None = None, + xdate: bool = True, + ydate: bool = False, + *, + data=None, + **kwargs, +) -> list[Line2D]: return gca().plot_date( - x, y, fmt=fmt, tz=tz, xdate=xdate, ydate=ydate, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + fmt=fmt, + tz=tz, + xdate=xdate, + ydate=ydate, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.psd) def psd( - x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, - noverlap=None, pad_to=None, sides=None, scale_by_freq=None, - return_line=None, *, data=None, **kwargs): + x: ArrayLike, + NFFT: int | None = None, + Fs: float | None = None, + Fc: int | None = None, + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike], ArrayLike] + | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + noverlap: int | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + scale_by_freq: bool | None = None, + return_line: bool | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray] | tuple[np.ndarray, np.ndarray, Line2D]: return gca().psd( - x, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend, window=window, - noverlap=noverlap, pad_to=pad_to, sides=sides, - scale_by_freq=scale_by_freq, return_line=return_line, - **({"data": data} if data is not None else {}), **kwargs) + x, + NFFT=NFFT, + Fs=Fs, + Fc=Fc, + detrend=detrend, + window=window, + noverlap=noverlap, + pad_to=pad_to, + sides=sides, + scale_by_freq=scale_by_freq, + return_line=return_line, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.quiver) -def quiver(*args, data=None, **kwargs): +def quiver(*args, data=None, **kwargs) -> Quiver: __ret = gca().quiver( - *args, **({"data": data} if data is not None else {}), - **kwargs) + *args, **({"data": data} if data is not None else {}), **kwargs + ) sci(__ret) return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.quiverkey) -def quiverkey(Q, X, Y, U, label, **kwargs): +def quiverkey( + Q: Quiver, X: float, Y: float, U: float, label: str, **kwargs +) -> QuiverKey: return gca().quiverkey(Q, X, Y, U, label, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.scatter) def scatter( - x, y, s=None, c=None, marker=None, cmap=None, norm=None, - vmin=None, vmax=None, alpha=None, linewidths=None, *, - edgecolors=None, plotnonfinite=False, data=None, **kwargs): + x: float | ArrayLike, + y: float | ArrayLike, + s: float | ArrayLike | None = None, + c: Sequence[Color] | Color | None = None, + marker: MarkerType | None = None, + cmap: str | Colormap | None = None, + norm: str | Normalize | None = None, + vmin: float | None = None, + vmax: float | None = None, + alpha: float | None = None, + linewidths: float | Sequence[float] | None = None, + *, + edgecolors: Literal["face", "none"] + | Color + | Sequence[Color] + | None = None, + plotnonfinite: bool = False, + data=None, + **kwargs, +) -> PathCollection: __ret = gca().scatter( - x, y, s=s, c=c, marker=marker, cmap=cmap, norm=norm, - vmin=vmin, vmax=vmax, alpha=alpha, linewidths=linewidths, - edgecolors=edgecolors, plotnonfinite=plotnonfinite, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + s=s, + c=c, + marker=marker, + cmap=cmap, + norm=norm, + vmin=vmin, + vmax=vmax, + alpha=alpha, + linewidths=linewidths, + edgecolors=edgecolors, + plotnonfinite=plotnonfinite, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.semilogx) -def semilogx(*args, **kwargs): +def semilogx(*args, **kwargs) -> list[Line2D]: return gca().semilogx(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.semilogy) -def semilogy(*args, **kwargs): +def semilogy(*args, **kwargs) -> list[Line2D]: return gca().semilogy(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.specgram) def specgram( - x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, - noverlap=None, cmap=None, xextent=None, pad_to=None, - sides=None, scale_by_freq=None, mode=None, scale=None, - vmin=None, vmax=None, *, data=None, **kwargs): + x: ArrayLike, + NFFT: int | None = None, + Fs: float | None = None, + Fc: int | None = None, + detrend: Literal["none", "mean", "linear"] + | Callable[[ArrayLike], ArrayLike] + | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + noverlap: int | None = None, + cmap: str | Colormap | None = None, + xextent: tuple[float, float] | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + scale_by_freq: bool | None = None, + mode: Literal["default", "psd", "magnitude", "angle", "phase"] + | None = None, + scale: Literal["default", "linear", "dB"] | None = None, + vmin: float | None = None, + vmax: float | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, np.ndarray, AxesImage]: __ret = gca().specgram( - x, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend, window=window, - noverlap=noverlap, cmap=cmap, xextent=xextent, pad_to=pad_to, - sides=sides, scale_by_freq=scale_by_freq, mode=mode, - scale=scale, vmin=vmin, vmax=vmax, - **({"data": data} if data is not None else {}), **kwargs) + x, + NFFT=NFFT, + Fs=Fs, + Fc=Fc, + detrend=detrend, + window=window, + noverlap=noverlap, + cmap=cmap, + xextent=xextent, + pad_to=pad_to, + sides=sides, + scale_by_freq=scale_by_freq, + mode=mode, + scale=scale, + vmin=vmin, + vmax=vmax, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret[-1]) return __ret @@ -2884,65 +3693,135 @@ def specgram( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.spy) def spy( - Z, precision=0, marker=None, markersize=None, aspect='equal', - origin='upper', **kwargs): + Z: ArrayLike, + precision: float | Literal["present"] = 0, + marker: str | None = None, + markersize: float | None = None, + aspect: Literal["equal", "auto"] | float | None = "equal", + origin: Literal["upper", "lower"] = "upper", + **kwargs, +) -> AxesImage: __ret = gca().spy( - Z, precision=precision, marker=marker, markersize=markersize, - aspect=aspect, origin=origin, **kwargs) - if isinstance(__ret, cm.ScalarMappable): sci(__ret) # noqa + Z, + precision=precision, + marker=marker, + markersize=markersize, + aspect=aspect, + origin=origin, + **kwargs, + ) + if isinstance(__ret, cm.ScalarMappable): + sci(__ret) # noqa return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.stackplot) def stackplot( - x, *args, labels=(), colors=None, baseline='zero', data=None, - **kwargs): + x, *args, labels=(), colors=None, baseline="zero", data=None, **kwargs +): return gca().stackplot( - x, *args, labels=labels, colors=colors, baseline=baseline, - **({"data": data} if data is not None else {}), **kwargs) + x, + *args, + labels=labels, + colors=colors, + baseline=baseline, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.stem) def stem( - *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, - label=None, - use_line_collection=_api.deprecation._deprecated_parameter, - orientation='vertical', data=None): + *args: ArrayLike | str, + linefmt: str | None = None, + markerfmt: str | None = None, + basefmt: str | None = None, + bottom: float = 0, + label: str | None = None, + use_line_collection: Any = _api.deprecation._deprecated_parameter, + orientation: Literal["vertical", "horizontal"] = "vertical", + data=None, +) -> StemContainer: return gca().stem( - *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt, - bottom=bottom, label=label, + *args, + linefmt=linefmt, + markerfmt=markerfmt, + basefmt=basefmt, + bottom=bottom, + label=label, use_line_collection=use_line_collection, orientation=orientation, - **({"data": data} if data is not None else {})) + **({"data": data} if data is not None else {}), + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.step) -def step(x, y, *args, where='pre', data=None, **kwargs): +def step( + x: ArrayLike, + y: ArrayLike, + *args, + where: Literal["pre", "post", "mid"] = "pre", + data: Any | None = None, + **kwargs, +) -> list[Line2D]: return gca().step( - x, y, *args, where=where, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + *args, + where=where, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.streamplot) def streamplot( - x, y, u, v, density=1, linewidth=None, color=None, cmap=None, - norm=None, arrowsize=1, arrowstyle='-|>', minlength=0.1, - transform=None, zorder=None, start_points=None, maxlength=4.0, - integration_direction='both', broken_streamlines=True, *, - data=None): + x, + y, + u, + v, + density=1, + linewidth=None, + color=None, + cmap=None, + norm=None, + arrowsize=1, + arrowstyle="-|>", + minlength=0.1, + transform=None, + zorder=None, + start_points=None, + maxlength=4.0, + integration_direction="both", + broken_streamlines=True, + *, + data=None, +): __ret = gca().streamplot( - x, y, u, v, density=density, linewidth=linewidth, color=color, - cmap=cmap, norm=norm, arrowsize=arrowsize, - arrowstyle=arrowstyle, minlength=minlength, - transform=transform, zorder=zorder, start_points=start_points, + x, + y, + u, + v, + density=density, + linewidth=linewidth, + color=color, + cmap=cmap, + norm=norm, + arrowsize=arrowsize, + arrowstyle=arrowstyle, + minlength=minlength, + transform=transform, + zorder=zorder, + start_points=start_points, maxlength=maxlength, integration_direction=integration_direction, broken_streamlines=broken_streamlines, - **({"data": data} if data is not None else {})) + **({"data": data} if data is not None else {}), + ) sci(__ret.lines) return __ret @@ -2950,47 +3829,84 @@ def streamplot( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.table) def table( - cellText=None, cellColours=None, cellLoc='right', - colWidths=None, rowLabels=None, rowColours=None, - rowLoc='left', colLabels=None, colColours=None, - colLoc='center', loc='bottom', bbox=None, edges='closed', - **kwargs): + cellText=None, + cellColours=None, + cellLoc="right", + colWidths=None, + rowLabels=None, + rowColours=None, + rowLoc="left", + colLabels=None, + colColours=None, + colLoc="center", + loc="bottom", + bbox=None, + edges="closed", + **kwargs, +): return gca().table( - cellText=cellText, cellColours=cellColours, cellLoc=cellLoc, - colWidths=colWidths, rowLabels=rowLabels, - rowColours=rowColours, rowLoc=rowLoc, colLabels=colLabels, - colColours=colColours, colLoc=colLoc, loc=loc, bbox=bbox, - edges=edges, **kwargs) + cellText=cellText, + cellColours=cellColours, + cellLoc=cellLoc, + colWidths=colWidths, + rowLabels=rowLabels, + rowColours=rowColours, + rowLoc=rowLoc, + colLabels=colLabels, + colColours=colColours, + colLoc=colLoc, + loc=loc, + bbox=bbox, + edges=edges, + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.text) -def text(x, y, s, fontdict=None, **kwargs): +def text( + x: float, + y: float, + s: str, + fontdict: dict[str, Any] | None = None, + **kwargs, +) -> Text: return gca().text(x, y, s, fontdict=fontdict, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.tick_params) -def tick_params(axis='both', **kwargs): +def tick_params(axis: Literal["both", "x", "y"] = "both", **kwargs) -> None: return gca().tick_params(axis=axis, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.ticklabel_format) def ticklabel_format( - *, axis='both', style='', scilimits=None, useOffset=None, - useLocale=None, useMathText=None): + *, + axis: Literal["both", "x", "y"] = "both", + style: Literal["", "sci", "scientific", "plain"] = "", + scilimits: tuple[int, int] | None = None, + useOffset: bool | float | None = None, + useLocale: bool | None = None, + useMathText: bool | None = None, +) -> None: return gca().ticklabel_format( - axis=axis, style=style, scilimits=scilimits, - useOffset=useOffset, useLocale=useLocale, - useMathText=useMathText) + axis=axis, + style=style, + scilimits=scilimits, + useOffset=useOffset, + useLocale=useLocale, + useMathText=useMathText, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.tricontour) def tricontour(*args, **kwargs): __ret = gca().tricontour(*args, **kwargs) - if __ret._A is not None: sci(__ret) # noqa + if __ret._A is not None: + sci(__ret) # noqa return __ret @@ -2998,18 +3914,35 @@ def tricontour(*args, **kwargs): @_copy_docstring_and_deprecators(Axes.tricontourf) def tricontourf(*args, **kwargs): __ret = gca().tricontourf(*args, **kwargs) - if __ret._A is not None: sci(__ret) # noqa + if __ret._A is not None: + sci(__ret) # noqa return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.tripcolor) def tripcolor( - *args, alpha=1.0, norm=None, cmap=None, vmin=None, vmax=None, - shading='flat', facecolors=None, **kwargs): + *args, + alpha=1.0, + norm=None, + cmap=None, + vmin=None, + vmax=None, + shading="flat", + facecolors=None, + **kwargs, +): __ret = gca().tripcolor( - *args, alpha=alpha, norm=norm, cmap=cmap, vmin=vmin, - vmax=vmax, shading=shading, facecolors=facecolors, **kwargs) + *args, + alpha=alpha, + norm=norm, + cmap=cmap, + vmin=vmin, + vmax=vmax, + shading=shading, + facecolors=facecolors, + **kwargs, + ) sci(__ret) return __ret @@ -3023,77 +3956,148 @@ def triplot(*args, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.violinplot) def violinplot( - dataset, positions=None, vert=True, widths=0.5, - showmeans=False, showextrema=True, showmedians=False, - quantiles=None, points=100, bw_method=None, *, data=None): + dataset: ArrayLike | Sequence[ArrayLike], + positions: ArrayLike | None = None, + vert: bool = True, + widths: float | ArrayLike = 0.5, + showmeans: bool = False, + showextrema: bool = True, + showmedians: bool = False, + quantiles: Sequence[float] | None = None, + points: int = 100, + bw_method: Literal["scott", "silverman"] + | float + | Callable[[GaussianKDE], float] + | None = None, + *, + data=None, +) -> dict[str, Collection]: return gca().violinplot( - dataset, positions=positions, vert=vert, widths=widths, - showmeans=showmeans, showextrema=showextrema, - showmedians=showmedians, quantiles=quantiles, points=points, + dataset, + positions=positions, + vert=vert, + widths=widths, + showmeans=showmeans, + showextrema=showextrema, + showmedians=showmedians, + quantiles=quantiles, + points=points, bw_method=bw_method, - **({"data": data} if data is not None else {})) + **({"data": data} if data is not None else {}), + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.vlines) def vlines( - x, ymin, ymax, colors=None, linestyles='solid', label='', *, - data=None, **kwargs): + x: float | ArrayLike, + ymin: float | ArrayLike, + ymax: float | ArrayLike, + colors: Sequence[Color] | None = None, + linestyles: LineStyleType = "solid", + label: str = "", + *, + data=None, + **kwargs, +) -> LineCollection: return gca().vlines( - x, ymin, ymax, colors=colors, linestyles=linestyles, - label=label, **({"data": data} if data is not None else {}), - **kwargs) + x, + ymin, + ymax, + colors=colors, + linestyles=linestyles, + label=label, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.xcorr) def xcorr( - x, y, normed=True, detrend=mlab.detrend_none, usevlines=True, - maxlags=10, *, data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + normed: bool = True, + detrend: Callable[[ArrayLike], ArrayLike] = mlab.detrend_none, + usevlines: bool = True, + maxlags: int = 10, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, LineCollection | Line2D, Line2D | None]: return gca().xcorr( - x, y, normed=normed, detrend=detrend, usevlines=usevlines, + x, + y, + normed=normed, + detrend=detrend, + usevlines=usevlines, maxlags=maxlags, - **({"data": data} if data is not None else {}), **kwargs) + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes._sci) -def sci(im): +def sci(im: ScalarMappable) -> None: return gca()._sci(im) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_title) -def title(label, fontdict=None, loc=None, pad=None, *, y=None, **kwargs): +def title( + label: str, + fontdict: dict[str, Any] | None = None, + loc: Literal["left", "center", "right"] | None = None, + pad: float | None = None, + *, + y: float | None = None, + **kwargs, +) -> Text: return gca().set_title( - label, fontdict=fontdict, loc=loc, pad=pad, y=y, **kwargs) + label, fontdict=fontdict, loc=loc, pad=pad, y=y, **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_xlabel) -def xlabel(xlabel, fontdict=None, labelpad=None, *, loc=None, **kwargs): +def xlabel( + xlabel: str, + fontdict: dict[str, Any] | None = None, + labelpad: float | None = None, + *, + loc: Literal["left", "center", "right"] | None = None, + **kwargs, +) -> Text: return gca().set_xlabel( - xlabel, fontdict=fontdict, labelpad=labelpad, loc=loc, - **kwargs) + xlabel, fontdict=fontdict, labelpad=labelpad, loc=loc, **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_ylabel) -def ylabel(ylabel, fontdict=None, labelpad=None, *, loc=None, **kwargs): +def ylabel( + ylabel: str, + fontdict: dict[str, Any] | None = None, + labelpad: float | None = None, + *, + loc: Literal["bottom", "center", "top"] | None = None, + **kwargs, +) -> Text: return gca().set_ylabel( - ylabel, fontdict=fontdict, labelpad=labelpad, loc=loc, - **kwargs) + ylabel, fontdict=fontdict, labelpad=labelpad, loc=loc, **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_xscale) -def xscale(value, **kwargs): +def xscale(value: str | ScaleBase, **kwargs) -> None: return gca().set_xscale(value, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_yscale) -def yscale(value, **kwargs): +def yscale(value: str | ScaleBase, **kwargs) -> None: return gca().set_yscale(value, **kwargs) @@ -3105,7 +4109,7 @@ def autumn(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('autumn') + set_cmap("autumn") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3116,7 +4120,7 @@ def bone(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('bone') + set_cmap("bone") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3127,7 +4131,7 @@ def cool(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('cool') + set_cmap("cool") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3138,7 +4142,7 @@ def copper(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('copper') + set_cmap("copper") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3149,7 +4153,7 @@ def flag(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('flag') + set_cmap("flag") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3160,7 +4164,7 @@ def gray(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('gray') + set_cmap("gray") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3171,7 +4175,7 @@ def hot(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('hot') + set_cmap("hot") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3182,7 +4186,7 @@ def hsv(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('hsv') + set_cmap("hsv") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3193,7 +4197,7 @@ def jet(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('jet') + set_cmap("jet") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3204,7 +4208,7 @@ def pink(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('pink') + set_cmap("pink") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3215,7 +4219,7 @@ def prism(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('prism') + set_cmap("prism") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3226,7 +4230,7 @@ def spring(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('spring') + set_cmap("spring") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3237,7 +4241,7 @@ def summer(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('summer') + set_cmap("summer") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3248,7 +4252,7 @@ def winter(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('winter') + set_cmap("winter") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3259,7 +4263,7 @@ def magma(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('magma') + set_cmap("magma") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3270,7 +4274,7 @@ def inferno(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('inferno') + set_cmap("inferno") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3281,7 +4285,7 @@ def plasma(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('plasma') + set_cmap("plasma") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3292,7 +4296,7 @@ def viridis(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('viridis') + set_cmap("viridis") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -3303,4 +4307,4 @@ def nipy_spectral(): This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('nipy_spectral') + set_cmap("nipy_spectral") diff --git a/lib/matplotlib/quiver.pyi b/lib/matplotlib/quiver.pyi new file mode 100644 index 000000000000..806a7eebd29f --- /dev/null +++ b/lib/matplotlib/quiver.pyi @@ -0,0 +1,182 @@ +import matplotlib.artist as martist +import matplotlib.collections as mcollections +from matplotlib import cbook +from matplotlib.axes import Axes +from matplotlib.colors import Color +from matplotlib.figure import Figure +from matplotlib.patches import CirclePolygon +from matplotlib.text import Text +from matplotlib.transforms import Transform, Bbox + + +import numpy as np +from numpy.typing import ArrayLike +from typing import Any, Literal, Sequence, overload + +class QuiverKey(martist.Artist): + halign: dict[Literal["N", "S", "E", "W"], Literal["left", "center", "right"]] + valign: dict[Literal["N", "S", "E", "W"], Literal["top", "center", "bottom"]] + pivot: dict[Literal["N", "S", "E", "W"], Literal["middle", "tip", "tail"]] + Q: Quiver + X: float + Y: float + U: float + angle: float + coord: Literal["axes", "figure", "data", "inches"] + color: Color | None + label: str + labelpos: Literal["N", "S", "E", "W"] + labelcolor: Color | None + fontproperties: dict[str, Any] + kw: dict[str, Any] + text: Text + zorder: float + def __init__( + self, + Q: Quiver, + X: float, + Y: float, + U: float, + label: str, + *, + angle: float = ..., + coordinates: Literal["axes", "figure", "data", "inches"] = ..., + color: Color | None = ..., + labelsep: float = ..., + labelpos: Literal["N", "S", "E", "W"] = ..., + labelcolor: Color | None = ..., + fontproperties: dict[str, Any] | None = ..., + **kwargs + ) -> None: ... + @property + def labelsep(self) -> float: ... + def set_figure(self, fig: Figure) -> None: ... + +class Quiver(mcollections.PolyCollection): + X: ArrayLike + Y: ArrayLike + XY: ArrayLike + U: ArrayLike + V: ArrayLike + Umask: ArrayLike + N: int + scale: float | None + headwidth: float + headlength: float + headaxislength: float + minshaft: float + minlength: float + units: Literal["width", "height", "dots", "inches", "x", "y", "xy"] + scale_units: Literal["width", "height", "dots", "inches", "x", "y", "xy"] | None + angles: Literal["uv", "xy"] | ArrayLike + width: float | None + pivot: Literal["tail", "middle", "tip"] + transform: Transform + polykw: dict[str, Any] + quiver_doc: str + + @overload + def __init__( + self, + ax: Axes, + U: ArrayLike, + V: ArrayLike, + C: ArrayLike = ..., + scale: float | None = ..., + headwidth: float = ..., + headlength: float = ..., + headaxislength: float = ..., + minshaft: float = ..., + minlength: float = ..., + units: Literal["width", "height", "dots", "inches", "x", "y", "xy"] = ..., + scale_units: Literal["width", "height", "dots", "inches", "x", "y", "xy"] + | None = ..., + angles: Literal["uv", "xy"] | ArrayLike = ..., + width: float | None = ..., + color: Color | Sequence[Color] = ..., + pivot: Literal["tail", "mid", "middle", "tip"] = ..., + **kwargs + ) -> None: ... + @overload + def __init__( + self, + ax: Axes, + X: ArrayLike, + Y: ArrayLike, + U: ArrayLike, + V: ArrayLike, + C: ArrayLike = ..., + scale: float | None = ..., + headwidth: float = ..., + headlength: float = ..., + headaxislength: float = ..., + minshaft: float = ..., + minlength: float = ..., + units: Literal["width", "height", "dots", "inches", "x", "y", "xy"] = ..., + scale_units: Literal["width", "height", "dots", "inches", "x", "y", "xy"] + | None = ..., + angles: Literal["uv", "xy"] | ArrayLike = ..., + width: float | None = ..., + color: Color | Sequence[Color] = ..., + pivot: Literal["tail", "mid", "middle", "tip"] = ..., + **kwargs + ) -> None: ... + def get_datalim(self, transData: Transform) -> Bbox: ... + def set_UVC( + self, U: ArrayLike, V: ArrayLike, C: ArrayLike | None = ... + ) -> None: ... + +class Barbs(mcollections.PolyCollection): + sizes: dict[str, float] + fill_empty: bool + barb_increments: dict[str, float] + rounding: bool + flip: np.ndarray + x: ArrayLike + y: ArrayLike + u: ArrayLike + v: ArrayLike + barbs_doc: str + + @overload + def __init__( + self, + ax: Axes, + U: ArrayLike, + V: ArrayLike, + C: ArrayLike = ..., + pivot: str = ..., + length: int = ..., + barbcolor: Color | Sequence[Color] | None = ..., + flagcolor: Color | Sequence[Color] | None = ..., + sizes: dict[str, float] | None = ..., + fill_empty: bool = ..., + barb_increments: dict[str, float] | None = ..., + rounding: bool = ..., + flip_barb: bool | ArrayLike = ..., + **kwargs + ) -> None: ... + @overload + def __init__( + self, + ax: Axes, + X: ArrayLike, + Y: ArrayLike, + U: ArrayLike, + V: ArrayLike, + C: ArrayLike = ..., + pivot: str = ..., + length: int = ..., + barbcolor: Color | Sequence[Color] | None = ..., + flagcolor: Color | Sequence[Color] | None = ..., + sizes: dict[str, float] | None = ..., + fill_empty: bool = ..., + barb_increments: dict[str, float] | None = ..., + rounding: bool = ..., + flip_barb: bool | ArrayLike = ..., + **kwargs + ) -> None: ... + def set_UVC( + self, U: ArrayLike, V: ArrayLike, C: ArrayLike | None = ... + ) -> None: ... + def set_offsets(self, xy: ArrayLike) -> None: ... diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 7d0425196d78..22b11f44e8b5 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -182,10 +182,7 @@ def validator(s): (s is None or isinstance(s, str) and s.lower() == "none")): return None if cls is str and not isinstance(s, str): - _api.warn_deprecated( - "3.5", message="Support for setting an rcParam that expects a " - "str value to a non-str value is deprecated since %(since)s " - "and support will be removed %(removal)s.") + raise ValueError(f'Could not convert {s!r} to str') try: return cls(s) except (TypeError, ValueError) as e: @@ -218,7 +215,7 @@ def _validate_pathlike(s): # between "" (cwd) and "." (cwd, but gets updated by user selections). return os.fsdecode(s) else: - return validate_string(s) # Emit deprecation warning. + return validate_string(s) def validate_fonttype(s): diff --git a/lib/matplotlib/rcsetup.pyi b/lib/matplotlib/rcsetup.pyi new file mode 100644 index 000000000000..3bbe03f65183 --- /dev/null +++ b/lib/matplotlib/rcsetup.pyi @@ -0,0 +1,160 @@ +import ast +from matplotlib import cbook +from matplotlib._enums import CapStyle, JoinStyle +from matplotlib._fontconfig_pattern import parse_fontconfig_pattern +from matplotlib.cbook import ls_mapper +from matplotlib.colors import Color, Colormap, is_color_like +from matplotlib.lines import LineStyleType, MarkEveryType + +from cycler import Cycler + +from typing import Any, Callable, Iterable, Literal, TypeVar + +interactive_bk: list[str] +non_interactive_bk: list[str] +all_backends: list[str] + +T = TypeVar("T") + +def _listify_validator(s: Callable[[Any], T]) -> Callable[[Any], list[T]]: ... + +class ValidateInStrings: + key: str + ignorecase: bool + valid: dict[str, str] + def __init__( + self, + key: str, + valid: Iterable[str], + ignorecase: bool = ..., + *, + _deprecated_since: str | None = ... + ) -> None: ... + def __call__(self, s: Any) -> str: ... + +def validate_any(s: Any) -> Any: ... +def validate_anylist(s: Any) -> list[Any]: ... +def validate_bool(b: Any) -> bool: ... +def validate_axisbelow(s: Any) -> bool | Literal["line"]: ... +def validate_dpi(s: Any) -> Literal["figure"] | float: ... +def validate_string(s: Any) -> str: ... +def validate_string_or_None(s: Any) -> str | None: ... +def validate_stringlist(s: Any) -> list[str]: ... +def validate_int(s: Any) -> int: ... +def validate_int_or_None(s: Any) -> int | None: ... +def validate_float(s: Any) -> float: ... +def validate_float_or_None(s: Any) -> float | None: ... +def validate_floatlist(s: Any) -> list[float]: ... +def validate_fonttype(s: Any) -> int: ... +def validate_backend(s: Any) -> str: ... +def validate_color_or_inherit(s: Any) -> Literal["inherit"] | Color: ... +def validate_color_or_auto(s: Any) -> Color | Literal["auto"]: ... +def validate_color_for_prop_cycle(s: Any) -> Color: ... +def validate_color(s: Any) -> Color: ... +def validate_colorlist(s: Any) -> list[Color]: ... +def _validate_color_or_linecolor( + s: Any, +) -> Color | Literal["linecolor", "markerfacecolor", "markeredgecolor"] | None: ... +def validate_aspect(s: Any) -> Literal["auto", "equal"] | float: ... +def validate_fontsize_None( + s: Any, +) -> Literal[ + "xx-small", + "x-small", + "small", + "medium", + "large", + "x-large", + "xx-large", + "smaller", + "larger", +] | float | None: ... +def validate_fontsize( + s: Any, +) -> Literal[ + "xx-small", + "x-small", + "small", + "medium", + "large", + "x-large", + "xx-large", + "smaller", + "larger", +] | float: ... +def validate_fontsizelist( + s: Any, +) -> list[ + Literal[ + "xx-small", + "x-small", + "small", + "medium", + "large", + "x-large", + "xx-large", + "smaller", + "larger", + ] + | float +]: ... +def validate_fontweight( + s: Any, +) -> Literal[ + "ultralight", + "light", + "normal", + "regular", + "book", + "medium", + "roman", + "semibold", + "demibold", + "demi", + "bold", + "heavy", + "extra bold", + "black", +] | int: ... +def validate_fontstretch( + s: Any, +) -> Literal[ + "ultra-condensed", + "extra-condensed", + "condensed", + "semi-condensed", + "normal", + "semi-expanded", + "expanded", + "extra-expanded", + "ultra-expanded", +] | int: ... +def validate_font_properties(s: Any) -> dict[str, Any]: ... +def validate_whiskers(s: Any) -> list[float] | float: ... +def validate_ps_distiller(s: Any) -> None | Literal["ghostscript", "xpdf"]: ... +def validate_fillstyle( + s: Any, +) -> Literal["full", "left", "right", "bottom", "top", "none"]: ... +def validate_fillstylelist( + s: Any, +) -> list[Literal["full", "left", "right", "bottom", "top", "none"]]: ... +def validate_markevery(s: Any) -> MarkEveryType: ... +def _validate_linestyle(s: Any) -> LineStyleType: ... +def validate_markeverylist(s: Any) -> list[MarkEveryType]: ... +def validate_bbox(s: Any) -> Literal["tight", "standard"] | None: ... +def validate_sketch(s: Any) -> None | tuple[float, float, float]: ... +def validate_hatch(s: Any) -> str: ... +def validate_hatchlist(s: Any): + list[str] + +def validate_dashlist(s: Any): + list[list[float]] + +# TODO: copy cycler overloads? +def cycler(*args, **kwargs) -> Cycler: ... +def validate_cycler(s: Any) -> Cycler: ... +def validate_hist_bins( + s: Any, +) -> Literal["auto", "sturges", "fd", "doane", "scott", "rice", "sqrt"] | int | list[ + float +]: ... diff --git a/lib/matplotlib/sankey.pyi b/lib/matplotlib/sankey.pyi new file mode 100644 index 000000000000..8f274bfe3adb --- /dev/null +++ b/lib/matplotlib/sankey.pyi @@ -0,0 +1,57 @@ +from matplotlib.axes import Axes +from matplotlib.patches import PathPatch +from matplotlib.path import Path +from matplotlib.transforms import Affine2D + +from typing import Any, Callable, Iterable + +import numpy as np + +RIGHT: int +UP: int +DOWN: int + +# TODO typing units +class Sankey: + diagrams: list[Any] + ax: Axes + unit: Any + format: str | Callable[[float], str] + scale: float + gap: float + radius: float + shoulder: float + offset: float + margin: float + pitch: float + tolerance: float + extent: np.ndarray + def __init__( + self, + ax: Axes | None = ..., + scale: float = ..., + unit: Any = ..., + format: str | Callable[[float], str] = ..., + gap: float = ..., + radius: float = ..., + shoulder: float = ..., + offset: float = ..., + head_angle: float = ..., + margin: float = ..., + tolerance: float = ..., + **kwargs + ) -> None: ... + def add( + self, + patchlabel: str = ..., + flows: Iterable[float] | None = ..., + orientations: Iterable[int] | None = ..., + labels: str | Iterable[str | None] = ..., + trunklength: float = ..., + pathlengths: float | Iterable[float] = ..., + prior: int | None = ..., + connect: tuple[int, int] = ..., + rotation: float = ..., + **kwargs + ): ... + def finish(self) -> list[Any]: ... diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index 534165cc72e5..01e09f11b444 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -710,11 +710,6 @@ def scale_factory(scale, axis, **kwargs): scale : {%(names)s} axis : `matplotlib.axis.Axis` """ - if scale != scale.lower(): - _api.warn_deprecated( - "3.5", message="Support for case-insensitive scales is deprecated " - "since %(since)s and support will be removed %(removal)s.") - scale = scale.lower() scale_cls = _api.check_getitem(_scale_mapping, scale=scale) return scale_cls(axis, **kwargs) diff --git a/lib/matplotlib/scale.pyi b/lib/matplotlib/scale.pyi new file mode 100644 index 000000000000..583a34d6443b --- /dev/null +++ b/lib/matplotlib/scale.pyi @@ -0,0 +1,193 @@ +from matplotlib.axis import Axis +from matplotlib.ticker import ( + AsinhLocator, + AutoLocator, + AutoMinorLocator, + LogFormatterSciNotation, + LogLocator, + LogitFormatter, + LogitLocator, + NullFormatter, + NullLocator, + ScalarFormatter, + SymmetricalLogLocator, +) +from matplotlib.transforms import IdentityTransform, Transform + +from typing import Callable, Literal, Iterable, Type +from numpy.typing import ArrayLike + +class ScaleBase: + def __init__(self, axis: Axis) -> None: ... + def get_transform(self) -> Transform: ... + def set_default_locators_and_formatters(self, axis: Axis) -> None: ... + def limit_range_for_scale( + self, vmin: float, vmax: float, minpos: float + ) -> tuple[float, float]: ... + +class LinearScale(ScaleBase): + name: str + +class FuncTransform(Transform): + input_dims: int + output_dims: int + def __init__( + self, + forward: Callable[[ArrayLike], ArrayLike], + inverse: Callable[[ArrayLike], ArrayLike], + ) -> None: ... + def transform_non_affine(self, values: ArrayLike) -> ArrayLike: ... + def inverted(self) -> FuncTransform: ... + +class FuncScale(ScaleBase): + name: str + def __init__( + self, + axis: Axis, + functions: tuple[ + Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike] + ], + ) -> None: ... + +class LogTransform(Transform): + input_dims: int + output_dims: int + base: float + def __init__( + self, base: float, nonpositive: Literal["clip", "mask"] = ... + ) -> None: ... + def transform_non_affine(self, a: ArrayLike) -> ArrayLike: ... + def inverted(self) -> InvertedLogTransform: ... + +class InvertedLogTransform(Transform): + input_dims: int + output_dims: int + base: float + def __init__(self, base: float) -> None: ... + def transform_non_affine(self, a: ArrayLike) -> ArrayLike: ... + def inverted(self) -> LogTransform: ... + +class LogScale(ScaleBase): + name: str + subs: Iterable[int] | None + def __init__( + self, + axis: Axis, + *, + base: float = ..., + subs: Iterable[int] | None = ..., + nonpositive: Literal["clip", "mask"] = ... + ) -> None: ... + @property + def base(self) -> float: ... + def get_transform(self) -> Transform: ... + +class FuncScaleLog(LogScale): + def __init__( + self, + axis: Axis, + functions: tuple[ + Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike] + ], + base: float = ..., + ) -> None: ... + @property + def base(self) -> float: ... + def get_transform(self) -> Transform: ... + +class SymmetricalLogTransform(Transform): + input_dims: int + output_dims: int + base: float + linthresh: float + linscale: float + def __init__(self, base: float, linthresh: float, linscale: float) -> None: ... + def inverted(self) -> InvertedSymmetricalLogTransform: ... + +class InvertedSymmetricalLogTransform(Transform): + input_dims: int + output_dims: int + base: float + linthresh: float + invlinthresh: float + linscale: float + def __init__(self, base: float, linthresh: float, linscale: float) -> None: ... + def inverted(self) -> SymmetricalLogTransform: ... + +class SymmetricalLogScale(ScaleBase): + name: str + subs: Iterable[int] | None + def __init__( + self, + axis: Axis, + *, + base: float = ..., + linthresh: float = ..., + subs: Iterable[int] | None = ..., + linscale: float = ... + ) -> None: ... + @property + def base(self) -> float: ... + @property + def linsthresh(self) -> float: ... + @property + def linscale(self) -> float: ... + def get_transform(self) -> SymmetricalLogTransform: ... + +class AsinhTransform(Transform): + input_dims: int + output_dims: int + linear_width: float + def __init__(self, linear_width: float) -> None: ... + def inverted(self) -> InvertedAsinhTransform: ... + +class InvertedAsinhTransform(Transform): + input_dims: int + output_dims: int + linear_width: float + def __init__(self, linear_width: float) -> None: ... + def inverted(self) -> AsinhTransform: ... + +class AsinhScale(ScaleBase): + name: str + auto_tick_multipliers: dict[int, tuple[int, ...]] + def __init__( + self, + axis: Axis, + *, + linear_width: float = ..., + base: float = ..., + subs: Iterable[int] | Literal["auto"] | None = ..., + **kwargs + ) -> None: ... + @property + def linear_width(self) -> float: ... + def get_transform(self) -> AsinhTransform: ... + +class LogitTransform(Transform): + input_dims: int + output_dims: int + def __init__(self, nonpositive: Literal["mask", "clip"] = ...) -> None: ... + def inverted(self) -> LogisticTransform: ... + +class LogisticTransform(Transform): + input_dims: int + output_dims: int + def __init__(self, nonpositive: Literal["mask", "clip"] = ...) -> None: ... + def inverted(self) -> LogitTransform: ... + +class LogitScale(ScaleBase): + name: str + def __init__( + self, + axis: Axis, + nonpositive: Literal["mask", "clip"] = ..., + *, + one_half: str = ..., + use_overline: bool = ... + ) -> None: ... + def get_transform(self) -> LogitTransform: ... + +def get_scale_names() -> list[str]: ... +def scale_factory(scale: str, axis: Axis, **kwargs): ... +def register_scale(scale_class: Type[ScaleBase]) -> None: ... diff --git a/lib/matplotlib/spines.pyi b/lib/matplotlib/spines.pyi new file mode 100644 index 000000000000..c56e29962f2c --- /dev/null +++ b/lib/matplotlib/spines.pyi @@ -0,0 +1,79 @@ +import matplotlib.patches as mpatches +from collections.abc import MutableMapping, Iterator +from matplotlib.artist import allow_rasterization +from matplotlib.axes import Axes +from matplotlib.axis import Axis +from matplotlib.colors import Color +from matplotlib.path import Path +from matplotlib.transforms import Transform + +from typing import Literal, TypeVar, Type + +class Spine(mpatches.Patch): + axes: Axes + spine_type: str + axis: Path + def __init__(self, axes: Axes, spine_type: str, path: Path, **kwargs) -> None: ... + def set_patch_arc( + self, center: tuple[float, float], radius: float, theta1: float, theta2: float + ) -> None: ... + def set_patch_circle(self, center: tuple[float, float], radius: float) -> None: ... + def set_patch_line(self) -> None: ... + def get_patch_transform(self) -> Transform: ... + def get_path(self) -> Path: ... + def register_axis(self, axis: Axis) -> None: ... + def clear(self) -> None: ... + def set_position( + self, + position: Literal["center", "zero"] + | tuple[Literal["outward", "axes", "data"], float], + ) -> None: ... + def get_position( + self, + ) -> Literal["center", "zero"] | tuple[ + Literal["outward", "axes", "data"], float + ]: ... + def get_spine_transform(self) -> Transform: ... + def set_bounds(self, low: float | None = ..., high: float | None = ...) -> None: ... + def get_bounds(self) -> tuple[float, float]: ... + + T = TypeVar("T", bound=Spine) + @classmethod + def linear_spine( + cls: Type[T], + axes: Axes, + spine_type: Literal["left", "right", "bottom", "top"], + **kwargs + ) -> T: ... + @classmethod + def arc_spine( + cls: Type[T], + axes: Axes, + spine_type: Literal["left", "right", "bottom", "top"], + center: tuple[float, float], + radius: float, + theta1: float, + theta2: float, + **kwargs + ) -> T: ... + @classmethod + def circular_spine( + cls: Type[T], axes: Axes, center: tuple[float, float], radius: float, **kwargs + ) -> T: ... + def set_color(self, c: Color | None) -> None: ... + +class SpinesProxy: + def __init__(self, spine_dict: dict[str, Spine]) -> None: ... + def __getattr__(self, name: str): ... + def __dir__(self) -> list[str]: ... + +class Spines(MutableMapping[str, Spine]): + def __init__(self, **kwargs: Spine) -> None: ... + @classmethod + def from_dict(cls, d: dict[str, Spine]) -> Spines: ... + def __getattr__(self, name: str) -> Spine: ... + def __getitem__(self, key: str) -> Spine: ... + def __setitem__(self, key: str, value: Spine) -> None: ... + def __delitem__(self, key: str) -> None: ... + def __iter__(self) -> Iterator[str]: ... + def __len__(self) -> int: ... diff --git a/lib/matplotlib/stackplot.pyi b/lib/matplotlib/stackplot.pyi new file mode 100644 index 000000000000..4163ac0c7438 --- /dev/null +++ b/lib/matplotlib/stackplot.pyi @@ -0,0 +1,16 @@ +from matplotlib.axes import Axes +from matplotlib.collections import PolyCollection +from matplotlib.colors import Color + +from typing import Iterable, Literal +from numpy.typing import ArrayLike + +def stackplot( + axes: Axes, + x: ArrayLike, + *args: ArrayLike, + labels: Iterable[str] = ..., + colors: Iterable[Color] | None = ..., + baseline: Literal["zero", "sym", "wiggle", "weighted_wiggle"] = ..., + **kwargs +) -> list[PolyCollection]: ... diff --git a/lib/matplotlib/streamplot.pyi b/lib/matplotlib/streamplot.pyi new file mode 100644 index 000000000000..de55c0766571 --- /dev/null +++ b/lib/matplotlib/streamplot.pyi @@ -0,0 +1,82 @@ +from matplotlib.axes import Axes +from matplotlib.colors import Color, Normalize, Colormap +from matplotlib.collections import LineCollection, PatchCollection +from matplotlib.patches import ArrowStyle +from matplotlib.transforms import Transform + +from typing import Literal + +from numpy.typing import ArrayLike + +def streamplot( + axes: Axes, + x: ArrayLike, + y: ArrayLike, + u: ArrayLike, + v: ArrayLike, + density: float | tuple[float, float] = ..., + linewidth: float | ArrayLike | None = ..., + color: Color | ArrayLike | None = ..., + cmap: str | Colormap | None = ..., + norm: str | Normalize | None = ..., + arrowsize: float = ..., + arrowstyle: str | ArrowStyle = ..., + minlength: float = ..., + transform: Transform | None = ..., + zorder: float | None = ..., + start_points: ArrayLike | None = ..., + maxlength: float = ..., + integration_direction: Literal["forward", "backward", "both"] = ..., + broken_streamlines: bool = ..., +) -> StreamplotSet: ... + +class StreamplotSet: + lines: LineCollection + arrows: PatchCollection + def __init__(self, lines: LineCollection, arrows: PatchCollection) -> None: ... + +class DomainMap: + grid: Grid + mask: StreamMask + x_grid2mask: float + y_grid2mask: float + x_mask2grid: float + y_mask2grid: float + x_data2grid: float + y_data2grid: float + def __init__(self, grid: Grid, mask: StreamMask) -> None: ... + def grid2mask(self, xi: float, yi: float) -> tuple[int, int]: ... + def mask2grid(self, xm: float, ym: float) -> tuple[float, float]: ... + def data2grid(self, xd: float, yd: float) -> tuple[float, float]: ... + def grid2data(self, xg: float, yg: float) -> tuple[float, float]: ... + def start_trajectory( + self, xg: float, yg: float, broken_streamlines: bool = ... + ) -> None: ... + def reset_start_point(self, xg: float, yg: float) -> None: ... + def update_trajectory(self, xg, yg, broken_streamlines: bool = ...) -> None: ... + def undo_trajectory(self) -> None: ... + +class Grid: + nx: int + ny: int + dx: float + dy: float + x_origin: float + y_origin: float + width: float + height: float + def __init__(self, x: ArrayLike, y: ArrayLike) -> None: ... + @property + def shape(self) -> tuple[int, int]: ... + def within_grid(self, xi: float, yi: float) -> bool: ... + +class StreamMask: + nx: int + ny: int + shape: tuple[int, int] + def __init__(self, density: float | tuple[float, float]) -> None: ... + def __getitem__(self, args): ... + +class InvalidIndexError(Exception): ... +class TerminateTrajectory(Exception): ... +class OutOfBounds(IndexError): ... diff --git a/lib/matplotlib/style/core.pyi b/lib/matplotlib/style/core.pyi new file mode 100644 index 000000000000..31f575eb717b --- /dev/null +++ b/lib/matplotlib/style/core.pyi @@ -0,0 +1,24 @@ +from collections.abc import Generator +from typing import Any +from pathlib import Path +import contextlib + +from matplotlib import RcParams + +StyleType = str | dict[str, Any] | Path | list[str | Path | dict[str, Any]] + +USER_LIBRARY_PATHS: list[str] = ... +STYLE_EXTENSION: str = ... + +def use(style: StyleType) -> None: ... +@contextlib.contextmanager +def context( + style: StyleType, after_reset: bool = ... +) -> Generator[None, None, None]: ... + +class _StyleLibrary(dict[str, RcParams]): ... + +library: _StyleLibrary +available: list[str] + +def reload_library() -> None: ... diff --git a/lib/matplotlib/table.pyi b/lib/matplotlib/table.pyi new file mode 100644 index 000000000000..81033064f201 --- /dev/null +++ b/lib/matplotlib/table.pyi @@ -0,0 +1,84 @@ +from .artist import Artist, allow_rasterization +from .axes import Axes +from .backend_bases import RendererBase +from .colors import Color +from .patches import Rectangle +from .path import Path +from .text import Text +from .transforms import Bbox + +from typing import Any, Literal, Sequence + +class Cell(Rectangle): + PAD: float + def __init__( + self, + xy: tuple[float, float], + width: float, + height: float, + edgecolor: Color = ..., + facecolor: Color = ..., + fill: bool = ..., + text: str = ..., + loc: Literal["left", "center", "right"] | None = ..., + fontproperties: dict[str, Any] | None = ..., + *, + visible_edges: str = ... + ) -> None: ... + def get_text(self) -> Text: ... + def set_fontsize(self, size: float) -> None: ... + def get_fontsize(self) -> float: ... + def auto_set_font_size(self, renderer: RendererBase) -> float: ... + def get_text_bounds( + self, renderer: RendererBase + ) -> tuple[float, float, float, float]: ... + def get_required_width(self, renderer: RendererBase) -> float: ... + def set_text_props(self, **kwargs) -> None: ... + @property + def visible_edges(self) -> str: ... + @visible_edges.setter + def visible_edges(self, value: str) -> None: ... + def get_path(self) -> Path: ... + +CustomCell = Cell + +class Table(Artist): + codes: dict[str, int] + FONTSIZE: float + AXESPAD: float + def __init__( + self, ax: Axes, loc: str | None = ..., bbox: Bbox | None = ..., **kwargs + ) -> None: ... + def add_cell(self, row: int, col: int, *args, **kwargs) -> Cell: ... + def __setitem__(self, position: tuple[int, int], cell: Cell) -> None: ... + def __getitem__(self, position: tuple[int, int]): ... + @property + def edges(self) -> str | None: ... + @edges.setter + def edges(self, value: str | None) -> None: ... + def draw(self, renderer) -> None: ... + def get_children(self) -> list[Artist]: ... + def get_window_extent(self, renderer: RendererBase | None = ...): ... + def auto_set_column_width(self, col: int | Sequence[int]) -> None: ... + def auto_set_font_size(self, value: bool = ...) -> None: ... + def scale(self, xscale: float, yscale: float) -> None: ... + def set_fontsize(self, size: float) -> None: ... + def get_celld(self) -> dict[tuple[int, int], Cell]: ... + +def table( + ax: Axes, + cellText: Sequence[Sequence[str]] | None = ..., + cellColours: Sequence[Sequence[Color]] | None = ..., + cellLoc: Literal["left", "center", "right"] = ..., + colWidths: Sequence[float] | None = ..., + rowLabels: Sequence[str] | None = ..., + rowColours: Sequence[Color] | None = ..., + rowLoc: Literal["left", "center", "right"] = ..., + colLabels: Sequence[str] | None = ..., + colColours: Sequence[Color] | None = ..., + colLoc: Literal["left", "center", "right"] = ..., + loc: str = ..., + bbox: Bbox | None = ..., + edges: str = ..., + **kwargs +) -> Table: ... diff --git a/lib/matplotlib/testing/conftest.py b/lib/matplotlib/testing/conftest.py index 21f6c707ecf8..41ed522b72d9 100644 --- a/lib/matplotlib/testing/conftest.py +++ b/lib/matplotlib/testing/conftest.py @@ -1,7 +1,7 @@ import pytest import sys import matplotlib -from matplotlib import _api, cbook +from matplotlib import _api def pytest_configure(config): @@ -13,8 +13,6 @@ def pytest_configure(config): ("markers", "flaky: (Provided by pytest-rerunfailures.)"), ("markers", "timeout: (Provided by pytest-timeout.)"), ("markers", "backend: Set alternate Matplotlib backend temporarily."), - ("markers", - "style: Set alternate Matplotlib style temporarily (deprecated)."), ("markers", "baseline_images: Compare output against references."), ("markers", "pytz: Tests that require pytz to be installed."), ("filterwarnings", "error"), @@ -56,16 +54,6 @@ def mpl_test_settings(request): if any(sys.modules.get(k) for k in ('PyQt4', 'PySide')): pytest.skip('Qt4 binding already imported') - # Default of cleanup and image_comparison too. - style = ["classic", "_classic_test_patch"] - style_marker = request.node.get_closest_marker('style') - if style_marker is not None: - assert len(style_marker.args) == 1, \ - "Marker 'style' must specify 1 style." - _api.warn_deprecated("3.5", name="style", obj_type="pytest marker", - alternative="@mpl.style.context(...)") - style, = style_marker.args - matplotlib.testing.setup() with _api.suppress_matplotlib_deprecation_warning(): if backend is not None: @@ -82,36 +70,14 @@ def mpl_test_settings(request): .format(backend, exc)) else: raise - matplotlib.style.use(style) + # Default of cleanup and image_comparison too. + matplotlib.style.use(["classic", "_classic_test_patch"]) try: yield finally: matplotlib.use(prev_backend) -@pytest.fixture -@_api.deprecated("3.5", alternative="none") -def mpl_image_comparison_parameters(request, extension): - # This fixture is applied automatically by the image_comparison decorator. - # - # The sole purpose of this fixture is to provide an indirect method of - # obtaining parameters *without* modifying the decorated function - # signature. In this way, the function signature can stay the same and - # pytest won't get confused. - # We annotate the decorated function with any parameters captured by this - # fixture so that they can be used by the wrapper in image_comparison. - baseline_images, = request.node.get_closest_marker('baseline_images').args - if baseline_images is None: - # Allow baseline image list to be produced on the fly based on current - # parametrization. - baseline_images = request.getfixturevalue('baseline_images') - - func = request.function - with cbook._setattr_cm(func.__wrapped__, - parameters=(baseline_images, extension)): - yield - - @pytest.fixture def pd(): """Fixture to import and configure pandas.""" diff --git a/lib/matplotlib/tests/baseline_images/test_polar/polar_log.png b/lib/matplotlib/tests/baseline_images/test_polar/polar_log.png new file mode 100644 index 000000000000..ab8e20b482a5 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_polar/polar_log.png differ diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 642316e4c000..c276e661960e 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -34,7 +34,7 @@ import matplotlib.text as mtext import matplotlib.ticker as mticker import matplotlib.transforms as mtransforms -import mpl_toolkits.axisartist as AA +import mpl_toolkits.axisartist as AA # type: ignore from numpy.testing import ( assert_allclose, assert_array_equal, assert_array_almost_equal) from matplotlib.testing.decorators import ( @@ -8115,19 +8115,13 @@ def test_artist_sublists(): with pytest.raises(IndexError, match='out of range'): ax.lines[len(lines) + 1] - # Deleting items (multiple or single) should warn. - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - del ax.lines[-1] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - del ax.lines[-1:] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - del ax.lines[1:] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - del ax.lines[0] + # Adding to other lists should produce a regular list. + assert ax.lines + [1, 2, 3] == [*lines, 1, 2, 3] + assert [1, 2, 3] + ax.lines == [1, 2, 3, *lines] + + # Adding to other tuples should produce a regular tuples. + assert ax.lines + (1, 2, 3) == (*lines, 1, 2, 3) + assert (1, 2, 3) + ax.lines == (1, 2, 3, *lines) # Lists should be empty after removing items. col.remove() @@ -8136,59 +8130,10 @@ def test_artist_sublists(): assert not ax.images patch.remove() assert not ax.patches + assert not ax.tables text.remove() assert not ax.texts - # Everything else should remain empty. - assert not ax.lines - assert not ax.tables - - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.texts property'): - ax.texts.append(text) - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.collections property'): - ax.collections.append(col) - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.images property'): - ax.images.append(im) - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.patches property'): - ax.patches.append(patch) - # verify things are back - assert list(ax.collections) == [col] - assert list(ax.images) == [im] - assert list(ax.patches) == [patch] - assert list(ax.texts) == [text] - - # Adding items should warn. - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines.append(lines[-2]) - assert list(ax.lines) == [lines[-2]] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines.append(lines[-1]) - assert list(ax.lines) == lines[-2:] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines.insert(-2, lines[0]) - assert list(ax.lines) == [lines[0], lines[-2], lines[-1]] - - # Modifying items should warn. - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines[0] = lines[0] - assert list(ax.lines) == [lines[0], lines[-2], lines[-1]] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines[1:1] = lines[1:-2] - assert list(ax.lines) == lines - - # Adding to other lists should produce a regular list. - assert ax.lines + [1, 2, 3] == [*lines, 1, 2, 3] - assert [1, 2, 3] + ax.lines == [1, 2, 3, *lines] - for ln in ax.lines: ln.remove() assert len(ax.lines) == 0 diff --git a/lib/matplotlib/tests/test_backend_gtk3.py b/lib/matplotlib/tests/test_backend_gtk3.py index 937ddef5a13f..6a95f47e1ddd 100644 --- a/lib/matplotlib/tests/test_backend_gtk3.py +++ b/lib/matplotlib/tests/test_backend_gtk3.py @@ -10,7 +10,7 @@ def test_correct_key(): pytest.xfail("test_widget_send_event is not triggering key_press_event") - from gi.repository import Gdk, Gtk + from gi.repository import Gdk, Gtk # type: ignore fig = plt.figure() buf = [] diff --git a/lib/matplotlib/tests/test_backend_qt.py b/lib/matplotlib/tests/test_backend_qt.py index f79546323c47..6610b9e2d9b7 100644 --- a/lib/matplotlib/tests/test_backend_qt.py +++ b/lib/matplotlib/tests/test_backend_qt.py @@ -18,7 +18,7 @@ try: - from matplotlib.backends.qt_compat import QtGui, QtWidgets # noqa + from matplotlib.backends.qt_compat import QtGui, QtWidgets # type: ignore # noqa from matplotlib.backends.qt_editor import _formlayout except ImportError: pytestmark = pytest.mark.skip('No usable Qt bindings') diff --git a/lib/matplotlib/tests/test_backends_interactive.py b/lib/matplotlib/tests/test_backends_interactive.py index f0d19842e439..476ee05856b0 100644 --- a/lib/matplotlib/tests/test_backends_interactive.py +++ b/lib/matplotlib/tests/test_backends_interactive.py @@ -47,7 +47,7 @@ def _get_testable_interactive_backends(): elif env["MPLBACKEND"] == 'macosx' and os.environ.get('TF_BUILD'): reason = "macosx backend fails on Azure" elif env["MPLBACKEND"].startswith('gtk'): - import gi + import gi # type: ignore version = env["MPLBACKEND"][3] repo = gi.Repository.get_default() if f'{version}.0' not in repo.enumerate_versions('Gtk'): diff --git a/lib/matplotlib/tests/test_basic.py b/lib/matplotlib/tests/test_basic.py index f9f17098871a..6fad2bacaf3f 100644 --- a/lib/matplotlib/tests/test_basic.py +++ b/lib/matplotlib/tests/test_basic.py @@ -10,7 +10,7 @@ def test_simple(): def test_override_builtins(): - import pylab + import pylab # type: ignore ok_to_override = { '__name__', '__doc__', diff --git a/lib/matplotlib/tests/test_category.py b/lib/matplotlib/tests/test_category.py index 6eb590d6e82d..87dece6346f7 100644 --- a/lib/matplotlib/tests/test_category.py +++ b/lib/matplotlib/tests/test_category.py @@ -3,7 +3,6 @@ import numpy as np import matplotlib as mpl -from matplotlib._api import MatplotlibDeprecationWarning from matplotlib.axes import Axes import matplotlib.pyplot as plt import matplotlib.category as cat @@ -101,17 +100,6 @@ def test_convert(self, vals): def test_convert_one_string(self, value): assert self.cc.convert(value, self.unit, self.ax) == 0 - def test_convert_one_number(self): - with pytest.warns(MatplotlibDeprecationWarning): - actual = self.cc.convert(0.0, self.unit, self.ax) - np.testing.assert_allclose(actual, np.array([0.])) - - def test_convert_float_array(self): - data = np.array([1, 2, 3], dtype=float) - with pytest.warns(MatplotlibDeprecationWarning): - actual = self.cc.convert(data, self.unit, self.ax) - np.testing.assert_allclose(actual, np.array([1., 2., 3.])) - @pytest.mark.parametrize("fvals", fvalues, ids=fids) def test_convert_fail(self, fvals): with pytest.raises(TypeError): diff --git a/lib/matplotlib/tests/test_cbook.py b/lib/matplotlib/tests/test_cbook.py index aa5c999b7079..289825e34002 100644 --- a/lib/matplotlib/tests/test_cbook.py +++ b/lib/matplotlib/tests/test_cbook.py @@ -1,6 +1,9 @@ +from __future__ import annotations + import itertools import pickle +from typing import Any from weakref import ref from unittest.mock import patch, Mock @@ -441,12 +444,12 @@ def test_sanitize_sequence(): assert k == cbook.sanitize_sequence(k) -fail_mapping = ( +fail_mapping: tuple[tuple[dict, dict], ...] = ( ({'a': 1, 'b': 2}, {'alias_mapping': {'a': ['b']}}), ({'a': 1, 'b': 2}, {'alias_mapping': {'a': ['a', 'b']}}), ) -pass_mapping = ( +pass_mapping: tuple[tuple[Any, dict, dict], ...] = ( (None, {}, {}), ({'a': 1, 'b': 2}, {'a': 1, 'b': 2}, {}), ({'b': 2}, {'a': 2}, {'alias_mapping': {'a': ['a', 'b']}}), diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py index ac1faa3c1cdc..fb8209f23fcb 100644 --- a/lib/matplotlib/tests/test_collections.py +++ b/lib/matplotlib/tests/test_collections.py @@ -394,7 +394,7 @@ def test_EllipseCollection(): @image_comparison(['polycollection_close.png'], remove_text=True) def test_polycollection_close(): - from mpl_toolkits.mplot3d import Axes3D + from mpl_toolkits.mplot3d import Axes3D # type: ignore vertsQuad = [ [[0., 0.], [0., 1.], [1., 1.], [1., 0.]], diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index ff893e71acdb..d75aa178e2a0 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -10,13 +10,14 @@ from numpy.testing import assert_array_equal, assert_array_almost_equal -from matplotlib import cbook, cm, cycler +from matplotlib import cbook, cm import matplotlib import matplotlib as mpl import matplotlib.colors as mcolors import matplotlib.colorbar as mcolorbar import matplotlib.pyplot as plt import matplotlib.scale as mscale +from matplotlib.rcsetup import cycler from matplotlib.testing.decorators import image_comparison, check_figures_equal @@ -1330,7 +1331,7 @@ def test_ndarray_subclass_norm(): # which objects when adding or subtracting with other # arrays. See #6622 and #8696 class MyArray(np.ndarray): - def __isub__(self, other): + def __isub__(self, other): # type: ignore raise RuntimeError def __add__(self, other): diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index 3da06a7d27d0..18f108c5f995 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -2,7 +2,7 @@ import platform import re -import contourpy +import contourpy # type: ignore import numpy as np from numpy.testing import ( assert_array_almost_equal, assert_array_almost_equal_nulp) @@ -62,15 +62,16 @@ def test_contour_shape_error(args, message): ax.contour(*args) -def test_contour_empty_levels(): - - x = np.arange(9) - z = np.random.random((9, 9)) - +def test_contour_no_valid_levels(): fig, ax = plt.subplots() - with pytest.warns(UserWarning) as record: - ax.contour(x, x, z, levels=[]) - assert len(record) == 1 + # no warning for empty levels. + ax.contour(np.random.rand(9, 9), levels=[]) + # no warning if levels is given and is not within the range of z. + cs = ax.contour(np.arange(81).reshape((9, 9)), levels=[100]) + # ... and if fmt is given. + ax.clabel(cs, fmt={100: '%1.2f'}) + # no warning if z is uniform. + ax.contour(np.ones((9, 9))) def test_contour_Nlevels(): @@ -84,33 +85,6 @@ def test_contour_Nlevels(): assert (cs1.levels == cs2.levels).all() -def test_contour_badlevel_fmt(): - # Test edge case from https://github.com/matplotlib/matplotlib/issues/9742 - # User supplied fmt for each level as a dictionary, but Matplotlib changed - # the level to the minimum data value because no contours possible. - # This was fixed in https://github.com/matplotlib/matplotlib/pull/9743 - x = np.arange(9) - z = np.zeros((9, 9)) - - fig, ax = plt.subplots() - fmt = {1.: '%1.2f'} - with pytest.warns(UserWarning) as record: - cs = ax.contour(x, x, z, levels=[1.]) - ax.clabel(cs, fmt=fmt) - assert len(record) == 1 - - -def test_contour_uniform_z(): - - x = np.arange(9) - z = np.ones((9, 9)) - - fig, ax = plt.subplots() - with pytest.warns(UserWarning) as record: - ax.contour(x, x, z) - assert len(record) == 1 - - @image_comparison(['contour_manual_labels'], remove_text=True, style='mpl20') def test_contour_manual_labels(): x, y = np.meshgrid(np.arange(0, 10), np.arange(0, 10)) diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 065e0f728536..f3ece07660e3 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -532,6 +532,13 @@ def test_savefig_pixel_ratio(backend): assert ratio1 == ratio2 +def test_savefig_preserve_layout_engine(tmp_path): + fig = plt.figure(layout='compressed') + fig.savefig(tmp_path / 'foo.png', bbox_inches='tight') + + assert fig.get_layout_engine()._compress + + def test_figure_repr(): fig = plt.figure(figsize=(10, 20), dpi=10) assert repr(fig) == "
" diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index 3724db1e1b43..afed8f8b0da5 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -14,9 +14,10 @@ from matplotlib.font_manager import ( findfont, findSystemFonts, FontEntry, FontProperties, fontManager, json_dump, json_load, get_font, is_opentype_cff_font, - MSUserFontDirectories, _get_fontconfig_fonts, ft2font, - ttfFontProperty, cbook) + MSUserFontDirectories, _get_fontconfig_fonts, ttfFontProperty) from matplotlib import pyplot as plt, rc_context +from matplotlib import cbook +from matplotlib import ft2font has_fclist = shutil.which('fc-list') is not None diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index a8d7fd107d8b..297fa70c0836 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -409,7 +409,7 @@ def test_warn_mixed_args_and_kwargs(self): "be discarded.") def test_parasite(self): - from mpl_toolkits.axes_grid1 import host_subplot + from mpl_toolkits.axes_grid1 import host_subplot # type: ignore host = host_subplot(111) par = host.twinx() diff --git a/lib/matplotlib/tests/test_mathtext.py b/lib/matplotlib/tests/test_mathtext.py index 2ee3e914d5f6..1603fa3f33f3 100644 --- a/lib/matplotlib/tests/test_mathtext.py +++ b/lib/matplotlib/tests/test_mathtext.py @@ -1,9 +1,12 @@ +from __future__ import annotations + import io from pathlib import Path import platform import re import shlex from xml.etree import ElementTree as ET +from typing import Any import numpy as np import pytest @@ -146,7 +149,7 @@ # stub should be of the form (None, N) where N is the number of strings that # used to be tested # Add new tests at the end. -font_test_specs = [ +font_test_specs: list[tuple[None | list[str], Any]] = [ ([], all), (['mathrm'], all), (['mathbf'], all), @@ -170,10 +173,10 @@ (['mathbf', 'mathsf'], [digits, uppercase, lowercase]) ] -font_tests = [] +font_tests: list[None | str] = [] for fonts, chars in font_test_specs: if fonts is None: - font_tests.extend([None] * chars) + font_tests.extend([None] * chars) # type: ignore else: wrapper = ''.join([ ' '.join(fonts), diff --git a/lib/matplotlib/tests/test_offsetbox.py b/lib/matplotlib/tests/test_offsetbox.py index a0116d5dfcd9..80026298326f 100644 --- a/lib/matplotlib/tests/test_offsetbox.py +++ b/lib/matplotlib/tests/test_offsetbox.py @@ -136,7 +136,7 @@ def test_get_packed_offsets(widths, total, sep, mode): _get_packed_offsets(widths, total, sep, mode=mode) -_Params = namedtuple('_params', 'wd_list, total, sep, expected') +_Params = namedtuple('_Params', 'wd_list, total, sep, expected') @pytest.mark.parametrize('widths, total, sep, expected', [ diff --git a/lib/matplotlib/tests/test_pickle.py b/lib/matplotlib/tests/test_pickle.py index ec6bdcc2fe14..2a9c1969db45 100644 --- a/lib/matplotlib/tests/test_pickle.py +++ b/lib/matplotlib/tests/test_pickle.py @@ -14,7 +14,7 @@ import matplotlib.pyplot as plt import matplotlib.transforms as mtransforms import matplotlib.figure as mfigure -from mpl_toolkits.axes_grid1 import parasite_axes +from mpl_toolkits.axes_grid1 import parasite_axes # type: ignore def test_simple(): diff --git a/lib/matplotlib/tests/test_polar.py b/lib/matplotlib/tests/test_polar.py index 1bde5bcc1142..1f8e6a75baca 100644 --- a/lib/matplotlib/tests/test_polar.py +++ b/lib/matplotlib/tests/test_polar.py @@ -434,3 +434,15 @@ def test_cursor_precision(): assert ax.format_coord(2, 0) == "θ=0.6π (115°), r=0.000" assert ax.format_coord(2, .1) == "θ=0.64π (115°), r=0.100" assert ax.format_coord(2, 1) == "θ=0.637π (114.6°), r=1.000" + + +@image_comparison(['polar_log.png'], style='default') +def test_polar_log(): + fig = plt.figure() + ax = fig.add_subplot(polar=True) + + ax.set_rscale('log') + ax.set_rlim(1, 1000) + + n = 100 + ax.plot(np.linspace(0, 2 * np.pi, n), np.logspace(0, 2, n)) diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index 8a7c1028574b..c17e88aee1ac 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -230,8 +230,6 @@ def generate_validator_testcases(valid): ), 'fail': ((set(), ValueError), (1, ValueError), - ((1, 2), _api.MatplotlibDeprecationWarning), - (np.array([1, 2]), _api.MatplotlibDeprecationWarning), ) }, {'validator': _listify_validator(validate_int, n=2), diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index c01e1ef171bf..4c4f2fdc240f 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -1,4 +1,3 @@ -from contextlib import nullcontext import functools from unittest import mock @@ -24,22 +23,16 @@ def ax(): return get_ax() -@pytest.mark.parametrize('kwargs, warning_msg', [ - (dict(), None), - (dict(drawtype='line', useblit=False), - "Support for drawtype='line' is deprecated"), - (dict(useblit=True, button=1), None), - (dict(drawtype='none', minspanx=10, minspany=10), - "Support for drawtype='none' is deprecated"), - (dict(minspanx=10, minspany=10, spancoords='pixels'), None), - (dict(props=dict(fill=True)), None), +@pytest.mark.parametrize('kwargs', [ + dict(), + dict(useblit=True, button=1), + dict(minspanx=10, minspany=10, spancoords='pixels'), + dict(props=dict(fill=True)), ]) -def test_rectangle_selector(ax, kwargs, warning_msg): +def test_rectangle_selector(ax, kwargs): onselect = mock.Mock(spec=noop, return_value=None) - with (pytest.warns(MatplotlibDeprecationWarning, match=warning_msg) - if warning_msg else nullcontext()): - tool = widgets.RectangleSelector(ax, onselect, **kwargs) + tool = widgets.RectangleSelector(ax, onselect, **kwargs) do_event(tool, 'press', xdata=100, ydata=100, button=1) do_event(tool, 'onmove', xdata=199, ydata=199, button=1) @@ -1006,11 +999,13 @@ def test_check_radio_buttons_image(): rax1 = plt.axes([0.05, 0.7, 0.15, 0.15]) rax2 = plt.axes([0.05, 0.2, 0.15, 0.15]) rb = widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3')) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, + match='The circles attribute was deprecated'): rb.circles # Trigger the old-style elliptic radiobuttons. cb = widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'), (False, True, True)) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, + match='The rectangles attribute was deprecated'): cb.rectangles # Trigger old-style Rectangle check boxes @@ -1041,7 +1036,8 @@ def test_check_buttons_rectangles(fig_test, fig_ref): # Test should be removed once .rectangles is removed cb = widgets.CheckButtons(fig_test.subplots(), ["", ""], [False, False]) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, + match='The rectangles attribute was deprecated'): cb.rectangles ax = fig_ref.add_subplot(xticks=[], yticks=[]) ys = [2/3, 1/3] @@ -1063,7 +1059,8 @@ def test_check_buttons_rectangles(fig_test, fig_ref): def test_check_buttons_lines(fig_test, fig_ref): # Test should be removed once .lines is removed cb = widgets.CheckButtons(fig_test.subplots(), ["", ""], [True, True]) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, + match='The lines attribute was deprecated'): cb.lines for rectangle in cb._rectangles: rectangle.set_visible(False) diff --git a/lib/matplotlib/texmanager.pyi b/lib/matplotlib/texmanager.pyi new file mode 100644 index 000000000000..1d829e7e20e7 --- /dev/null +++ b/lib/matplotlib/texmanager.pyi @@ -0,0 +1,39 @@ +from .backend_bases import RendererBase + +from matplotlib import cbook, dviread +from matplotlib.colors import Color + +import numpy as np + +class TexManager: + texcache: str + @classmethod + def get_basefile( + cls, tex: str, fontsize: float, dpi: float | None = ... + ) -> str: ... + @classmethod + def get_font_preamble(cls) -> str: ... + @classmethod + def get_custom_preamble(cls) -> str: ... + @classmethod + def make_tex(cls, tex: str, fontsize: float) -> str: ... + @classmethod + def make_dvi(cls, tex: str, fontsize: float) -> str: ... + @classmethod + def make_png(cls, tex: str, fontsize: float, dpi: float) -> str: ... + @classmethod + def get_grey( + cls, tex: str, fontsize: float | None = ..., dpi: float | None = ... + ) -> np.ndarray: ... + @classmethod + def get_rgba( + cls, + tex: str, + fontsize: float | None = ..., + dpi: float | None = ..., + rgb: Color = ..., + ) -> np.ndarray: ... + @classmethod + def get_text_width_height_descent( + cls, tex: str, fontsize, renderer: RendererBase | None = ... + ) -> tuple[int, int, int]: ... diff --git a/lib/matplotlib/text.pyi b/lib/matplotlib/text.pyi new file mode 100644 index 000000000000..28aa7bd260c9 --- /dev/null +++ b/lib/matplotlib/text.pyi @@ -0,0 +1,206 @@ +from . import artist, cbook +from .artist import Artist +from .backend_bases import RendererBase +from .colors import Color +from .font_manager import FontProperties +from .offsetbox import DraggableAnnotation +from .path import Path +from .patches import FancyArrowPatch, FancyBboxPatch, Rectangle +from .textpath import TextPath +from .transforms import ( + Affine2D, + Bbox, + BboxBase, + BboxTransformTo, + IdentityTransform, + Transform, +) + +from typing import Any, Callable, Iterable, Literal + +class Text(Artist): + zorder: float + def __init__( + self, + x: float = ..., + y: float = ..., + text: Any = ..., + color: Color | None = ..., + verticalalignment: Literal[ + "bottom", "baseline", "center", "center_baseline", "top" + ] = ..., + horizontalalignment: Literal["left", "center", "right"] = ..., + multialignment: Literal["left", "center", "right"] | None = ..., + fontproperties: str | Path | FontProperties | None = ..., + rotation: float | Literal["vertical", "horizontal"] | None = ..., + linespacing: float | None = ..., + rotation_mode: Literal["default", "anchor"] | None = ..., + usetex: bool | None = ..., + wrap: bool = ..., + transform_rotates_text: bool = ..., + *, + parse_math: bool | None = ..., + **kwargs + ) -> None: ... + def update(self, kwargs: dict[str, Any]) -> None: ... + def get_rotation(self) -> float: ... + def get_transform_rotates_text(self) -> bool: ... + def set_rotation_mode(self, m: None | Literal["default", "anchor"]) -> None: ... + def get_rotation_mode(self) -> None | Literal["default", "anchor"]: ... + def set_bbox(self, rectprops: dict[str, Any]) -> None: ... + def get_bbox_patch(self) -> None | FancyBboxPatch: ... + def update_bbox_position_size(self, renderer: RendererBase) -> None: ... + def get_wrap(self) -> bool: ... + def set_wrap(self, wrap: bool) -> None: ... + def get_color(self) -> Color: ... + def get_fontproperties(self) -> FontProperties: ... + def get_fontfamily(self) -> list[str]: ... + def get_fontname(self) -> str: ... + def get_fontstyle(self) -> Literal["normal", "italic", "oblique"]: ... + def get_fontsize(self) -> float | str: ... + def get_fontvariant(self) -> Literal["normal", "small-caps"]: ... + def get_fontweight(self) -> int | str: ... + def get_stretch(self) -> int | str: ... + def get_horizontalalignment(self) -> Literal["left", "center", "right"]: ... + def get_unitless_position(self) -> tuple[float, float]: ... + def get_position(self) -> tuple[float, float]: ... + def get_text(self) -> str: ... + def get_verticalalignment( + self, + ) -> Literal["bottom", "baseline", "center", "center_baseline", "top"]: ... + def set_backgroundcolor(self, color: Color) -> None: ... + def set_color(self, color: Color) -> None: ... + def set_horizontalalignment( + self, align: Literal["left", "center", "right"] + ) -> None: ... + def set_multialignment(self, align: Literal["left", "center", "right"]) -> None: ... + def set_linespacing(self, spacing: float) -> None: ... + def set_fontfamily(self, fontname: str | Iterable[str]) -> None: ... + def set_fontvariant(self, variant: Literal["normal", "small-caps"]) -> None: ... + def set_fontstyle( + self, fontstyle: Literal["normal", "italic", "oblique"] + ) -> None: ... + def set_fontsize(self, fontsize: float | str) -> None: ... + def get_math_fontfamily(self) -> str: ... + def set_math_fontfamily(self, fontfamily: str) -> None: ... + def set_fontweight(self, weight: int | str) -> None: ... + def set_fontstretch(self, stretch: int | str) -> None: ... + def set_position(self, xy: tuple[float, float]) -> None: ... + def set_x(self, x: float) -> None: ... + def set_y(self, y: float) -> None: ... + def set_rotation(self, s: float) -> None: ... + def set_transform_rotates_text(self, t: bool) -> None: ... + def set_verticalalignment( + self, align: Literal["bottom", "baseline", "center", "center_baseline", "top"] + ) -> None: ... + def set_text(self, s: Any) -> None: ... + def set_fontproperties(self, fp: FontProperties | str | Path | None) -> None: ... + def set_usetex(self, usetex: bool | None) -> None: ... + def get_usetex(self) -> bool: ... + def set_parse_math(self, parse_math: bool) -> None: ... + def get_parse_math(self) -> bool: ... + def set_fontname(self, fontname: str | Iterable[str]): ... + +class OffsetFrom: + def __init__( + self, + artist: Artist | BboxBase | Transform, + ref_coord: tuple[float, float], + unit: Literal["points", "pixels"] = ..., + ) -> None: ... + def set_unit(self, unit: Literal["points", "pixels"]) -> None: ... + def get_unit(self) -> Literal["points", "pixels"]: ... + def __call__(self, renderer: RendererBase) -> Transform: ... + +class _AnnotationBase: + xy: tuple[float, float] + xycoords: str | tuple[str, str] | Artist | Transform | Callable[ + [RendererBase], Bbox | Transform + ] + def __init__( + self, + xy, + xycoords: str + | tuple[str, str] + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] = ..., + annotation_clip: bool | None = ..., + ) -> None: ... + def set_annotation_clip(self, b: bool | None) -> None: ... + def get_annotation_clip(self) -> bool | None: ... + def draggable( + self, state: bool | None = ..., use_blit: bool = ... + ) -> DraggableAnnotation | None: ... + +class Annotation(Text, _AnnotationBase): + arrowprops: dict[str, Any] | None + arrow_patch: FancyArrowPatch | None + def __init__( + self, + text: str, + xy: tuple[float, float], + xytext: tuple[float, float] | None = ..., + xycoords: str + | tuple[str, str] + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] = ..., + textcoords: str + | tuple[str, str] + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | None = ..., + arrowprops: dict[str, Any] | None = ..., + annotation_clip: bool | None = ..., + **kwargs + ) -> None: ... + @property + def xycoords( + self, + ) -> str | tuple[str, str] | Artist | Transform | Callable[ + [RendererBase], Bbox | Transform + ]: ... + @xycoords.setter + def xycoords( + self, + xycoords: str + | tuple[str, str] + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform], + ) -> None: ... + @property + def xyann(self) -> tuple[float, float]: ... + @xyann.setter + def xyann(self, xytext: tuple[float, float]) -> None: ... + def get_anncoords( + self, + ) -> str | tuple[str, str] | Artist | Transform | Callable[ + [RendererBase], Bbox | Transform + ]: ... + def set_anncoords( + self, + coords: str + | tuple[str, str] + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform], + ) -> None: ... + @property + def anncoords( + self, + ) -> str | tuple[str, str] | Artist | Transform | Callable[ + [RendererBase], Bbox | Transform + ]: ... + @anncoords.setter + def anncoords( + self, + coords: str + | tuple[str, str] + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform], + ) -> None: ... + def update_positions(self, renderer: RendererBase) -> None: ... diff --git a/lib/matplotlib/textpath.pyi b/lib/matplotlib/textpath.pyi new file mode 100644 index 000000000000..6ee014f05810 --- /dev/null +++ b/lib/matplotlib/textpath.pyi @@ -0,0 +1,78 @@ +from matplotlib import dviread +from matplotlib.font_manager import FontProperties, get_font +from matplotlib.ft2font import LOAD_NO_HINTING, LOAD_TARGET_LIGHT, FT2Font +from matplotlib.mathtext import MathTextParser +from matplotlib.path import Path +from matplotlib.texmanager import TexManager +from matplotlib.transforms import Affine2D + +import numpy as np + +from typing import Literal + +class TextToPath: + FONT_SCALE: float + DPI: float + mathtext_parser: MathTextParser + def __init__(self) -> None: ... + def get_text_width_height_descent( + self, s: str, prop: FontProperties, ismath: bool | Literal["TeX"] + ) -> tuple[float, float, float]: ... + def get_text_path( + self, prop: FontProperties, s: str, ismath: bool | Literal["TeX"] = ... + ) -> list[np.ndarray]: ... + def get_glyphs_with_font( + self, + font: FT2Font, + s: str, + glyph_map: dict[str, tuple[np.ndarray, np.ndarray]] | None = ..., + return_new_glyphs_only: bool = ..., + ) -> tuple[ + list[tuple[str, float, float, float]], + dict[str, tuple[np.ndarray, np.ndarray]], + list[tuple[list[tuple[float, float]], list[int]]], + ]: ... + def get_glyphs_mathtext( + self, + prop: FontProperties, + s: str, + glyph_map: dict[str, tuple[np.ndarray, np.ndarray]] | None = ..., + return_new_glyphs_only: bool = ..., + ) -> tuple[ + list[tuple[str, float, float, float]], + dict[str, tuple[np.ndarray, np.ndarray]], + list[tuple[list[tuple[float, float]], list[int]]], + ]: ... + def get_texmanager(self) -> TexManager: ... + def get_glyphs_tex( + self, + prop: FontProperties, + s: str, + glyph_map: dict[str, tuple[np.ndarray, np.ndarray]] | None = ..., + return_new_glyphs_only: bool = ..., + ) -> tuple[ + list[tuple[str, float, float, float]], + dict[str, tuple[np.ndarray, np.ndarray]], + list[tuple[list[tuple[float, float]], list[int]]], + ]: ... + +text_to_path: TextToPath + +class TextPath(Path): + def __init__( + self, + xy: tuple[float, float], + s: str, + size: float | None = ..., + prop: FontProperties | None = ..., + _interpolation_steps: int = ..., + usetex: bool = ..., + ) -> None: ... + def set_size(self, size: float | None) -> None: ... + def get_size(self) -> float | None: ... + + # These are read only... there actually are protections in the base class, so probably can be deleted... + @property # type: ignore[misc] + def vertices(self) -> np.ndarray: ... # type: ignore[override] + @property # type: ignore[misc] + def codes(self) -> np.ndarray: ... # type: ignore[override] diff --git a/lib/matplotlib/ticker.pyi b/lib/matplotlib/ticker.pyi new file mode 100644 index 000000000000..743157711031 --- /dev/null +++ b/lib/matplotlib/ticker.pyi @@ -0,0 +1,296 @@ +from matplotlib.axis import Axis +from matplotlib.transforms import Transform +from matplotlib.projections.polar import _AxisWrapper + +from typing import Any, Callable, Sequence, Literal +import numpy as np + +class _DummyAxis: + __name__: str + def __init__(self, minpos: float = ...) -> None: ... + def get_view_interval(self) -> tuple[float, float]: ... + def set_view_interval(self, vmin: float, vmax, float) -> None: ... + def get_minpos(self) -> float: ... + def get_data_interval(self) -> tuple[float, float]: ... + def set_data_interval(self, vmin: float, vmax: float) -> None: ... + def get_tick_space(self) -> int: ... + +class TickHelper: + axis: None | Axis | _DummyAxis | _AxisWrapper + def set_axis(self, axis: Axis | _DummyAxis | None) -> None: ... + def create_dummy_axis(self, **kwargs) -> None: ... + +class Formatter(TickHelper): + locs: list[float] + def __call__(self, x: float, pos: int | None = ...) -> str: ... + def format_ticks(self, values: list[float]): ... + def format_data(self, value: float): ... + def format_data_short(self, value: float): ... + def get_offset(self) -> str: ... + def set_locs(self, locs: list[float]) -> None: ... + @staticmethod + def fix_minus(s: str) -> str: ... + +class NullFormatter(Formatter): ... + +class FixedFormatter(Formatter): + seq: Sequence[str] + offset_string: str + def __init__(self, seq: Sequence[str]) -> None: ... + def set_offset_string(self, ofs: str) -> None: ... + +class FuncFormatter(Formatter): + func: Callable[[float, int | None], str] + offset_string: str + # Callable[[float, int | None], str] | Callable[[float], str] + def __init__(self, func: Callable[..., str]) -> None: ... + def set_offset_string(self, ofs: str) -> None: ... + +class FormatStrFormatter(Formatter): + fmt: str + def __init__(self, fmt: str) -> None: ... + +class StrMethodFormatter(Formatter): + fmt: str + def __init__(self, fmt: str) -> None: ... + +class ScalarFormatter(Formatter): + orderOfMagnitude: int + format: str + def __init__( + self, + useOffset: bool | float | None = ..., + useMathText: bool | None = ..., + useLocale: bool | None = ..., + ) -> None: ... + offset: float + def get_useOffset(self) -> bool: ... + def set_useOffset(self, val: bool | float) -> None: ... + @property + def useOffset(self) -> bool: ... + @useOffset.setter + def useOffset(self, val: bool | float) -> None: ... + def get_useLocale(self) -> bool: ... + def set_useLocale(self, val: bool | None) -> None: ... + @property + def useLocale(self) -> bool: ... + @useLocale.setter + def useLocale(self, val: bool | None) -> None: ... + def get_useMathText(self) -> bool: ... + def set_useMathText(self, val: bool | None) -> None: ... + @property + def useMathText(self) -> bool: ... + @useMathText.setter + def useMathText(self, val: bool | None) -> None: ... + def set_scientific(self, b: bool) -> None: ... + def set_powerlimits(self, lims: tuple[int, int]) -> None: ... + def format_data_short(self, value: float | int | np.ma.MaskedArray): ... + def format_data(self, value: float): ... + +class LogFormatter(Formatter): + minor_thresholds: tuple[float, float] + def __init__( + self, + base: float = ..., + labelOnlyBase: bool = ..., + minor_thresholds: tuple[float, float] | None = ..., + linthresh: float | None = ..., + ) -> None: ... + def set_base(self, base: float) -> None: ... + labelOnlyBase: bool + def set_label_minor(self, labelOnlyBase: bool) -> None: ... + def set_locs(self, locs: Any | None = ...) -> None: ... + def format_data(self, value: float) -> str: ... + def format_data_short(self, value: float) -> str: ... + +class LogFormatterExponent(LogFormatter): ... +class LogFormatterMathtext(LogFormatter): ... +class LogFormatterSciNotation(LogFormatterMathtext): ... + +class LogitFormatter(Formatter): + def __init__( + self, + *, + use_overline: bool = ..., + one_half: str = ..., + minor: bool = ..., + minor_threshold: int = ..., + minor_number: int = ... + ) -> None: ... + def use_overline(self, use_overline: bool) -> None: ... + def set_one_half(self, one_half: str) -> None: ... + def set_minor_threshold(self, minor_threshold: int) -> None: ... + def set_minor_number(self, minor_number: int) -> None: ... + def format_data_short(self, value: float) -> str: ... + +class EngFormatter(Formatter): + ENG_PREFIXES: dict[int, str] + unit: str + places: int | None + sep: str + def __init__( + self, + unit: str = ..., + places: int | None = ..., + sep: str = ..., + *, + usetex: bool | None = ..., + useMathText: bool | None = ... + ) -> None: ... + def get_usetex(self) -> bool: ... + def set_usetex(self, val: bool | None) -> None: ... + @property + def usetex(self) -> bool: ... + @usetex.setter + def usetex(self, val: bool | None) -> None: ... + def get_useMathText(self) -> bool: ... + def set_useMathText(self, val: bool | None) -> None: ... + @property + def useMathText(self) -> bool: ... + @useMathText.setter + def useMathText(self, val: bool | None) -> None: ... + def format_eng(self, num: float) -> str: ... + +class PercentFormatter(Formatter): + xmax: float + decimals: int | None + def __init__( + self, + xmax: float = ..., + decimals: int | None = ..., + symbol: str | None = ..., + is_latex: bool = ..., + ) -> None: ... + def format_pct(self, x: float, display_range: float) -> str: ... + def convert_to_pct(self, x: float) -> float: ... + @property + def symbol(self) -> str: ... + @symbol.setter + def symbol(self, symbol: str) -> None: ... + +class Locator(TickHelper): + MAXTICKS: int + def tick_values(self, vmin: float, vmax: float) -> Sequence[float]: ... + def set_params(self) -> None: ... + def __call__(self) -> Sequence[float]: ... + def raise_if_exceeds(self, locs: Sequence[float]) -> Sequence[float]: ... + def nonsingular(self, v0: float, v1: float) -> tuple[float, float]: ... + def view_limits(self, vmin: float, vmax: float) -> tuple[float, float]: ... + +class IndexLocator(Locator): + offset: float + def __init__(self, base: float, offset: float) -> None: ... + def set_params( + self, base: float | None = ..., offset: float | None = ... + ) -> None: ... + +class FixedLocator(Locator): + nbins: int | None + def __init__(self, locs: Sequence[float], nbins: int | None = ...) -> None: ... + def set_params(self, nbins: int | None = ...) -> None: ... + +class NullLocator(Locator): ... + +class LinearLocator(Locator): + presets: dict[tuple[float, float], Sequence[float]] + def __init__( + self, + numticks: int | None = ..., + presets: dict[tuple[float, float], Sequence[float]] | None = ..., + ) -> None: ... + @property + def numticks(self) -> int: ... + @numticks.setter + def numticks(self, numticks: int | None) -> None: ... + def set_params( + self, + numticks: int | None = ..., + presets: dict[tuple[float, float], Sequence[float]] | None = ..., + ) -> None: ... + +class MultipleLocator(Locator): + def __init__(self, base: float = ...) -> None: ... + def set_params(self, base: float | None = ...) -> None: ... + def view_limits(self, dmin: float, dmax: float) -> tuple[float, float]: ... + +class _Edge_integer: + step: float + def __init__(self, step: float, offset: float) -> None: ... + def closeto(self, ms: float, edge: float) -> bool: ... + def le(self, x: float) -> float: ... + def ge(self, x: float) -> float: ... + +class MaxNLocator(Locator): + default_params: dict[str, Any] + def __init__(self, nbins: int | Literal["auto"] | None = ..., **kwargs) -> None: ... + def set_params(self, **kwargs) -> None: ... + +class LogLocator(Locator): + numdecs: float + numticks: int | None + def __init__( + self, + base: float = ..., + subs: None | Literal["auto", "all"] | Sequence[float] = ..., + numdecs: float = ..., + numticks: int | None = ..., + ) -> None: ... + def set_params( + self, + base: float | None = ..., + subs: Literal["auto", "all"] | Sequence[float] | None = ..., + numdecs: float | None = ..., + numticks: int | None = ..., + ) -> None: ... + +class SymmetricalLogLocator(Locator): + numticks: int + def __init__( + self, + transform: Transform | None = ..., + subs: Sequence[float] | None = ..., + linthresh: float | None = ..., + base: float | None = ..., + ) -> None: ... + def set_params( + self, subs: Sequence[float] | None = ..., numticks: int | None = ... + ) -> None: ... + +class AsinhLocator(Locator): + linear_width: float + numticks: int + symthresh: float + base: int + subs: Sequence[float] | None + def __init__( + self, + linear_width: float, + numticks: int = ..., + symthresh: float = ..., + base: int = ..., + subs: Sequence[float] | None = ..., + ) -> None: ... + def set_params( + self, + numticks: int | None = ..., + symthresh: float | None = ..., + base: int | None = ..., + subs: Sequence[float] | None = ..., + ) -> None: ... + +class LogitLocator(MaxNLocator): + def __init__( + self, minor: bool = ..., *, nbins: Literal["auto"] | int = ... + ) -> None: ... + def set_params(self, minor: bool | None = ..., **kwargs) -> None: ... + @property + def minor(self) -> bool: ... + @minor.setter + def minor(self, value: bool) -> None: ... + +class AutoLocator(MaxNLocator): + def __init__(self) -> None: ... + +class AutoMinorLocator(Locator): + ndivs: int + def __init__(self, n: int | None = ...) -> None: ... diff --git a/lib/matplotlib/transforms.pyi b/lib/matplotlib/transforms.pyi new file mode 100644 index 000000000000..0f75be33b4ff --- /dev/null +++ b/lib/matplotlib/transforms.pyi @@ -0,0 +1,343 @@ +from .path import Path +from .patches import Patch +from .figure import Figure +from typing import Any, Iterable, Sequence, Literal +from matplotlib.path import Path +from matplotlib._path import ( + affine_transform as affine_transform, + count_bboxes_overlapping_bbox as count_bboxes_overlapping_bbox, + update_path_extents as update_path_extents, +) +import numpy as np +from numpy.typing import ArrayLike + +DEBUG: bool + +class TransformNode: + INVALID_NON_AFFINE: int + INVALID_AFFINE: int + INVALID: int + is_bbox: bool + # Implemented as a standard attr in base class, but functionally readonly and some subclasses implement as such + @property + def is_affine(self) -> bool: ... + pass_through: bool + def __init__(self, shorthand_name: str | None = ...) -> None: ... + def __copy__(self) -> TransformNode: ... + def invalidate(self) -> None: ... + def set_children(self, *children: TransformNode): ... + def frozen(self) -> TransformNode: ... + +class BboxBase(TransformNode): + is_bbox: bool + is_affine: bool + def frozen(self) -> TransformNode: ... + def __array__(self, *args, **kwargs): ... + @property + def x0(self) -> float: ... + @property + def y0(self) -> float: ... + @property + def x1(self) -> float: ... + @property + def y1(self) -> float: ... + @property + def p0(self) -> tuple[float, float]: ... + @property + def p1(self) -> tuple[float, float]: ... + @property + def xmin(self) -> float: ... + @property + def ymin(self) -> float: ... + @property + def xmax(self) -> float: ... + @property + def ymax(self) -> float: ... + @property + def min(self) -> tuple[float, float]: ... + @property + def max(self) -> tuple[float, float]: ... + @property + def intervalx(self) -> tuple[float, float]: ... + @property + def intervaly(self) -> tuple[float, float]: ... + @property + def width(self) -> float: ... + @property + def height(self) -> float: ... + @property + def size(self) -> tuple[float, float]: ... + @property + def bounds(self) -> tuple[float, float, float, float]: ... + @property + def extents(self) -> tuple[float, float, float, float]: ... + def get_points(self) -> np.ndarray: ... + def containsx(self, x: float) -> bool: ... + def containsy(self, y: float) -> bool: ... + def contains(self, x: float, y: float) -> bool: ... + def overlaps(self, other: BboxBase) -> bool: ... + def fully_containsx(self, x: float) -> bool: ... + def fully_containsy(self, y: float) -> bool: ... + def fully_contains(self, x: float, y: float) -> bool: ... + def fully_overlaps(self, other: BboxBase) -> bool: ... + def transformed(self, transform: Transform) -> Bbox: ... + coefs: dict[str, tuple[float, float]] + # anchored type can be s/str/Literal["C", "SW", "S", "SE", "E", "NE", "N", "NW", "W"] + def anchored( + self, c: tuple[float, float] | str, container: BboxBase | None = ... + ): ... + def shrunk(self, mx: float, my: float) -> Bbox: ... + def shrunk_to_aspect( + self, + box_aspect: float, + container: BboxBase | None = ..., + fig_aspect: float = ..., + ) -> Bbox: ... + def splitx(self, *args: float) -> list[Bbox]: ... + def splity(self, *args: float) -> list[Bbox]: ... + def count_contains(self, vertices: ArrayLike) -> int: ... + def count_overlaps(self, bboxes: Iterable[BboxBase]) -> int: ... + def expanded(self, sw: float, sh: float) -> Bbox: ... + def padded(self, p: float) -> Bbox: ... + def translated(self, tx: float, ty: float) -> Bbox: ... + def corners(self) -> np.ndarray: ... + def rotated(self, radians: float) -> Bbox: ... + @staticmethod + def union(bboxes: Sequence[BboxBase]) -> Bbox: ... + @staticmethod + def intersection(bbox1: BboxBase, bbox2: BboxBase) -> Bbox: ... + +class Bbox(BboxBase): + def __init__(self, points: ArrayLike, **kwargs) -> None: ... + @staticmethod + def unit() -> Bbox: ... + @staticmethod + def null() -> Bbox: ... + @staticmethod + def from_bounds(x0: float, y0: float, width: float, height: float) -> Bbox: ... + @staticmethod + def from_extents(*args: float, minpos: float | None = ...) -> Bbox: ... + def __format__(self, fmt: str) -> str: ... + def ignore(self, value: bool) -> None: ... + def update_from_path( + self, + path: Path, + ignore: bool | None = ..., + updatex: bool = ..., + updatey: bool = ..., + ) -> None: ... + def update_from_data_x(self, x: ArrayLike, ignore: bool | None = ...) -> None: ... + def update_from_data_y(self, y: ArrayLike, ignore: bool | None = ...) -> None: ... + def update_from_data_xy( + self, + xy: ArrayLike, + ignore: bool | None = ..., + updatex: bool = ..., + updatey: bool = ..., + ) -> None: ... + @property + def minpos(self) -> float: ... + @property + def minposx(self) -> float: ... + @property + def minposy(self) -> float: ... + def get_points(self) -> np.ndarray: ... + def set_points(self, points: ArrayLike) -> None: ... + def set(self, other: Bbox) -> None: ... + def mutated(self) -> bool: ... + def mutatedx(self) -> bool: ... + def mutatedy(self) -> bool: ... + +class TransformedBbox(BboxBase): + def __init__(self, bbox: Bbox, transform: Transform, **kwargs) -> None: ... + def get_points(self) -> np.ndarray: ... + +class LockableBbox(BboxBase): + def __init__( + self, + bbox: BboxBase, + x0: float | None = ..., + y0: float | None = ..., + x1: float | None = ..., + y1: float | None = ..., + **kwargs + ) -> None: ... + @property + def locked_x0(self) -> float | None: ... + @locked_x0.setter + def locked_x0(self, x0: float | None) -> None: ... + @property + def locked_y0(self) -> float | None: ... + @locked_y0.setter + def locked_y0(self, y0: float | None) -> None: ... + @property + def locked_x1(self) -> float | None: ... + @locked_x1.setter + def locked_x1(self, x1: float | None) -> None: ... + @property + def locked_y1(self) -> float | None: ... + @locked_y1.setter + def locked_y1(self, y1: float | None) -> None: ... + +class Transform(TransformNode): + input_dims: int | None + output_dims: int | None + is_separable: bool + # Implemented as a standard attr in base class, but functionally readonly and some subclasses implement as such + @property + def has_inverse(self) -> bool: ... + def __init_subclass__(cls) -> None: ... + def __add__(self, other: Transform) -> Transform: ... + @property + def depth(self) -> int: ... + def contains_branch(self, other: Transform) -> bool: ... + def contains_branch_seperately( + self, other_transform: Transform + ) -> Sequence[bool]: ... + def __sub__(self, other: Transform) -> Transform: ... + def __array__(self, *args, **kwargs) -> np.ndarray: ... + def transform(self, values: ArrayLike) -> Transform: ... + def transform_affine(self, values: ArrayLike) -> np.ndarray: ... + def transform_non_affine(self, values: ArrayLike) -> ArrayLike: ... + def transform_bbox(self, bbox: BboxBase) -> Bbox: ... + def get_affine(self) -> Transform: ... + def get_matrix(self) -> np.ndarray: ... + def transform_point(self, point: ArrayLike) -> np.ndarray: ... + def transform_path(self, path: ArrayLike) -> np.ndarray: ... + def transform_path_affine(self, path: ArrayLike) -> np.ndarray: ... + def transform_path_non_affine(self, path: ArrayLike) -> np.ndarray: ... + def transform_angles( + self, + angles: ArrayLike, + pts: ArrayLike, + radians: bool = ..., + pushoff: float = ..., + ) -> np.ndarray: ... + def inverted(self) -> Transform: ... + +class TransformWrapper(Transform): + pass_through: bool + def __init__(self, child: Transform) -> None: ... + def __eq__(self, other: object) -> bool: ... + def frozen(self) -> Transform: ... + def set(self, child: Transform) -> None: ... + +class AffineBase(Transform): + is_affine: Literal[True] + def __init__(self, *args, **kwargs) -> None: ... + def __eq__(self, other: object) -> bool: ... + +class Affine2DBase(AffineBase): + input_dims: Literal[2] + output_dims: Literal[2] + def frozen(self): ... + @property + def is_separable(self): ... + def to_values(self): ... + +class Affine2D(Affine2DBase): + def __init__(self, matrix: ArrayLike | None = ..., **kwargs) -> None: ... + @staticmethod + def from_values( + a: float, b: float, c: float, d: float, e: float, f: float + ) -> Affine2D: ... + @staticmethod + def identity() -> Affine2D: ... + def clear(self) -> Affine2D: ... + def rotate(self, theta: float) -> Affine2D: ... + def rotate_deg(self, degrees: float) -> Affine2D: ... + def rotate_around(self, x: float, y: float, theta: float) -> Affine2D: ... + def rotate_deg_around(self, x: float, y: float, degrees: float) -> Affine2D: ... + def translate(self, tx: float, ty: float) -> Affine2D: ... + def scale(self, sx: float, sy: float | None = ...) -> Affine2D: ... + def skew(self, xShear: float, yShear: float) -> Affine2D: ... + def skew_deg(self, xShear: float, yShear: float) -> Affine2D: ... + +class IdentityTransform(Affine2DBase): ... + +class _BlendedMixin: + def __eq__(self, other: object) -> bool: ... + def contains_branch_seperately(self, transform: Transform) -> Sequence[bool]: ... + +class BlendedGenericTransform(_BlendedMixin, Transform): + input_dims: Literal[2] + output_dims: Literal[2] + is_separable: bool + pass_through: bool + def __init__( + self, x_transform: Transform, y_transform: Transform, **kwargs + ) -> None: ... + @property + def depth(self) -> int: ... + def contains_branch(self, other: Transform) -> Literal[False]: ... + @property + def is_affine(self) -> bool: ... + @property + def has_inverse(self) -> bool: ... + +class BlendedAffine2D(_BlendedMixin, Affine2DBase): + def __init__( + self, x_transform: Transform, y_transform: Transform, **kwargs + ) -> None: ... + +def blended_transform_factory( + x_transform: Transform, y_transform: Transform +) -> BlendedGenericTransform | BlendedAffine2D: ... + +class CompositeGenericTransform(Transform): + pass_through: bool + input_dims: int + output_dims: int + def __init__(self, a: Transform, b: Transform, **kwargs) -> None: ... + +class CompositeAffine2D(Affine2DBase): + def __init__(self, a: Affine2DBase, b: Affine2DBase, **kwargs) -> None: ... + @property + def depth(self) -> int: ... + +def composite_transform_factory(a: Transform, b: Transform) -> Transform: ... + +class BboxTransform(Affine2DBase): + def __init__(self, boxin: BboxBase, boxout: BboxBase, **kwargs) -> None: ... + +class BboxTransformTo(Affine2DBase): + def __init__(self, boxout: BboxBase, **kwargs) -> None: ... + +class BboxTransformToMaxOnly(BboxTransformTo): ... + +class BboxTransformFrom(Affine2DBase): + def __init__(self, boxin: BboxBase, **kwargs) -> None: ... + +class ScaledTranslation(Affine2DBase): + def __init__( + self, xt: float, yt: float, scale_trans: Affine2DBase, **kwargs + ) -> None: ... + +class AffineDeltaTransform(Affine2DBase): + def __init__(self, transform: Affine2DBase, **kwargs) -> None: ... + +class TransformedPath(TransformNode): + def __init__(self, path: Path, transform: Transform) -> None: ... + def get_transformed_points_and_affine(self) -> tuple[Path, Transform]: ... + def get_transformed_path_and_affine(self) -> tuple[Path, Transform]: ... + def get_fully_transformed_path(self) -> Path: ... + +class TransformedPatchPath(TransformedPath): + def __init__(self, patch: Patch) -> None: ... + +def nonsingular( + vmin: float, + vmax: float, + expander: float = ..., + tiny: float = ..., + increasing: bool = ..., +) -> tuple[float, float]: ... +def interval_contains(interval: tuple[float, float], val: float): ... +def interval_contains_open(interval: tuple[float, float], val: float): ... +def offset_copy( + trans: Transform, + fig: Figure | None = ..., + x: float = ..., + y: float = ..., + units: Literal["inches", "points", "dots"] = ..., +): ... diff --git a/lib/matplotlib/tri/_triangulation.pyi b/lib/matplotlib/tri/_triangulation.pyi new file mode 100644 index 000000000000..ea24d6b7874c --- /dev/null +++ b/lib/matplotlib/tri/_triangulation.pyi @@ -0,0 +1,33 @@ +from matplotlib import _tri +from matplotlib.tri._trifinder import TriFinder + +import numpy as np +from numpy.typing import ArrayLike +from typing import Any + +class Triangulation: + x: np.ndarray + y: np.ndarray + mask: np.ndarray + is_delaunay: bool + triangles: np.ndarray + def __init__( + self, + x: ArrayLike, + y: ArrayLike, + triangles: ArrayLike | None = ..., + mask: ArrayLike | None = ..., + ) -> None: ... + def calculate_plane_coefficients(self, z: ArrayLike): ... + @property + def edges(self) -> np.ndarray: ... + def get_cpp_triangulation(self) -> _tri.Triangulation: ... + def get_masked_triangles(self) -> np.ndarray: ... + @staticmethod + def get_from_args_and_kwargs( + *args, **kwargs + ) -> tuple[Triangulation, tuple[Any, ...], dict[str, Any]]: ... + def get_trifinder(self) -> TriFinder: ... + @property + def neighbors(self) -> np.ndarray: ... + def set_mask(self, mask: None | ArrayLike) -> None: ... diff --git a/lib/matplotlib/tri/_tricontour.pyi b/lib/matplotlib/tri/_tricontour.pyi new file mode 100644 index 000000000000..31929d866156 --- /dev/null +++ b/lib/matplotlib/tri/_tricontour.pyi @@ -0,0 +1,52 @@ +from matplotlib.axes import Axes +from matplotlib.contour import ContourSet +from matplotlib.tri._triangulation import Triangulation + +from numpy.typing import ArrayLike +from typing import overload + +# TODO: more explicit args/kwargs (for all things in this module)? + +class TriContourSet(ContourSet): + def __init__(self, ax: Axes, *args, **kwargs) -> None: ... + +@overload +def tricontour( + ax: Axes, + triangulation: Triangulation, + z: ArrayLike, + levels: int | ArrayLike = ..., + **kwargs +) -> TriContourSet: ... +@overload +def tricontour( + ax: Axes, + x: ArrayLike, + y: ArrayLike, + z: ArrayLike, + levels: int | ArrayLike = ..., + *, + triangles: ArrayLike = ..., + mask: ArrayLike = ..., + **kwargs +) -> TriContourSet: ... +@overload +def tricontourf( + ax: Axes, + triangulation: Triangulation, + z: ArrayLike, + levels: int | ArrayLike = ..., + **kwargs +) -> TriContourSet: ... +@overload +def tricontourf( + ax: Axes, + x: ArrayLike, + y: ArrayLike, + z: ArrayLike, + levels: int | ArrayLike = ..., + *, + triangles: ArrayLike = ..., + mask: ArrayLike = ..., + **kwargs +) -> TriContourSet: ... diff --git a/lib/matplotlib/tri/_trifinder.pyi b/lib/matplotlib/tri/_trifinder.pyi new file mode 100644 index 000000000000..2020e4aa2907 --- /dev/null +++ b/lib/matplotlib/tri/_trifinder.pyi @@ -0,0 +1,9 @@ +from matplotlib.tri import Triangulation +from numpy.typing import ArrayLike + +class TriFinder: + def __init__(self, triangulation: Triangulation) -> None: ... + +class TrapezoidMapTriFinder(TriFinder): + def __init__(self, triangulation: Triangulation) -> None: ... + def __call__(self, x: ArrayLike, y: ArrayLike) -> ArrayLike: ... diff --git a/lib/matplotlib/tri/_triinterpolate.pyi b/lib/matplotlib/tri/_triinterpolate.pyi new file mode 100644 index 000000000000..8a56b22acdb2 --- /dev/null +++ b/lib/matplotlib/tri/_triinterpolate.pyi @@ -0,0 +1,30 @@ +from matplotlib.tri import Triangulation, TriFinder + +from typing import Literal +import numpy as np +from numpy.typing import ArrayLike + +class TriInterpolator: + def __init__( + self, + triangulation: Triangulation, + z: ArrayLike, + trifinder: TriFinder | None = ..., + ) -> None: ... + # __call__ and gradient are not actually implemented by the ABC, but are specified as required + def __call__(self, x: ArrayLike, y: ArrayLike) -> np.ma.MaskedArray: ... + def gradient( + self, x: ArrayLike, y: ArrayLike + ) -> tuple[np.ma.MaskedArray, np.ma.MaskedArray]: ... + +class LinearTriInterpolator(TriInterpolator): ... + +class CubicTriInterpolator(TriInterpolator): + def __init__( + self, + triangulation: Triangulation, + z: ArrayLike, + kind: Literal["min_E", "geom", "user"] = ..., + trifinder: TriFinder | None = ..., + dz: tuple[ArrayLike, ArrayLike] | None = ..., + ) -> None: ... diff --git a/lib/matplotlib/tri/_tripcolor.pyi b/lib/matplotlib/tri/_tripcolor.pyi new file mode 100644 index 000000000000..4448a5d1d3f8 --- /dev/null +++ b/lib/matplotlib/tri/_tripcolor.pyi @@ -0,0 +1,40 @@ +from matplotlib.axes import Axes +from matplotlib.collections import PolyCollection, TriMesh +from matplotlib.colors import Normalize, Colormap +from matplotlib.tri._triangulation import Triangulation + +from numpy.typing import ArrayLike + +from typing import overload, Literal + +@overload +def tripcolor( + ax: Axes, + triangulation: Triangulation, + c: ArrayLike = ..., + *, + alpha: float = ..., + norm: str | Normalize | None = ..., + cmap: str | Colormap | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + shading: Literal["flat", "gouraud"] = ..., + facecolors: ArrayLike | None = ..., + **kwargs +): ... +@overload +def tripcolor( + ax: Axes, + x: ArrayLike, + y: ArrayLike, + c: ArrayLike = ..., + *, + alpha: float = ..., + norm: str | Normalize | None = ..., + cmap: str | Colormap | None = ..., + vmin: float | None = ..., + vmax: float | None = ..., + shading: Literal["flat", "gouraud"] = ..., + facecolors: ArrayLike | None = ..., + **kwargs +): ... diff --git a/lib/matplotlib/tri/_triplot.pyi b/lib/matplotlib/tri/_triplot.pyi new file mode 100644 index 000000000000..6224276afdb8 --- /dev/null +++ b/lib/matplotlib/tri/_triplot.pyi @@ -0,0 +1,15 @@ +from matplotlib.tri._triangulation import Triangulation +from matplotlib.axes import Axes +from matplotlib.lines import Line2D + +from typing import overload +from numpy.typing import ArrayLike + +@overload +def triplot( + ax: Axes, triangulation: Triangulation, *args, **kwargs +) -> tuple[Line2D, Line2D]: ... +@overload +def triplot( + ax: Axes, x: ArrayLike, y: ArrayLike, triangles: ArrayLike = ..., *args, **kwargs +) -> tuple[Line2D, Line2D]: ... diff --git a/lib/matplotlib/tri/_trirefine.pyi b/lib/matplotlib/tri/_trirefine.pyi new file mode 100644 index 000000000000..e620850a1533 --- /dev/null +++ b/lib/matplotlib/tri/_trirefine.pyi @@ -0,0 +1,20 @@ +from matplotlib.tri._triangulation import Triangulation +from matplotlib.tri._triinterpolate import TriInterpolator + +import numpy as np +from numpy.typing import ArrayLike + +class TriRefiner: + def __init__(self, triangulation: Triangulation) -> None: ... + +class UniformTriRefiner(TriRefiner): + def __init__(self, triangulation: Triangulation) -> None: ... + def refine_triangulation( + self, return_tri_index: bool = ..., subdiv: int = ... + ) -> tuple[Triangulation, np.ndarray]: ... + def refine_field( + self, + z: ArrayLike, + triinterpolator: TriInterpolator | None = ..., + subdiv: int = ..., + ) -> tuple[Triangulation, np.ndarray]: ... diff --git a/lib/matplotlib/tri/_tritools.pyi b/lib/matplotlib/tri/_tritools.pyi new file mode 100644 index 000000000000..9b5e1bec4b81 --- /dev/null +++ b/lib/matplotlib/tri/_tritools.pyi @@ -0,0 +1,12 @@ +from matplotlib.tri import Triangulation + +import numpy as np + +class TriAnalyzer: + def __init__(self, triangulation: Triangulation) -> None: ... + @property + def scale_factors(self) -> tuple[float, float]: ... + def circle_ratios(self, rescale: bool = ...) -> np.ndarray: ... + def get_flat_tri_mask( + self, min_circle_ratio: float = ..., rescale: bool = ... + ) -> np.ndarray: ... diff --git a/lib/matplotlib/units.py b/lib/matplotlib/units.py index 2bcfcaf2eb12..e3480f228bb4 100644 --- a/lib/matplotlib/units.py +++ b/lib/matplotlib/units.py @@ -46,7 +46,7 @@ def default_units(x, axis): import numpy as np from numpy import ma -from matplotlib import _api, cbook +from matplotlib import cbook class ConversionError(TypeError): @@ -131,23 +131,6 @@ def convert(obj, unit, axis): """ return obj - @staticmethod - @_api.deprecated("3.5") - def is_numlike(x): - """ - The Matplotlib datalim, autoscaling, locators etc work with scalars - which are the units converted to floats given the current unit. The - converter may be passed these floats, or arrays of them, even when - units are set. - """ - if np.iterable(x): - for thisx in x: - if thisx is ma.masked: - continue - return isinstance(thisx, Number) - else: - return isinstance(x, Number) - class DecimalConverter(ConversionInterface): """Converter for decimal.Decimal data to float.""" diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 8ca7a52a86d4..1dc1dd5f77ae 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -325,6 +325,7 @@ class Slider(SliderBase): Slider value. """ + @_api.make_keyword_only("3.7", name="valinit") def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, closedmin=True, closedmax=True, slidermin=None, slidermax=None, dragging=True, valstep=None, @@ -597,6 +598,7 @@ class RangeSlider(SliderBase): Slider value. """ + @_api.make_keyword_only("3.7", name="valinit") def __init__( self, ax, @@ -1190,8 +1192,8 @@ def lines(self): l1.set_visible(current_status[i]) l2.set_visible(current_status[i]) self._lines.append((l1, l2)) - self.ax.add_patch(l1) - self.ax.add_patch(l2) + self.ax.add_line(l1) + self.ax.add_line(l2) if not hasattr(self, "_rectangles"): with _api.suppress_matplotlib_deprecation_warning(): _ = self.rectangles @@ -1221,8 +1223,7 @@ class TextBox(AxesWidget): The color of the text box when hovering. """ - DIST_FROM_LEFT = _api.deprecate_privatize_attribute("3.5") - + @_api.make_keyword_only("3.7", name="color") def __init__(self, ax, label, initial='', color='.95', hovercolor='1', label_pad=.01, textalignment="left"): @@ -1246,8 +1247,6 @@ def __init__(self, ax, label, initial='', """ super().__init__(ax) - self._DIST_FROM_LEFT = .05 - self._text_position = _api.check_getitem( {"left": 0.05, "center": 0.5, "right": 0.95}, textalignment=textalignment) @@ -1727,7 +1726,7 @@ class Cursor(AxesWidget): -------- See :doc:`/gallery/widgets/cursor`. """ - + @_api.make_keyword_only("3.7", "horizOn") def __init__(self, ax, horizOn=True, vertOn=True, useblit=False, **lineprops): super().__init__(ax) @@ -1981,9 +1980,6 @@ def __init__(self, ax, onselect, useblit=False, button=None, self._prev_event = None self._state = set() - eventpress = _api.deprecate_privatize_attribute("3.5") - eventrelease = _api.deprecate_privatize_attribute("3.5") - state = _api.deprecate_privatize_attribute("3.5") state_modifier_keys = _api.deprecate_privatize_attribute("3.6") def set_active(self, active): @@ -2408,8 +2404,7 @@ def on_select(min: float, max: float) -> Any See also: :doc:`/gallery/widgets/span_selector` """ - @_api.rename_parameter("3.5", "rectprops", "props") - @_api.rename_parameter("3.5", "span_stays", "interactive") + @_api.make_keyword_only("3.7", name="minspan") def __init__(self, ax, onselect, direction, minspan=0, useblit=False, props=None, onmove_callback=None, interactive=False, button=None, handle_props=None, grab_range=10, @@ -2465,24 +2460,6 @@ def __init__(self, ax, onselect, direction, minspan=0, useblit=False, # prev attribute is deprecated but we still need to maintain it self._prev = (0, 0) - rect = _api.deprecated("3.5")( - property(lambda self: self._selection_artist) - ) - - rectprops = _api.deprecated("3.5")( - property(lambda self: self._props) - ) - - active_handle = _api.deprecate_privatize_attribute("3.5") - - pressv = _api.deprecate_privatize_attribute("3.5") - - span_stays = _api.deprecated("3.5")( - property(lambda self: self._interactive) - ) - - prev = _api.deprecate_privatize_attribute("3.5") - def new_axes(self, ax): """Set SpanSelector to operate on a new Axes.""" self.ax = ax @@ -2784,6 +2761,7 @@ class ToolLineHandles: for details. """ + @_api.make_keyword_only("3.7", "line_props") def __init__(self, ax, positions, direction, line_props=None, useblit=True): self.ax = ax @@ -2894,6 +2872,7 @@ class ToolHandles: for details. """ + @_api.make_keyword_only("3.7", "marker") def __init__(self, ax, x, y, marker='o', marker_props=None, useblit=True): self.ax = ax props = {'marker': marker, 'markersize': 7, 'markerfacecolor': 'w', @@ -3059,18 +3038,11 @@ class RectangleSelector(_SelectorWidget): See also: :doc:`/gallery/widgets/rectangle_selector` """ - @_api.rename_parameter("3.5", "maxdist", "grab_range") - @_api.rename_parameter("3.5", "marker_props", "handle_props") - @_api.rename_parameter("3.5", "rectprops", "props") - @_api.delete_parameter("3.5", "drawtype") - @_api.delete_parameter("3.5", "lineprops") - def __init__(self, ax, onselect, drawtype='box', - minspanx=0, minspany=0, useblit=False, - lineprops=None, props=None, spancoords='data', - button=None, grab_range=10, handle_props=None, - interactive=False, state_modifier_keys=None, - drag_from_anywhere=False, ignore_event_outside=False, - use_data_coordinates=False): + def __init__(self, ax, onselect, *, minspanx=0, minspany=0, useblit=False, + props=None, spancoords='data', button=None, grab_range=10, + handle_props=None, interactive=False, + state_modifier_keys=None, drag_from_anywhere=False, + ignore_event_outside=False, use_data_coordinates=False): super().__init__(ax, onselect, useblit=useblit, button=button, state_modifier_keys=state_modifier_keys, use_data_coordinates=use_data_coordinates) @@ -3086,34 +3058,13 @@ def __init__(self, ax, onselect, drawtype='box', # interactive bounding box to allow the polygon to be easily resized self._allow_creation = True - if drawtype == 'none': # draw a line but make it invisible - _api.warn_deprecated( - "3.5", message="Support for drawtype='none' is deprecated " - "since %(since)s and will be removed " - "%(removal)s." - "Use props=dict(visible=False) instead.") - drawtype = 'line' - self._visible = False - - if drawtype == 'box': - if props is None: - props = dict(facecolor='red', edgecolor='black', - alpha=0.2, fill=True) - self._props = {**props, 'animated': self.useblit} - self._visible = self._props.pop('visible', self._visible) - to_draw = self._init_shape(**self._props) - self.ax.add_patch(to_draw) - if drawtype == 'line': - _api.warn_deprecated( - "3.5", message="Support for drawtype='line' is deprecated " - "since %(since)s and will be removed " - "%(removal)s.") - if lineprops is None: - lineprops = dict(color='black', linestyle='-', - linewidth=2, alpha=0.5) - self._props = {**lineprops, 'animated': self.useblit} - to_draw = Line2D([0, 0], [0, 0], visible=False, **self._props) - self.ax.add_line(to_draw) + if props is None: + props = dict(facecolor='red', edgecolor='black', + alpha=0.2, fill=True) + self._props = {**props, 'animated': self.useblit} + self._visible = self._props.pop('visible', self._visible) + to_draw = self._init_shape(**self._props) + self.ax.add_patch(to_draw) self._selection_artist = to_draw self._set_aspect_ratio_correction() @@ -3123,7 +3074,6 @@ def __init__(self, ax, onselect, drawtype='box', _api.check_in_list(['data', 'pixels'], spancoords=spancoords) self.spancoords = spancoords - self._drawtype = drawtype self.grab_range = grab_range @@ -3154,20 +3104,6 @@ def __init__(self, ax, onselect, drawtype='box', self._extents_on_press = None - to_draw = _api.deprecated("3.5")( - property(lambda self: self._selection_artist) - ) - - drawtype = _api.deprecate_privatize_attribute("3.5") - - active_handle = _api.deprecate_privatize_attribute("3.5") - - interactive = _api.deprecate_privatize_attribute("3.5") - - maxdist = _api.deprecated("3.5", name="maxdist", alternative="grab_range")( - property(lambda self: self.grab_range, - lambda self, value: setattr(self, "grab_range", value))) - @property def _handles_artists(self): return (*self._center_handle.artists, *self._corner_handles.artists, @@ -3240,8 +3176,7 @@ def _release(self, event): spancoords=self.spancoords) # check if drawn distance (if it exists) is not too small in # either x or y-direction - minspanxy = (spanx <= self.minspanx or spany <= self.minspany) - if (self._drawtype != 'none' and minspanxy): + if spanx <= self.minspanx or spany <= self.minspany: if self._selection_completed: # Call onselect, only when the selection is already existing self.onselect(self._eventpress, self._eventrelease) @@ -3405,13 +3340,7 @@ def _onmove(self, event): @property def _rect_bbox(self): - if self._drawtype == 'box': - return self._selection_artist.get_bbox().bounds - else: - x, y = self._selection_artist.get_data() - x0, x1 = min(x), max(x) - y0, y1 = min(y), max(y) - return x0, y0, x1 - x0, y1 - y0 + return self._selection_artist.get_bbox().bounds def _set_aspect_ratio_correction(self): aspect_ratio = self.ax._get_aspect_ratio() @@ -3510,8 +3439,6 @@ def rotation(self, value): # call extents setter to draw shape and update handles positions self.extents = self.extents - draw_shape = _api.deprecate_privatize_attribute('3.5') - def _draw_shape(self, extents): x0, x1, y0, y1 = extents xmin, xmax = sorted([x0, x1]) @@ -3524,15 +3451,11 @@ def _draw_shape(self, extents): xmax = min(xmax, xlim[1]) ymax = min(ymax, ylim[1]) - if self._drawtype == 'box': - self._selection_artist.set_x(xmin) - self._selection_artist.set_y(ymin) - self._selection_artist.set_width(xmax - xmin) - self._selection_artist.set_height(ymax - ymin) - self._selection_artist.set_angle(self.rotation) - - elif self._drawtype == 'line': - self._selection_artist.set_data([xmin, xmax], [ymin, ymax]) + self._selection_artist.set_x(xmin) + self._selection_artist.set_y(ymin) + self._selection_artist.set_width(xmax - xmin) + self._selection_artist.set_height(ymax - ymin) + self._selection_artist.set_angle(self.rotation) def _set_active_handle(self, event): """Set active handle based on the location of the mouse event.""" @@ -3600,9 +3523,6 @@ class EllipseSelector(RectangleSelector): -------- :doc:`/gallery/widgets/rectangle_selector` """ - - draw_shape = _api.deprecate_privatize_attribute('3.5') - def _init_shape(self, **props): return Ellipse((0, 0), 0, 1, visible=False, **props) @@ -3614,29 +3534,17 @@ def _draw_shape(self, extents): a = (xmax - xmin) / 2. b = (ymax - ymin) / 2. - if self._drawtype == 'box': - self._selection_artist.center = center - self._selection_artist.width = 2 * a - self._selection_artist.height = 2 * b - self._selection_artist.angle = self.rotation - else: - rad = np.deg2rad(np.arange(31) * 12) - x = a * np.cos(rad) + center[0] - y = b * np.sin(rad) + center[1] - self._selection_artist.set_data(x, y) + self._selection_artist.center = center + self._selection_artist.width = 2 * a + self._selection_artist.height = 2 * b + self._selection_artist.angle = self.rotation @property def _rect_bbox(self): - if self._drawtype == 'box': - x, y = self._selection_artist.center - width = self._selection_artist.width - height = self._selection_artist.height - return x - width / 2., y - height / 2., width, height - else: - x, y = self._selection_artist.get_data() - x0, x1 = min(x), max(x) - y0, y1 = min(y), max(y) - return x0, y0, x1 - x0, y1 - y0 + x, y = self._selection_artist.center + width = self._selection_artist.width + height = self._selection_artist.height + return x - width / 2., y - height / 2., width, height class LassoSelector(_SelectorWidget): @@ -3680,9 +3588,8 @@ def onselect(verts): which corresponds to all buttons. """ - @_api.rename_parameter("3.5", "lineprops", "props") - def __init__(self, ax, onselect=None, useblit=True, props=None, - button=None): + @_api.make_keyword_only("3.7", name="useblit") + def __init__(self, ax, onselect, useblit=True, props=None, button=None): super().__init__(ax, onselect, useblit=useblit, button=button) self.verts = None props = { @@ -3695,18 +3602,10 @@ def __init__(self, ax, onselect=None, useblit=True, props=None, self.ax.add_line(line) self._selection_artist = line - @_api.deprecated("3.5", alternative="press") - def onpress(self, event): - self.press(event) - def _press(self, event): self.verts = [self._get_data(event)] self._selection_artist.set_visible(True) - @_api.deprecated("3.5", alternative="release") - def onrelease(self, event): - self.release(event) - def _release(self, event): if self.verts is not None: self.verts.append(self._get_data(event)) @@ -3801,9 +3700,7 @@ class PolygonSelector(_SelectorWidget): point. """ - @_api.rename_parameter("3.5", "lineprops", "props") - @_api.rename_parameter("3.5", "markerprops", "handle_props") - @_api.rename_parameter("3.5", "vertex_select_radius", "grab_range") + @_api.make_keyword_only("3.7", name="useblit") def __init__(self, ax, onselect, useblit=False, props=None, handle_props=None, grab_range=10, *, draw_bounding_box=False, box_handle_props=None, @@ -3910,16 +3807,6 @@ def _scale_polygon(self, event): self._draw_polygon() self._old_box_extents = self._box.extents - line = _api.deprecated("3.5")( - property(lambda self: self._selection_artist) - ) - - vertex_select_radius = _api.deprecated("3.5", name="vertex_select_radius", - alternative="grab_range")( - property(lambda self: self.grab_range, - lambda self, value: setattr(self, "grab_range", value)) - ) - @property def _handles_artists(self): return self._polygon_handles.artists @@ -4111,16 +3998,17 @@ class Lasso(AxesWidget): The parent Axes for the widget. xy : (float, float) Coordinates of the start of the lasso. + callback : callable + Whenever the lasso is released, the *callback* function is called and + passed the vertices of the selected path. useblit : bool, default: True Whether to use blitting for faster drawing (if supported by the backend). See the tutorial :doc:`/tutorials/advanced/blitting` for details. - callback : callable - Whenever the lasso is released, the *callback* function is called and - passed the vertices of the selected path. """ - def __init__(self, ax, xy, callback=None, useblit=True): + @_api.make_keyword_only("3.7", name="useblit") + def __init__(self, ax, xy, callback, useblit=True): super().__init__(ax) self.useblit = useblit and self.canvas.supports_blit diff --git a/lib/matplotlib/widgets.pyi b/lib/matplotlib/widgets.pyi new file mode 100644 index 000000000000..89907a143ebf --- /dev/null +++ b/lib/matplotlib/widgets.pyi @@ -0,0 +1,467 @@ +from . import backend_tools, cbook, colors, ticker, transforms +from .artist import Artist +from .axes import Axes +from .backend_bases import FigureCanvasBase, Event, MouseEvent, MouseButton +from .collections import LineCollection +from .figure import Figure +from .lines import Line2D +from .patches import Circle, Ellipse, Polygon, Rectangle +from .text import Text +from .transforms import Affine2D, TransformedPatchPath + +import PIL + +from typing import Any, Callable, Literal, Iterable, Sequence, Collection +from numpy.typing import ArrayLike +import numpy as np + +class LockDraw: + def __init__(self) -> None: ... + def __call__(self, o: Any) -> None: ... + def release(self, o: Any) -> None: ... + def available(self, o: Any) -> bool: ... + def isowner(self, o: Any) -> bool: ... + def locked(self) -> bool: ... + +class Widget: + drawon: bool + eventson: bool + active: bool + def set_active(self, active: bool) -> None: ... + def get_active(self) -> None: ... + def ignore(self, event) -> bool: ... + +class AxesWidget(Widget): + ax: Axes + canvas: FigureCanvasBase | None + def __init__(self, ax: Axes) -> None: ... + def connect_event(self, event: Event, callback: Callable) -> None: ... + def disconnect_events(self) -> None: ... + +class Button(AxesWidget): + label: Text + color: colors.Color + hovercolor: colors.Color + def __init__( + self, + ax: Axes, + label: str, + image: ArrayLike | PIL.Image.Image | None = ..., + color: colors.Color = ..., + hovercolor: colors.Color = ..., + *, + useblit: bool = ... + ) -> None: ... + def on_clicked(self, func: Callable[[Event], Any]): ... + def disconnect(self, cid: int) -> None: ... + +class SliderBase(AxesWidget): + orientation: Literal["horizontal", "vertical"] + closedmin: bool + closedmax: bool + valmin: float + valmax: float + valstep: float | ArrayLike | None + drag_active: bool + valfmt: str + def __init__( + self, + ax: Axes, + orientation: Literal["horizontal", "vertical"], + closedmin: bool, + closedmax: bool, + valmin: float, + valmax: float, + valfmt: str, + dragging: Slider | None, + valstep: float | ArrayLike | None, + ) -> None: ... + def disconnect(self, cid: int) -> None: ... + def reset(self) -> None: ... + +class Slider(SliderBase): + slidermin: Slider | None + slidermax: Slider | None + val: float + valinit: float + track: Rectangle + poly: Polygon + hline: Line2D + vline: Line2D + label: Text + valtext: Text + def __init__( + self, + ax: Axes, + label: str, + valmin: float, + valmax: float, + valinit: float = ..., + valfmt: str | None = ..., + closedmin: bool = ..., + closedmax: bool = ..., + slidermin: Slider | None = ..., + slidermax: Slider | None = ..., + dragging: bool = ..., + valstep: float | ArrayLike | None = ..., + orientation: Literal["horizontal", "vertical"] = ..., + *, + initcolor: colors.Color = ..., + track_color: colors.Color = ..., + handle_style: dict[str, Any] | None = ..., + **kwargs + ) -> None: ... + def set_val(self, val: float) -> None: ... + def on_changed(self, func: Callable[[float], Any]) -> int: ... + +class RangeSlider(SliderBase): + val: tuple[float, float] + valinit: tuple[float, float] + track: Rectangle + poly: Polygon + label: Text + valtext: Text + def __init__( + self, + ax: Axes, + label: str, + valmin: float, + valmax: float, + valinit: tuple[float, float] | None = ..., + valfmt: str | None = ..., + closedmin: bool = ..., + closedmax: bool = ..., + dragging: bool = ..., + valstep: float | ArrayLike | None = ..., + orientation: Literal["horizontal", "vertical"] = ..., + track_color: colors.Color = ..., + handle_style: dict[str, Any] | None = ..., + **kwargs + ) -> None: ... + def set_min(self, min: float) -> None: ... + def set_max(self, max: float) -> None: ... + def set_val(self, val: ArrayLike) -> None: ... + def on_changed(self, func: Callable[[tuple[float, float]], Any]) -> int: ... + +class CheckButtons(AxesWidget): + labels: list[Text] + lines: list[tuple[Line2D, Line2D]] + rectangles: list[Rectangle] + def __init__( + self, + ax: Axes, + labels: Sequence[str], + actives: Iterable[bool] | None = ..., + *, + useblit: bool = ... + ) -> None: ... + def set_active(self, index: int) -> None: ... + def get_status(self) -> list[bool]: ... + def on_clicked(self, func: Callable[[str], Any]) -> int: ... + def disconnect(self, cid: int) -> None: ... + +class TextBox(AxesWidget): + label: Text + text_disp: Text + cursor_index: int + cursor: LineCollection + color: colors.Color + hovercolor: colors.Color + capturekeystrokes: bool + def __init__( + self, + ax: Axes, + label: str, + initial: str = ..., + color: colors.Color = ..., + hovercolor: colors.Color = ..., + label_pad: float = ..., + textalignment: Literal["left", "center", "right"] = ..., + ) -> None: ... + @property + def text(self) -> str: ... + def set_val(self, val: str) -> None: ... + def begin_typing(self, x) -> None: ... + def stop_typing(self) -> None: ... + def on_text_change(self, func: Callable[[str], Any]) -> int: ... + def on_submit(self, func: Callable[[str], Any]) -> int: ... + def disconnect(self, cid: int) -> None: ... + +class RadioButtons(AxesWidget): + activecolor: colors.Color + value_selected: str + labels: list[Text] + def __init__( + self, + ax: Axes, + labels: Iterable[str], + active: int = ..., + activecolor: colors.Color = ..., + ) -> None: ... + def set_active(self, index: int) -> None: ... + def on_clicked(self, func: Callable[[str], Any]) -> int: ... + def disconnect(self, cid: int) -> None: ... + @property + def circles(self) -> list[Circle]: ... + +class SubplotTool(Widget): + figure: Figure + targetfig: Figure + buttonreset: Button + def __init__(self, targetfig: Figure, toolfig: Figure) -> None: ... + +class Cursor(AxesWidget): + visible: bool + horizOn: bool + vertOn: bool + useblit: bool + lineh: Line2D + linev: Line2D + background: Any + needclear: bool + def __init__( + self, + ax: Axes, + horizOn: bool = ..., + vertOn: bool = ..., + useblit: bool = ..., + **lineprops + ) -> None: ... + def clear(self, event: Event) -> None: ... + def onmove(self, event: Event) -> None: ... + +class MultiCursor(Widget): + axes: Sequence[Axes] + horizOn: bool + vertOn: bool + visible: bool + useblit: bool + needclear: bool + vlines: list[Line2D] + hlines: list[Line2D] + def __init__( + self, + canvas: Any, + axes: Sequence[Axes], + useblit: bool = ..., + horizOn: bool = ..., + vertOn: bool = ..., + **lineprops + ) -> None: ... + def connect(self) -> None: ... + def disconnect(self) -> None: ... + def clear(self, event: Event) -> None: ... + def onmove(self, event: Event) -> None: ... + +class _SelectorWidget(AxesWidget): + onselect: Callable[[float, float], Any] + useblit: bool + background: Any + validButtons: list[MouseButton] + def __init__( + self, + ax: Axes, + onselect: Callable[[float, float], Any], + useblit: bool = ..., + button: MouseButton | Collection[MouseButton] | None = ..., + state_modifier_keys: dict[str, str] | None = ..., + use_data_coordinates: bool = ..., + ) -> None: ... + def update_background(self, event: Event) -> None: ... + def connect_default_events(self) -> None: ... + def ignore(self, event: Event) -> bool: ... + def update(self) -> None: ... + def press(self, event: Event) -> bool: ... + def release(self, event: Event) -> bool: ... + def onmove(self, event: Event) -> bool: ... + def on_scroll(self, event: Event) -> None: ... + def on_key_press(self, event: Event) -> None: ... + def on_key_release(self, event: Event) -> None: ... + def set_visible(self, visible: bool) -> None: ... + def get_visible(self) -> bool: ... + @property + def visible(self) -> bool: ... + @visible.setter + def visible(self, visible: bool) -> None: ... + def clear(self) -> None: ... + @property + def artists(self) -> tuple[Artist]: ... + def set_props(self, **props) -> None: ... + def set_handle_props(self, **handle_props) -> None: ... + def add_state(self, state: str) -> None: ... + def remove_state(self, state: str) -> None: ... + +class SpanSelector(_SelectorWidget): + snap_values: ArrayLike | None + onmove_callback: Callable[[float, float], Any] + minspan: float + grab_range: float + drag_from_anywhere: bool + ignore_event_outside: bool + canvas: FigureCanvasBase | None + def __init__( + self, + ax: Axes, + onselect: Callable[[float, float], Any], + direction: Literal["horizontal", "vertical"], + minspan: float = ..., + useblit: bool = ..., + props: dict[str, Any] | None = ..., + onmove_callback: Callable[[float, float], Any] | None = ..., + interactive: bool = ..., + button: MouseButton | Collection[MouseButton] | None = ..., + handle_props: dict[str, Any] | None = ..., + grab_range: float = ..., + state_modifier_keys: dict[str, str] | None = ..., + drag_from_anywhere: bool = ..., + ignore_event_outside: bool = ..., + snap_values: ArrayLike | None = ..., + ) -> None: ... + def new_axes(self, ax: Axes) -> None: ... + def connect_default_events(self) -> None: ... + @property + def direction(self) -> Literal["horizontal", "vertical"]: ... + @direction.setter + def direction(self, direction: Literal["horizontal", "vertical"]) -> None: ... + @property + def extents(self) -> tuple[float, float]: ... + @extents.setter + def extents(self, extents: tuple[float, float]) -> None: ... + +class ToolLineHandles: + ax: Axes + def __init__( + self, + ax: Axes, + positions: ArrayLike, + direction: Literal["horizontal", "vertical"], + line_props: dict[str, Any] | None = ..., + useblit: bool = ..., + ) -> None: ... + @property + def artists(self) -> tuple[Line2D]: ... + @property + def positions(self) -> list[float]: ... + @property + def direction(self) -> Literal["horizontal", "vertical"]: ... + def set_data(self, positions: ArrayLike) -> None: ... + def set_visible(self, value: bool) -> None: ... + def set_animated(self, value: bool) -> None: ... + def remove(self) -> None: ... + def closest(self, x: float, y: float) -> tuple[int, float]: ... + +class ToolHandles: + ax: Axes + def __init__( + self, + ax: Axes, + x: ArrayLike, + y: ArrayLike, + marker: str = ..., + marker_props: dict[str, Any] | None = ..., + useblit: bool = ..., + ) -> None: ... + @property + def x(self) -> ArrayLike: ... + @property + def y(self) -> ArrayLike: ... + @property + def artists(self) -> tuple[Line2D]: ... + def set_data(self, pts: ArrayLike, y: ArrayLike | None = ...) -> None: ... + def set_visible(self, val: bool) -> None: ... + def set_animated(self, val: bool) -> None: ... + def closest(self, x: float, y: float) -> tuple[int, float]: ... + +class RectangleSelector(_SelectorWidget): + drag_from_anywhere: bool + ignore_event_outside: bool + minspanx: float + minspany: float + spancoords: Literal["data", "pixels"] + grab_range: float + def __init__( + self, + ax: Axes, + onselect: Callable[[MouseEvent, MouseEvent], Any], + drawtype: str = ..., + minspanx: float = ..., + minspany: float = ..., + useblit: bool = ..., + lineprops: dict[str, Any] | None = ..., + props: dict[str, Any] | None = ..., + spancoords: Literal["data", "pixels"] = ..., + button: MouseButton | Collection[MouseButton] | None = ..., + grab_range: float = ..., + handle_props: dict[str, Any] | None = ..., + interactive: bool = ..., + state_modifier_keys: dict[str, str] | None = ..., + drag_from_anywhere: bool = ..., + ignore_event_outside: bool = ..., + use_data_coordinates: bool = ..., + ) -> None: ... + @property + def corners(self) -> tuple[np.ndarray, np.ndarray]: ... + @property + def edge_centers(self) -> tuple[np.ndarray, np.ndarray]: ... + @property + def center(self) -> tuple[float, float]: ... + @property + def extents(self) -> tuple[float, float, float, float]: ... + @extents.setter + def extents(self, extents: tuple[float, float, float, float]) -> None: ... + @property + def rotation(self) -> float: ... + @rotation.setter + def rotation(self, value: float) -> None: ... + @property + def geometry(self) -> np.ndarray: ... + +class EllipseSelector(RectangleSelector): ... + +class LassoSelector(_SelectorWidget): + verts: None | list[tuple[float, float]] + def __init__( + self, + ax: Axes, + onselect: Callable[[list[tuple[float, float]]], Any] | None = ..., + useblit: bool = ..., + props: dict[str, Any] | None = ..., + button: MouseButton | Collection[MouseButton] | None = ..., + ) -> None: ... + +class PolygonSelector(_SelectorWidget): + grab_range: float + def __init__( + self, + ax: Axes, + onselect: Callable[[ArrayLike, ArrayLike], Any], + useblit: bool = ..., + props: dict[str, Any] | None = ..., + handle_props: dict[str, Any] | None = ..., + grab_range: float = ..., + *, + draw_bounding_box: bool = ..., + box_handle_props: dict[str, Any] | None = ..., + box_props: dict[str, Any] | None = ... + ) -> None: ... + def onmove(self, event: Event) -> bool: ... + @property + def verts(self) -> list[tuple[float, float]]: ... + @verts.setter + def verts(self, xys: Sequence[tuple[float, float]]) -> None: ... + +class Lasso(AxesWidget): + useblit: bool + background: Any + verts: list[tuple[float, float]] | None + line: Line2D + callback: Callable[[list[tuple[float, float]]], Any] + def __init__( + self, + ax: Axes, + xy: tuple[float, float], + callback: Callable[[list[tuple[float, float]]], Any] | None = ..., + useblit: bool = ..., + ) -> None: ... + def onrelease(self, event: Event) -> None: ... + def onmove(self, event: Event) -> None: ... diff --git a/lib/mpl_toolkits/axes_grid1/axes_divider.py b/lib/mpl_toolkits/axes_grid1/axes_divider.py index 143a2f35cb19..2a6bd0d5da08 100644 --- a/lib/mpl_toolkits/axes_grid1/axes_divider.py +++ b/lib/mpl_toolkits/axes_grid1/axes_divider.py @@ -202,17 +202,9 @@ def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None): x0, y0 = x, y if nx1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing nx1=None to mean nx+1 is " - "deprecated since %(since)s; in a future version, nx1=None " - "will mean 'up to the last cell'.") - nx1 = nx + 1 + nx1 = -1 if ny1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing ny1=None to mean ny+1 is " - "deprecated since %(since)s; in a future version, ny1=None " - "will mean 'up to the last cell'.") - ny1 = ny + 1 + ny1 = -1 x1, w1 = x0 + ox[nx] / fig_w, (ox[nx1] - ox[nx]) / fig_w y1, h1 = y0 + oy[ny] / fig_h, (oy[ny1] - oy[ny]) / fig_h @@ -299,17 +291,9 @@ def __init__(self, axes_divider, nx, ny, nx1=None, ny1=None): self._nx, self._ny = nx - _xrefindex, ny - _yrefindex if nx1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing nx1=None to mean nx+1 is " - "deprecated since %(since)s; in a future version, nx1=None " - "will mean 'up to the last cell'.") - nx1 = nx + 1 + nx1 = len(self._axes_divider) if ny1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing ny1=None to mean ny+1 is " - "deprecated since %(since)s; in a future version, ny1=None " - "will mean 'up to the last cell'.") - ny1 = ny + 1 + ny1 = len(self._axes_divider[0]) self._nx1 = nx1 - _xrefindex self._ny1 = ny1 - _yrefindex @@ -600,11 +584,7 @@ def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None): x0, y0, ox, hh = _locate( x, y, w, h, summed_ws, equal_hs, fig_w, fig_h, self.get_anchor()) if nx1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing nx1=None to mean nx+1 is " - "deprecated since %(since)s; in a future version, nx1=None " - "will mean 'up to the last cell'.") - nx1 = nx + 1 + nx1 = -1 x1, w1 = x0 + ox[nx] / fig_w, (ox[nx1] - ox[nx]) / fig_w y1, h1 = y0, hh return mtransforms.Bbox.from_bounds(x1, y1, w1, h1) @@ -639,11 +619,7 @@ def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None): y0, x0, oy, ww = _locate( y, x, h, w, summed_hs, equal_ws, fig_h, fig_w, self.get_anchor()) if ny1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing ny1=None to mean ny+1 is " - "deprecated since %(since)s; in a future version, ny1=None " - "will mean 'up to the last cell'.") - ny1 = ny + 1 + ny1 = -1 x1, w1 = x0, ww y1, h1 = y0 + oy[ny] / fig_h, (oy[ny1] - oy[ny]) / fig_h return mtransforms.Bbox.from_bounds(x1, y1, w1, h1) diff --git a/lib/mpl_toolkits/axes_grid1/axes_grid.py b/lib/mpl_toolkits/axes_grid1/axes_grid.py index 51925bfde5e3..1d6d6265e86f 100644 --- a/lib/mpl_toolkits/axes_grid1/axes_grid.py +++ b/lib/mpl_toolkits/axes_grid1/axes_grid.py @@ -20,7 +20,6 @@ def _tick_only(ax, bottom_on, left_on): class CbarAxesBase: def __init__(self, *args, orientation, **kwargs): self.orientation = orientation - self._locator = None # deprecated. super().__init__(*args, **kwargs) def colorbar(self, mappable, *, ticks=None, **kwargs): diff --git a/pyproject.toml b/pyproject.toml index 907b05a39ba4..df5c025eb310 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,3 +6,6 @@ requires = [ "pybind11>=2.6", "setuptools_scm>=7", ] + +[tool.mypy] +exclude = ["lib/matplotlib/(sphinxext|backends|testing)", "lib/mpl_toolkits"] diff --git a/requirements/testing/all.txt b/requirements/testing/all.txt index 299cb0817dcb..173c5a4a9909 100644 --- a/requirements/testing/all.txt +++ b/requirements/testing/all.txt @@ -1,5 +1,6 @@ # pip requirements for all the CI builds +black certifi coverage!=6.3 psutil diff --git a/requirements/testing/mypy.txt b/requirements/testing/mypy.txt new file mode 100644 index 000000000000..93a7fc7e39ca --- /dev/null +++ b/requirements/testing/mypy.txt @@ -0,0 +1,27 @@ +# Extra pip requirements for the GitHub Actions flake8 build + +mypy + +# Extra stubs distributed separately from the main pypi package +pandas-stubs +types-pillow +types-python-dateutil +types-psutil + +sphinx + +# Default requirements, included here because mpl itself does not +# need to be installed for mypy to run, but deps are needed +# and pip has no --deps-only install command +contourpy>=1.0.1 +cycler>=0.10 +fonttools>=4.22.0 +kiwisolver>=1.0.1 +numpy>=1.19 +packaging>=20.0 +pillow>=6.2.0 +pyparsing>=2.3.1 +python-dateutil>=2.7 +setuptools_scm>=7 + +importlib-resources>=3.2.0 ; python_version < "3.10" diff --git a/tools/boilerplate.py b/tools/boilerplate.py index 0b00d7a12b4a..0ea5afb8f40b 100644 --- a/tools/boilerplate.py +++ b/tools/boilerplate.py @@ -13,12 +13,15 @@ # runtime with the proper signatures, a static pyplot.py is simpler for static # analysis tools to parse. +import ast from enum import Enum +import functools import inspect from inspect import Parameter from pathlib import Path import sys -import textwrap +import subprocess + # This line imports the installed copy of matplotlib, and not the local copy. import numpy as np @@ -117,6 +120,17 @@ def __repr__(self): return self._repr +class direct_repr: + """ + A placeholder class to destringify annotations from ast + """ + def __init__(self, value): + self._repr = value + + def __repr__(self): + return self._repr + + def generate_function(name, called_fullname, template, **kwargs): """ Create a wrapper function *pyplot_name* calling *call_name*. @@ -139,10 +153,6 @@ def generate_function(name, called_fullname, template, **kwargs): **kwargs Additional parameters are passed to ``template.format()``. """ - text_wrapper = textwrap.TextWrapper( - break_long_words=False, width=70, - initial_indent=' ' * 8, subsequent_indent=' ' * 8) - # Get signature of wrapped function. class_name, called_name = called_fullname.split('.') class_ = {'Axes': Axes, 'Figure': Figure}[class_name] @@ -153,16 +163,16 @@ def generate_function(name, called_fullname, template, **kwargs): # redecorated with make_keyword_only by _copy_docstring_and_deprecators. if decorator and decorator.func is _api.make_keyword_only: meth = meth.__wrapped__ - signature = inspect.signature(meth) + + annotated_trees = get_ast_mro_trees(class_) + signature = get_matching_signature(meth, annotated_trees) + # Replace self argument. params = list(signature.parameters.values())[1:] signature = str(signature.replace(parameters=[ param.replace(default=value_formatter(param.default)) if param.default is not param.empty else param for param in params])) - if len('def ' + name + signature) >= 80: - # Move opening parenthesis before newline. - signature = '(\n' + text_wrapper.fill(signature).replace('(', '', 1) # How to call the wrapped function. call = '(' + ', '.join(( # Pass "intended-as-positional" parameters positionally to avoid @@ -174,9 +184,6 @@ def generate_function(name, called_fullname, template, **kwargs): # Only pass the data kwarg if it is actually set, to avoid forcing # third-party subclasses to support it. '**({{"data": data}} if data is not None else {{}})' - # Avoid linebreaks in the middle of the expression, by using \0 as a - # placeholder that will be substituted after wrapping. - .replace(' ', '\0') if param.name == "data" else '{0}={0}' if param.kind in [ @@ -190,9 +197,6 @@ def generate_function(name, called_fullname, template, **kwargs): if param.kind is Parameter.VAR_KEYWORD else None).format(param.name) for param in params) + ')' - MAX_CALL_PREFIX = 18 # len(' __ret = gca().') - if MAX_CALL_PREFIX + max(len(name), len(called_name)) + len(call) >= 80: - call = '(\n' + text_wrapper.fill(call[1:]).replace('\0', ' ') # Bail out in case of name collision. for reserved in ('gca', 'gci', 'gcf', '__ret'): if reserved in params: @@ -379,6 +383,79 @@ def build_pyplot(pyplot_path): pyplot.writelines(pyplot_orig) pyplot.writelines(boilerplate_gen()) + # Run black to autoformat pyplot + subprocess.run( + [sys.executable, "-m", "black", "--line-length=79", pyplot_path] + ) + + +### Methods for retrieving signatures from pyi stub files + +def get_ast_tree(cls): + path = Path(inspect.getfile(cls)) + stubpath = path.with_suffix(".pyi") + path = stubpath if stubpath.exists() else path + tree = ast.parse(path.read_text()) + for item in tree.body: + if isinstance(item, ast.ClassDef) and item.name == cls.__name__: + return item + raise ValueError(f"Cannot find {cls.__name__} in ast") + + +@functools.lru_cache +def get_ast_mro_trees(cls): + return [get_ast_tree(c) for c in cls.__mro__ if c.__module__ != "builtins"] + + +def get_matching_signature(method, trees): + sig = inspect.signature(method) + for tree in trees: + for item in tree.body: + if not isinstance(item, ast.FunctionDef): + continue + if item.name == method.__name__: + return update_sig_from_node(item, sig) + # The following methods are implemented outside of the mro of Axes + # and thus do not get their annotated versions found with current code + # stackplot + # streamplot + # table + # tricontour + # tricontourf + # tripcolor + # triplot + + # import warnings + # warnings.warn(f"'{method.__name__}' not found") + return sig + + +def update_sig_from_node(node, sig): + params = dict(sig.parameters) + args = node.args + allargs = ( + *args.posonlyargs, + *args.args, + args.vararg, + *args.kwonlyargs, + args.kwarg, + ) + for param in allargs: + if param is None: + continue + if param.annotation is None: + continue + annotation = direct_repr(ast.unparse(param.annotation)) + params[param.arg] = params[param.arg].replace(annotation=annotation) + + if node.returns is not None: + return inspect.Signature( + params.values(), + return_annotation=direct_repr(ast.unparse(node.returns)) + ) + else: + return inspect.Signature(params.values()) + if __name__ == '__main__': # Write the matplotlib.pyplot file.