Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sdk/ml/azure-ai-ml/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

### Bugs Fixed

### Other Changes

- Ensuring that azureml-dataprep-rslex is only installed for PyPy below 3.10 and CPython below 3.13.

## 1.30.0 (2025-10-29)

Expand Down
11,444 changes: 0 additions & 11,444 deletions sdk/ml/azure-ai-ml/NOTICE.txt

This file was deleted.

3 changes: 2 additions & 1 deletion sdk/ml/azure-ai-ml/dev_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ azure-mgmt-resourcegraph<9.0.0,>=2.0.0
azure-mgmt-resource<23.0.0,>=3.0.0
pytest-reportlog
python-dotenv
azureml-dataprep-rslex>=2.22.0; python_version < "3.13"
azureml-dataprep-rslex>=2.22.0; platform_python_implementation == "CPython" and python_version < "3.13"
azureml-dataprep-rslex>=2.22.0; platform_python_implementation == "PyPy" and python_version < "3.10"
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import os, sys
import os
import platform
import sys
from pathlib import Path
from typing import Iterable
from unittest.mock import ANY, Mock, patch
Expand Down Expand Up @@ -26,6 +28,9 @@
from azure.ai.ml.operations import DataOperations, DatastoreOperations
from azure.core.paging import ItemPaged

IS_CPYTHON = platform.python_implementation() == "CPython"
IS_PYPY = platform.python_implementation() == "PyPy"


