Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Initial implementation of type stubs (mypy/PEP484) #24976

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
26b0114
Initially make mypy pass for tests
ksunden Dec 7, 2022
9b341f1
Insert the majority of the pyi stub files
ksunden Dec 9, 2022
0205b4a
__init__.pyi, add __all__ to __init__
ksunden Dec 14, 2022
4fe4fab
Add mypy to reviewdog workflow
ksunden Dec 27, 2022
e0d5ab8
Add __future__ imports to tests where inline type hints are included
ksunden Dec 27, 2022
f2b6a6c
Update boilerplate to include annotations from pyi files
ksunden Jan 3, 2023
189e0a2
pyplot autogenerated bits with annotations
ksunden Jan 3, 2023
191b374
Use black for autogenerated portions of pyplot. remove textwrap usage
ksunden Jan 5, 2023
b094c38
Type handwritten portion of pyplot
ksunden Jan 4, 2023
8479f2b
Update for api changes since mypy branch was started
ksunden Jan 5, 2023
0da7900
STY: run black over pyi stub files
ksunden Jan 6, 2023
aee7c2e
Make Color a union type of 3/4-tuple of floats and str
ksunden Jan 6, 2023
46d6c01
Resolve some typing todos
ksunden Jan 6, 2023
333de75
Update Axes.pyi pie stub to include hatch, regenerate pyplot with hat…
ksunden Jan 11, 2023
94e6f7b
Redistribute types defined in _typing to their logical homes
ksunden Jan 11, 2023
2f44fbc
Get sphinx building without errors
ksunden Jan 12, 2023
bd9d307
Update for expired 3.5 deprecations
ksunden Jan 13, 2023
fda8600
Boilerplate.py review comments
ksunden Jan 16, 2023
ef5713e
Review and CI warnings
ksunden Jan 17, 2023
13eb563
DOC: Add development release note and note to add type hints into cod…
ksunden Feb 23, 2023
10d2225
Add more explicit error message for [r,theta]grids
ksunden Feb 23, 2023
253b5ab
Best practices for type hint stub files (flake8-pyi)
ksunden Feb 28, 2023
10c9b7c
Reorganize to typing.py, rename Color to ColorType
ksunden Feb 28, 2023
f7aa64a
Update for recent internal API changes
ksunden Mar 1, 2023
3580507
Add script for identifying missing/broken type hints
ksunden Mar 1, 2023
97ad790
DOC: Update sphinx to include typing module (and remove aliases which…
ksunden Mar 9, 2023
eaa97fb
Mypy type ignore in pyplot
ksunden Mar 8, 2023
e19f283
Address approx 100 issues identified by mypy.stubtest
ksunden Mar 9, 2023
75275b1
Add mypy stubtest CI checks
ksunden Mar 22, 2023
16c75ad
Include pyi stubs in wheels/sdists
ksunden Mar 22, 2023
5ddea14
Ignore missing imports in mypy config
ksunden Mar 22, 2023
7f6bca9
Relax excludes on mypy config to not require source loc 'lib/'
ksunden Mar 22, 2023
f98df12
Fix missing stubs from ci that didn't flag locally
ksunden Mar 22, 2023
ae6744d
Re disambiguate pyplot Axes references
ksunden Mar 22, 2023
055b648
Add docs to tools/check_typehints.py
ksunden Mar 29, 2023
76316a9
Update for changes on main: Axes.ecdf, guiEvent read only, param depr…
ksunden Mar 29, 2023
bd4469d
Review comments from Qulogic
ksunden Mar 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ exclude_lines =
def __str__
def __repr__
if __name__ == .__main__.:
if TYPE_CHECKING:
if typing.TYPE_CHECKING:
30 changes: 30 additions & 0 deletions .github/workflows/mypy-stubtest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
name: Mypy Stubtest
on: [pull_request]

permissions:
contents: read
checks: write

jobs:
mypy-stubtest:
name: mypy-stubtest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Python 3
uses: actions/setup-python@v4
with:
python-version: 3.9

- name: Install mypy
run: |
pip3 install -r requirements/testing/mypy.txt -r requirements/testing/all.txt
pip3 install .

- name: Run mypy stubtest
run: |
# the ignore missing imports can be removed when typed cycler is released and used
MPLBACKEND=agg python -m mypy.stubtest matplotlib --mypy-config-file pyproject.toml \
--allowlist ci/mypy-stubtest-allowlist.txt
34 changes: 34 additions & 0 deletions .github/workflows/reviewdog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.9

- 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
Expand Down
257 changes: 257 additions & 0 deletions ci/mypy-stubtest-allowlist.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
# Non-typed (and private) modules/functions
matplotlib.backends.*
matplotlib.tests.*
matplotlib.pylab.*
matplotlib._.*
matplotlib.rcsetup._listify_validator
matplotlib.rcsetup._validate_linestyle
matplotlib.ft2font.*
matplotlib.testing.*
matplotlib.sphinxext.*

# set methods have heavy dynamic usage of **kwargs, with differences for subclasses
# which results in technically inconsistent signatures, but not actually a problem
matplotlib.*\.set$

# Typed inline, inconsistencies largely due to imports
matplotlib.pyplot.*
matplotlib.typing.*

# _preprocess_data arg decorator
matplotlib.axes.*Axes.acorr
matplotlib.axes.*Axes.angle_spectrum
matplotlib.axes.*Axes.bar
matplotlib.axes.*Axes.barbs
matplotlib.axes.*Axes.boxplot
matplotlib.axes.*Axes.broken_barh
matplotlib.axes.*Axes.cohere
matplotlib.axes.*Axes.contour
matplotlib.axes.*Axes.contourf
matplotlib.axes.*Axes.csd
matplotlib.axes.*Axes.ecdf
matplotlib.axes.*Axes.errorbar
matplotlib.axes.*Axes.eventplot
matplotlib.axes.*Axes.fill_between
matplotlib.axes.*Axes.fill_betweenx
matplotlib.axes.*Axes.hexbin
matplotlib.axes.*Axes.hist
matplotlib.axes.*Axes.hist2d
matplotlib.axes.*Axes.hlines
matplotlib.axes.*Axes.imshow
matplotlib.axes.*Axes.magnitude_spectrum
matplotlib.axes.*Axes.pcolor
matplotlib.axes.*Axes.pcolorfast
matplotlib.axes.*Axes.pcolormesh
matplotlib.axes.*Axes.phase_spectrum
matplotlib.axes.*Axes.pie
matplotlib.axes.*Axes.plot_date
matplotlib.axes.*Axes.psd
matplotlib.axes.*Axes.quiver
matplotlib.axes.*Axes.scatter
matplotlib.axes.*Axes.specgram
matplotlib.axes.*Axes.stairs
matplotlib.axes.*Axes.stem
matplotlib.axes.*Axes.violinplot
matplotlib.axes.*Axes.vlines
matplotlib.axes.*Axes.xcorr

# Other decorator modifying signature (maybe investigate)
matplotlib.axis.Axis.draw
matplotlib.offsetbox.*Offset[Bb]ox.get_offset

# Inconsistent super/sub class signatures (other than just arg name)
matplotlib.ticker.MultipleLocator.set_params
matplotlib.text.Annotation.get_window_extent

# Inconsistent super/sub class parameter name (maybe rename for consistency)
matplotlib.axis.Axis.set_clip_path
matplotlib.axis.Tick.set_clip_path
matplotlib.image.NonUniformImage.set_filternorm
matplotlib.image.NonUniformImage.set_filterrad
matplotlib.projections.geo.AitoffAxes.AitoffTransform.transform_non_affine
matplotlib.projections.geo.AitoffAxes.InvertedAitoffTransform.transform_non_affine
matplotlib.projections.geo.HammerAxes.HammerTransform.transform_non_affine
matplotlib.projections.geo.HammerAxes.InvertedHammerTransform.transform_non_affine
matplotlib.projections.geo.LambertAxes.InvertedLambertTransform.transform_non_affine
matplotlib.projections.geo.LambertAxes.LambertTransform.transform_non_affine
matplotlib.projections.geo.MollweideAxes.InvertedMollweideTransform.transform_non_affine
matplotlib.projections.geo.MollweideAxes.MollweideTransform.transform_non_affine
matplotlib.projections.polar.InvertedPolarTransform.transform_non_affine
matplotlib.projections.polar.PolarTransform.transform_non_affine
matplotlib.projections.polar.RadialLocator.nonsingular
matplotlib.scale.AsinhTransform.transform_non_affine
matplotlib.scale.InvertedAsinhTransform.transform_non_affine
matplotlib.scale.InvertedSymmetricalLogTransform.transform_non_affine
matplotlib.scale.LogisticTransform.transform_non_affine
matplotlib.scale.LogitTransform.transform_non_affine
matplotlib.scale.SymmetricalLogTransform.transform_non_affine
matplotlib.table.Cell.set_transform
matplotlib.ticker.LogLocator.nonsingular
matplotlib.ticker.LogitLocator.nonsingular
matplotlib.transforms.Affine2DBase.transform_affine
matplotlib.transforms.AffineBase.transform_non_affine
matplotlib.transforms.BlendedGenericTransform.transform_non_affine
matplotlib.transforms.CompositeGenericTransform.transform_affine
matplotlib.transforms.CompositeGenericTransform.transform_non_affine
matplotlib.transforms.IdentityTransform.transform_affine
matplotlib.transforms.IdentityTransform.transform_non_affine
matplotlib.transforms.IdentityTransform.transform

# Stdlib/Enum considered inconsistent (no fault of ours, I don't think)
matplotlib.backend_bases._Mode.__new__
matplotlib.units.Number.__hash__

# Property read-write vs read-only weirdness, fix if possible
matplotlib.offsetbox.DraggableBase.canvas
matplotlib.offsetbox.DraggableBase.cids
matplotlib.transforms.BboxTransform.is_separable
matplotlib.transforms.BboxTransformFrom.is_separable
matplotlib.transforms.BboxTransformTo.is_separable
matplotlib.transforms.BlendedAffine2D.is_separable
matplotlib.transforms.CompositeGenericTransform.is_separable
matplotlib.transforms.TransformWrapper.input_dims
matplotlib.transforms.TransformWrapper.is_separable
matplotlib.transforms.TransformWrapper.output_dims

# 3.6 deprecations
matplotlib.colorbar.Colorbar.__init__
matplotlib.figure.Figure.callbacks
matplotlib.figure.Figure.set_constrained_layout
matplotlib.figure.Figure.set_constrained_layout_pads
matplotlib.figure.Figure.set_tight_layout
matplotlib.figure.SubFigure.callbacks

# 3.7 deprecations
matplotlib.cm.register_cmap
matplotlib.cm.unregister_cmap
matplotlib.collections.PolyCollection.span_where
matplotlib.gridspec.GridSpecBase.get_grid_positions
matplotlib.widgets.Lasso.__init__
matplotlib.widgets.PolygonSelector.__init__
matplotlib.widgets.Slider.__init__
matplotlib.widgets.RangeSlider.__init__
matplotlib.widgets.TextBox.__init__
matplotlib.widgets.Cursor.__init__
matplotlib.widgets.MultiCursor.__init__
matplotlib.widgets.SpanSelector.__init__
matplotlib.widgets.ToolLineHandles.__init__
matplotlib.widgets.ToolHandles.__init__
matplotlib.widgets.LassoSelector.__init__
matplotlib.widgets.MultiCursor.needclear

# 3.8 deprecations
matplotlib.axes._base._AxesBase.get_tightbbox
matplotlib.cbook.get_sample_data
matplotlib.contour.ContourSet.allkinds
matplotlib.contour.ContourSet.allsegs
matplotlib.contour.ContourSet.tcolors
matplotlib.contour.ContourSet.tlinewidths
matplotlib.figure.FigureBase.get_tightbbox

# positional-only argument name lacking leading underscores
matplotlib.axes._base._AxesBase.axis

# Aliases (dynamically generated, not type hinted)
matplotlib.collections.Collection.get_dashes
matplotlib.collections.Collection.get_ec
matplotlib.collections.Collection.get_edgecolors
matplotlib.collections.Collection.get_facecolors
matplotlib.collections.Collection.get_fc
matplotlib.collections.Collection.get_linestyles
matplotlib.collections.Collection.get_linewidths
matplotlib.collections.Collection.get_ls
matplotlib.collections.Collection.get_lw
matplotlib.collections.Collection.get_transOffset
matplotlib.collections.Collection.set_aa
matplotlib.collections.Collection.set_antialiaseds
matplotlib.collections.Collection.set_dashes
matplotlib.collections.Collection.set_ec
matplotlib.collections.Collection.set_edgecolors
matplotlib.collections.Collection.set_facecolors
matplotlib.collections.Collection.set_fc
matplotlib.collections.Collection.set_linestyles
matplotlib.collections.Collection.set_linewidths
matplotlib.collections.Collection.set_ls
matplotlib.collections.Collection.set_lw
matplotlib.collections.Collection.set_transOffset
matplotlib.lines.Line2D.get_aa
matplotlib.lines.Line2D.get_c
matplotlib.lines.Line2D.get_ds
matplotlib.lines.Line2D.get_ls
matplotlib.lines.Line2D.get_lw
matplotlib.lines.Line2D.get_mec
matplotlib.lines.Line2D.get_mew
matplotlib.lines.Line2D.get_mfc
matplotlib.lines.Line2D.get_mfcalt
matplotlib.lines.Line2D.get_ms
matplotlib.lines.Line2D.set_aa
matplotlib.lines.Line2D.set_c
matplotlib.lines.Line2D.set_ds
matplotlib.lines.Line2D.set_ls
matplotlib.lines.Line2D.set_lw
matplotlib.lines.Line2D.set_mec
matplotlib.lines.Line2D.set_mew
matplotlib.lines.Line2D.set_mfc
matplotlib.lines.Line2D.set_mfcalt
matplotlib.lines.Line2D.set_ms
matplotlib.patches.Patch.get_aa
matplotlib.patches.Patch.get_ec
matplotlib.patches.Patch.get_fc
matplotlib.patches.Patch.get_ls
matplotlib.patches.Patch.get_lw
matplotlib.patches.Patch.set_aa
matplotlib.patches.Patch.set_ec
matplotlib.patches.Patch.set_fc
matplotlib.patches.Patch.set_ls
matplotlib.patches.Patch.set_lw
matplotlib.text.Text.get_c
matplotlib.text.Text.get_family
matplotlib.text.Text.get_font
matplotlib.text.Text.get_font_properties
matplotlib.text.Text.get_ha
matplotlib.text.Text.get_name
matplotlib.text.Text.get_size
matplotlib.text.Text.get_style
matplotlib.text.Text.get_va
matplotlib.text.Text.get_variant
matplotlib.text.Text.get_weight
matplotlib.text.Text.set_c
matplotlib.text.Text.set_family
matplotlib.text.Text.set_font
matplotlib.text.Text.set_font_properties
matplotlib.text.Text.set_ha
matplotlib.text.Text.set_ma
matplotlib.text.Text.set_name
matplotlib.text.Text.set_size
matplotlib.text.Text.set_stretch
matplotlib.text.Text.set_style
matplotlib.text.Text.set_va
matplotlib.text.Text.set_variant
matplotlib.text.Text.set_weight
matplotlib.axes._base._AxesBase.get_fc
matplotlib.axes._base._AxesBase.set_fc

# Other dynamic python behaviors not type hinted
matplotlib.projections.polar.PolarAxes.InvertedPolarTransform
matplotlib.projections.polar.PolarAxes.PolarAffine
matplotlib.projections.polar.PolarAxes.PolarTransform
matplotlib.projections.polar.PolarAxes.RadialLocator
matplotlib.projections.polar.PolarAxes.ThetaFormatter
matplotlib.projections.polar.PolarAxes.ThetaLocator
matplotlib.rcsetup.defaultParams

# Maybe should be abstractmethods, required for subclasses, stubs define once
matplotlib.tri.*TriInterpolator.__call__
matplotlib.tri.*TriInterpolator.gradient

# Functionally a method call, but actually a class instance, type hinted as former
matplotlib.rcsetup.validate_fillstyle

# C-defined method without docstring indicating signature
matplotlib.transforms.count_bboxes_overlapping_bbox
matplotlib.transforms.update_path_extents

# TypeVar used only in type hints
matplotlib.backend_bases.FigureCanvasBase._T
matplotlib.backend_managers.ToolManager._T
matplotlib.spines.Spine._T
1 change: 1 addition & 0 deletions doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ Alphabetical list of modules:
transformations.rst
tri_api.rst
type1font.rst
typing_api.rst
units_api.rst
widgets_api.rst
_api_api.rst
Expand Down
18 changes: 18 additions & 0 deletions doc/api/next_api_changes/development/24976-KS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Provisional support for PEP484 Type Hint Annotations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

New public API should be type hinted in ``.pyi`` stub files (except ``pyplot`` and tests
which are typed in-line).
Tests should be type hinted minimally, essentially only when ``mypy`` generates errors.

CI and configuration for running ``mypy`` have been added.


Generation of ``pyplot.py`` requires ``black``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The autogenerated portions of ``pyplot.py`` use ``black`` autoformatting to ensure
syntax-correct, readable output code.

As such ``black`` is now a development and test requirement (for the test which
regenerates ``pyplot``).
11 changes: 11 additions & 0 deletions doc/api/typing_api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*********************
``matplotlib.typing``
*********************

.. autodata:: matplotlib.typing.ColorType
.. autodata:: matplotlib.typing.ColourType
.. autodata:: matplotlib.typing.LineStyleType
.. autodata:: matplotlib.typing.DrawStyleType
.. autodata:: matplotlib.typing.MarkEveryType
.. autodata:: matplotlib.typing.FillStyleType
.. autodata:: matplotlib.typing.RcStyleType
5 changes: 5 additions & 0 deletions doc/devel/coding_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ rules before submitting a pull request:
by the contributor's initials. (see :file:`doc/api/api_changes.rst` for more
information)

* If you add new public API or change public API, update or add the
corresponding type hints. Most often this is found in the corresponding
``.pyi`` file for the ``.py`` file which was edited. Changes in ``pyplot.py``
are type hinted inline.

* See below for additional points about :ref:`keyword-argument-processing`, if
applicable for your pull request.

Expand Down
Loading