From cf3e3e682e2d447114299e49914e5e63daf05a29 Mon Sep 17 00:00:00 2001 From: Diego Ferigo Date: Tue, 22 Sep 2026 11:02:59 +0200 Subject: [PATCH] Gate checkout-only CLI tests with source_checkout_root --- .../gate-checkout-only-cli-tests.skip | 1 + source/isaaclab/test/cli/test_env_commands.py | 21 ++++++++++--------- source/isaaclab/test/cli/test_install.py | 2 +- .../test/cli/test_install_command_parsing.py | 1 + .../test/cli/test_install_commands.py | 5 +++-- .../test/cli/test_teleop_entrypoints.py | 6 +++--- 6 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 source/isaaclab/changelog.d/gate-checkout-only-cli-tests.skip diff --git a/source/isaaclab/changelog.d/gate-checkout-only-cli-tests.skip b/source/isaaclab/changelog.d/gate-checkout-only-cli-tests.skip new file mode 100644 index 000000000000..677b2d1bac01 --- /dev/null +++ b/source/isaaclab/changelog.d/gate-checkout-only-cli-tests.skip @@ -0,0 +1 @@ +# Test-only change; no changelog entry or version bump. diff --git a/source/isaaclab/test/cli/test_env_commands.py b/source/isaaclab/test/cli/test_env_commands.py index d29d7d0f668d..43aea874ad47 100644 --- a/source/isaaclab/test/cli/test_env_commands.py +++ b/source/isaaclab/test/cli/test_env_commands.py @@ -8,6 +8,7 @@ import os import shutil import subprocess +from pathlib import Path from unittest import mock import pytest @@ -59,11 +60,11 @@ def test_environment_setup_accepts_marked_source_build(tmp_path): envs._reject_downloaded_isaac_sim("uv") -def test_launcher_rejects_downloaded_isaac_sim_with_active_environment(tmp_path): +def test_launcher_rejects_downloaded_isaac_sim_with_active_environment(source_checkout_root: Path, tmp_path): """Platform launchers must reject an active environment before selecting its Python.""" launcher_name = "isaaclab.bat" if envs.is_windows() else "isaaclab.sh" launcher = tmp_path / launcher_name - shutil.copy2(envs.ISAACLAB_ROOT / launcher_name, launcher) + shutil.copy2(source_checkout_root / launcher_name, launcher) (tmp_path / "_isaac_sim").mkdir() environment = os.environ.copy() @@ -78,10 +79,10 @@ def test_launcher_rejects_downloaded_isaac_sim_with_active_environment(tmp_path) @pytest.mark.skipif(envs.is_windows(), reason="Linux launcher behavior") -def test_launcher_uses_bundled_python_with_inactive_default_environment(tmp_path): +def test_launcher_uses_bundled_python_with_inactive_default_environment(source_checkout_root: Path, tmp_path): """An inactive default environment must not override the bundled Python.""" launcher = tmp_path / "isaaclab.sh" - shutil.copy2(envs.ISAACLAB_ROOT / "isaaclab.sh", launcher) + shutil.copy2(source_checkout_root / "isaaclab.sh", launcher) bundled_python = tmp_path / "_isaac_sim" / "python.sh" bundled_python.parent.mkdir() bundled_python.write_text("#!/usr/bin/env bash\necho bundled-python\n") @@ -102,10 +103,10 @@ def test_launcher_uses_bundled_python_with_inactive_default_environment(tmp_path @pytest.mark.skipif(envs.is_windows(), reason="Linux launcher behavior") -def test_launcher_accepts_virtual_environment_on_bundled_python(tmp_path): +def test_launcher_accepts_virtual_environment_on_bundled_python(source_checkout_root: Path, tmp_path): """A virtual environment created on the package's own Python runs that interpreter, so it is allowed.""" launcher = tmp_path / "isaaclab.sh" - shutil.copy2(envs.ISAACLAB_ROOT / "isaaclab.sh", launcher) + shutil.copy2(source_checkout_root / "isaaclab.sh", launcher) bundled_python = tmp_path / "_isaac_sim" / "python.sh" bundled_python.parent.mkdir() bundled_python.write_text("#!/usr/bin/env bash\necho bundled-python\n") @@ -126,10 +127,10 @@ def test_launcher_accepts_virtual_environment_on_bundled_python(tmp_path): @pytest.mark.skipif(envs.is_windows(), reason="Linux launcher behavior") -def test_launcher_rejects_virtual_environment_on_foreign_python(tmp_path): +def test_launcher_rejects_virtual_environment_on_foreign_python(source_checkout_root: Path, tmp_path): """A virtual environment built on another interpreter stays rejected.""" launcher = tmp_path / "isaaclab.sh" - shutil.copy2(envs.ISAACLAB_ROOT / "isaaclab.sh", launcher) + shutil.copy2(source_checkout_root / "isaaclab.sh", launcher) (tmp_path / "_isaac_sim").mkdir() venv = tmp_path / "venv" (venv / "bin").mkdir(parents=True) @@ -145,10 +146,10 @@ def test_launcher_rejects_virtual_environment_on_foreign_python(tmp_path): @pytest.mark.skipif(envs.is_windows(), reason="Linux launcher behavior") -def test_launcher_allows_relinking_unmarked_source_build(tmp_path): +def test_launcher_allows_relinking_unmarked_source_build(source_checkout_root: Path, tmp_path): """The source-build command must bypass downloaded-package environment rejection.""" launcher = tmp_path / "isaaclab.sh" - shutil.copy2(envs.ISAACLAB_ROOT / "isaaclab.sh", launcher) + shutil.copy2(source_checkout_root / "isaaclab.sh", launcher) (tmp_path / "_isaac_sim").mkdir() active_python = tmp_path / "virtual-env" / "bin" / "python" active_python.parent.mkdir(parents=True) diff --git a/source/isaaclab/test/cli/test_install.py b/source/isaaclab/test/cli/test_install.py index 89d762f4661a..08f64e7ebc55 100644 --- a/source/isaaclab/test/cli/test_install.py +++ b/source/isaaclab/test/cli/test_install.py @@ -371,7 +371,7 @@ class TestEnsureNewton: def _completed(stdout: str = "", returncode: int = 0) -> subprocess.CompletedProcess: return subprocess.CompletedProcess(args=[], returncode=returncode, stdout=stdout, stderr="") - def test_installs_pinned_release_when_absent(self): + def test_installs_pinned_release_when_absent(self, source_checkout_root: Path): """When the pinned release is not installed, uninstall Newton then install it.""" from isaaclab.cli.commands import install diff --git a/source/isaaclab/test/cli/test_install_command_parsing.py b/source/isaaclab/test/cli/test_install_command_parsing.py index a24f6df1cd1d..aef4d22766e5 100644 --- a/source/isaaclab/test/cli/test_install_command_parsing.py +++ b/source/isaaclab/test/cli/test_install_command_parsing.py @@ -200,6 +200,7 @@ def _make_mock_env(**extra_env): return env +@pytest.mark.usefixtures("source_checkout_root") class TestCommandInstallDispatch: """Test that command_install() calls the right functions with the right args.""" diff --git a/source/isaaclab/test/cli/test_install_commands.py b/source/isaaclab/test/cli/test_install_commands.py index 132d3d433dbd..d39249244d34 100644 --- a/source/isaaclab/test/cli/test_install_commands.py +++ b/source/isaaclab/test/cli/test_install_commands.py @@ -420,6 +420,7 @@ def test_probe_receives_original_pythonpath(self, tmp_path): # --------------------------------------------------------------------------- +@pytest.mark.usefixtures("source_checkout_root") class TestEnsureCudaTorch: """Tests for :func:`_ensure_cuda_torch` across architectures and environment types. @@ -973,14 +974,14 @@ def test_all_non_nvidia_packages_are_repointed(self, tmp_path, pkg_name): class TestInstallRootExtraExcludesIsaacSim: """The ``teleop`` extra lists Isaac Sim for uv, but pip must never resolve it inline.""" - def test_root_extra_dependencies_exclude_isaacsim(self): + def test_root_extra_dependencies_exclude_isaacsim(self, source_checkout_root: Path): """pip has no override mechanism, so isaacsim + isaacteleop in one pass cannot resolve.""" dependencies = install_cmd._root_extra_dependencies("teleop") assert not any(d.startswith("isaacsim") for d in dependencies) assert any(d.startswith("isaacteleop") for d in dependencies) - def test_install_root_extra_omits_isaacsim_from_the_pip_command(self, tmp_path): + def test_install_root_extra_omits_isaacsim_from_the_pip_command(self, source_checkout_root: Path, tmp_path): """``./isaaclab.sh -i teleop`` must not hand Isaac Sim to pip alongside Isaac Teleop.""" python_exe = str(tmp_path / "python") pip_cmd = [python_exe, "-m", "pip"] diff --git a/source/isaaclab/test/cli/test_teleop_entrypoints.py b/source/isaaclab/test/cli/test_teleop_entrypoints.py index a459e5f5bb69..8c56e014f220 100644 --- a/source/isaaclab/test/cli/test_teleop_entrypoints.py +++ b/source/isaaclab/test/cli/test_teleop_entrypoints.py @@ -27,13 +27,13 @@ @pytest.mark.parametrize(("command", "script_parts"), TELEOP_WORKFLOWS.items()) -def test_teleop_workflow_help_exposes_task_preset_selectors(command, script_parts): +def test_teleop_workflow_help_exposes_task_preset_selectors(source_checkout_root: Path, command, script_parts): """Every teleop workflow accepts the task preset selectors documented for teleoperation.""" - script = cli.ISAACLAB_ROOT.joinpath(*script_parts) + script = source_checkout_root.joinpath(*script_parts) result = subprocess.run( [sys.executable, str(script), "--help"], - cwd=cli.ISAACLAB_ROOT, + cwd=source_checkout_root, capture_output=True, text=True, check=False,