From c768050024a256223afd164df0d06e0bee98d640 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Tue, 9 May 2023 18:48:27 -0500 Subject: [PATCH] [TYP] Reduce stubtest ignores Broadly makes the type hints more reflective of runtime behavior, though does incur some type:ignore comments because of sub/superclass interactions --- ci/mypy-stubtest-allowlist.txt | 18 +++--------------- lib/matplotlib/_path.pyi | 4 ++-- lib/matplotlib/projections/polar.pyi | 10 +++++++++- lib/matplotlib/text.pyi | 2 ++ lib/matplotlib/ticker.pyi | 5 ++++- lib/matplotlib/transforms.pyi | 5 ----- 6 files changed, 20 insertions(+), 24 deletions(-) diff --git a/ci/mypy-stubtest-allowlist.txt b/ci/mypy-stubtest-allowlist.txt index d6419ca0cff4..58daf948c03b 100644 --- a/ci/mypy-stubtest-allowlist.txt +++ b/ci/mypy-stubtest-allowlist.txt @@ -17,14 +17,12 @@ matplotlib.*\.set$ matplotlib.pyplot.* matplotlib.typing.* -# Other decorator modifying signature (maybe investigate) +# Other decorator modifying signature +# Runtime picks up *args **kwargs, but only decorated by a decorator that uses @wraps so? matplotlib.axis.Axis.draw +# Backcompat decorator which does not modify runtime reported signature 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.projections.polar.RadialLocator.nonsingular matplotlib.ticker.LogLocator.nonsingular @@ -163,12 +161,6 @@ 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 @@ -178,10 +170,6 @@ 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 diff --git a/lib/matplotlib/_path.pyi b/lib/matplotlib/_path.pyi index c5491adcad35..5656375953da 100644 --- a/lib/matplotlib/_path.pyi +++ b/lib/matplotlib/_path.pyi @@ -3,5 +3,5 @@ import numpy as np from .transforms import BboxBase def affine_transform(points: np.ndarray, trans: np.ndarray) -> np.ndarray: ... -def count_bboxes_overlapping_bbox(a: BboxBase, bboxes: Sequence[BboxBase]) -> int: ... -def update_path_extents(*args, **kwargs): ... +def count_bboxes_overlapping_bbox(bbox: BboxBase, bboxes: Sequence[BboxBase]) -> int: ... +def update_path_extents(path, trans, rect, minpos, ignore): ... diff --git a/lib/matplotlib/projections/polar.pyi b/lib/matplotlib/projections/polar.pyi index f1787fd1dddb..3dfc12b7a744 100644 --- a/lib/matplotlib/projections/polar.pyi +++ b/lib/matplotlib/projections/polar.pyi @@ -12,7 +12,7 @@ from matplotlib.ticker import _DummyAxis import numpy as np from numpy.typing import ArrayLike from collections.abc import Sequence -from typing import Any, Literal, overload +from typing import Any, ClassVar, Literal, overload class PolarTransform(mtransforms.Transform): input_dims: int @@ -84,6 +84,14 @@ class _WedgeBbox(mtransforms.Bbox): ) -> None: ... class PolarAxes(Axes): + + PolarTransform: ClassVar[type] = PolarTransform + PolarAffine: ClassVar[type] = PolarAffine + InvertedPolarTransform: ClassVar[type] = InvertedPolarTransform + ThetaFormatter: ClassVar[type] = ThetaFormatter + RadialLocator: ClassVar[type] = RadialLocator + ThetaLocator: ClassVar[type] = ThetaLocator + name: str use_sticky_edges: bool def __init__( diff --git a/lib/matplotlib/text.pyi b/lib/matplotlib/text.pyi index e6d5896c0bb9..3508ce8b9196 100644 --- a/lib/matplotlib/text.pyi +++ b/lib/matplotlib/text.pyi @@ -208,3 +208,5 @@ class Annotation(Text, _AnnotationBase): | Callable[[RendererBase], Bbox | Transform], ) -> None: ... def update_positions(self, renderer: RendererBase) -> None: ... + # Drops `dpi` parameter from superclass + def get_window_extent(self, renderer: RendererBase | None = ...) -> Bbox: ... # type: ignore[override] diff --git a/lib/matplotlib/ticker.pyi b/lib/matplotlib/ticker.pyi index 48077336c54d..e53a665432e2 100644 --- a/lib/matplotlib/ticker.pyi +++ b/lib/matplotlib/ticker.pyi @@ -172,6 +172,8 @@ class PercentFormatter(Formatter): class Locator(TickHelper): MAXTICKS: int def tick_values(self, vmin: float, vmax: float) -> Sequence[float]: ... + # Implementation accepts **kwargs, but is a no-op other than a warning + # Typing as **kwargs would require each subclass to accept **kwargs for mypy def set_params(self) -> None: ... def __call__(self) -> Sequence[float]: ... def raise_if_exceeds(self, locs: Sequence[float]) -> Sequence[float]: ... @@ -211,7 +213,8 @@ class LinearLocator(Locator): class MultipleLocator(Locator): def __init__(self, base: float = ...) -> None: ... - def set_params(self, base: float | None = ...) -> None: ... + # Makes set_params `base` argument mandatory + def set_params(self, base: float | None) -> None: ... # type: ignore[override] def view_limits(self, dmin: float, dmax: float) -> tuple[float, float]: ... class _Edge_integer: diff --git a/lib/matplotlib/transforms.pyi b/lib/matplotlib/transforms.pyi index 3d4648fd082d..6084a94017e9 100644 --- a/lib/matplotlib/transforms.pyi +++ b/lib/matplotlib/transforms.pyi @@ -1,11 +1,6 @@ from .path import Path from .patches import Patch from .figure import Figure -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 from collections.abc import Iterable, Sequence