Repository: aeon-toolkit/aeon
Pull request #1420 (2024-04-13 22:44:18)

[MNT] `dask` CI fix, ReadTheDocs fix and expanded full pytest actions tag
Stops `dask` from crashing the Python 3.11 CI by lowering the version bound again. If someone wants `dask` for these versions, they will have to update to the latest version and resolve the resulting issues.

Updates the full pytest tag to use all Python versions in PRs.

aeon-actions-bot[bot]: 
## Thank you for contributing to `aeon`

I have added the following labels to this PR based on the title: **[ $\\color{#EC843A}{\\textsf{maintenance}}$ ]**.
I have added the following labels to this PR based on the changes made: **[ $\\color{#31FCCD}{\\textsf{forecasting}}$, $\\color{#41A8F6}{\\textsf{transformations}}$ ]**. Feel free to change these if they do not properly represent the PR.

The [Checks](https://github.com/aeon-toolkit/aeon/pull/1420/checks) tab will show the status of our automated tests. You can click on individual test runs in the tab or "Details" in the panel below to see more information if there is a failure.

If our `pre-commit` code quality check fails, any trivial fixes will automatically be pushed to your PR unless it is a draft.

Don't hesitate to ask questions on the `aeon` [Slack](
https://join.slack.com/t/aeon-toolkit/shared_invite/zt-22vwvut29-HDpCu~7VBUozyfL_8j3dLA) channel if you have any.
    
MatthewMiddlehurst: Im going to run this without the tag quick just to check its still ok.
MatthewMiddlehurst: nope, still a bit broken unfortunately 🙁. No idea why it is running all Python versions without the tag
MatthewMiddlehurst: Ok looks good now. Also fixed a Sphinx issue thats going to impact every PR. Suddenly popped up while testing this.

Patch:
diff --git a/aeon/forecasting/base/_base.py b/aeon/forecasting/base/_base.py
index af0f0c6a..ac04f6f5 100644
--- a/aeon/forecasting/base/_base.py
+++ b/aeon/forecasting/base/_base.py
@@ -397,7 +397,6 @@ class BaseForecaster(BaseEstimator):
             y_pred = self._vectorize("predict", X=X_inner, fh=fh)
 
         # convert to output type, identical with last y type seen
-
         y_out = convert_to(
             y_pred,
             self._y_mtype_last_seen,
@@ -1412,7 +1411,6 @@ class BaseForecaster(BaseEstimator):
 
         if not requires_vectorization:
             # converts y, skips conversion if already of right type
-
             y_inner = convert_to(
                 y,
                 to_type=y_inner_type,
diff --git a/aeon/utils/validation/_input.py b/aeon/utils/validation/_input.py
index 2d0ae257..73b957cb 100644
--- a/aeon/utils/validation/_input.py
+++ b/aeon/utils/validation/_input.py
@@ -47,19 +47,21 @@ def _abstract_type(input_type: str) -> str:
     return "Unknown"
 
 
-def abstract_types(input_types: list) -> list:
+def abstract_types(input_types) -> list:
     """Return the abstract types based on the string identifier of the input.
 
     Parameters
     ----------
-    input_types : list of str
-        List of string representation of the input types.
+    input_types : str or list of str
+        String or list of string representations of the input types.
 
     Returns
     -------
     list of str
         Abstract type of the input, one of Series, Panel, Hierarchical or Unknown.
     """
+    if isinstance(input_types, str):
+        input_types = [input_types]
     return [_abstract_type(x) for x in input_types]
 
 
diff --git a/pyproject.toml b/pyproject.toml
index 2faf6625..d96f4765 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -59,7 +59,7 @@ dependencies = [
 [project.optional-dependencies]
 all_extras = [
     "cloudpickle",
-    "dask<2024.3.0; python_version < '3.12'",
+    "dask[dataframe]<2024.3.0; python_version < '3.11'",
     "esig>=0.9.7,<0.9.8.3; python_version < '3.11'",
     "filterpy>=1.4.5",
     "gluonts>=0.12.4",
@@ -116,7 +116,7 @@ binder = [
     "jupyterlab",
 ]
 docs = [
-    "sphinx<8.0.0",
+    "sphinx<7.3.0",
     "sphinx-design",
     "sphinx-version-warning",
     "sphinx_issues",


Test patch:
diff --git a/.github/workflows/pr_pytest.yml b/.github/workflows/pr_pytest.yml
index 2d0735b1..06b212d0 100644
--- a/.github/workflows/pr_pytest.yml
+++ b/.github/workflows/pr_pytest.yml
@@ -93,7 +93,15 @@ jobs:
       fail-fast: false
       matrix:
         os: [ ubuntu-20.04, macOS-13, windows-2022 ]
-        python-version: [ "3.8", "3.10", "3.12" ]
+        python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
+        # skip python versions unless the PR has the 'full pytest actions' label
+        pr-testing:
+          - ${{ (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'full pytest actions')) }}
+        exclude:
+          - pr-testing: true
+            python-version: "3.9"
+          - pr-testing: true
+            python-version: "3.11"
 
     steps:
       - name: Checkout main
diff --git a/aeon/forecasting/tests/test_interval_wrappers.py b/aeon/forecasting/tests/test_interval_wrappers.py
index 7415eb66..cc10bd5c 100644
--- a/aeon/forecasting/tests/test_interval_wrappers.py
+++ b/aeon/forecasting/tests/test_interval_wrappers.py
@@ -7,7 +7,6 @@ import pandas as pd
 import pytest
 
 from aeon.datasets import load_airline
-from aeon.datatypes import convert_to
 from aeon.forecasting.conformal import ConformalIntervals
 from aeon.forecasting.model_evaluation import evaluate
 from aeon.forecasting.model_selection import (
@@ -17,6 +16,7 @@ from aeon.forecasting.model_selection import (
 from aeon.forecasting.naive import NaiveForecaster, NaiveVariance
 from aeon.performance_metrics.forecasting import mean_squared_error
 from aeon.testing.test_config import PR_TESTING
+from aeon.utils.conversion import convert_series
 
 if PR_TESTING:
     INTERVAL_WRAPPERS = [NaiveVariance]
@@ -49,7 +49,7 @@ def test_wrapper_series_mtype(wrapper, override_y_type, input_type):
     "pd.DataFrame only" forecaster by restricting its y_inner_type tag to pd.Series.
     """
     y = load_airline()
-    y = convert_to(y, to_type=input_type)
+    y = convert_series(y, input_type)
 
     f = NaiveForecaster()
 
diff --git a/aeon/transformations/tests/test_base.py b/aeon/transformations/tests/test_base.py
index 0b35fa1f..9e624d5d 100644
--- a/aeon/transformations/tests/test_base.py
+++ b/aeon/transformations/tests/test_base.py
@@ -17,7 +17,6 @@ import numpy as np
 import pandas as pd
 from numpy.testing import assert_array_equal
 
-from aeon.datatypes import mtype_to_scitype
 from aeon.testing.utils.data_gen import get_examples, make_series
 from aeon.testing.utils.scenarios_transformers import (
     TransformerFitTransformHierarchicalMultivariate,
@@ -31,6 +30,7 @@ from aeon.transformations.base import BaseTransformer
 from aeon.transformations.boxcox import BoxCoxTransformer
 from aeon.transformations.compose import FitInTransform
 from aeon.utils.validation import (
+    abstract_types,
     is_collection,
     is_hierarchical,
     is_single_series,
@@ -39,15 +39,12 @@ from aeon.utils.validation import (
 
 
 def inner_X_types(est):
-    """Return list of types supported by class est, as list of str."""
+    """Return list of abstract types supported by class est, as list of str."""
     if isclass(est):
         X_inner_type = est.get_class_tag("X_inner_type")
     else:
         X_inner_type = est.get_tag("X_inner_type")
-    X_inner_types = mtype_to_scitype(
-        X_inner_type, return_unique=True, coerce_to_list=True
-    )
-    return X_inner_types
+    return abstract_types(X_inner_type)
 
 
 class _DummyOne(BaseTransformer):