From d4902e47470af3157f0085d6fba9239ee58a11d9 Mon Sep 17 00:00:00 2001 From: Avasam Date: Tue, 27 May 2025 22:18:33 -0400 Subject: [PATCH 1/3] Fix most mypy "misc" issues --- pyproject.toml | 21 ++++- stubs/skimage/__init__.pyi | 1 - stubs/skimage/data/__init__.pyi | 91 ++++++++++++++++++- stubs/skimage/data/_fetchers.pyi | 3 + stubs/sklearn/gaussian_process/kernels.pyi | 23 ----- stubs/sklearn/metrics/_regression.pyi | 4 +- stubs/sklearn/preprocessing/_data.pyi | 42 +-------- stubs/sklearn/utils/_isfinite.pyi | 12 ++- .../models/auto/configuration_auto.pyi | 6 +- stubs/vispy/ext/cocoapy.pyi | 13 +-- stubs/vispy/testing/_testing.pyi | 9 +- stubs/vispy/visuals/transforms/_util.pyi | 7 +- 12 files changed, 140 insertions(+), 92 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f61829f0..00f8a0ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ hygiene = ["ruff ==0.11.*"] tests = [ # Tools used for testing "docopt-ng", - "mypy ==1.13.*", + "mypy ==1.15.*", "pyright", # Typed libraries and stubs @@ -21,7 +21,7 @@ tests = [ "scipy-stubs", "typing_extensions", - # Untyped libraries, used to prevent "reportMissingImports" and get inferred typing + # Untyped libraries and partial stubs. Used to prevent "reportMissingImports" and get inferred typing "joblib", "networkx", "PyOpenGL", @@ -140,6 +140,7 @@ reportUnsupportedDunderAll = "error" [tool.mypy] python_version = "3.9" # Target oldest supported Python version strict = true +follow_untyped_imports = true # Don't infer symbols from untyped packages as Any check_untyped_defs = true # Strict check on all defs show_column_numbers = true warn_unused_ignores = false # Change from pandas @@ -159,6 +160,20 @@ disable_error_code = [ "valid-type", # 967 errors in 115 files "override", # 790 errors in 220 files "assignment", # 773 errors in 172 files - "misc", # 692 errors in 132 files "attr-defined", # 202 errors in 75 files ] + +[[tool.mypy.overrides]] +# These modules are to be removed soon, not worth solving many issues +module = ["matplotlib.*", "networkx.*"] +disable_error_code = [ + "valid-type", + "override", + "assignment", + "misc", +] +[[tool.mypy.overrides]] +module = ["sympy.*", "skimage.*", "sklearn.*"] +# TODO: Too many untyped decorators still left +# https://github.com/python/mypy/issues/19148 +disable_error_code = ["misc"] diff --git a/stubs/skimage/__init__.pyi b/stubs/skimage/__init__.pyi index 41b3ebfa..db0041fa 100644 --- a/stubs/skimage/__init__.pyi +++ b/stubs/skimage/__init__.pyi @@ -4,7 +4,6 @@ from ._shared.version_requirements import ensure_python_version as ensure_python __version__: str = ... submodules: list = ... -__getattr__ = ... __lazy_dir__ = ... def __dir__(): ... diff --git a/stubs/skimage/data/__init__.pyi b/stubs/skimage/data/__init__.pyi index b72deea2..e918ea0d 100644 --- a/stubs/skimage/data/__init__.pyi +++ b/stubs/skimage/data/__init__.pyi @@ -1,5 +1,88 @@ -from .._shared import lazy as lazy +from ._binary_blobs import binary_blobs +from ._fetchers import ( + astronaut, + brain, + brick, + camera, + cat, + cell, + cells3d, + checkerboard, + chelsea, + clock, + coffee, + coins, + colorwheel, + data_dir, + download_all, + eagle, + file_hash, + grass, + gravel, + horse, + hubble_deep_field, + human_mitosis, + immunohistochemistry, + kidney, + lbp_frontal_face_cascade_filename, + lfw_subset, + lily, + logo, + microaneurysms, + moon, + nickel_solidification, + page, + palisades_of_vogt as palisades_of_vogt, + protein_transport, + retina, + rocket, + shepp_logan_phantom, + skin, + stereo_motorcycle, + text, + vortex, +) -__getattr__ = ... -__dir__ = ... -__all__ = ... # pyright: ignore[reportUnsupportedDunderAll] # TODO +__all__ = [ + "astronaut", + "binary_blobs", + "brain", + "brick", + "camera", + "cat", + "cell", + "cells3d", + "checkerboard", + "chelsea", + "clock", + "coffee", + "coins", + "colorwheel", + "data_dir", + "download_all", + "eagle", + "file_hash", + "grass", + "gravel", + "horse", + "hubble_deep_field", + "human_mitosis", + "immunohistochemistry", + "kidney", + "lbp_frontal_face_cascade_filename", + "lfw_subset", + "lily", + "logo", + "microaneurysms", + "moon", + "nickel_solidification", + "page", + "protein_transport", + "retina", + "rocket", + "shepp_logan_phantom", + "skin", + "stereo_motorcycle", + "text", + "vortex", +] diff --git a/stubs/skimage/data/_fetchers.pyi b/stubs/skimage/data/_fetchers.pyi index 3ea9bfc0..4a954c9f 100644 --- a/stubs/skimage/data/_fetchers.pyi +++ b/stubs/skimage/data/_fetchers.pyi @@ -1,5 +1,7 @@ from os import PathLike +def file_hash(fname, alg="sha256") -> str: ... + legacy_data_dir = ... skimage_distribution_dir = ... @@ -46,6 +48,7 @@ def hubble_deep_field(): ... def retina(): ... def shepp_logan_phantom(): ... def colorwheel(): ... +def palisades_of_vogt(): ... def rocket(): ... def stereo_motorcycle(): ... def lfw_subset(): ... diff --git a/stubs/sklearn/gaussian_process/kernels.pyi b/stubs/sklearn/gaussian_process/kernels.pyi index 8fe96e5e..9b0b56f9 100644 --- a/stubs/sklearn/gaussian_process/kernels.pyi +++ b/stubs/sklearn/gaussian_process/kernels.pyi @@ -23,29 +23,6 @@ class Hyperparameter(NamedTuple): value_type: str name: str - # A raw namedtuple is very memory efficient as it packs the attributes - # in a struct to get rid of the __dict__ of attributes in particular it - # does not copy the string for the keys on each instance. - # By deriving a namedtuple class just to introduce the __init__ method we - # would also reintroduce the __dict__ on the instance. By telling the - # Python interpreter that this subclass uses static __slots__ instead of - # dynamic attributes. Furthermore we don't need any additional slot in the - # subclass so we set __slots__ to the empty tuple. - __slots__ = ... - - def __new__( - cls, - name: str, - value_type: str, - bounds: ndarray | str | tuple[float, int] | tuple[float, float], - n_elements: int = 1, - fixed=None, - ) -> Self: ... - - # This is mainly a testing utility to check that two hyperparameters - # are equal. - def __eq__(self, other) -> bool: ... - class Kernel(metaclass=ABCMeta): def get_params(self, deep: bool = True) -> dict: ... def set_params(self, **params) -> Self: ... diff --git a/stubs/sklearn/metrics/_regression.pyi b/stubs/sklearn/metrics/_regression.pyi index 6e81a847..867c83f4 100644 --- a/stubs/sklearn/metrics/_regression.pyi +++ b/stubs/sklearn/metrics/_regression.pyi @@ -56,10 +56,10 @@ def mean_squared_error( sample_weight: None | ArrayLike = None, multioutput: ArrayLike | Literal["raw_values", "uniform_average"] = "uniform_average", ) -> ndarray | Float: ... +@overload @deprecated( "`squared` is deprecated in 1.4 and will be removed in 1.6. Use `root_mean_squared_error` instead to calculate the root mean squared error." ) -@overload def mean_squared_error( y_true: MatrixLike | ArrayLike, y_pred: MatrixLike | ArrayLike, @@ -76,10 +76,10 @@ def mean_squared_log_error( sample_weight: None | ArrayLike = None, multioutput: ArrayLike | Literal["raw_values", "uniform_average"] = "uniform_average", ) -> float | ndarray: ... +@overload @deprecated( "`squared` is deprecated in 1.4 and will be removed in 1.6. Use `root_mean_squared_log_error` instead to calculate the root mean squared logarithmic error." ) -@overload def mean_squared_log_error( y_true: MatrixLike | ArrayLike, y_pred: MatrixLike | ArrayLike, diff --git a/stubs/sklearn/preprocessing/_data.pyi b/stubs/sklearn/preprocessing/_data.pyi index 78f226da..07fe2b0e 100644 --- a/stubs/sklearn/preprocessing/_data.pyi +++ b/stubs/sklearn/preprocessing/_data.pyi @@ -112,12 +112,10 @@ class StandardScaler(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): def transform(self, X: spmatrix, copy: None | bool = None) -> spmatrix: ... @overload def transform(self, X: ArrayLike, copy: None | bool = None) -> ndarray: ... - def transform(self, X: MatrixLike, copy: None | bool = None) -> ndarray | spmatrix: ... @overload def inverse_transform(self, X: spmatrix, copy: None | bool = None) -> spmatrix: ... @overload def inverse_transform(self, X: ArrayLike, copy: None | bool = None) -> ndarray: ... - def inverse_transform(self, X: MatrixLike | ArrayLike, copy: None | bool = None) -> ndarray | spmatrix: ... class MaxAbsScaler(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): n_samples_seen_: int = ... @@ -135,12 +133,10 @@ class MaxAbsScaler(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): def transform(self, X: spmatrix) -> spmatrix: ... @overload def transform(self, X: ArrayLike) -> ndarray: ... - def transform(self, X: MatrixLike | ArrayLike) -> ndarray | spmatrix: ... @overload def inverse_transform(self, X: spmatrix) -> spmatrix: ... @overload def inverse_transform(self, X: ArrayLike) -> ndarray: ... - def inverse_transform(self, X: MatrixLike | ArrayLike) -> ndarray | spmatrix: ... def maxabs_scale(X: MatrixLike | ArrayLike, *, axis: Int = 0, copy: bool = True): ... @@ -166,12 +162,10 @@ class RobustScaler(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): def transform(self, X: spmatrix) -> spmatrix: ... @overload def transform(self, X: ArrayLike) -> ndarray: ... - def transform(self, X: MatrixLike | ArrayLike) -> ndarray | spmatrix: ... @overload def inverse_transform(self, X: spmatrix) -> spmatrix: ... @overload def inverse_transform(self, X: ArrayLike) -> ndarray: ... - def inverse_transform(self, X: MatrixLike | ArrayLike) -> ndarray | spmatrix: ... @overload def robust_scale( @@ -186,7 +180,7 @@ def robust_scale( ) -> spmatrix: ... @overload def robust_scale( - X: ndarray, + X: ArrayLike, *, axis: Int = 0, with_centering: bool = True, @@ -195,16 +189,6 @@ def robust_scale( copy: bool = True, unit_variance: bool = False, ) -> ndarray: ... -def robust_scale( - X: MatrixLike, - *, - axis: Int = 0, - with_centering: bool = True, - with_scaling: bool = True, - quantile_range: tuple[float, float] = ..., - copy: bool = True, - unit_variance: bool = False, -) -> ndarray | spmatrix: ... @overload def normalize( X: spmatrix, @@ -241,14 +225,6 @@ def normalize( copy: bool = True, return_norm: Literal[False] = False, ) -> ndarray: ... -def normalize( - X: MatrixLike | ArrayLike, - norm: Literal["l1", "l2", "max"] = "l2", - *, - axis: int = 1, - copy: bool = True, - return_norm: bool = False, -) -> csr_matrix | tuple[ndarray | spmatrix, ndarray] | ndarray: ... class Normalizer(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): feature_names_in_: ndarray = ... @@ -262,7 +238,6 @@ class Normalizer(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): def transform(self, X: spmatrix, copy: None | bool = None) -> spmatrix: ... @overload def transform(self, X: ArrayLike, copy: None | bool = None) -> ndarray: ... - def transform(self, X: MatrixLike | ArrayLike, copy: None | bool = None) -> ndarray | spmatrix: ... def binarize(X: MatrixLike | ArrayLike, *, threshold: Float = 0.0, copy: bool = True) -> ndarray | spmatrix: ... @@ -278,7 +253,6 @@ class Binarizer(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): def transform(self, X: spmatrix, copy: None | bool = None) -> spmatrix: ... @overload def transform(self, X: ArrayLike, copy: None | bool = None) -> ndarray: ... - def transform(self, X: MatrixLike | ArrayLike, copy: None | bool = None) -> ndarray | spmatrix: ... class KernelCenterer(ClassNamePrefixFeaturesOutMixin, TransformerMixin, BaseEstimator): feature_names_in_: ndarray = ... @@ -294,7 +268,6 @@ class KernelCenterer(ClassNamePrefixFeaturesOutMixin, TransformerMixin, BaseEsti def add_dummy_feature(X: spmatrix, value: Float = 1.0) -> spmatrix: ... @overload def add_dummy_feature(X: ArrayLike, value: Float = 1.0) -> ndarray: ... -def add_dummy_feature(X: MatrixLike | ArrayLike, value: Float = 1.0) -> ndarray | spmatrix: ... class QuantileTransformer(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): feature_names_in_: ndarray = ... @@ -324,12 +297,10 @@ class QuantileTransformer(OneToOneFeatureMixin, TransformerMixin, BaseEstimator) def transform(self, X: spmatrix) -> spmatrix: ... @overload def transform(self, X: ArrayLike) -> ndarray: ... - def transform(self, X: MatrixLike | ArrayLike) -> ndarray | spmatrix: ... @overload def inverse_transform(self, X: spmatrix) -> spmatrix: ... @overload def inverse_transform(self, X: ArrayLike) -> ndarray: ... - def inverse_transform(self, X: MatrixLike | ArrayLike) -> ndarray | spmatrix: ... @overload def quantile_transform( @@ -355,17 +326,6 @@ def quantile_transform( random_state: RandomState | None | Int = None, copy: bool = True, ) -> ndarray: ... -def quantile_transform( - X: MatrixLike | ArrayLike, - *, - axis: Int = 0, - n_quantiles: Int = 1000, - output_distribution: Literal["uniform", "normal"] = "uniform", - ignore_implicit_zeros: bool = False, - subsample: Int = ..., - random_state: RandomState | None | Int = None, - copy: bool = True, -) -> ndarray | spmatrix: ... class PowerTransformer(OneToOneFeatureMixin, TransformerMixin, BaseEstimator): feature_names_in_: ndarray = ... diff --git a/stubs/sklearn/utils/_isfinite.pyi b/stubs/sklearn/utils/_isfinite.pyi index 8e2a94b7..1c7a59ac 100644 --- a/stubs/sklearn/utils/_isfinite.pyi +++ b/stubs/sklearn/utils/_isfinite.pyi @@ -1,7 +1,17 @@ from enum import IntEnum +from typing import Final import numpy as np -class FiniteStatus(IntEnum): ... +__test__: dict + +class FiniteStatus(IntEnum): + all_finite = 0 + has_nan = 1 + has_infinite = 2 + +all_finite: Final = FiniteStatus.all_finite +has_nan: Final = FiniteStatus.has_nan +has_infinite: Final = FiniteStatus.has_infinite def cy_isfinite(a: np.ndarray, allow_nan: bool = False) -> bool: ... diff --git a/stubs/transformers-stubs/models/auto/configuration_auto.pyi b/stubs/transformers-stubs/models/auto/configuration_auto.pyi index 5b92d5d3..6725b9bd 100644 --- a/stubs/transformers-stubs/models/auto/configuration_auto.pyi +++ b/stubs/transformers-stubs/models/auto/configuration_auto.pyi @@ -5,7 +5,7 @@ from typing import Any, NoReturn, TypeVar from transformers.configuration_utils import PretrainedConfig -_F = TypeVar("_F", bound=Callable[..., Any]) +_CallableT = TypeVar("_CallableT", bound=Callable) CONFIG_MAPPING_NAMES: OrderedDict[str, str] MODEL_NAMES_MAPPING: OrderedDict[str, str] @@ -35,7 +35,9 @@ class _LazyLoadAllMappings(OrderedDict[str, str]): def __iter__(self) -> Iterator[str]: ... def __contains__(self, item: object) -> bool: ... -def replace_list_option_in_docstrings(config_to_class=None, use_model_types: bool = True) -> Callable[[_F], _F]: ... +def replace_list_option_in_docstrings( + config_to_class=None, use_model_types: bool = True +) -> Callable[[_CallableT], _CallableT]: ... class AutoConfig: def __init__(self) -> None: ... diff --git a/stubs/vispy/ext/cocoapy.pyi b/stubs/vispy/ext/cocoapy.pyi index 05867113..0379eb90 100644 --- a/stubs/vispy/ext/cocoapy.pyi +++ b/stubs/vispy/ext/cocoapy.pyi @@ -40,6 +40,7 @@ from ctypes import ( sizeof, util, ) +from typing import ClassVar # Based on Pyglet code @@ -61,17 +62,17 @@ CGImageEncoding: str = ... NSZoneEncoding: str = ... class NSPoint(Structure): - _fields_: list = ... + _fields_: ClassVar[list] CGPoint = NSPoint class NSSize(Structure): - _fields_: list = ... + _fields_: ClassVar[list] CGSize = NSSize class NSRect(Structure): - _fields_: list = ... + _fields_: ClassVar[list] CGRect = NSRect @@ -82,10 +83,10 @@ unichar = ... CGGlyph = ... class CFRange(Structure): - _fields_: list = ... + _fields_: ClassVar[list] class NSRange(Structure): - _fields_: list = ... + _fields_: ClassVar[list] CFTypeID = ... CFNumberType = ... @@ -112,7 +113,7 @@ def should_use_fpret(restype): ... def send_message(receiver, selName, *args, **kwargs): ... class OBJC_SUPER(Structure): - _fields_: list = ... + _fields_: ClassVar[list] OBJC_SUPER_PTR = ... diff --git a/stubs/vispy/testing/_testing.pyi b/stubs/vispy/testing/_testing.pyi index fb9dd9f4..b077e8de 100644 --- a/stubs/vispy/testing/_testing.pyi +++ b/stubs/vispy/testing/_testing.pyi @@ -1,7 +1,6 @@ -# ----------------------------------------------------------------------------- -# Copyright (c) Vispy Development Team. All Rights Reserved. -# Distributed under the (new) BSD License. See LICENSE.txt for more info. -# ----------------------------------------------------------------------------- +from typing import TypeVar + +_T = TypeVar("_T") skipif = ... @@ -13,7 +12,7 @@ def SkipTest(*args, **kwargs): ... def _safe_rep(obj, short=False): ... def _safe_str(obj): ... def _format_msg(msg, std_msg): ... -def nottest(func): ... +def nottest(func: _T) -> _T: ... def assert_raises(exp, func, *args, **kwargs): ... def assert_in(member, container, msg=None): ... def assert_true(x, msg=None): ... diff --git a/stubs/vispy/visuals/transforms/_util.pyi b/stubs/vispy/visuals/transforms/_util.pyi index 774010ba..8953e7e3 100644 --- a/stubs/vispy/visuals/transforms/_util.pyi +++ b/stubs/vispy/visuals/transforms/_util.pyi @@ -1,13 +1,12 @@ -from typing import Callable +from typing import Callable, TypeVar from numpy.typing import ArrayLike -# Copyright (c) Vispy Development Team. All Rights Reserved. -# Distributed under the (new) BSD License. See LICENSE.txt for more info. +_CallableT = TypeVar("_CallableT", bound=Callable) def arg_to_array(func: Callable) -> Callable: ... def as_vec4(obj: ArrayLike, default: ArrayLike = ...) -> ArrayLike: ... -def arg_to_vec4(func): ... +def arg_to_vec4(func: _CallableT) -> _CallableT: ... class TransformCache: def __init__(self, max_age=1): ... From f640878212ca2458df7b7bacd11dada23170e0db Mon Sep 17 00:00:00 2001 From: Avasam Date: Tue, 27 May 2025 22:57:55 -0400 Subject: [PATCH 2/3] Remove import-untyped from disabled error codes --- pyproject.toml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 00f8a0ca..31e28122 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -140,9 +140,11 @@ reportUnsupportedDunderAll = "error" [tool.mypy] python_version = "3.9" # Target oldest supported Python version strict = true -follow_untyped_imports = true # Don't infer symbols from untyped packages as Any check_untyped_defs = true # Strict check on all defs show_column_numbers = true +# Not all imports in these stubs are gonna be typed +# Don't infer symbols from untyped packages as Any +follow_untyped_imports = true warn_unused_ignores = false # Change from pandas # Partial stubs are acceptable disallow_any_generics = false @@ -150,8 +152,6 @@ disallow_incomplete_defs = false disallow_untyped_defs = false # Suppressing errors disable_error_code = [ - # Not all imports in these stubs are gonna be typed - "import-untyped", # mypy's overload implementation differs from pyright # `assert-type` issues is tests mostly comme from checking overloads # Since this project is specific to Pylance, just ignore them @@ -167,8 +167,6 @@ disable_error_code = [ # These modules are to be removed soon, not worth solving many issues module = ["matplotlib.*", "networkx.*"] disable_error_code = [ - "valid-type", - "override", "assignment", "misc", ] From c26508c829b445d4c6cb2487bad3d1369dc40dad Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 28 May 2025 04:13:52 -0400 Subject: [PATCH 3/3] Update count --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 861d2c97..b2c3ddc4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -160,7 +160,7 @@ disable_error_code = [ # as they are inherited from the implementation. "override", # TODO - "assignment", # 773 errors in 172 files + "assignment", # 744 errors in 155 files ] [[tool.mypy.overrides]]