From 72a8cd108fb5ad3d437c9f883d689da3a2c97671 Mon Sep 17 00:00:00 2001 From: Ivan Podkidyshev Date: Tue, 22 Sep 2026 15:50:25 +0200 Subject: [PATCH 1/3] Restore deprecated CLI handler compatibility imports Signed-off-by: Ivan Podkidyshev --- doc/DEV.rst | 7 +++ src/cloudai/cli/handlers.py | 65 ++++++++++++++++++++++++++++ tests/cli/__init__.py | 15 +++++++ tests/cli/test_handlers.py | 86 +++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 src/cloudai/cli/handlers.py create mode 100644 tests/cli/__init__.py create mode 100644 tests/cli/test_handlers.py diff --git a/doc/DEV.rst b/doc/DEV.rst index e2a6c27c6..c1ca82f19 100644 --- a/doc/DEV.rst +++ b/doc/DEV.rst @@ -31,6 +31,13 @@ This chapter targets developers who want to contribute to the project's core. runners --> _core systems --> _core +Handler imports +--------------- + +Shared orchestration lives in ``cloudai.handlers``. The CLI calls this module directly. +Existing imports from ``cloudai.cli.handlers`` continue to work and emit ``DeprecationWarning`` when called. +These handlers are internal implementation details; avoid calling them directly from integrations. + Core Modules ------------ diff --git a/src/cloudai/cli/handlers.py b/src/cloudai/cli/handlers.py new file mode 100644 index 000000000..3f3d91ab1 --- /dev/null +++ b/src/cloudai/cli/handlers.py @@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES +# Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import functools +import typing +import warnings + +import cloudai.handlers + +_P = typing.ParamSpec("_P") +_R = typing.TypeVar("_R") + + +def _deprecated(function: typing.Callable[_P, _R]) -> typing.Callable[_P, _R]: + @functools.wraps(function) + def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _R: + warnings.warn( + f"cloudai.cli.handlers.{function.__name__} is deprecated; do not call CLI handlers directly.", + DeprecationWarning, + stacklevel=2, + ) + return getattr(cloudai.handlers, function.__name__)(*args, **kwargs) + + return wrapper + + +_log_installation_dirs = _deprecated(cloudai.handlers._log_installation_dirs) +handle_install_and_uninstall = _deprecated(cloudai.handlers.handle_install_and_uninstall) +prepare_installation = _deprecated(cloudai.handlers.prepare_installation) +_scenario_installables = _deprecated(cloudai.handlers._scenario_installables) +handle_dse_job = _deprecated(cloudai.handlers.handle_dse_job) +_record_run_failure = _deprecated(cloudai.handlers._record_run_failure) +generate_reports = _deprecated(cloudai.handlers.generate_reports) +handle_non_dse_job = _deprecated(cloudai.handlers.handle_non_dse_job) +register_signal_handlers = _deprecated(cloudai.handlers.register_signal_handlers) +_setup_system_and_scenario = _deprecated(cloudai.handlers._setup_system_and_scenario) +_handle_single_sbatch = _deprecated(cloudai.handlers._handle_single_sbatch) +_check_installation = _deprecated(cloudai.handlers._check_installation) +handle_dry_run_and_run = _deprecated(cloudai.handlers.handle_dry_run_and_run) +handle_generate_report = _deprecated(cloudai.handlers.handle_generate_report) +expand_file_list = _deprecated(cloudai.handlers.expand_file_list) +_ensure_kube_config_exists = _deprecated(cloudai.handlers._ensure_kube_config_exists) +verify_system_configs = _deprecated(cloudai.handlers.verify_system_configs) +verify_test_configs = _deprecated(cloudai.handlers.verify_test_configs) +verify_test_scenarios = _deprecated(cloudai.handlers.verify_test_scenarios) +handle_verify_all_configs = _deprecated(cloudai.handlers.handle_verify_all_configs) +load_tomls_by_type = _deprecated(cloudai.handlers.load_tomls_by_type) +handle_list_registered_items = _deprecated(cloudai.handlers.handle_list_registered_items) +validate_domain_randomization_active = _deprecated(cloudai.handlers.validate_domain_randomization_active) +load_test_toml_file = _deprecated(cloudai.handlers.load_test_toml_file) +format_toml_decode_error = _deprecated(cloudai.handlers.format_toml_decode_error) +prepare_output_dir = _deprecated(cloudai.handlers.prepare_output_dir) diff --git a/tests/cli/__init__.py b/tests/cli/__init__.py new file mode 100644 index 000000000..3ac11851d --- /dev/null +++ b/tests/cli/__init__.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES +# Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/cli/test_handlers.py b/tests/cli/test_handlers.py new file mode 100644 index 000000000..936321f76 --- /dev/null +++ b/tests/cli/test_handlers.py @@ -0,0 +1,86 @@ +# SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES +# Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import inspect +from unittest.mock import Mock, call + +import pytest + +import cloudai.cli.handlers +import cloudai.handlers + + +@pytest.mark.parametrize( + "name", + [ + "_log_installation_dirs", + "handle_install_and_uninstall", + "prepare_installation", + "_scenario_installables", + "handle_dse_job", + "_record_run_failure", + "generate_reports", + "handle_non_dse_job", + "register_signal_handlers", + "_setup_system_and_scenario", + "_handle_single_sbatch", + "_check_installation", + "handle_dry_run_and_run", + "handle_generate_report", + "expand_file_list", + "_ensure_kube_config_exists", + "verify_system_configs", + "verify_test_configs", + "verify_test_scenarios", + "handle_verify_all_configs", + "load_tomls_by_type", + "handle_list_registered_items", + "validate_domain_randomization_active", + "load_test_toml_file", + "format_toml_decode_error", + "prepare_output_dir", + ], +) +def test_legacy_handler(name: str, monkeypatch: pytest.MonkeyPatch): + original = getattr(cloudai.handlers, name) + legacy = getattr(cloudai.cli.handlers, name) + signature = inspect.signature(original) + assert inspect.signature(legacy) == signature + assert legacy.__doc__ == original.__doc__ + + target = Mock() + monkeypatch.setattr(cloudai.handlers, name, target) + kwargs = {parameter: object() for parameter in signature.parameters} + args = tuple(kwargs.values()) + required_args = tuple( + value + for parameter, value in kwargs.items() + if signature.parameters[parameter].default is inspect.Parameter.empty + ) + warning = rf"cloudai\.cli\.handlers\.{name} is deprecated" + for positional, keywords in [(args, {}), ((), kwargs), (required_args, {})]: + with pytest.warns(DeprecationWarning, match=warning) as recorded: + assert legacy(*positional, **keywords) is target.return_value + assert len(recorded) == 1 + assert recorded[0].filename == __file__ + + assert target.call_args_list == [call(*args), call(**kwargs), call(*required_args)] + + error = RuntimeError("handler failure") + target.side_effect = error + with pytest.warns(DeprecationWarning, match=warning), pytest.raises(RuntimeError) as raised: + legacy(*required_args) + assert raised.value is error From 2a52be594d7358bbbcff7c0f40649ada4c47aa09 Mon Sep 17 00:00:00 2001 From: Ivan Podkidyshev Date: Tue, 22 Sep 2026 15:59:06 +0200 Subject: [PATCH 2/3] Keep compatibility shims limited to public functions Signed-off-by: Ivan Podkidyshev --- doc/DEV.rst | 7 --- src/cloudai/cli/handlers.py | 7 --- tests/cli/__init__.py | 15 ------- tests/cli/test_handlers.py | 86 ------------------------------------- 4 files changed, 115 deletions(-) delete mode 100644 tests/cli/__init__.py delete mode 100644 tests/cli/test_handlers.py diff --git a/doc/DEV.rst b/doc/DEV.rst index c1ca82f19..e2a6c27c6 100644 --- a/doc/DEV.rst +++ b/doc/DEV.rst @@ -31,13 +31,6 @@ This chapter targets developers who want to contribute to the project's core. runners --> _core systems --> _core -Handler imports ---------------- - -Shared orchestration lives in ``cloudai.handlers``. The CLI calls this module directly. -Existing imports from ``cloudai.cli.handlers`` continue to work and emit ``DeprecationWarning`` when called. -These handlers are internal implementation details; avoid calling them directly from integrations. - Core Modules ------------ diff --git a/src/cloudai/cli/handlers.py b/src/cloudai/cli/handlers.py index 3f3d91ab1..40ddb434d 100644 --- a/src/cloudai/cli/handlers.py +++ b/src/cloudai/cli/handlers.py @@ -37,22 +37,15 @@ def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _R: return wrapper -_log_installation_dirs = _deprecated(cloudai.handlers._log_installation_dirs) handle_install_and_uninstall = _deprecated(cloudai.handlers.handle_install_and_uninstall) prepare_installation = _deprecated(cloudai.handlers.prepare_installation) -_scenario_installables = _deprecated(cloudai.handlers._scenario_installables) handle_dse_job = _deprecated(cloudai.handlers.handle_dse_job) -_record_run_failure = _deprecated(cloudai.handlers._record_run_failure) generate_reports = _deprecated(cloudai.handlers.generate_reports) handle_non_dse_job = _deprecated(cloudai.handlers.handle_non_dse_job) register_signal_handlers = _deprecated(cloudai.handlers.register_signal_handlers) -_setup_system_and_scenario = _deprecated(cloudai.handlers._setup_system_and_scenario) -_handle_single_sbatch = _deprecated(cloudai.handlers._handle_single_sbatch) -_check_installation = _deprecated(cloudai.handlers._check_installation) handle_dry_run_and_run = _deprecated(cloudai.handlers.handle_dry_run_and_run) handle_generate_report = _deprecated(cloudai.handlers.handle_generate_report) expand_file_list = _deprecated(cloudai.handlers.expand_file_list) -_ensure_kube_config_exists = _deprecated(cloudai.handlers._ensure_kube_config_exists) verify_system_configs = _deprecated(cloudai.handlers.verify_system_configs) verify_test_configs = _deprecated(cloudai.handlers.verify_test_configs) verify_test_scenarios = _deprecated(cloudai.handlers.verify_test_scenarios) diff --git a/tests/cli/__init__.py b/tests/cli/__init__.py deleted file mode 100644 index 3ac11851d..000000000 --- a/tests/cli/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES -# Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/tests/cli/test_handlers.py b/tests/cli/test_handlers.py deleted file mode 100644 index 936321f76..000000000 --- a/tests/cli/test_handlers.py +++ /dev/null @@ -1,86 +0,0 @@ -# SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES -# Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import inspect -from unittest.mock import Mock, call - -import pytest - -import cloudai.cli.handlers -import cloudai.handlers - - -@pytest.mark.parametrize( - "name", - [ - "_log_installation_dirs", - "handle_install_and_uninstall", - "prepare_installation", - "_scenario_installables", - "handle_dse_job", - "_record_run_failure", - "generate_reports", - "handle_non_dse_job", - "register_signal_handlers", - "_setup_system_and_scenario", - "_handle_single_sbatch", - "_check_installation", - "handle_dry_run_and_run", - "handle_generate_report", - "expand_file_list", - "_ensure_kube_config_exists", - "verify_system_configs", - "verify_test_configs", - "verify_test_scenarios", - "handle_verify_all_configs", - "load_tomls_by_type", - "handle_list_registered_items", - "validate_domain_randomization_active", - "load_test_toml_file", - "format_toml_decode_error", - "prepare_output_dir", - ], -) -def test_legacy_handler(name: str, monkeypatch: pytest.MonkeyPatch): - original = getattr(cloudai.handlers, name) - legacy = getattr(cloudai.cli.handlers, name) - signature = inspect.signature(original) - assert inspect.signature(legacy) == signature - assert legacy.__doc__ == original.__doc__ - - target = Mock() - monkeypatch.setattr(cloudai.handlers, name, target) - kwargs = {parameter: object() for parameter in signature.parameters} - args = tuple(kwargs.values()) - required_args = tuple( - value - for parameter, value in kwargs.items() - if signature.parameters[parameter].default is inspect.Parameter.empty - ) - warning = rf"cloudai\.cli\.handlers\.{name} is deprecated" - for positional, keywords in [(args, {}), ((), kwargs), (required_args, {})]: - with pytest.warns(DeprecationWarning, match=warning) as recorded: - assert legacy(*positional, **keywords) is target.return_value - assert len(recorded) == 1 - assert recorded[0].filename == __file__ - - assert target.call_args_list == [call(*args), call(**kwargs), call(*required_args)] - - error = RuntimeError("handler failure") - target.side_effect = error - with pytest.warns(DeprecationWarning, match=warning), pytest.raises(RuntimeError) as raised: - legacy(*required_args) - assert raised.value is error From 49adfb1f272e0e542ca5e0cc656c52f714810c15 Mon Sep 17 00:00:00 2001 From: Ivan Podkidyshev Date: Tue, 29 Sep 2026 20:51:21 +0200 Subject: [PATCH 3/3] Fix CLI compatibility module copyright year Signed-off-by: Ivan Podkidyshev --- src/cloudai/cli/handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloudai/cli/handlers.py b/src/cloudai/cli/handlers.py index 40ddb434d..de41076f9 100644 --- a/src/cloudai/cli/handlers.py +++ b/src/cloudai/cli/handlers.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES -# Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License");