Skip to content

Type hinting developer docs #26051

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 4 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions ci/mypy-stubtest-allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,14 @@ 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.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
matplotlib.ticker.LogLocator.__init__
matplotlib.ticker.LogLocator.set_params

Expand Down
2 changes: 2 additions & 0 deletions doc/devel/coding_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ will run on all supported platforms and versions of Python.

- If *Linting* fails, you have a code style issue, which will be listed
as annotations on the pull request's diff.
- If *Mypy* or *Stubtest* fails, you have inconsistency in type hints, which
will be listed as annotations in the diff.
- If a GitHub Actions or AppVeyor run fails, search the log for ``FAILURES``.
The subsequent section will contain information on the failed tests.
- If CircleCI fails, likely you have some reStructuredText style issue in
Expand Down
33 changes: 33 additions & 0 deletions doc/devel/contribute.rst
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ Introducing
- Use ``_api.warn_deprecated()`` for general deprecation warnings
- Use the decorator ``@_api.deprecated`` to deprecate classes, functions,
methods, or properties
- Use ``@_api.deprecate_privatize_attribute`` to annotate deprecation of
attributes while keeping the internal private version.
- To warn on changes of the function signature, use the decorators
``@_api.delete_parameter``, ``@_api.rename_parameter``, and
``@_api.make_keyword_only``
Expand All @@ -354,6 +356,23 @@ Introducing

You can use standard rst cross references in *alternative*.

3. Make appropriate changes to the type hints in the associated ``.pyi`` file.
The general guideline is to match runtime reported behavior.

- Items marked with ``@_api.deprecated`` or ``@_api.deprecate_privatize_attribute``
are generally kept during the expiry period, and thus no changes are needed on
introduction.
- Items decorated with ``@_api.rename_parameter`` or ``@_api.make_keyword_only``
report the *new* (post deprecation) signature at runtime, and thus *should* be
updated on introduction.
- Items decorated with ``@_api.delete_parameter`` should include a default value hint
for the deleted parameter, even if it did not previously have one (e.g.
``param: <type> = ...``). Even so, the decorator changes the default value to a
sentinel value which should not be included in the type stub. Thus, Mypy Stubtest
needs to be informed of the inconsistency by placing the method into
:file:`ci/mypy-stubtest-allowlist.txt` under a heading indicating the deprecation
version number.

Expiring
~~~~~~~~

Expand All @@ -365,6 +384,19 @@ Expiring
information. For the content, you can usually copy the deprecation notice
and adapt it slightly.
2. Change the code functionality and remove any related deprecation warnings.
3. Make appropriate changes to the type hints in the associated ``.pyi`` file.

- Items marked with ``@_api.deprecated`` or ``@_api.deprecate_privatize_attribute``
are to be removed on expiry.
- Items decorated with ``@_api.rename_parameter`` or ``@_api.make_keyword_only``
will have been updated at introduction, and require no change now.
- Items decorated with ``@_api.delete_parameter`` will need to be updated to the
final signature, in the same way as the ``.py`` file signature is updated.
The entry in :file:`ci/mypy-stubtest-allowlist.txt` should be removed.
- Any other entries in :file:`ci/mypy-stubtest-allowlist.txt` under a version's
deprecations should be double checked, as only ``delete_parameter`` should normally
require that mechanism for deprecation. For removed items that were not in the stub
file, only deleting from the allowlist is required.

Adding new API
--------------
Expand All @@ -391,6 +423,7 @@ New modules and files: installation
* If you have added new files or directories, or reorganized existing
ones, make sure the new files are included in the match patterns in
in *package_data* in :file:`setupext.py`.
* New modules *may* be typed inline or using parallel stub file like existing modules.

C/C++ extensions
----------------
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/axes/_base.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,9 @@ class _AxesBase(martist.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: ...
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/figure.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ class FigureBase(Artist):
def get_tightbbox(
self,
renderer: RendererBase | None = ...,
*,
bbox_extra_artists: Iterable[Artist] | None = ...,
) -> Bbox: ...

Expand Down
12 changes: 10 additions & 2 deletions lib/matplotlib/widgets.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class Slider(SliderBase):
label: str,
valmin: float,
valmax: float,
*,
valinit: float = ...,
valfmt: str | None = ...,
closedmin: bool = ...,
Expand All @@ -105,7 +106,6 @@ class Slider(SliderBase):
dragging: bool = ...,
valstep: float | ArrayLike | None = ...,
orientation: Literal["horizontal", "vertical"] = ...,
*,
initcolor: ColorType = ...,
track_color: ColorType = ...,
handle_style: dict[str, Any] | None = ...,
Expand All @@ -127,6 +127,7 @@ class RangeSlider(SliderBase):
label: str,
valmin: float,
valmax: float,
*,
valinit: tuple[float, float] | None = ...,
valfmt: str | None = ...,
closedmin: bool = ...,
Expand Down Expand Up @@ -181,6 +182,7 @@ class TextBox(AxesWidget):
ax: Axes,
label: str,
initial: str = ...,
*,
color: ColorType = ...,
hovercolor: ColorType = ...,
label_pad: float = ...,
Expand Down Expand Up @@ -236,6 +238,7 @@ class Cursor(AxesWidget):
def __init__(
self,
ax: Axes,
*,
horizOn: bool = ...,
vertOn: bool = ...,
useblit: bool = ...,
Expand Down Expand Up @@ -317,6 +320,7 @@ class SpanSelector(_SelectorWidget):
ax: Axes,
onselect: Callable[[float, float], Any],
direction: Literal["horizontal", "vertical"],
*,
minspan: float = ...,
useblit: bool = ...,
props: dict[str, Any] | None = ...,
Expand Down Expand Up @@ -348,6 +352,7 @@ class ToolLineHandles:
ax: Axes,
positions: ArrayLike,
direction: Literal["horizontal", "vertical"],
*,
line_props: dict[str, Any] | None = ...,
useblit: bool = ...,
) -> None: ...
Expand All @@ -370,6 +375,7 @@ class ToolHandles:
ax: Axes,
x: ArrayLike,
y: ArrayLike,
*,
marker: str = ...,
marker_props: dict[str, Any] | None = ...,
useblit: bool = ...,
Expand Down Expand Up @@ -436,6 +442,7 @@ class LassoSelector(_SelectorWidget):
self,
ax: Axes,
onselect: Callable[[list[tuple[float, float]]], Any],
*,
useblit: bool = ...,
props: dict[str, Any] | None = ...,
button: MouseButton | Collection[MouseButton] | None = ...,
Expand All @@ -447,11 +454,11 @@ class PolygonSelector(_SelectorWidget):
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 = ...
Expand All @@ -473,6 +480,7 @@ class Lasso(AxesWidget):
ax: Axes,
xy: tuple[float, float],
callback: Callable[[list[tuple[float, float]]], Any],
*,
useblit: bool = ...,
) -> None: ...
def onrelease(self, event: Event) -> None: ...
Expand Down