Skip to content

Commit 11fd38f

Browse files
authored
Adds supporting Python 3_12 (#1102)
2 parents ba5fb25 + c4136c2 commit 11fd38f

8 files changed

+42
-25
lines changed

.github/workflows/run-unittests-default_setup.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: "[Py3.9-3.11] - Default Tests"
1+
name: "[Py3.9-3.12] - Default Tests"
22

33
on:
44
workflow_dispatch:

.github/workflows/run-unittests-py310-py311.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: "[Py3.10-3.11] - All Unit Tests"
1+
name: "[Py3.10-3.12] - All Unit Tests"
22

33
on:
44
workflow_dispatch:
@@ -23,6 +23,7 @@ permissions:
2323
# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359
2424
env:
2525
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 5
26+
ENV TF_USE_LEGACY_KERAS: 1
2627

2728
jobs:
2829
test:
@@ -33,7 +34,7 @@ jobs:
3334
strategy:
3435
fail-fast: false
3536
matrix:
36-
python-version: ["3.10", "3.11"]
37+
python-version: ["3.10", "3.11", "3.12"]
3738
name: ["unitary", "slow_tests"]
3839
include:
3940
- name: "unitary"

pyproject.toml

+7-3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ classifiers = [
4848
"Programming Language :: Python :: 3.9",
4949
"Programming Language :: Python :: 3.10",
5050
"Programming Language :: Python :: 3.11",
51+
"Programming Language :: Python :: 3.12",
5152
]
5253

5354
# PEP 508 – Dependency specification for Python Software Packages - https://peps.python.org/pep-0508/
@@ -105,9 +106,11 @@ huggingface = [
105106
notebook = ["ipython>=7.23.1, <8.0", "ipywidgets~=7.6.3"]
106107
onnx = [
107108
"lightgbm",
108-
"onnx>=1.12.0,<=1.15.0", # v 1.15.0 set base on onnxrutime version and onnx opset support - https://onnxruntime.ai/docs/reference/compatibility.html#onnx-opset-support
109+
"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
110+
"onnx>=1.12.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
109111
"onnxmltools>=1.10.0",
110-
"onnxruntime~=1.17.0,!=1.16.0", # v1.17.0 used in Oracle Database 23ai; avoid v1.16 https://github.com/microsoft/onnxruntime/issues/17631, revealed by unit tests
112+
"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
113+
"onnxruntime; 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
111114
"oracle_ads[viz]",
112115
"protobuf",
113116
"skl2onnx>=1.10.4",
@@ -131,7 +134,8 @@ optuna = ["optuna==2.9.0", "oracle_ads[viz]"]
131134
spark = ["pyspark>=3.0.0"]
132135
tensorflow = [
133136
"oracle_ads[viz]",
134-
"tensorflow<=2.15.1" # 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)
137+
"tensorflow<=2.15.1; 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)
138+
"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)
135139
]
136140
text = [
137141
"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.

test-requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ pytest-cov
1212
pytest-xdist
1313
pytest-asyncio
1414
ruff
15+
setuptools

tests/unitary/default_setup/pipeline/test_pipeline_run.py

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22

3-
# Copyright (c) 2024 Oracle and/or its affiliates.
3+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
44
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
55

66
from datetime import datetime
@@ -494,7 +494,6 @@ def test_logs_custom(self, mock_stop_condition):
494494
)
495495

496496
with patch.object(OCIModelMixin, "deserialize") as mock_deserialize:
497-
498497
mock_deserialize.return_value = oci.logging.models.Log(**OCI_LOG_DETAILS)
499498

500499
consolidated_log = pipeline_run.logs(log_type="custom_log")
@@ -528,7 +527,6 @@ def test_logs_service(self, mock_get_service_logging):
528527
pipeline_run.logs(log_type="service_log")
529528

530529
with patch.object(OCIModelMixin, "deserialize") as mock_deserialize:
531-
532530
mock_deserialize.return_value = oci.logging.models.Log(**OCI_LOG_DETAILS)
533531
pipeline_run.log_details = oci.data_science.models.PipelineRunLogDetails(
534532
**PIPELINE_RUN_LOG_DETAILS
@@ -558,7 +556,6 @@ def test_logs_service(self, mock_get_service_logging):
558556
@patch.object(OCIModelMixin, "sync")
559557
def test_logs_both(self, mock_sync, mock_stop_condition, mock_get_service_logging):
560558
with patch.object(OCIModelMixin, "deserialize") as mock_deserialize:
561-
562559
mock_deserialize.return_value = oci.logging.models.Log(**OCI_LOG_DETAILS)
563560

564561
pipeline_run = PipelineRun()
@@ -595,7 +592,6 @@ def test_logs_both(self, mock_sync, mock_stop_condition, mock_get_service_loggin
595592
@patch.object(PipelineRun, "_stop_condition", return_value=True)
596593
def test_custom_logging(self, mock_stop_condition):
597594
with patch.object(OCIModelMixin, "deserialize") as mock_deserialize:
598-
599595
mock_deserialize.return_value = oci.logging.models.Log(**OCI_LOG_DETAILS)
600596
pipeline_run = PipelineRun()
601597
pipeline_run.log_details = oci.data_science.models.PipelineRunLogDetails(
@@ -617,7 +613,6 @@ def test_custom_logging(self, mock_stop_condition):
617613
@patch.object(PipelineRun, "_get_service_logging")
618614
def test_service_logging(self, mock_get_service_logging):
619615
with patch.object(OCIModelMixin, "deserialize") as mock_deserialize:
620-
621616
mock_deserialize.return_value = oci.logging.models.Log(**OCI_LOG_DETAILS)
622617

623618
pipeline_run = PipelineRun()
@@ -644,7 +639,6 @@ def test_service_logging(self, mock_get_service_logging):
644639
@patch.object(PipelineRun, "_search_service_logs")
645640
def test_get_service_logging(self, mock_search_service_logs):
646641
with patch.object(OCIModelMixin, "deserialize") as mock_deserialize:
647-
648642
mock_deserialize.return_value = oci.logging.models.Log(**OCI_LOG_DETAILS)
649643
pipeline_run = PipelineRun()
650644
pipeline_run.id = PIPELINE_RUN_OCID
@@ -701,7 +695,7 @@ def test_watch_service_log(self, mock_logs, mock_stream_log):
701695
mock_logs.return_value = ConsolidatedLog(OCILog(log_type="SERVICE"))
702696

703697
pipeline_run.watch(log_type="service_log")
704-
mock_logs.called_with(log_type="service_log")
698+
mock_logs.assert_called_with(log_type="service_log")
705699
mock_stream_log.assert_called_with(mock_logs.return_value, [], 3, "service_log")
706700

707701
@patch.object(PipelineRun, "_PipelineRun__stream_log")
@@ -712,7 +706,7 @@ def test_watch_custom_log(self, mock_logs, mock_stream_log):
712706
mock_logs.return_value = ConsolidatedLog(OCILog(log_type="CUSTOM"))
713707

714708
pipeline_run.watch(log_type="custom_log")
715-
mock_logs.called_with(log_type="custom_log")
709+
mock_logs.assert_called_with(log_type="custom_log")
716710
mock_stream_log.assert_called_with(mock_logs.return_value, [], 3, "custom_log")
717711

718712
@patch.object(PipelineRun, "_PipelineRun__stream_log")
@@ -726,7 +720,7 @@ def test_watch_both_log(self, mock_logs, mock_stream_log):
726720
)
727721

728722
pipeline_run.watch()
729-
mock_logs.called_with(log_type=None)
723+
mock_logs.assert_called_with(log_type=None)
730724
mock_stream_log.assert_called_with(mock_logs.return_value, [], 3, None)
731725

732726
def test_build_filter_expression(self):

tests/unitary/with_extras/model/test_model_framework_sklearn_model.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#!/usr/bin/env python
22

3-
# Copyright (c) 2021, 2023 Oracle and/or its affiliates.
3+
# Copyright (c) 2021, 2025 Oracle and/or its affiliates.
44
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
55

66
"""Unit tests for model frameworks. Includes tests for:
7-
- SklearnModel
7+
- SklearnModel
88
"""
9+
910
import base64
1011
import os
1112
import shutil
@@ -15,7 +16,7 @@
1516
import onnx
1617
import onnxruntime as rt
1718
import pandas as pd
18-
import pytest
19+
import pytest, sys
1920
from ads.model.framework.sklearn_model import SklearnModel
2021
from ads.model.serde.model_serializer import SklearnOnnxModelSerializer
2122
from joblib import load
@@ -325,6 +326,7 @@ def test_serialize_using_pipeline_joblib(self):
325326
loaded_model = load(file)
326327
assert len(loaded_model.predict(self.X_test)) != 0
327328

329+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
328330
def test_serialize_and_load_model_as_onnx_xgboost_pipeline(self):
329331
"""
330332
Test serialize and load pipeline using Sklearn API with xgboost model.
@@ -365,6 +367,7 @@ def test_serialize_and_load_model_as_joblib_xgboost_pipeline(self):
365367
loaded_model = load(file)
366368
assert len(loaded_model.predict(self.X_iris)) != 0
367369

370+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
368371
def test_serialize_and_load_model_as_onnx_lgb_pipeline(self):
369372
"""
370373
Test serialize and load pipeline using Sklearn API with lightgbm model.
@@ -405,6 +408,7 @@ def test_serialize_and_load_model_as_joblib_lgb_pipeline(self):
405408
loaded_model = load(file)
406409
assert len(loaded_model.predict(self.X_iris)) != 0
407410

411+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
408412
def test_serialize_and_load_model_as_onnx_lgb_reg_pipeline(self):
409413
"""
410414
Test serialize and load pipeline using Sklearn API with lightgbm regressor model.

tests/unitary/with_extras/model/test_model_framework_tensorflow_model.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#!/usr/bin/env python
22

3-
# Copyright (c) 2022, 2023 Oracle and/or its affiliates.
3+
# Copyright (c) 2022, 2025 Oracle and/or its affiliates.
44
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
55

66
"""Unit tests for model frameworks. Includes tests for:
7-
- TensorFlowModel
7+
- TensorFlowModel
88
"""
9+
910
import base64
1011
import os
1112
import shutil
@@ -17,7 +18,7 @@
1718
import numpy as np
1819
import onnxruntime as rt
1920
import pandas as pd
20-
import pytest
21+
import pytest, sys
2122
import tensorflow as tf
2223
import tempfile
2324
from ads.model.framework.tensorflow_model import TensorFlowModel
@@ -91,6 +92,7 @@ def setup_class(cls):
9192
cls.training_conda_env = CONDA_PACK_PATH
9293
cls.training_python_version = SUPPORTED_PYTHON_VERSION
9394

95+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
9496
def test_serialize_with_incorrect_model_file_name_onnx(self):
9597
"""
9698
Test wrong model_file_name for onnx format.
@@ -139,6 +141,7 @@ def test_serialize_using_tf_with_modelname(self):
139141
os.path.join(tmp_model_dir, test_tf_model.model_file_name)
140142
)
141143

144+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
142145
def test_serialize_using_onnx_without_modelname(self):
143146
"""
144147
Test serialize_model using onnx without model_file_name
@@ -156,6 +159,7 @@ def test_serialize_using_onnx_without_modelname(self):
156159
)
157160
assert os.path.exists(os.path.join(tmp_model_dir, "model.onnx"))
158161

162+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
159163
def test_serialize_using_onnx_with_modelname(self):
160164
"""
161165
Test serialize_model using onnx with correct model_file_name
@@ -173,6 +177,7 @@ def test_serialize_using_onnx_with_modelname(self):
173177
os.path.join(tmp_model_dir, test_tf_model.model_file_name)
174178
)
175179

180+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
176181
def test_to_onnx(self):
177182
"""
178183
Test if TensorFlowOnnxModelSerializer.serialize() generate onnx model result.
@@ -189,6 +194,7 @@ def test_to_onnx(self):
189194
)
190195
assert os.path.exists(os.path.join(tmp_model_dir, model_file_name))
191196

197+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
192198
def test_to_onnx_reload(self):
193199
"""
194200
Test reloading the model generated by
@@ -209,6 +215,7 @@ def test_to_onnx_reload(self):
209215
is not None
210216
)
211217

218+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
212219
def test_to_onnx_without_dummy_input(self):
213220
"""
214221
Test if TensorFlowOnnxModelSerializer.serialize() raise expected error.
@@ -224,6 +231,7 @@ def test_to_onnx_without_dummy_input(self):
224231
)
225232
assert os.path.isfile(os.path.join(tmp_model_dir, model_file_name))
226233

234+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
227235
def test_to_onnx_without_path(self):
228236
"""
229237
Test if TensorFlowOnnxModelSerializer.serialize() raise expected error.
@@ -310,6 +318,7 @@ def test_prepare_default(self):
310318
)
311319
assert os.path.exists(os.path.join(tmp_model_dir, "model.h5"))
312320

321+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
313322
def test_prepare_onnx_with_input_signature(self):
314323
"""
315324
Test if TensorFlowModel.prepare onnx serialization
@@ -326,6 +335,7 @@ def test_prepare_onnx_with_input_signature(self):
326335
)
327336
assert os.path.exists(os.path.join(tmp_model_dir, "model.onnx"))
328337

338+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
329339
def test_prepare_onnx_with_X_sample(self):
330340
"""
331341
Test if TensorFlowModel.prepare raise expected error
@@ -342,6 +352,7 @@ def test_prepare_onnx_with_X_sample(self):
342352
)
343353
assert isinstance(test_tf_model.verify(self.x_test[:1].tolist()), dict)
344354

