diff --git a/.github/workflows/pr_typecheck.yml b/.github/workflows/pr_typecheck.yml new file mode 100644 index 0000000000..6e093b4996 --- /dev/null +++ b/.github/workflows/pr_typecheck.yml @@ -0,0 +1,43 @@ +name: PR Typecheck + +on: + push: + branches: + - main + pull_request: + branches: + - main + paths: + - "aeon/**" + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + typecheck: + # run the code coverage job if a PR has the '' label + if: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'run typecheck test') }} + runs-on: ubuntu-22.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install aeon, dependencies and mypy + uses: nick-fields/retry@v3 + with: + timeout_minutes: 30 + max_attempts: 3 + command: python -m pip install .[all_extras,unstable_extras,dev] mypy + + - name: Show dependencies + run: python -m pip list + + - name: Run mypy typecheck + run: mypy aeon/ diff --git a/aeon/classification/distance_based/_proximity_forest.py b/aeon/classification/distance_based/_proximity_forest.py index aa034f54fc..44871a2500 100644 --- a/aeon/classification/distance_based/_proximity_forest.py +++ b/aeon/classification/distance_based/_proximity_forest.py @@ -3,6 +3,8 @@ The Proximity Forest is an ensemble of Proximity Trees. """ +from typing import Optional + __all__ = ["ProximityForest"] from typing import Union @@ -87,7 +89,7 @@ def __init__( self, n_trees=100, n_splitters: int = 5, - max_depth: int = None, + max_depth: Optional[int] = None, min_samples_split: int = 2, random_state: Union[int, np.random.RandomState, None] = None, n_jobs: int = 1, diff --git a/aeon/classification/distance_based/_proximity_tree.py b/aeon/classification/distance_based/_proximity_tree.py index dda47493f2..f2c3cd36e6 100644 --- a/aeon/classification/distance_based/_proximity_tree.py +++ b/aeon/classification/distance_based/_proximity_tree.py @@ -5,7 +5,7 @@ aeon distances. """ -from typing import Union +from typing import Optional, Union import numpy as np from numba import njit @@ -118,7 +118,7 @@ class ProximityTree(BaseClassifier): def __init__( self, n_splitters: int = 5, - max_depth: int = None, + max_depth: Optional[int] = None, min_samples_split: int = 2, random_state: Union[int, np.random.RandomState, None] = None, ) -> None: diff --git a/aeon/classification/distance_based/_time_series_neighbors.py b/aeon/classification/distance_based/_time_series_neighbors.py index b2702ad307..20ca5a3f8d 100644 --- a/aeon/classification/distance_based/_time_series_neighbors.py +++ b/aeon/classification/distance_based/_time_series_neighbors.py @@ -5,6 +5,8 @@ distances in aeon.distances. """ +from typing import Optional + __maintainer__ = [] __all__ = ["KNeighborsTimeSeriesClassifier"] @@ -72,7 +74,7 @@ class KNeighborsTimeSeriesClassifier(BaseClassifier): def __init__( self, distance: Union[str, Callable] = "dtw", - distance_params: dict = None, + distance_params: Optional[dict] = None, n_neighbors: int = 1, weights: Union[str, Callable] = "uniform", n_jobs: int = 1, diff --git a/aeon/classification/shapelet_based/_sast.py b/aeon/classification/shapelet_based/_sast.py index 26b5144660..096a845529 100644 --- a/aeon/classification/shapelet_based/_sast.py +++ b/aeon/classification/shapelet_based/_sast.py @@ -3,6 +3,8 @@ Pipeline classifier using the SAST transformer and an sklearn classifier. """ +from typing import Optional + __maintainer__ = ["TonyBagnall"] __all__ = ["SASTClassifier"] @@ -69,7 +71,7 @@ def __init__( length_list=None, stride: int = 1, nb_inst_per_class: int = 1, - seed: int = None, + seed: Optional[int] = None, classifier=None, n_jobs: int = -1, ) -> None: diff --git a/aeon/clustering/_clara.py b/aeon/clustering/_clara.py index d6cdc8957b..0121922fbb 100644 --- a/aeon/clustering/_clara.py +++ b/aeon/clustering/_clara.py @@ -1,5 +1,7 @@ """Time series kmedoids.""" +from typing import Optional + __maintainer__ = [] from typing import Callable, Union @@ -118,14 +120,14 @@ def __init__( n_clusters: int = 8, init_algorithm: Union[str, np.ndarray] = "random", distance: Union[str, Callable] = "msm", - n_samples: int = None, + n_samples: Optional[int] = None, n_sampling_iters: int = 10, n_init: int = 1, max_iter: int = 300, tol: float = 1e-6, verbose: bool = False, - random_state: Union[int, RandomState] = None, - distance_params: dict = None, + random_state: Optional[Union[int, RandomState]] = None, + distance_params: Optional[dict] = None, ): self.init_algorithm = init_algorithm self.distance = distance diff --git a/aeon/clustering/_clarans.py b/aeon/clustering/_clarans.py index c1790e49ec..0d15bc7b81 100644 --- a/aeon/clustering/_clarans.py +++ b/aeon/clustering/_clarans.py @@ -1,5 +1,7 @@ """Time series kmedoids.""" +from typing import Optional + __maintainer__ = [] import math @@ -104,11 +106,11 @@ def __init__( n_clusters: int = 8, init_algorithm: Union[str, np.ndarray] = "random", distance: Union[str, Callable] = "msm", - max_neighbours: int = None, + max_neighbours: Optional[int] = None, n_init: int = 10, verbose: bool = False, - random_state: Union[int, RandomState] = None, - distance_params: dict = None, + random_state: Optional[Union[int, RandomState]] = None, + distance_params: Optional[dict] = None, ): self.max_neighbours = max_neighbours diff --git a/aeon/clustering/_k_means.py b/aeon/clustering/_k_means.py index eecd62172a..54d05e8c84 100644 --- a/aeon/clustering/_k_means.py +++ b/aeon/clustering/_k_means.py @@ -1,5 +1,7 @@ """Time series kmeans.""" +from typing import Optional + __maintainer__ = [] from typing import Callable, Union @@ -163,11 +165,11 @@ def __init__( max_iter: int = 300, tol: float = 1e-6, verbose: bool = False, - random_state: Union[int, RandomState] = None, + random_state: Optional[Union[int, RandomState]] = None, averaging_method: Union[str, Callable[[np.ndarray], np.ndarray]] = "ba", - distance_params: dict = None, - average_params: dict = None, - init_algorithm: Union[str, np.ndarray] = None, + distance_params: Optional[dict] = None, + average_params: Optional[dict] = None, + init_algorithm: Optional[Union[str, np.ndarray]] = None, ): self.init = init self.init_algorithm = init_algorithm diff --git a/aeon/clustering/_k_medoids.py b/aeon/clustering/_k_medoids.py index 021f20d726..9a0a91ae9c 100644 --- a/aeon/clustering/_k_medoids.py +++ b/aeon/clustering/_k_medoids.py @@ -1,5 +1,7 @@ """Time series kmedoids.""" +from typing import Optional + __maintainer__ = [] import warnings @@ -157,8 +159,8 @@ def __init__( max_iter: int = 300, tol: float = 1e-6, verbose: bool = False, - random_state: Union[int, RandomState] = None, - distance_params: dict = None, + random_state: Optional[Union[int, RandomState]] = None, + distance_params: Optional[dict] = None, ): self.init_algorithm = init_algorithm self.distance = distance diff --git a/aeon/clustering/_k_shape.py b/aeon/clustering/_k_shape.py index 8331533a21..585e7dc841 100644 --- a/aeon/clustering/_k_shape.py +++ b/aeon/clustering/_k_shape.py @@ -1,6 +1,6 @@ """Time series kshapes.""" -from typing import Union +from typing import Optional, Union import numpy as np from numpy.random import RandomState @@ -82,7 +82,7 @@ def __init__( max_iter: int = 300, tol: float = 1e-4, verbose: bool = False, - random_state: Union[int, RandomState] = None, + random_state: Optional[Union[int, RandomState]] = None, ): self.init_algorithm = init_algorithm self.n_init = n_init diff --git a/aeon/clustering/_k_shapes.py b/aeon/clustering/_k_shapes.py index 31dfcd6d27..6a3ae9eb44 100644 --- a/aeon/clustering/_k_shapes.py +++ b/aeon/clustering/_k_shapes.py @@ -1,6 +1,6 @@ """Time series kshapes.""" -from typing import Union +from typing import Optional, Union import numpy as np from deprecated.sphinx import deprecated @@ -83,7 +83,7 @@ def __init__( max_iter: int = 300, tol: float = 1e-4, verbose: bool = False, - random_state: Union[int, RandomState] = None, + random_state: Optional[Union[int, RandomState]] = None, ): self.init_algorithm = init_algorithm self.n_init = n_init diff --git a/aeon/clustering/_kernel_k_means.py b/aeon/clustering/_kernel_k_means.py index 5c3fd1edcd..f39d1c5059 100644 --- a/aeon/clustering/_kernel_k_means.py +++ b/aeon/clustering/_kernel_k_means.py @@ -1,6 +1,6 @@ """Time series kernel kmeans.""" -from typing import Union +from typing import Optional, Union import numpy as np from numpy.random import RandomState @@ -99,7 +99,7 @@ def __init__( kernel_params: Union[dict, None] = None, verbose: bool = False, n_jobs: Union[int, None] = None, - random_state: Union[int, RandomState] = None, + random_state: Optional[Union[int, RandomState]] = None, ): self.kernel = kernel self.n_init = n_init diff --git a/aeon/clustering/base.py b/aeon/clustering/base.py index c971a680fe..bf4b6c83e7 100644 --- a/aeon/clustering/base.py +++ b/aeon/clustering/base.py @@ -1,5 +1,7 @@ """Base class for clustering.""" +from typing import Optional + __maintainer__ = [] __all__ = ["BaseClusterer"] @@ -22,7 +24,7 @@ class BaseClusterer(BaseCollectionEstimator, ABC): Number of clusters for model. """ - def __init__(self, n_clusters: int = None): + def __init__(self, n_clusters: Optional[int] = None): self.n_clusters = n_clusters # required for compatibility with some sklearn interfaces e.g. # CalibratedClassifierCV diff --git a/aeon/datasets/_data_loaders.py b/aeon/datasets/_data_loaders.py index 4a31d24a97..c5af7189ec 100644 --- a/aeon/datasets/_data_loaders.py +++ b/aeon/datasets/_data_loaders.py @@ -1,5 +1,7 @@ """Dataset loading functions.""" +from typing import Optional + __all__ = [ # Load functions "load_from_tsfile", "load_from_tsf_file", @@ -680,7 +682,7 @@ def load_from_tsv_file(full_file_path_and_name): def _convert_tsf_to_hierarchical( data: pd.DataFrame, metadata, - freq: str = None, + freq: Optional[str] = None, value_column_name: str = "series_value", ) -> pd.DataFrame: """Convert the data from default_tsf to pd_multiindex_hier. diff --git a/aeon/regression/distance_based/_time_series_neighbors.py b/aeon/regression/distance_based/_time_series_neighbors.py index a0d7275d23..2de7285a23 100644 --- a/aeon/regression/distance_based/_time_series_neighbors.py +++ b/aeon/regression/distance_based/_time_series_neighbors.py @@ -5,6 +5,8 @@ It can also be used with callables, or aeon (pairwise transformer) estimators. """ +from typing import Optional + __maintainer__ = [] __all__ = ["KNeighborsTimeSeriesRegressor"] @@ -72,7 +74,7 @@ class KNeighborsTimeSeriesRegressor(BaseRegressor): def __init__( self, distance: Union[str, Callable] = "dtw", - distance_params: dict = None, + distance_params: Optional[dict] = None, n_neighbors: int = 1, weights: Union[str, Callable] = "uniform", n_jobs: int = 1, diff --git a/aeon/segmentation/_ggs.py b/aeon/segmentation/_ggs.py index 7fab9217b9..c423dd2836 100644 --- a/aeon/segmentation/_ggs.py +++ b/aeon/segmentation/_ggs.py @@ -36,6 +36,7 @@ import logging import math from dataclasses import dataclass, field +from typing import Optional import numpy as np import numpy.typing as npt @@ -457,7 +458,7 @@ def __init__( lamb: float = 1.0, max_shuffles: int = 250, verbose: bool = False, - random_state: int = None, + random_state: Optional[int] = None, ): self.k_max = k_max self.lamb = lamb diff --git a/aeon/segmentation/_hmm.py b/aeon/segmentation/_hmm.py index b23f5a761c..49c8b277b5 100644 --- a/aeon/segmentation/_hmm.py +++ b/aeon/segmentation/_hmm.py @@ -7,6 +7,7 @@ """ import warnings +from typing import Optional import numpy as np from scipy.stats import norm @@ -137,7 +138,7 @@ def __init__( self, emission_funcs: list, transition_prob_mat: np.ndarray, - initial_probs: np.ndarray = None, + initial_probs: Optional[np.ndarray] = None, ): self.initial_probs = initial_probs self.emission_funcs = emission_funcs diff --git a/aeon/similarity_search/matrix_profiles/stomp.py b/aeon/similarity_search/matrix_profiles/stomp.py index 5bfdfa0959..e95b981f46 100644 --- a/aeon/similarity_search/matrix_profiles/stomp.py +++ b/aeon/similarity_search/matrix_profiles/stomp.py @@ -1,5 +1,7 @@ """Implementation of stomp for euclidean and squared euclidean distance profile.""" +from typing import Optional + __maintainer__ = ["baraline"] @@ -29,7 +31,7 @@ def stomp_euclidean_matrix_profile( k: int = 1, threshold: float = np.inf, inverse_distance: bool = False, - exclusion_size: int = None, + exclusion_size: Optional[int] = None, ): """ Compute a euclidean euclidean matrix profile using STOMP [1]_. @@ -109,7 +111,7 @@ def stomp_squared_matrix_profile( k: int = 1, threshold: float = np.inf, inverse_distance: bool = False, - exclusion_size: int = None, + exclusion_size: Optional[int] = None, ): """ Compute a squared euclidean matrix profile using STOMP [1]_. @@ -198,7 +200,7 @@ def stomp_normalized_euclidean_matrix_profile( k: int = 1, threshold: float = np.inf, inverse_distance: bool = False, - exclusion_size: int = None, + exclusion_size: Optional[int] = None, ): """ Compute a euclidean matrix profile using STOMP [1]_. @@ -296,7 +298,7 @@ def stomp_normalized_squared_matrix_profile( k: int = 1, threshold: float = np.inf, inverse_distance: bool = False, - exclusion_size: int = None, + exclusion_size: Optional[int] = None, ): """ Compute a squared euclidean matrix profile using STOMP [1]_. diff --git a/aeon/testing/data_generation/hierarchical.py b/aeon/testing/data_generation/hierarchical.py index 1c28a5366c..178ee25f7b 100644 --- a/aeon/testing/data_generation/hierarchical.py +++ b/aeon/testing/data_generation/hierarchical.py @@ -1,5 +1,7 @@ """Hierarchical Data Generators.""" +from typing import Optional + __maintainer__ = [] from itertools import product @@ -20,8 +22,8 @@ def _make_hierarchical( same_cutoff: bool = True, n_columns: int = 1, all_positive: bool = True, - index_type: str = None, - random_state: Union[int, np.random.RandomState] = None, + index_type: Optional[str] = None, + random_state: Optional[Union[int, np.random.RandomState]] = None, add_nan: bool = False, ) -> pd.DataFrame: """Generate hierarchical multiindex type for testing. diff --git a/aeon/testing/data_generation/segmentation.py b/aeon/testing/data_generation/segmentation.py index 41c3ab9fe9..b8ccd22aff 100644 --- a/aeon/testing/data_generation/segmentation.py +++ b/aeon/testing/data_generation/segmentation.py @@ -1,6 +1,6 @@ """Synthetic data generating functions.""" -from typing import Union +from typing import Optional, Union import numpy as np import numpy.typing as npt @@ -11,8 +11,8 @@ def piecewise_normal_multivariate( means: npt.ArrayLike, lengths: npt.ArrayLike, variances: Union[npt.ArrayLike, float] = 1.0, - covariances: npt.ArrayLike = None, - random_state: Union[int, np.random.RandomState] = None, + covariances: Optional[npt.ArrayLike] = None, + random_state: Optional[Union[int, np.random.RandomState]] = None, ) -> npt.ArrayLike: """ Generate multivariate series from segments. @@ -136,7 +136,7 @@ def piecewise_normal( means: npt.ArrayLike, lengths: npt.ArrayLike, std_dev: Union[npt.ArrayLike, float] = 1.0, - random_state: Union[int, np.random.RandomState] = None, + random_state: Optional[Union[int, np.random.RandomState]] = None, ) -> npt.ArrayLike: """ Generate series from segments. @@ -199,7 +199,7 @@ def piecewise_multinomial( n_trials: int, lengths: npt.ArrayLike, p_vals: npt.ArrayLike, - random_state: Union[int, np.random.RandomState] = None, + random_state: Optional[Union[int, np.random.RandomState]] = None, ) -> npt.ArrayLike: """ Generate series from segments. @@ -276,7 +276,7 @@ def piecewise_multinomial( def piecewise_poisson( lambdas: npt.ArrayLike, lengths: npt.ArrayLike, - random_state: Union[int, np.random.RandomState] = None, + random_state: Optional[Union[int, np.random.RandomState]] = None, ) -> npt.ArrayLike: """ Generate series using Possion distribution. diff --git a/aeon/testing/estimator_checking/_estimator_checking.py b/aeon/testing/estimator_checking/_estimator_checking.py index a7d71a8c2b..bd5af8ff88 100644 --- a/aeon/testing/estimator_checking/_estimator_checking.py +++ b/aeon/testing/estimator_checking/_estimator_checking.py @@ -1,5 +1,7 @@ """Interface compliance checkers for aeon estimators.""" +from typing import Optional + __maintainer__ = ["MatthewMiddlehurst"] __all__ = [ "parametrize_with_checks", @@ -97,10 +99,10 @@ def check_estimator( estimator: Union[BaseEstimator, type[BaseEstimator]], raise_exceptions: bool = False, use_first_parameter_set: bool = False, - checks_to_run: Union[str, list[str]] = None, - checks_to_exclude: Union[str, list[str]] = None, - full_checks_to_run: Union[str, list[str]] = None, - full_checks_to_exclude: Union[str, list[str]] = None, + checks_to_run: Optional[Union[str, list[str]]] = None, + checks_to_exclude: Optional[Union[str, list[str]]] = None, + full_checks_to_run: Optional[Union[str, list[str]]] = None, + full_checks_to_exclude: Optional[Union[str, list[str]]] = None, verbose: bool = False, ): """Check if estimator adheres to `aeon` conventions. diff --git a/aeon/testing/mock_estimators/_mock_clusterers.py b/aeon/testing/mock_estimators/_mock_clusterers.py index ff79c192e7..0563129909 100644 --- a/aeon/testing/mock_estimators/_mock_clusterers.py +++ b/aeon/testing/mock_estimators/_mock_clusterers.py @@ -1,3 +1,5 @@ +from typing import Optional + import numpy as np from aeon.clustering.base import BaseClusterer @@ -7,7 +9,7 @@ class MockCluster(BaseClusterer): """Mock Cluster for testing base class fit/predict.""" - def __init__(self, n_clusters: int = None): + def __init__(self, n_clusters: Optional[int] = None): super().__init__(n_clusters) def _fit(self, X): diff --git a/aeon/transformations/collection/channel_selection/_channel_scorer.py b/aeon/transformations/collection/channel_selection/_channel_scorer.py index 5a59257fec..32c211dceb 100644 --- a/aeon/transformations/collection/channel_selection/_channel_scorer.py +++ b/aeon/transformations/collection/channel_selection/_channel_scorer.py @@ -1,4 +1,5 @@ import math +from typing import Optional import numpy as np from sklearn.metrics import accuracy_score @@ -40,7 +41,7 @@ class methods. Approximately as described in [1]_. def __init__( self, - classifier: BaseClassifier = None, + classifier: Optional[BaseClassifier] = None, proportion: float = 0.4, ): self.proportion = proportion diff --git a/aeon/transformations/collection/shapelet_based/_rsast.py b/aeon/transformations/collection/shapelet_based/_rsast.py index 52ccf4e491..32fb2f1605 100644 --- a/aeon/transformations/collection/shapelet_based/_rsast.py +++ b/aeon/transformations/collection/shapelet_based/_rsast.py @@ -103,7 +103,7 @@ def __init__( n_random_points: int = 10, len_method: str = "both", nb_inst_per_class: int = 10, - seed: int = None, + seed: Optional[int] = None, n_jobs: int = 1, # Parllel Processing ): self.n_random_points = n_random_points diff --git a/aeon/utils/conversion/_convert_tsf.py b/aeon/utils/conversion/_convert_tsf.py index 23712cc339..2b5ef3c8b8 100644 --- a/aeon/utils/conversion/_convert_tsf.py +++ b/aeon/utils/conversion/_convert_tsf.py @@ -1,5 +1,7 @@ """Data generators.""" +from typing import Optional + __maintainer__ = [] @@ -9,7 +11,7 @@ def _convert_tsf_to_hierarchical( data: pd.DataFrame, metadata: dict, - freq: str = None, + freq: Optional[str] = None, value_column_name: str = "series_value", ) -> pd.DataFrame: """Convert the data from default_tsf to pd_multiindex_hier. diff --git a/aeon/utils/datetime.py b/aeon/utils/datetime.py index 8f366c94cc..1478d86ba4 100644 --- a/aeon/utils/datetime.py +++ b/aeon/utils/datetime.py @@ -1,5 +1,7 @@ """Time format related utilities.""" +from typing import Optional + __maintainer__ = [] __all__ = [] @@ -65,7 +67,7 @@ def get_time_index(X): def _coerce_duration_to_int( duration: Union[int, pd.Timedelta, pd.tseries.offsets.BaseOffset, pd.Index], - freq: str = None, + freq: Optional[str] = None, ) -> Union[int, pd.Index]: """Coerce durations into integer representations for a given unit of duration. diff --git a/aeon/utils/validation/__init__.py b/aeon/utils/validation/__init__.py index 3f34bc611c..f0f155567e 100644 --- a/aeon/utils/validation/__init__.py +++ b/aeon/utils/validation/__init__.py @@ -1,5 +1,7 @@ """Validation and checking functions for time series.""" +from typing import Optional + __all__ = [ "is_int", "is_float", @@ -194,7 +196,7 @@ def check_n_jobs(n_jobs: int) -> int: def check_window_length( window_length: ACCEPTED_WINDOW_LENGTH_TYPES, - n_timepoints: int = None, + n_timepoints: Optional[int] = None, name: str = "window_length", ) -> NON_FLOAT_WINDOW_LENGTH_TYPES: """Validate window length. diff --git a/aeon/utils/validation/series.py b/aeon/utils/validation/series.py index f42c684a8b..1465e2f01b 100644 --- a/aeon/utils/validation/series.py +++ b/aeon/utils/validation/series.py @@ -1,5 +1,7 @@ """Functions for checking input data.""" +from typing import Optional + __all__ = [ "check_series", "check_time_index", @@ -305,7 +307,7 @@ def check_series( def check_time_index( index: Union[pd.Index, np.array], allow_empty: bool = False, - enforce_index_type: bool = None, + enforce_index_type: Optional[bool] = None, var_name: str = "input", ) -> pd.Index: """Check time index. diff --git a/build_tools/pr_open_commenter.py b/build_tools/pr_open_commenter.py index 6d7a4d78d8..f64388bf0a 100644 --- a/build_tools/pr_open_commenter.py +++ b/build_tools/pr_open_commenter.py @@ -119,6 +119,7 @@ These checkboxes will add labels to enable/disable CI functionality for this PR. This may not take effect immediately, and a new commit may be required to run the new configuration. - [ ] Run `pre-commit` checks for all files +- [ ] Run `mypy` typecheck tests - [ ] Run all `pytest` tests and configurations - [ ] Run all notebook example tests - [ ] Run numba-disabled `codecov` tests diff --git a/build_tools/pr_welcome_edited.py b/build_tools/pr_welcome_edited.py index d079713ec5..c402f5b89d 100644 --- a/build_tools/pr_welcome_edited.py +++ b/build_tools/pr_welcome_edited.py @@ -40,6 +40,7 @@ def check_label_option(label, option): label_options = [ ("full pre-commit", "Run `pre-commit` checks for all files"), + ("run typecheck test", "Run `mypy` typecheck tests"), ("full pytest actions", "Run all `pytest` tests and configurations"), ("full examples run", "Run all notebook example tests"), ("codecov actions", "Run numba-disabled `codecov` tests"), diff --git a/pyproject.toml b/pyproject.toml index 30b0bad47a..84a308ff65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -160,6 +160,9 @@ select = ["D"] [tool.ruff.lint.pydocstyle] convention = "numpy" +[tool.mypy] +mypy_path = "aeon/" + [tool.pytest.ini_options] # ignore certain folders and pytest warnings testpaths = "aeon"