diff --git a/.github/workflows/run-unittests-default_setup.yml b/.github/workflows/run-unittests-default_setup.yml index c2378bb51..ef1c9d37d 100644 --- a/.github/workflows/run-unittests-default_setup.yml +++ b/.github/workflows/run-unittests-default_setup.yml @@ -1,4 +1,4 @@ -name: "[Py3.9-3.12] - Default Tests" +name: "[Py3.9-3.13] - Default Tests" on: workflow_dispatch: @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 @@ -55,9 +55,8 @@ jobs: NoDependency: True run: | set -x # print commands that are executed - $CONDA/bin/conda init - source /home/runner/.bashrc - conda install python=${{ matrix.python-version }} - pip install -r test-requirements.txt - conda list + python --version + python -m pip --version + python -m pip install -r test-requirements.txt + python -m pip list python -m pytest -v -p no:warnings --durations=5 tests/unitary/default_setup diff --git a/.github/workflows/run-unittests-py310-py311.yml b/.github/workflows/run-unittests-py310-py311.yml index 3644ece9b..f3767bab6 100644 --- a/.github/workflows/run-unittests-py310-py311.yml +++ b/.github/workflows/run-unittests-py310-py311.yml @@ -1,4 +1,4 @@ -name: "[Py3.10-3.12] - All Unit Tests" +name: "[Py3.10-3.13] - All Unit Tests" on: workflow_dispatch: @@ -33,7 +33,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12", "3.13"] name: ["unitary", "slow_tests"] include: - name: "unitary" diff --git a/.github/workflows/test-env-setup/action.yml b/.github/workflows/test-env-setup/action.yml index 22df9290c..8b1fc10dc 100644 --- a/.github/workflows/test-env-setup/action.yml +++ b/.github/workflows/test-env-setup/action.yml @@ -17,8 +17,7 @@ runs: sudo apt update sudo apt-get install libkrb5-dev graphviz - $CONDA/bin/conda init - source /home/runner/.bashrc - conda install python=${{ matrix.python-version }} - pip install -r dev-requirements.txt - conda list + python --version + python -m pip --version + python -m pip install -r dev-requirements.txt + python -m pip list diff --git a/THIRD_PARTY_LICENSES.txt b/THIRD_PARTY_LICENSES.txt index 36dabb41d..c5ed7bc61 100644 --- a/THIRD_PARTY_LICENSES.txt +++ b/THIRD_PARTY_LICENSES.txt @@ -379,6 +379,12 @@ skl2onnx * Source code: https://github.com/onnx/sklearn-onnx * Project home: https://onnx.ai/sklearn-onnx/ +setuptools +* Copyright Python Packaging Authority and contributors +* License: MIT License +* Source code: https://github.com/pypa/setuptools +* Project home: https://setuptools.pypa.io/ + spacy * Copyright (C) 2016-2022 ExplosionAI GmbH, 2016 spaCy GmbH, 2015 Matthew Honnibal * License: The MIT License diff --git a/ads/model/model_artifact_boilerplate/artifact_introspection_test/model_artifact_validate.py b/ads/model/model_artifact_boilerplate/artifact_introspection_test/model_artifact_validate.py index 00cd7ed77..1667e3800 100644 --- a/ads/model/model_artifact_boilerplate/artifact_introspection_test/model_artifact_validate.py +++ b/ads/model/model_artifact_boilerplate/artifact_introspection_test/model_artifact_validate.py @@ -29,7 +29,7 @@ TESTS_PATH = os.path.join(_cwd, "resources", "tests.yaml") HTML_PATH = os.path.join(_cwd, "resources", "template.html") CONFIG_PATH = os.path.join(_cwd, "resources", "config.yaml") -PYTHON_VER_PATTERN = "^([3])(\.([6-9]|1[0-2]))(\.\d+)?$" +PYTHON_VER_PATTERN = r"^([3])(\.([6-9]|1[0-3]))(\.\d+)?$" PAR_URL = "https://objectstorage.us-ashburn-1.oraclecloud.com/p/WyjtfVIG0uda-P3-2FmAfwaLlXYQZbvPZmfX1qg0-sbkwEQO6jpwabGr2hMDBmBp/n/ociodscdev/b/service-conda-packs/o/service_pack/index.json" TESTS = { diff --git a/ads/telemetry/telemetry.py b/ads/telemetry/telemetry.py index dc167a757..03ebaad84 100644 --- a/ads/telemetry/telemetry.py +++ b/ads/telemetry/telemetry.py @@ -251,7 +251,7 @@ def print(self) -> None: def _prepare(self, value: str): """Replaces the special characters with the `_` in the input string.""" return ( - re.sub("[^a-zA-Z0-9\.\-\_\&\=]", "_", re.sub(r"\s+", " ", value)) + re.sub(r"[^a-zA-Z0-9.\-_&=]", "_", re.sub(r"\s+", " ", value)) if value else "" ) diff --git a/ads/text_dataset/dataset.py b/ads/text_dataset/dataset.py index 781356b4a..c18d8511a 100644 --- a/ads/text_dataset/dataset.py +++ b/ads/text_dataset/dataset.py @@ -18,7 +18,7 @@ class DataLoader: - """ + r""" DataLoader binds engine, FileProcessor and File handler(in this case it is fsspec) together to produce a dataframe of parsed text from files. diff --git a/docs/python313-support-scope.md b/docs/python313-support-scope.md new file mode 100644 index 000000000..003445b9d --- /dev/null +++ b/docs/python313-support-scope.md @@ -0,0 +1,126 @@ +# ADS Python 3.13 Support Scope + +This audit supports ODSC-88492 and records the Python 3.13 readiness surface +used to update package metadata and CI coverage. + +## Current Support Markers + +- `pyproject.toml` sets `requires-python = ">=3.8"` and now advertises + classifiers through Python 3.13 after the validation below passed. +- Default unit CI in `.github/workflows/run-unittests-default_setup.yml` now + runs Python 3.9, 3.10, 3.11, 3.12, and 3.13. +- Full unit CI in `.github/workflows/run-unittests-py310-py311.yml` now runs + Python 3.10, 3.11, 3.12, and 3.13. +- Operator, forecast, and forecast explainer CI workflows run Python 3.10 and + 3.11 only. +- `docs/source/user_guide/cli/quickstart.rst` now documents CLI support as + Python >=3.8, <=3.13. +- Model-artifact validation tests now classify Python 3.13 as supported in + `tests/unitary/default_setup/model/test_model_introspect.py`. +- Several model framework tests are skipped on Python 3.12+ for dependency or + framework compatibility, including TensorFlow, sklearn export, xgboost export, + and default model artifact tests. +- Low-code operator metadata pins runtime Python versions below 3.13: + regression, anomaly, and forecast `MLoperator` files use Python 3.11; PII and + recommender conda environment files use Python 3.9. + +## Dependency Surfaces To Validate + +Validate installation and tests in this order so support is not advertised ahead +of dependency resolution: + +1. Core package install from `pyproject.toml` `[project.dependencies]`. +2. Default unit test environment from `test-requirements.txt`. +3. Full development environment from `dev-requirements.txt`, which installs + `.[aqua,bds,data,geo,huggingface,llm,notebook,onnx,opctl,optuna,spark,tensorflow,text,torch,viz]` + plus `.[testsuite]`. +4. Operator service environment from `test-requirements-operators.txt`, which + installs `.[forecast]` and `.[anomaly]` plus operator test dependencies. + +The optional extras with explicit Python-version-sensitive or high-risk runtime +constraints are: + +- `onnx`: `onnx`, `onnxruntime`, and `skl2onnx` switch pins at Python 3.12. + Python 3.13 uses `onnx>=1.18,<2`, `onnxruntime~=1.22.0`, + `onnxmltools>=1.16,<2`, and `skl2onnx>=1.20,<2` to avoid the removed + `onnx.mapping` import path used by older ONNX converter releases. It also + constrains `setuptools<81` while ADS keeps `xgboost<=1.7` in this extra, + because that XGBoost line still imports `pkg_resources`. +- `tensorflow`: TensorFlow switches at Python 3.12 and must remain compatible + with the Keras/tf2onnx behavior noted in the existing comments. +- `huggingface`: `tf-keras` is present for Keras 3 compatibility and should be + validated with the TensorFlow surface. +- `text` and `pii`: spaCy is constrained below 3.8 in `text`, while `pii` pins + `spacy==3.6.1`, `spacy-transformers==1.2.5`, `scrubadub==2.0.1`, and + `scrubadub_spacy`. +- `forecast`, `anomaly`, and `regression`: these carry the largest operator + dependency surface, including `numpy<2.0.0`, `pmdarima`, `prophet`, + `cmdstanpy`, `pytorch-lightning`, `salesforce-merlion[all]`, and shared + `opctl` dependencies. On Python 3.13, `neuralprophet` and + `salesforce-merlion[all]` are deferred because their current releases require + NumPy 1.x, which has no wheel-backed Python 3.13 install path in this + validation environment. +- `boosted`, `notebook`, and `onnx`: these keep `scikit-learn<1.6.0`; validate + whether that bound still resolves on Python 3.13. +- `geo`: `geopandas<1.0.0` and the Python 3.13 Fiona dependency line need + wheel and dependency resolution checks on Python 3.13. +- `testsuite`: validate all pinned test dependencies, especially + `category_encoders==2.6.3`, `cohere==4.53`, `fastparquet==2024.2.0`, + `notebook==6.4.12`, `pyarrow>=15.0.0`, and `tables>3.9.0`. +- `aqua`: validate `openai==1.109.1`, `notebook>=6.4,<=6.6`, and shared + `huggingface_hub` constraints. + +## Initial Support Scope + +Treat the following as in scope for ODSC-88492: + +- Core ADS installation on Python 3.13 from source and wheel. +- Default setup unit tests in `tests/unitary/default_setup`. +- Full unitary coverage from `.github/workflows/run-unittests-py310-py311.yml`, + including `tests/unitary` and `tests/unitary/with_extras/model` after the + dependency set resolves. +- Model artifact and runtime metadata validation for Python 3.13, including + `inference_python_version`, `training_python_version`, service conda metadata + parsing, and model introspection validation. +- Required service conda optional extras represented by `dev-requirements.txt` + and `test-requirements-operators.txt`. +- CI matrix updates for default setup and full unit validation after the above + install and test surfaces pass. +- Package classifier update and any license metadata updates after dependency + changes are finalized. + +## Deferred Or Separately Tracked Scope + +Do not block initial Python 3.13 metadata on these areas unless service conda +requirements explicitly make them mandatory: + +- Recommender operator tests, because `test-requirements-operators.txt` leaves + `.[recommender]` commented out today. +- Forecast explainer coverage beyond the existing dedicated workflow, if its + third-party explainer stack does not resolve on Python 3.13 with the required + service environment. +- NeuralProphet-backed forecast functionality and Salesforce Merlion-backed + anomaly functionality on Python 3.13, until upstream releases support a + Python 3.13-compatible NumPy dependency line. +- PII operator functionality on Python 3.13, because the current extra pins + `spacy==3.6.1`, `spacy-transformers==1.2.5`, `scrubadub==2.0.1`, and + `scrubadub_spacy`, which remain tied to the older spaCy stack. +- Low-code operator runtime version bumps from Python 3.9 or 3.11 to 3.13. + Those YAML/MLoperator defaults affect generated operator environments and + should be handled only after service conda runtime images are available. +- Historical model examples and fixture values that intentionally reference + older Python versions. + +## Validation Handoff + +Later beads should record exact commands and results for: + +- `python -m pip install -e .` +- `python -m pip install -r test-requirements.txt` +- `python -m pip install -r dev-requirements.txt` +- `python -m pip install -r test-requirements-operators.txt` +- `python -m pytest -v -p no:warnings --durations=5 tests/unitary/default_setup` +- Full unitary workflow-equivalent coverage from + `.github/workflows/run-unittests-py310-py311.yml`. +- Targeted model artifact/runtime tests covering Python 3.13 acceptance. +- Source distribution and wheel build/install validation. diff --git a/docs/source/user_guide/cli/quickstart.rst b/docs/source/user_guide/cli/quickstart.rst index 1311ec627..283366295 100644 --- a/docs/source/user_guide/cli/quickstart.rst +++ b/docs/source/user_guide/cli/quickstart.rst @@ -11,7 +11,7 @@ Install ADS CLI * Linux/Mac (Intel CPU) * For Mac on M series - Experimental. * For Windows: Use `Windows Subsystem for Linux (WSL) `_ -* python >=3.8, <=3.10 +* python >=3.8, <=3.13 ``ads`` cli provides a command line interface to Jobs API related features. Set up your development environment, build docker images compliant with Notebook session and Data Science Jobs, build and publish conda pack locally, start distributed training, etc. diff --git a/pyproject.toml b/pyproject.toml index 9d32b8497..471e849c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] # PEP 508 – Dependency specification for Python Software Packages - https://peps.python.org/pep-0508/ @@ -104,7 +105,8 @@ data = [ ] geo = [ "geopandas<1.0.0", # in v1.0.0 removed the built-in dataset 'naturalearth_lowres', fix when relax version of geopandas needed - "fiona<=1.9.6", + "fiona<=1.9.6; python_version < '3.13'", + "fiona>=1.10.1,<2; python_version >= '3.13'", "oracle_ads[viz]" ] huggingface = [ @@ -119,14 +121,18 @@ notebook = [ onnx = [ "lightgbm", "onnx>=1.12.0,<=1.15.0; python_version < '3.12'", # v 1.15.0 set base on onnxrutime version and onnx opset support - https://onnxruntime.ai/docs/reference/compatibility.html#onnx-opset-support - "onnx~=1.17.0; python_version >= '3.12'", # v 1.15.0 set base on onnxrutime version and onnx opset support - https://onnxruntime.ai/docs/reference/compatibility.html#onnx-opset-support - "onnxmltools~=1.13.0", + "onnx~=1.17.0; python_version >= '3.12' and python_version < '3.13'", # v 1.15.0 set base on onnxrutime version and onnx opset support - https://onnxruntime.ai/docs/reference/compatibility.html#onnx-opset-support + "onnx>=1.18,<2; python_version >= '3.13'", + "onnxmltools~=1.13.0; python_version < '3.13'", + "onnxmltools>=1.16,<2; python_version >= '3.13'", "onnxruntime~=1.17.0,!=1.16.0; python_version < '3.12'", # v1.17.0 used in Oracle Database 23ai; avoid v1.16 https://github.com/microsoft/onnxruntime/issues/17631, revealed by unit tests "onnxruntime~=1.22.0; python_version >= '3.12'", # v1.17.0 used in Oracle Database 23ai; avoid v1.16 https://github.com/microsoft/onnxruntime/issues/17631, revealed by unit tests "oracle_ads[viz]", "protobuf", + "setuptools<81; python_version >= '3.13'", "skl2onnx>=1.10.4; python_version < '3.12'", - "skl2onnx~=1.18.0; python_version >= '3.12'", + "skl2onnx~=1.18.0; python_version >= '3.12' and python_version < '3.13'", + "skl2onnx>=1.20,<2; python_version >= '3.13'", "tf2onnx", "xgboost<=1.7", "scikit-learn>=1.0,<1.6.0", @@ -152,7 +158,8 @@ tensorflow = [ "tensorflow; python_version >= '3.12'" # v2.16.1 with consequence on tf2onnx v1.16.1 (latest) has an issue with Keras 3 installed in py3.11+ (https://github.com/onnx/tensorflow-onnx/issues/2319) ] text = [ - "spacy>=3.4.2,<3.8", # the first version of spacy that supports python 3.11 is spacy v3.4.2; 3.8.2 has dependency conflict. + "spacy>=3.4.2,<3.8; python_version < '3.13'", # the first version of spacy that supports python 3.11 is spacy v3.4.2; 3.8.2 has dependency conflict. + "spacy>=3.8,<4; python_version >= '3.13'", "wordcloud>=1.8.1" ] torch = [ @@ -177,9 +184,9 @@ forecast = [ "rich", "autots", "mlforecast==1.0.2", - "neuralprophet>=0.7.0", + "neuralprophet>=0.7.0; python_version < '3.13'", "pytorch-lightning==2.5.5", - "numpy<2.0.0", + "numpy<2.0.0; python_version < '3.13'", "oci-cli", "optuna", "pmdarima", @@ -200,7 +207,7 @@ anomaly = [ "report-creator==1.0.37", "rrcf==0.4.4", "scikit-learn<1.6.0", - "salesforce-merlion[all]==2.0.4" + "salesforce-merlion[all]==2.0.4; python_version < '3.13'" ] recommender = [ "oracle_ads[opctl]", @@ -241,7 +248,8 @@ aqua = [ # Revisit this section continuously and update to recent version of libraries. focus on pyt3.9/3.10 versions. testsuite = [ "arff", - "autogen-agentchat<0.4", + "pyautogen>=0.4,<0.5; python_version >= '3.13'", + "autogen-agentchat<0.4; python_version < '3.13'", "category_encoders==2.6.3", # set version to avoid backtracking "cohere==4.53", # set version to avoid backtracking "faiss-cpu", diff --git a/tests/unitary/default_setup/model/test_model_introspect.py b/tests/unitary/default_setup/model/test_model_introspect.py index 44756940c..2b385f4f2 100644 --- a/tests/unitary/default_setup/model/test_model_introspect.py +++ b/tests/unitary/default_setup/model/test_model_introspect.py @@ -258,12 +258,12 @@ def test_python_version_check(self): ) import re - supported_python_version = [f"3.{minor}" for minor in range(6, 12)] + supported_python_version = [f"3.{minor}" for minor in range(6, 14)] for version in supported_python_version: m = re.match(at.PYTHON_VER_PATTERN, str(version)) assert m and m.group(), "Python version check failed." - unsupported_python_version = ["3.5", "3.13"] + unsupported_python_version = ["3.5", "3.14"] for version in unsupported_python_version: m = re.match(at.PYTHON_VER_PATTERN, str(version)) assert not m, "Python version check failed."