355+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
345356
def test_verify_onnx_without_input(self):
346357
"""
347358
Test if TensorFlowModel.verify in onnx serialization

tests/unitary/with_extras/model/test_model_framework_xgboost_model.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4-
# Copyright (c) 2021, 2023 Oracle and/or its affiliates.
4+
# Copyright (c) 2021, 2025 Oracle and/or its affiliates.
55
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
66

77
"""Unit tests for model frameworks. Includes tests for:
8-
- XGBoostModel
8+
- XGBoostModel
99
"""
10+
1011
import base64
1112
import os
1213
import shutil
@@ -33,7 +34,6 @@ def setup_method(cls):
3334
os.makedirs(tmp_model_dir, exist_ok=True)
3435

3536
def setup_class(cls):
36-
3737
X, y = make_classification(n_samples=100, n_informative=5, n_classes=2)
3838
(
3939
X_train_classification,
@@ -167,6 +167,7 @@ def test_serialize_and_load_model_as_json_sklearn_api(self):
167167
pred_json = loaded_model.predict(self.X_test_classification)
168168
assert all(pred_sklearn == pred_json)
169169

170+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
170171
def test_serialize_and_load_model_as_onnx_sklearn_api(self):
171172
"""
172173
Test serialize and load model using Sklearn API.
@@ -188,6 +189,7 @@ def test_serialize_and_load_model_as_onnx_sklearn_api(self):
188189
d = np.abs(pred_onx - pred_xgboost)
189190
assert d.max() <= 1
190191

192+
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="Skipped for Python 3.12+")
191193
def test_serialize_with_model_file_name(self):
192194
"""
193195
Test correct and wrong model_file_name format.

0 commit comments

Comments
 (0)