@pytest.fixture
def mock_datastore_operation(
Expand Down Expand Up @@ -577,8 +582,8 @@ def test_create_with_datastore(
)

@pytest.mark.skipif(
sys.version_info >= (3, 13),
reason="Skipping because Python version is 3.13 or above. azureml.dataprep.rslex do not support py313",
(IS_CPYTHON and sys.version_info >= (3, 13)) or (IS_PYPY and sys.version_info >= (3, 10)),
reason="Skipping because CPython version is >=3.13 or PyPy version is >=3.10. azureml.dataprep.rslex do not support it",
)
def test_mount_persistent(
self,
Expand All @@ -601,8 +606,8 @@ def test_mount_persistent(
mock_data_operations._compute_operation.update_data_mounts.assert_called_once()

@pytest.mark.skipif(
sys.version_info >= (3, 13),
reason="Skipping because Python version is 3.13 or above. azureml.dataprep.rslex do not support py313",
(IS_CPYTHON and sys.version_info >= (3, 13)) or (IS_PYPY and sys.version_info >= (3, 10)),
reason="Skipping because CPython version is >=3.13 or PyPy version is >=3.10. azureml.dataprep.rslex do not support it",
)
def test_mount_non_persistent(
self,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import os, sys
import os
import platform
import sys
from unittest.mock import Mock, patch

import pytest
Expand All @@ -8,6 +10,9 @@
from azure.ai.ml.entities._datastore.datastore import Datastore
from azure.ai.ml.operations import DatastoreOperations

IS_CPYTHON = platform.python_implementation() == "CPython"
IS_PYPY = platform.python_implementation() == "PyPy"


@pytest.fixture
def mock_datastore_operation(
Expand Down Expand Up @@ -69,8 +74,8 @@ def test_create(self, mock_from_rest, mock_datastore_operation: DatastoreOperati
mock_datastore_operation._operation.create_or_update.assert_called_once()

@pytest.mark.skipif(
sys.version_info >= (3, 13),
reason="Skipping because Python version is 3.13 or above. azureml.dataprep.rslex do not support py313",
(IS_CPYTHON and sys.version_info >= (3, 13)) or (IS_PYPY and sys.version_info >= (3, 10)),
reason="Skipping because CPython version is >=3.13 or PyPy version is >=3.10. azureml.dataprep.rslex do not support it",
)
def test_mount_persistent(
self,
Expand All @@ -94,8 +99,8 @@ def test_mount_persistent(
mock_datastore_operation._compute_operation.update_data_mounts.assert_called_once()

@pytest.mark.skipif(
sys.version_info >= (3, 13),
reason="Skipping because Python version is 3.13 or above. azureml.dataprep.rslex do not support py313",
(IS_CPYTHON and sys.version_info >= (3, 13)) or (IS_PYPY and sys.version_info >= (3, 10)),
reason="Skipping because CPython version is >=3.13 or PyPy version is >=3.10. azureml.dataprep.rslex do not support it",
)
def test_mount_non_persistent(
self,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import sys
import platform
import subprocess
import sys

import pytest

PACKAGE_NAME = "azureml-dataprep-rslex"
IS_CPYTHON = platform.python_implementation() == "CPython"
IS_PYPY = platform.python_implementation() == "PyPy"


def is_package_installed(package_name):
Expand All @@ -16,14 +20,36 @@ def is_package_installed(package_name):
@pytest.mark.unittest
@pytest.mark.core_sdk_test
class TestPackageInstallation:
"""Test class to validate package installation across Python versions."""
"""Test class to validate package installation across Python versions and environments."""

@pytest.mark.skipif(sys.version_info < (3, 13), reason="Skipping because Python version is below 3.13")
def test_package_not_installed_in_python_3_13(self):
"""Ensure azureml-dataprep-rslex is NOT installed in Python 3.13+."""
assert not is_package_installed(PACKAGE_NAME), f"{PACKAGE_NAME} should not be installed in Python 3.13+"
@pytest.mark.skipif(
not (IS_CPYTHON and sys.version_info >= (3, 13)),
reason="Skipping because environment is not >= cpython 3.13",
)
def test_package_not_installed_in_cpython_3_13(self):
assert not is_package_installed(
PACKAGE_NAME
), f"{PACKAGE_NAME} should not be installed in CPython 3.13 or above environment."

@pytest.mark.skipif(sys.version_info >= (3, 13), reason="Skipping because Python version is 3.13 or above")
def test_package_installed_below_python_3_13(self):
"""Ensure azureml-dataprep-rslex IS installed in Python < 3.13."""
assert is_package_installed(PACKAGE_NAME), f"{PACKAGE_NAME} should be installed in Python < 3.13"
@pytest.mark.skipif(
not (IS_CPYTHON and sys.version_info < (3, 13)),
reason="Skipping because environment is not below cpython 3.13",
)
def test_package_installed_below_cpython_3_13(self):
assert is_package_installed(PACKAGE_NAME), f"{PACKAGE_NAME} should be installed in CPython < 3.13."

@pytest.mark.skipif(
not (IS_PYPY and sys.version_info >= (3, 10)),
reason="Skipping because environment is not >= pypy 3.10",
)
def test_package_not_installed_in_pypy_3_10(self):
assert not is_package_installed(
PACKAGE_NAME
), f"{PACKAGE_NAME} should not be installed in PyPy 3.10 or above environment."

@pytest.mark.skipif(
not (IS_PYPY and sys.version_info < (3, 10)),
reason="Skipping because environment is not below pypy 3.10",
)
def test_package_installed_below_pypy_3_10(self):
assert is_package_installed(PACKAGE_NAME), f"{PACKAGE_NAME} should be installed in PyPy < 3.10 environment."
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import importlib
import platform
import re
import sys
from importlib import reload
Expand Down Expand Up @@ -64,7 +65,8 @@ def mock_function_multi_return_expected(__self, mock_arg):
@pytest.mark.unittest
@pytest.mark.pipeline_test
@pytest.mark.skipif(
condition=sys.version_info >= (3, 13), reason="historical implementation doesn't support Python 3.13+"
condition=sys.version_info >= (3, 13) or platform.python_implementation() == "PyPy",
reason="historical implementation doesn't support Python 3.13+, and relies on CPython bytecode optimization; PyPy does not support required opcodes",
)
class TestPersistentLocalsProfiler:
@classmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# ---------------------------------------------------------
import os
import platform
from unittest.mock import patch

import pytest
Expand Down Expand Up @@ -100,6 +101,10 @@ def test_pipeline_telemetry_value(self):
assert v["node_type"] == '{"automl": 1}'
assert v["node_source"] == '{"BUILDER": 1}'

@pytest.mark.skipif(
platform.python_implementation() == "PyPy",
reason="Test relies on CPython-specific bytecode optimization and is not intended for PyPy",
)
def test_dsl_pipeline_telemetry_value(self):
path = "./tests/test_configs/components/helloworld_component.yml"

Expand All @@ -117,6 +122,10 @@ def pipeline_no_arg():
assert v["node_source"] == '{"YAML.COMPONENT": 1}'

@patch.dict(os.environ, {AZUREML_PRIVATE_FEATURES_ENV_VAR: "True"})
@pytest.mark.skipif(
platform.python_implementation() == "PyPy",
reason="Relies on CPython bytecode optimization; PyPy does not support required opcodes",
)
def test_dsl_subpipeline_telemetry_value(self):
path = "./tests/test_configs/components/helloworld_component.yml"
component_func1 = load_component(path)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import os
import platform
from unittest.mock import Mock, patch

import jwt
Expand Down Expand Up @@ -155,6 +156,10 @@ def test_get(self, mock_method, mock_job_operation: JobOperations) -> None:
# use mock_component_hash to avoid passing a Mock object as client key
@pytest.mark.usefixtures("mock_component_hash")
@patch.object(JobOperations, "_get_job")
@pytest.mark.skipif(
platform.python_implementation() == "PyPy",
reason="Relies on CPython bytecode optimization; PyPy does not support required opcodes",
)
def test_get_job(self, mock_method, mock_job_operation: JobOperations) -> None:
from azure.ai.ml import Input, dsl, load_component

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import platform
from pathlib import Path

import pydash
Expand Down Expand Up @@ -2020,6 +2021,10 @@ def test_pipeline_node_with_identity(self):
},
}

@pytest.mark.skipif(
platform.python_implementation() == "PyPy",
reason="Relies on CPython bytecode optimization; PyPy does not support required opcodes",
)
def test_pipeline_parameter_with_empty_value(self, client: MLClient) -> None:
input_types_func = load_component(source="./tests/test_configs/components/input_types_component.yml")

Expand Down Expand Up @@ -2057,6 +2062,10 @@ def empty_value_pipeline(
assert "number" in rest_obj.properties.inputs
assert "str_param" in rest_obj.properties.inputs

@pytest.mark.skipif(
platform.python_implementation() == "PyPy",
reason="Relies on CPython bytecode optimization; PyPy does not support required opcodes",
)
def test_pipeline_input_as_runsettings_value(self, client: MLClient) -> None:
input_types_func = load_component(source="./tests/test_configs/components/input_types_component.yml")

Expand Down Expand Up @@ -2103,6 +2112,10 @@ def test_pipeline_job_automl_with_job_tier_in_pipeline(self) -> None:
rest_obj = pipeline_job._to_rest_object()
assert rest_obj.properties.jobs["text_ner_node"]["queue_settings"] == {"job_tier": "spot"}

@pytest.mark.skipif(
platform.python_implementation() == "PyPy",
reason="Relies on CPython bytecode optimization; PyPy does not support required opcodes",
)
def test_pipeline_with_duplicate_output(self) -> None:
component_path = "./tests/test_configs/components/helloworld_component.yml"
comp_func = load_component(source=component_path)
Expand Down Expand Up @@ -2195,6 +2208,10 @@ def test_pipeline_job_with_data_binding_expression_on_spark_resource(self, mock_
"runtime_version": "3.4.0",
}

@pytest.mark.skipif(
platform.python_implementation() == "PyPy",
reason="Relies on CPython bytecode optimization; PyPy does not support required opcodes",
)
def test_local_input_in_pipeline_job(self, client: MLClient, tmp_path: Path):
file_path = tmp_path / "mock_input_file"
file_path.touch(exist_ok=True)
Expand Down
Loading
Loading