feat(isaac): [isaac] extras + entry-point + PEP 562 lazy import (1/5 of #31 split)#44
Conversation
strands-labs#31 split) Part 1 / 5 of the split of strands-labs#31 — tracked by strands-labs#42. Adds the package skeleton for the Isaac Sim backend with zero `omni` overhead on `import strands_robots_sim`: - `pyproject.toml`: - new `[isaac]` extra (lightweight Isaac-companion deps that ARE pip-installable: `usd-core>=24.5,<26.0`, `warp-lang>=1.13.0`). Comment explains that Isaac Sim itself is NOT installable from PyPI — must come via Omniverse Launcher / Isaac Lab / nvcr.io. - new `[all]` aggregate extra (currently delegates to `[isaac]`; will gain `[newton]` etc. as later backends land). - new `[project.entry-points."strands_robots.backends"]` declaring both `isaac` and `isaac_sim` aliases pointing at `strands_robots_sim.isaac.simulation:IsaacSimulation` (the class itself lands in PR-4 / `feat(isaac): IsaacSimulation backend`). - new `pytest>=7.0` in `dev` extras and `[tool.hatch.envs.default]` deps so future PRs in this split chain can run pytest under `hatch run test`. - new `[tool.pytest.ini_options]` with a `gpu` marker so PR-4's GPU-only integ tests can gate on `STRANDS_GPU_TEST=1`. - `strands_robots_sim/isaac/__init__.py`: PEP 562 lazy stub — declares `__all__ = ["IsaacSimulation", "IsaacConfig"]` and routes attribute access through `__getattr__` to deferred imports of `.simulation` and `.config`. The bare `import strands_robots_sim.isaac` does NOT import any `omni` modules; that overhead only fires when a caller actually accesses `IsaacSimulation` or `IsaacConfig`. - `strands_robots_sim/isaac/tests/__init__.py`: empty package marker so future test files in this directory are collectable. Test files themselves land in subsequent slices alongside the code they cover. CI signal: lint clean (black / isort / flake8); the existing `hatch run test` import-smoke passes (it doesn't touch `isaac`, so no missing-submodule errors). Pytest doesn't run yet from `hatch run test` — the test command stays as the import-smoke placeholder in this slice and flips to `pytest strands_robots_sim/isaac/tests/` in PR-3 once the first real test files land. Why this lands first: PR-2 / PR-3 / PR-4 all import from `strands_robots_sim.isaac`, so the package stub + extras + entry points have to exist before any of those files can be code-reviewed against current `main`. Original work by @cagataycali in strands-labs#31 (`413ff15..befb1e3`); this slice cherry-picks just the foundation files. Review-thread anchors on the original commits stay intact for whichever child PR consumes the relevant code.
cagataycali
left a comment
There was a problem hiding this comment.
Local review on Thor — lazy contract works, but ships zero tests
Verified locally:
pip install -e .cleanimport strands_robots_sim.isaacadds zeroomni.*modules tosys.modules✅strands_robots_sim.isaac.__all__ == ['IsaacSimulation', 'IsaacConfig']✅pytest strands_robots_sim/isaac/tests/→ 0 tests collected ❌
Why this matters
This PR is the structural parent of PR45/46/47/48 — they all branched from this commit (3a0a854). So merging this lands the foundation. But it ships with zero test coverage; the lazy-import contract claim is verified only by manual probing, not by CI.
Meanwhile, the orphan PR43 (feat/isaac-extras-and-lazy-import) ships 10 cleanly-passing tests that verify exactly what PR-1 delivers:
- 6 tests in
TestEntryPointDeclaration— pyproject parsing +importlib.metadatadiscovery - 4 tests in
TestLazyImportSurface— including theomni.*-not-loaded assertion that the PR description promises
Those tests don't depend on PR-2/3/4/5 — they only inspect the surface PR-1 actually creates. Safe to land here.
Recommendation
Before merging, port these from PR43:
strands_robots_sim/isaac/tests/test_entrypoint.py(140 LOC, 10 tests)pytest>=7.0in the[isaac]extra (currently in[default]env only)- Switch hatch
testscript frompython -c "import strands_robots_sim; ..."topytest strands_robots_sim/isaac/tests/ -v
Then close PR43.
What works ✅
- Lazy
__init__.py(43 LOC) — clean PEP 562 stub pyproject.tomlextras + entry-points — bothisaacandisaac_simaliases declared correctly- Lazy contract holds at runtime
- Lint clean
Waiting on the test port before approving.
…abs#43 (PR strands-labs#44 R1) Closes @cagataycali's R1 review on strands-labs#44 -- the lazy-import contract ships with concrete CI signal now, not just a manual probe in the PR description. Three coordinated changes per the review: 1. **Port `tests/test_entrypoint.py` (140 LOC, 10 tests)** from the closed orphan PR strands-labs#43 (`feat/isaac-extras-and-lazy-import`). These tests verify *only* PR-1's surface and have **zero dependency on `simulation.py`** (which lands in PR-4 of the strands-labs#31 split): - `TestEntryPointDeclaration` (6 tests): - `test_pyproject_exists` - `test_isaac_entry_point_declared_in_pyproject` - `test_isaac_sim_alias_entry_point_declared_in_pyproject` - `test_isaac_extra_declared_in_pyproject` - `test_isaac_extra_includes_pytest` - `test_entry_points_visible_via_importlib_metadata_when_installed` (skips with actionable hint when not pip-installed) - `TestLazyImportSurface` (4 tests): - `test_import_isaac_does_not_load_omni` -- pins the `omni`-not- loaded contract via `sys.modules` set diff before/after import. - `test_isaac_subpackage_exposes_lazy_attrs_in___all__` - `test_unknown_attr_raises_attributeerror` -- pins the PEP 562 `__getattr__` raises `AttributeError` (not `ImportError`) on unknown attrs. - `test_dunder_getattr_is_present` 2. **Add `pytest>=7.0` to the `[isaac]` extra** in `pyproject.toml`. Means `pip install '.[isaac]'` covers the test deps without a separate dev extra on CI hosts. Also pinned by `test_isaac_extra_includes_pytest`. 3. **Flip `hatch run test`** from the import-smoke placeholder (`python -c "import strands_robots_sim; ..."`) to `pytest strands_robots_sim/isaac/tests/ -v`. The 10 tests collect and pass standalone; PR-4's simulation-module tests join the collection automatically when that PR rebases. Verification: - `pytest strands_robots_sim/isaac/tests/ -v` -> **10 passed in 0.14s** - `black --check` / `isort --check-only` / `flake8` (max-line=120) on `strands_robots_sim/` + `examples/` -> clean - AST parse on touched files -> ok - The 10 tests have no import path through `simulation.py`; they validate only PR-1's actual surface (pyproject parsing, entry- point declaration, PEP 562 `__getattr__` contract). The original `test_entrypoint.py` on `cagataycali/feat/isaac-sim` imports from `strands_robots_sim.isaac.simulation`, which is why PR-1 of the split couldn't ship that file unmodified. The version ported here was rewritten on the strands-labs#43 branch specifically for the PR-1 surface; cleanly self-contained against this slice.
|
Thanks for the review. R1 fix pushed as
The ported tests are designed for PR-1's surface specifically — they read Downstream impact on the rest of the chain
Let me know if you'd prefer a different rebase strategy (e.g., merge commit on #45-#48 instead of rebase to preserve their commit SHAs for any inline-thread anchors). |
…#45) * feat(isaac): [isaac] extras + entry-point + PEP 562 lazy import (1/5 of #31 split) Part 1 / 5 of the split of #31 — tracked by #42. Adds the package skeleton for the Isaac Sim backend with zero `omni` overhead on `import strands_robots_sim`: - `pyproject.toml`: - new `[isaac]` extra (lightweight Isaac-companion deps that ARE pip-installable: `usd-core>=24.5,<26.0`, `warp-lang>=1.13.0`). Comment explains that Isaac Sim itself is NOT installable from PyPI — must come via Omniverse Launcher / Isaac Lab / nvcr.io. - new `[all]` aggregate extra (currently delegates to `[isaac]`; will gain `[newton]` etc. as later backends land). - new `[project.entry-points."strands_robots.backends"]` declaring both `isaac` and `isaac_sim` aliases pointing at `strands_robots_sim.isaac.simulation:IsaacSimulation` (the class itself lands in PR-4 / `feat(isaac): IsaacSimulation backend`). - new `pytest>=7.0` in `dev` extras and `[tool.hatch.envs.default]` deps so future PRs in this split chain can run pytest under `hatch run test`. - new `[tool.pytest.ini_options]` with a `gpu` marker so PR-4's GPU-only integ tests can gate on `STRANDS_GPU_TEST=1`. - `strands_robots_sim/isaac/__init__.py`: PEP 562 lazy stub — declares `__all__ = ["IsaacSimulation", "IsaacConfig"]` and routes attribute access through `__getattr__` to deferred imports of `.simulation` and `.config`. The bare `import strands_robots_sim.isaac` does NOT import any `omni` modules; that overhead only fires when a caller actually accesses `IsaacSimulation` or `IsaacConfig`. - `strands_robots_sim/isaac/tests/__init__.py`: empty package marker so future test files in this directory are collectable. Test files themselves land in subsequent slices alongside the code they cover. CI signal: lint clean (black / isort / flake8); the existing `hatch run test` import-smoke passes (it doesn't touch `isaac`, so no missing-submodule errors). Pytest doesn't run yet from `hatch run test` — the test command stays as the import-smoke placeholder in this slice and flips to `pytest strands_robots_sim/isaac/tests/` in PR-3 once the first real test files land. Why this lands first: PR-2 / PR-3 / PR-4 all import from `strands_robots_sim.isaac`, so the package stub + extras + entry points have to exist before any of those files can be code-reviewed against current `main`. Original work by @cagataycali in #31 (`413ff15..befb1e3`); this slice cherry-picks just the foundation files. Review-thread anchors on the original commits stay intact for whichever child PR consumes the relevant code. * review(isaac): port 10 entry-point + lazy-import tests from #43 (PR #44 R1) Closes @cagataycali's R1 review on #44 -- the lazy-import contract ships with concrete CI signal now, not just a manual probe in the PR description. Three coordinated changes per the review: 1. **Port `tests/test_entrypoint.py` (140 LOC, 10 tests)** from the closed orphan PR #43 (`feat/isaac-extras-and-lazy-import`). These tests verify *only* PR-1's surface and have **zero dependency on `simulation.py`** (which lands in PR-4 of the #31 split): - `TestEntryPointDeclaration` (6 tests): - `test_pyproject_exists` - `test_isaac_entry_point_declared_in_pyproject` - `test_isaac_sim_alias_entry_point_declared_in_pyproject` - `test_isaac_extra_declared_in_pyproject` - `test_isaac_extra_includes_pytest` - `test_entry_points_visible_via_importlib_metadata_when_installed` (skips with actionable hint when not pip-installed) - `TestLazyImportSurface` (4 tests): - `test_import_isaac_does_not_load_omni` -- pins the `omni`-not- loaded contract via `sys.modules` set diff before/after import. - `test_isaac_subpackage_exposes_lazy_attrs_in___all__` - `test_unknown_attr_raises_attributeerror` -- pins the PEP 562 `__getattr__` raises `AttributeError` (not `ImportError`) on unknown attrs. - `test_dunder_getattr_is_present` 2. **Add `pytest>=7.0` to the `[isaac]` extra** in `pyproject.toml`. Means `pip install '.[isaac]'` covers the test deps without a separate dev extra on CI hosts. Also pinned by `test_isaac_extra_includes_pytest`. 3. **Flip `hatch run test`** from the import-smoke placeholder (`python -c "import strands_robots_sim; ..."`) to `pytest strands_robots_sim/isaac/tests/ -v`. The 10 tests collect and pass standalone; PR-4's simulation-module tests join the collection automatically when that PR rebases. Verification: - `pytest strands_robots_sim/isaac/tests/ -v` -> **10 passed in 0.14s** - `black --check` / `isort --check-only` / `flake8` (max-line=120) on `strands_robots_sim/` + `examples/` -> clean - AST parse on touched files -> ok - The 10 tests have no import path through `simulation.py`; they validate only PR-1's actual surface (pyproject parsing, entry- point declaration, PEP 562 `__getattr__` contract). The original `test_entrypoint.py` on `cagataycali/feat/isaac-sim` imports from `strands_robots_sim.isaac.simulation`, which is why PR-1 of the split couldn't ship that file unmodified. The version ported here was rewritten on the #43 branch specifically for the PR-1 surface; cleanly self-contained against this slice. * feat(isaac): IsaacConfig dataclass with validation (2/5 of #31 split) Part 2 / 5 of the split of #31 — tracked by #42. Branched off PR-1 (`pr1/isaac-foundation` -> #44); rebases cleanly to `main` once PR-1 merges. Adds the configuration dataclass that `IsaacSimulation` (PR-4) consumes: - `strands_robots_sim/isaac/config.py` (116 LOC): `IsaacConfig` dataclass with: - `num_envs`, `device` (default `"cuda:0"`), `headless` (default `True` -- safe for cloud/CI runners), `render_mode`, `physics_dt`, `gravity`, `ground_plane`, `camera_width`, `camera_height`, `rtx_pathtracing`, `nucleus_url`. - environment-variable overrides via `STRANDS_ISAAC_*` (`HEADLESS`, `RTX_PATHTRACING`, `NUCLEUS_URL`). - dataclass-level validation in `__post_init__` so e.g. `IsaacConfig(num_envs=0)` raises `ValueError` at construction. - `from_kwargs` classmethod that PR-4's `IsaacSimulation.__init__` uses to validate caller-supplied kwargs and surface unknown keys as `TypeError` (the R1 "reject unknown kwargs" pin). No `omni` / Isaac Sim imports. Pure-Python dataclass; can be imported on any host without a GPU. Tests for this module ship in PR-4 alongside `test_unit.py::TestIsaacConfig` (cleaner than carving a test slice for ~120 LOC of dataclass). CI signal: lint clean (black / isort / flake8); the lazy `__init__.py` from PR-1 now resolves `IsaacConfig` to a real class when accessed -- the `from strands_robots_sim.isaac import IsaacConfig` import path becomes live in this slice. Original work by @cagataycali in #31 (`413ff15`); this slice cherry-picks just `config.py`. R1's `from_kwargs` validation pin (commit `32ef307`) is already baked into this file. * fix(isaac): address review comment on PR #45 cagataycali's comment at strands_robots_sim/isaac/config.py:116 flagged that from_kwargs was promised by the PR description but missing from the slice. Added the classmethod so PR-4 (#47) can DRY its unknown-kwarg validation against IsaacConfig.from_kwargs rather than inlining dataclasses.fields() reflection at simulation.py:174-180.
…split) (#46) * feat(isaac): [isaac] extras + entry-point + PEP 562 lazy import (1/5 of #31 split) Part 1 / 5 of the split of #31 — tracked by #42. Adds the package skeleton for the Isaac Sim backend with zero `omni` overhead on `import strands_robots_sim`: - `pyproject.toml`: - new `[isaac]` extra (lightweight Isaac-companion deps that ARE pip-installable: `usd-core>=24.5,<26.0`, `warp-lang>=1.13.0`). Comment explains that Isaac Sim itself is NOT installable from PyPI — must come via Omniverse Launcher / Isaac Lab / nvcr.io. - new `[all]` aggregate extra (currently delegates to `[isaac]`; will gain `[newton]` etc. as later backends land). - new `[project.entry-points."strands_robots.backends"]` declaring both `isaac` and `isaac_sim` aliases pointing at `strands_robots_sim.isaac.simulation:IsaacSimulation` (the class itself lands in PR-4 / `feat(isaac): IsaacSimulation backend`). - new `pytest>=7.0` in `dev` extras and `[tool.hatch.envs.default]` deps so future PRs in this split chain can run pytest under `hatch run test`. - new `[tool.pytest.ini_options]` with a `gpu` marker so PR-4's GPU-only integ tests can gate on `STRANDS_GPU_TEST=1`. - `strands_robots_sim/isaac/__init__.py`: PEP 562 lazy stub — declares `__all__ = ["IsaacSimulation", "IsaacConfig"]` and routes attribute access through `__getattr__` to deferred imports of `.simulation` and `.config`. The bare `import strands_robots_sim.isaac` does NOT import any `omni` modules; that overhead only fires when a caller actually accesses `IsaacSimulation` or `IsaacConfig`. - `strands_robots_sim/isaac/tests/__init__.py`: empty package marker so future test files in this directory are collectable. Test files themselves land in subsequent slices alongside the code they cover. CI signal: lint clean (black / isort / flake8); the existing `hatch run test` import-smoke passes (it doesn't touch `isaac`, so no missing-submodule errors). Pytest doesn't run yet from `hatch run test` — the test command stays as the import-smoke placeholder in this slice and flips to `pytest strands_robots_sim/isaac/tests/` in PR-3 once the first real test files land. Why this lands first: PR-2 / PR-3 / PR-4 all import from `strands_robots_sim.isaac`, so the package stub + extras + entry points have to exist before any of those files can be code-reviewed against current `main`. Original work by @cagataycali in #31 (`413ff15..befb1e3`); this slice cherry-picks just the foundation files. Review-thread anchors on the original commits stay intact for whichever child PR consumes the relevant code. * review(isaac): port 10 entry-point + lazy-import tests from #43 (PR #44 R1) Closes @cagataycali's R1 review on #44 -- the lazy-import contract ships with concrete CI signal now, not just a manual probe in the PR description. Three coordinated changes per the review: 1. **Port `tests/test_entrypoint.py` (140 LOC, 10 tests)** from the closed orphan PR #43 (`feat/isaac-extras-and-lazy-import`). These tests verify *only* PR-1's surface and have **zero dependency on `simulation.py`** (which lands in PR-4 of the #31 split): - `TestEntryPointDeclaration` (6 tests): - `test_pyproject_exists` - `test_isaac_entry_point_declared_in_pyproject` - `test_isaac_sim_alias_entry_point_declared_in_pyproject` - `test_isaac_extra_declared_in_pyproject` - `test_isaac_extra_includes_pytest` - `test_entry_points_visible_via_importlib_metadata_when_installed` (skips with actionable hint when not pip-installed) - `TestLazyImportSurface` (4 tests): - `test_import_isaac_does_not_load_omni` -- pins the `omni`-not- loaded contract via `sys.modules` set diff before/after import. - `test_isaac_subpackage_exposes_lazy_attrs_in___all__` - `test_unknown_attr_raises_attributeerror` -- pins the PEP 562 `__getattr__` raises `AttributeError` (not `ImportError`) on unknown attrs. - `test_dunder_getattr_is_present` 2. **Add `pytest>=7.0` to the `[isaac]` extra** in `pyproject.toml`. Means `pip install '.[isaac]'` covers the test deps without a separate dev extra on CI hosts. Also pinned by `test_isaac_extra_includes_pytest`. 3. **Flip `hatch run test`** from the import-smoke placeholder (`python -c "import strands_robots_sim; ..."`) to `pytest strands_robots_sim/isaac/tests/ -v`. The 10 tests collect and pass standalone; PR-4's simulation-module tests join the collection automatically when that PR rebases. Verification: - `pytest strands_robots_sim/isaac/tests/ -v` -> **10 passed in 0.14s** - `black --check` / `isort --check-only` / `flake8` (max-line=120) on `strands_robots_sim/` + `examples/` -> clean - AST parse on touched files -> ok - The 10 tests have no import path through `simulation.py`; they validate only PR-1's actual surface (pyproject parsing, entry- point declaration, PEP 562 `__getattr__` contract). The original `test_entrypoint.py` on `cagataycali/feat/isaac-sim` imports from `strands_robots_sim.isaac.simulation`, which is why PR-1 of the split couldn't ship that file unmodified. The version ported here was rewritten on the #43 branch specifically for the PR-1 surface; cleanly self-contained against this slice. * feat(isaac): procedural USD builders (SO-100, Panda, G1) (3/5 of #31 split) Part 3 / 5 of the split of #31 — tracked by #42. Branched off PR-1 (`pr1/isaac-foundation` -> #44); rebases cleanly onto `main` once PR-1 merges. Adds the procedural USD robot builders that `IsaacSimulation` (PR-4) consumes via `add_robot(data_config=<name>, procedural=True)` without requiring binary asset downloads from Nucleus: - `strands_robots_sim/isaac/procedural.py` (258 LOC): - `ProceduralRobot` named-tuple shape: `(prim_root, num_joints, joint_names, body_names, parent_body_indices)`. - `get_procedural_robot(name: str) -> ProceduralRobot` registry. - Three builders behind the registry: - `_build_so100`: 6-DOF SO-100 arm (HuggingFace's open-source teaching arm). - `_build_franka_panda`: 9-DOF Panda + 2-DOF gripper. - `_build_unitree_g1`: 21-DOF G1 humanoid (1 torso + 6 left leg + 6 right leg + 4 left arm + 4 right arm). - All builders are pure-Python; no `omni` / Isaac Sim imports. - `strands_robots_sim/isaac/tests/test_procedural_g1_dof.py` (~70 LOC, 3 tests): Carved out of cagataycali's original `test_phase1_doc_honesty.py` -- the `TestG1DOFCount` class only. The companion `TestIsaacDocsPhase1Banner` class (which reads `docs/backends/isaac.md`) lands in PR-5 alongside the docs file itself. Pin tests: - `test_g1_actual_joint_count_is_21`: truth-source pin against `procedural.py`'s actual joint set. - `test_g1_module_docstring_advertises_21_not_29`: pin against R2's stale 29-DOF claim in the module docstring (commit `85e180f`). - `test_g1_builder_docstring_advertises_21_not_29`: same pin on the `_build_unitree_g1` function docstring. CI signal: lint clean (black / isort / flake8); the 3 G1-DOF pin tests pass standalone (`pytest strands_robots_sim/isaac/tests/ test_procedural_g1_dof.py -v` -> 3 passed). Note: this slice does NOT pin the kinematic-tree topology defect on the G1 joint graph (duplicate `(parent_body, child_body)` edges -- e.g. `l_hip_roll` and `l_hip_pitch` both map bodies 3 -> 4). That defect is documented in `procedural.py` line 165 as deferred to Phase 2; it requires intermediate massless link bodies that this Phase 1 stub does not instantiate. The dormant- on-Phase-1 framing is the same one R2 captured. Why this lands in parallel with PR-2 (config): both are pure modules with no cross-dependencies; either can land first. PR-4 (simulation) needs both. Original work by @cagataycali in #31 (`413ff15..85e180f`); this slice cherry-picks `procedural.py` plus the carved-out G1 test file. R2's DOF-count fix (commit `85e180f`) is already baked into this file's docstrings. * fix(isaac): add Phase-1 fail-fast guard for duplicate kinematic edges cagataycali's comment at strands_robots_sim/isaac/procedural.py:213 flagged that the documented duplicate-edge defect on G1 is silently returned by _build_unitree_g1 and would only surface as a cryptic USD/MuJoCo articulation error two layers down on Phase-2 wireup. Adds _validate_kinematic_tree(), wired into the end of all three procedural builders, opt-in via STRANDS_ISAAC_VALIDATE_KINEMATICS=1 (Phase-2 dev path). Default is no-op so Phase-1 callers (which never instantiate the articulation) are unaffected; with the env var set, G1 raises ValueError naming the duplicate edges + offending joints, while SO-100 and Panda still build cleanly. Pinned by tests/test_procedural_kinematic_guard.py: default-off behaviour, accepted env values (1/true/yes, case-insensitive), G1 raises with diagnostic context, SO-100 and Panda pass guard when enabled.
Summary
Part 1 / 5 of the split of #31 — tracked by
#42.Adds the package skeleton for the Isaac Sim backend with zero
omnioverhead onimport strands_robots_sim. Lands first; PR-2 (config) / PR-3 (procedural) / PR-4 (simulation) all import fromstrands_robots_sim.isaac, so this stub + extras + entry-points has to exist before they can be code-reviewed against currentmain.What's in this slice
pyproject.toml[isaac]+[all]extras;strands_robots.backendsentry-points;pytest>=7.0in dev + hatch envs;gpupytest markerstrands_robots_sim/isaac/__init__.py__getattr__defers imports of.simulationand.configuntil first attribute accessstrands_robots_sim/isaac/tests/__init__.pyWhy each bit
[isaac]extra — declares the Isaac-companion deps that ARE pip-installable (usd-core>=24.5,<26.0,warp-lang>=1.13.0). Inline comment inpyproject.tomlmakes clear that Isaac Sim itself is not PyPI-installable; users install it via Omniverse Launcher, Isaac Lab, ornvcr.io/nvidia/isaac-sim:4.5.0.Entry-points — both
isaacandisaac_simaliases pointing atstrands_robots_sim.isaac.simulation:IsaacSimulation. The target class itself lands in PR-4; declaring it now means PR-4'stest_entry_points_declared_in_pyproject(which readspyproject.tomldirectly) can pass against either an installed package or the source tree.Lazy
__init__.py—import strands_robots_sim.isaacdoes NOT pullomni/ Isaac Sim /usd-core. That overhead only fires when a caller actually accessesIsaacSimulationorIsaacConfig— preserving the "lightweight import" contract of the rest of the package.pytest>=7.0+ markers config — added now so subsequent slices can run pytest underhatch run testwithout each PR having to re-add the dependency. Thegpumarker pre-declares the gate that PR-4'stest_gpu_integ.pywill use (STRANDS_GPU_TEST=1).CI signal
hatch run test(the existing import-smokepython -c "import strands_robots_sim; print(...)") — passes; doesn't touchisaac, so no missing-submodule errors.hatch run lint(black --check/isort --check-only/flake8overstrands_robots_sim/+examples/) — clean.python -c "import strands_robots_sim.isaac; print(strands_robots_sim.isaac.__all__)"→['IsaacSimulation', 'IsaacConfig']. The lazy stub doesn't import anyomnimodules at this point.The hatch test command stays as the import-smoke placeholder in this slice and will flip to
pytest strands_robots_sim/isaac/tests/in PR-3, when the first real test files land.Dependency chain
PR-1 (this) → unblocks PR-2 / PR-3 / PR-4 / PR-5 (parallel-mergeable after this lands).
Diff: 3 files, +68 / -0 LOC.
Original authorship
Original work by @cagataycali in #31 (
413ff15..befb1e3). This slice cherry-picks just the foundation files; the R1-R4 review-thread anchors on the original commits stay intact for whichever child PR consumes the relevant code (per #42's review-thread bookkeeping note).