diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6b4f2b831..796ab1260 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -41,6 +41,10 @@ jobs: python-version: '3.12' os: ubuntu-latest test-id: include + - julia-version: '1' + python-version: '3.8' + os: ubuntu-latest + test-id: include steps: - uses: actions/checkout@v4 diff --git a/pyproject.toml b/pyproject.toml index 7a5398348..a6276195d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ authors = [ description = "Simple and efficient symbolic regression" readme = {file = "README.md", content-type = "text/markdown"} license = {file = "LICENSE"} -requires-python = ">=3.10" +requires-python = ">=3.8" classifiers = [ "Programming Language :: Python :: 3", "Operating System :: OS Independent", @@ -39,7 +39,7 @@ dev = [ "mypy>=1,<2", "nbval>=0.11,<0.12", "pandas-stubs", - "pre-commit>=3.7,<5", + "pre-commit>=3.0,<5", "pytest-cov>=5,<7", "pytest>=8,<9", "tensorboard>=2,<3", diff --git a/pysr/__init__.py b/pysr/__init__.py index aabbb669e..c9089dfe8 100644 --- a/pysr/__init__.py +++ b/pysr/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging import os diff --git a/pysr/denoising.py b/pysr/denoising.py index 92a640ee8..fbf17468b 100644 --- a/pysr/denoising.py +++ b/pysr/denoising.py @@ -1,5 +1,7 @@ """Functions for denoising data during preprocessing.""" +from __future__ import annotations + from typing import cast import numpy as np diff --git a/pysr/export.py b/pysr/export.py index c1b589b84..0389c792f 100644 --- a/pysr/export.py +++ b/pysr/export.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import copy from collections.abc import Callable diff --git a/pysr/export_latex.py b/pysr/export_latex.py index 55d24de0b..f00fc48ad 100644 --- a/pysr/export_latex.py +++ b/pysr/export_latex.py @@ -1,5 +1,7 @@ """Functions to help export PySR equations to LaTeX.""" +from __future__ import annotations + import pandas as pd import sympy # type: ignore from sympy.printing.latex import LatexPrinter # type: ignore diff --git a/pysr/export_numpy.py b/pysr/export_numpy.py index 163726d6f..c67834985 100644 --- a/pysr/export_numpy.py +++ b/pysr/export_numpy.py @@ -1,5 +1,7 @@ """Code for exporting discovered expressions to numpy""" +from __future__ import annotations + import warnings import numpy as np diff --git a/pysr/export_sympy.py b/pysr/export_sympy.py index 9ee617344..c041a3f1e 100644 --- a/pysr/export_sympy.py +++ b/pysr/export_sympy.py @@ -1,5 +1,7 @@ """Define utilities to export to sympy""" +from __future__ import annotations + from collections.abc import Callable import sympy # type: ignore diff --git a/pysr/expression_specs.py b/pysr/expression_specs.py index c35ef0319..e029217a3 100644 --- a/pysr/expression_specs.py +++ b/pysr/expression_specs.py @@ -1,7 +1,9 @@ +from __future__ import annotations + import copy from abc import ABC, abstractmethod from textwrap import dedent -from typing import TYPE_CHECKING, Any, NewType, TypeAlias, overload +from typing import TYPE_CHECKING, Any, NewType, overload import numpy as np import pandas as pd @@ -10,6 +12,11 @@ from .julia_helpers import jl_array from .julia_import import AnyValue, SymbolicRegression, jl +try: + from typing import TypeAlias +except ImportError: + from typing_extensions import TypeAlias + # For type checking purposes if TYPE_CHECKING: from .sr import PySRRegressor # pragma: no cover diff --git a/pysr/feature_selection.py b/pysr/feature_selection.py index 13fca487c..047fca513 100644 --- a/pysr/feature_selection.py +++ b/pysr/feature_selection.py @@ -1,5 +1,7 @@ """Functions for doing feature selection during preprocessing.""" +from __future__ import annotations + import logging from typing import cast diff --git a/pysr/julia_extensions.py b/pysr/julia_extensions.py index 950c292ea..d7e5de580 100644 --- a/pysr/julia_extensions.py +++ b/pysr/julia_extensions.py @@ -1,5 +1,7 @@ """This file installs and loads extensions for SymbolicRegression.""" +from __future__ import annotations + from typing import Literal from .julia_import import Pkg, jl diff --git a/pysr/julia_registry_helpers.py b/pysr/julia_registry_helpers.py index 2c2162e75..ad34a98b1 100644 --- a/pysr/julia_registry_helpers.py +++ b/pysr/julia_registry_helpers.py @@ -1,5 +1,7 @@ """Utilities for managing Julia registry preferences during package operations.""" +from __future__ import annotations + import os import warnings from collections.abc import Callable diff --git a/pysr/logger_specs.py b/pysr/logger_specs.py index f4c0a3dff..c13c3afd9 100644 --- a/pysr/logger_specs.py +++ b/pysr/logger_specs.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from abc import ABC, abstractmethod from dataclasses import dataclass from typing import Any diff --git a/pysr/sr.py b/pysr/sr.py index 12b44ec8f..bb122b526 100644 --- a/pysr/sr.py +++ b/pysr/sr.py @@ -1,5 +1,7 @@ """Define the PySRRegressor scikit-learn interface.""" +from __future__ import annotations + import copy import logging import os @@ -13,7 +15,7 @@ from io import StringIO from multiprocessing import cpu_count from pathlib import Path -from typing import Any, Literal, cast +from typing import Any, List, Literal, Tuple, Union, cast import numpy as np import pandas as pd @@ -94,7 +96,7 @@ def _process_constraints( ) constraints[op] = (-1, -1) - constraint_tuple = cast(tuple[int, int], constraints[op]) + constraint_tuple = cast(Tuple[int, int], constraints[op]) if op in ["plus", "sub", "+", "-"]: if constraint_tuple[0] != constraint_tuple[1]: raise NotImplementedError( @@ -1313,7 +1315,7 @@ def julia_options_(self): def julia_state_(self): """The deserialized state.""" return cast( - tuple[VectorValue, AnyValue] | None, + Union[Tuple[VectorValue, AnyValue], None], jl_deserialize(self.julia_state_stream_), ) @@ -1640,7 +1642,7 @@ def _validate_data_X_y(self, X: Any, y: Any) -> tuple[ndarray, ndarray]: raw_out = self._validate_data(X=X, y=y, reset=True, multi_output=True) # type: ignore else: raw_out = validate_data(self, X=X, y=y, reset=True, multi_output=True) # type: ignore - return cast(tuple[ndarray, ndarray], raw_out) + return cast(Tuple[ndarray, ndarray], raw_out) def _validate_data_X(self, X: Any) -> ndarray: if OLD_SKLEARN: @@ -2629,7 +2631,7 @@ def get_hof(self, search_output=None) -> pd.DataFrame | list[pd.DataFrame]: _validate_export_mappings(self.extra_jax_mappings, self.extra_torch_mappings) - equation_file_contents = cast(list[pd.DataFrame], self.equation_file_contents_) + equation_file_contents = cast(List[pd.DataFrame], self.equation_file_contents_) ret_outputs = [ pd.concat( diff --git a/pysr/utils.py b/pysr/utils.py index e18a5b4c3..95ec49028 100644 --- a/pysr/utils.py +++ b/pysr/utils.py @@ -4,15 +4,15 @@ import inspect import re from pathlib import Path -from typing import Any, TypeVar +from typing import Any, List, TypeVar, Union from numpy import ndarray from sklearn.utils.validation import _check_feature_names_in # type: ignore T = TypeVar("T", bound=Any) -ArrayLike = ndarray | list[T] -PathLike = str | Path +ArrayLike = Union[ndarray, List[T]] +PathLike = Union[str, Path] _regexp_im = re.compile(r"\b(\d+\.\d+)im\b")