feat: make IsaacLab pip/uv installable via workspace meta-package#5201
feat: make IsaacLab pip/uv installable via workspace meta-package#5201lgulich wants to merge 8 commits intoisaac-sim:mainfrom
Conversation
- Move package metadata from setup.py to pyproject.toml [project] sections for isaaclab, isaaclab-assets, isaaclab-tasks, isaaclab-rl - Add inter-package dependencies (isaaclab_tasks depends on isaaclab, etc.) - Add isaacsim[all,extscache]==5.1.0 as dependency of isaaclab - Add root isaac-lab meta-package with uv workspace configuration - Add extra-index-url for pypi.nvidia.com and PyTorch CUDA wheels - Set index-strategy = "unsafe-best-match" for cross-index resolution - Add extra-build-dependencies for flatdict (needs setuptools) - Keep setup.py as backward-compatible shims for isaaclab.sh --install Downstream projects can now add isaac-lab to their pyproject.toml and install everything via uv sync. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR migrates all package metadata from
Confidence Score: 4/5Mostly safe to merge; one P1 concern about the missing Python upper-bound on the isaaclab sub-package. Score of 4 reflects one P1 finding: the <3.12 upper bound is enforced at the meta-package level but not propagated to source/isaaclab/pyproject.toml, risking silent failures on unsupported Python versions. All other findings are P2 style/maintenance suggestions. source/isaaclab/pyproject.toml needs <3.12 added to requires-python; source/isaaclab_rl/pyproject.toml all extra needs documentation or automation to prevent drift. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
META["isaac-lab\nmeta-package v2.3.2"]
IL["isaaclab v0.54.3"]
IA["isaaclab-assets v0.2.4"]
IT["isaaclab-tasks v0.11.14"]
IRL["isaaclab-rl v0.5.0"]
ISIM["isaacsim\nall,extscache==5.1.0"]
META --> IL
META --> IA
META --> IT
META --> IRL
IL --> ISIM
IA --> IL
IT --> IL
IT --> IA
IRL --> IL
IRL --> IA
IRL --> IT
Reviews (1): Last reviewed commit: "feat: make IsaacLab pip/uv installable v..." | Re-trigger Greptile |
| dependencies = [ | ||
| "isaacsim[all,extscache]==5.1.0", | ||
| "numpy<2", | ||
| "torch>=2.7", | ||
| "onnx>=1.18.0", | ||
| "prettytable==3.3.0", | ||
| "toml", | ||
| "hidapi==0.14.0.post2", | ||
| "gymnasium==1.2.1", | ||
| "trimesh", | ||
| "pyglet<2", | ||
| "transformers==4.57.6", | ||
| "einops", | ||
| "warp-lang", | ||
| "pillow==11.3.0", | ||
| "pytest", | ||
| "pytest-mock", | ||
| "junitparser", | ||
| "flatdict", | ||
| "flaky", | ||
| "packaging", | ||
| 'pin-pink==3.1.0 ; platform_system == "Linux" and platform_machine in "x86_64,AMD64,aarch64,arm64"', | ||
| 'daqp==0.7.2 ; platform_system == "Linux" and platform_machine in "x86_64,AMD64,aarch64,arm64"', | ||
| 'dex-retargeting==0.4.6 ; platform_system == "Linux" and platform_machine in "x86_64,AMD64"', | ||
| ] |
There was a problem hiding this comment.
The old setup.py listed "starlette==0.49.1" with a # livestream comment; it is absent from the new pyproject.toml. starlette is not directly imported in the current isaaclab source, so the removal may be intentional — please confirm it was a deliberate omission and not an oversight during the migration.
There was a problem hiding this comment.
Deliberate removal. starlette==0.49.1 conflicts with isaacsim's fastapi dependency which requires starlette>=0.40.0,<0.46.0. Starlette is provided transitively by isaacsim via fastapi, so the explicit pin is not needed.
When installed from git (non-editable), config/extension.toml is not available in site-packages. Fall back to importlib.metadata for version and package info. This affects isaaclab, isaaclab_assets, isaaclab_tasks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AppLauncher looks for .kit files 4 dirs up from app_launcher.py, which only works in editable installs. Bundle stripped .kit files inside the isaaclab package (without IsaacLab Kit extension deps and source path) and add fallback path resolution in AppLauncher. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Also add fallback path in SimulationContext for pip installs, matching the AppLauncher fix. Include rendering_modes/*.kit in package data. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add <3.12 upper bound to requires-python in all sub-packages (P1) - Re-pin flatdict==4.0.0 to match original setup.py (P2) - Add NOTE comment to isaaclab-rl 'all' extra about manual sync (P2) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of duplicating all packages, reference the other extras by name. This stays in sync automatically when extras are added or changed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pre-commit hook requires a blank line after the module docstring. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@myurasov-nv for viz |
There was a problem hiding this comment.
Review: pip/uv installable meta-package
This is a well-motivated and well-structured PR. Making IsaacLab pip install-able from downstream projects is a significant ergonomic improvement. The approach — PEP 621 [project] sections, uv workspace, backward-compatible setup.py shims, bundled .kit files with fallback path resolution — is sound.
Below are observations organized by severity.
🔴 Issues
1. starlette dependency dropped silently
The old source/isaaclab/setup.py had starlette==0.49.1 (for livestream). The new pyproject.toml doesn't include it. If any user code or IsaacLab code imports starlette for livestreaming, this will be a runtime ImportError on fresh pip/uv installs. Was this intentional? If livestream is now handled by an isaacsim extension, it's fine — but worth noting in the PR description.
2. isaaclab_rl/__init__.py not updated with extension.toml fallback
The __init__.py files for isaaclab, isaaclab_assets, and isaaclab_tasks all get the conditional extension.toml → importlib.metadata fallback. But isaaclab_rl/__init__.py is not modified. Checking the current code: it doesn't load extension.toml at the top, so this is fine — just verifying it doesn't break. 👍
3. isaaclab_mimic and isaaclab_contrib not included in workspace
The uv workspace only has 4 members. The repo has 6 sub-packages (isaaclab_contrib, isaaclab_mimic). If someone does uv sync from root and then tries to import isaaclab_mimic, it won't be installed. Is this intentional scope reduction, or a follow-up? Should be documented.
4. Version pinning drift risk
Versions are now hardcoded in 5 separate pyproject.toml files (root isaac-lab 2.3.2, isaaclab 0.54.3, isaaclab-assets 0.2.4, isaaclab-tasks 0.11.14, isaaclab-rl 0.5.0) AND still in extension.toml for editable installs. There's no single source of truth anymore. The __init__.py fallback logic picks one or the other based on install mode, but they could diverge. Consider either:
- Reading version from
extension.tomlat build time (dynamic version) - Or having the
pyproject.tomlbe authoritative and deprecating theextension.tomlversion field
🟡 Suggestions
5. requires-python narrowed to >=3.11,<3.12
The old setup.py had python_requires=">=3.10". The new pyproject.toml says >=3.11,<3.12. This is fine for Isaac Sim 5.1 (which requires 3.11), but it's a breaking change for anyone on 3.10. Worth calling out in the PR description. Also — the root pyproject.toml and sub-packages all have >=3.11,<3.12, which is consistent. 👍
6. unsafe-best-match index strategy
This is documented in the PR body but worth noting: index-strategy = "unsafe-best-match" in [tool.uv] means uv will pick the best-matching version across ALL configured indexes, which can lead to dependency confusion attacks if a malicious package with a higher version is published to PyPI with the same name as an internal NVIDIA package. For a framework like IsaacLab this is likely acceptable (the NVIDIA packages are all on pypi.nvidia.com), but downstream users should understand the security implications.
7. Bundled .kit files are large (~1000 lines)
The 6 bundled .kit files add ~1000+ lines to the package. These appear to be copies of the existing apps/ directory .kit files, bundled inside the Python package for non-editable installs. This works but creates a maintenance burden — any .kit change needs to be mirrored. Consider symlinking or generating these from a single source, or at minimum adding a comment noting they're copies.
8. rendering_modes/extension.toml is a dummy file
The file at source/isaaclab/isaaclab/apps/rendering_modes/extension.toml contains only # This is not an extension. If this is needed to prevent Kit from treating the directory as an extension, add a brief explanation comment. Otherwise it looks like an accidental inclusion.
9. [tool.setuptools.packages.find] in isaaclab pyproject.toml
The config uses include = ["isaaclab*"] which will match isaaclab and all sub-packages. This is correct, but in a workspace where isaaclab_assets, isaaclab_tasks, etc. are siblings, make sure the find doesn't accidentally pull in adjacent packages. Since where = ["."] is relative to source/isaaclab/, it should be scoped correctly.
✅ What looks good
- Clean separation:
pyproject.tomlfor metadata,setup.pyas shim for backward compat - Proper inter-package dependencies (
isaaclab-tasks→isaaclab+isaaclab-assets) isaacsim[all,extscache]==5.1.0as a first-class dependency — this is the key enabler- Fallback path resolution in
AppLauncherandSimulationContextis minimal and correct extension.toml→importlib.metadatafallback is well-implementedextra-index-urlfor NVIDIA and PyTorch CUDA wheels- Optional dependencies in
isaaclab-rl(sb3, skrl, rl-games, rsl-rl) are well-organized - Test plan is solid (though
isaaclab.sh --installis unchecked — please verify before merge)
Overall: strong direction. Address the starlette question, document the scope (4/6 packages), and verify the isaaclab.sh --install shim path, and this is good to go.
| "isaacsim[all,extscache]==5.1.0", | ||
| "numpy<2", | ||
| "torch>=2.7", | ||
| "onnx>=1.18.0", |
There was a problem hiding this comment.
isaacsim[all,extscache]==5.1.0 — this is the key enabler for pip-installability. Pinning to exact version is the right call since Kit extensions are not semver-compatible across Isaac Sim versions.
One concern: when Isaac Sim 5.2 ships, every downstream project pinned to isaac-lab will need to wait for a new release. Consider whether a >=5.1.0,<5.2 range would be more practical, or if exact pin is intentional.
|
|
||
| [tool.setuptools] | ||
| include-package-data = true | ||
|
|
There was a problem hiding this comment.
The old setup.py included starlette==0.49.1 for livestream support. This dependency is absent here. Was this intentional? If livestream functionality depends on starlette being installed, this will break for pip/uv users.
| __version__ = ISAACLAB_METADATA["package"]["version"] | ||
| else: | ||
| from importlib.metadata import metadata | ||
|
|
There was a problem hiding this comment.
Clean fallback pattern. One thought: if this is a non-editable install, ISAACLAB_METADATA will only have version and description keys under package, while editable installs get the full extension.toml dict (repository, keywords, authors, etc.). Any downstream code that accesses other fields of ISAACLAB_METADATA["package"] will get a KeyError in non-editable mode.
Consider either:
- Documenting which keys are guaranteed
- Populating more fields from
importlib.metadatain the fallback
|
|
||
| [tool.uv] | ||
| extra-index-url = ["https://pypi.nvidia.com", "https://download.pytorch.org/whl/cu128"] | ||
| index-strategy = "unsafe-best-match" |
There was a problem hiding this comment.
| index-strategy = "unsafe-best-match" | |
| [tool.uv.extra-build-dependencies] | |
| flatdict = ["setuptools"] |
What's the story here? flatdict needs setuptools as a build dep? Is this a known upstream issue with flatdict's build, or a workaround for something specific? A brief comment would help future maintainers.
| # If nothing is provided resolve the experience file based on the headless flag | ||
| kit_app_exp_path = os.environ["EXP_PATH"] | ||
| # Try repo layout first (editable install), then bundled apps (pip/uv install) | ||
| isaaclab_app_exp_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), *[".."] * 4, "apps") |
There was a problem hiding this comment.
This fallback path (.. instead of ../../../..) for bundled apps is correct. The directory structure for editable is source/isaaclab/isaaclab/app/ → 4 levels up to apps/, while for installed it's site-packages/isaaclab/app/ → 1 level up to isaaclab/apps/.
Nit: the same pattern is duplicated in simulation_context.py. Consider extracting a helper function like get_isaaclab_apps_path() to avoid the duplication.
Problem
Today, there's no way to
pip installoruv syncIsaacLab from a downstream project. Installation requires cloning the repo and runningisaaclab.sh --install, which:isaacsimwith the correct index URLThis makes it impossible to declare IsaacLab as a dependency in a downstream
pyproject.tomland have everything "just work."Solution
Add modern Python packaging (
pyproject.tomlwith PEP 621[project]sections) to 4 core sub-packages and create a rootisaac-labmeta-package with a uv workspace. A downstream project can now install everything with:Or with a
requirements.txt:Changes
setup.pytopyproject.toml[project]sections forisaaclab,isaaclab-assets,isaaclab-tasks,isaaclab-rlisaaclab-tasksdepends onisaaclabandisaaclab-assets)isaacsim[all,extscache]==5.1.0as a dependency ofisaaclabisaac-labmeta-package with[tool.uv.workspace]configurationextra-index-urlforpypi.nvidia.comand PyTorch CUDA wheelsindex-strategy = "unsafe-best-match"for cross-index resolution.kitexperience files inside theisaaclabpackage with fallback path resolution inAppLauncherandSimulationContext(so the sim boots without the repo layout)extension.tomlloading optional in__init__.py(fall back toimportlib.metadatafor non-editable installs)setup.pyas backward-compatible shims soisaaclab.sh --installstill worksTest plan
uv lockresolves 245 packages successfullyuv syncinstalls all packages into a fresh venv from a downstream projectimportlib.metadata.version()import isaaclabandimport isaaclab_rlwork in non-editable installrequirements.txtapproach also installs and runs correctlyisaaclab.sh --installstill works with the shim setup.py files🤖 Generated with Claude Code