Skip to content

Modernize packaging and version management across sub-packages#5640

Open
diegoferigo-rai wants to merge 4 commits into
isaac-sim:developfrom
diegoferigo-rai:diegoferigo/isaaclab3
Open

Modernize packaging and version management across sub-packages#5640
diegoferigo-rai wants to merge 4 commits into
isaac-sim:developfrom
diegoferigo-rai:diegoferigo/isaaclab3

Conversation

@diegoferigo-rai
Copy link
Copy Markdown

Description

This pull request modernizes packaging and version management across IsaacLab sub-packages to align with current Python packaging practices and reduce maintenance overhead.

The main change is replacing custom version parsing in package __init__.py files with importlib.metadata.version, with a fallback to 0.0.0 when a package is not installed. In addition, setup scripts were standardized to use setuptools and find_namespace_packages for more consistent package discovery.

This PR also improves package metadata handling by loading version and related metadata from config/extension.toml where appropriate, reducing duplication across setup files. Finally, testing-related dependencies that were previously included in the main install path are now exposed through a dedicated [testing] extra, keeping the default installation lighter and making optional dependencies explicit.

These changes simplify initialization logic, remove redundant code, and make the packaging setup more robust and easier to maintain.

Fixes partially:

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Screenshots

N/A

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the changelog and the corresponding version in the extension's config/extension.toml file
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

Find the main package and all subpackages, without requiring __init__.py. This is the generic version of find_packages which requires __init__.py files.
@github-actions github-actions Bot added asset New asset feature or request isaac-mimic Related to Isaac Mimic team labels May 15, 2026
@diegoferigo-rai diegoferigo-rai marked this pull request as ready for review May 15, 2026 16:35
Copy link
Copy Markdown

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

This PR modernizes packaging and version management across 14 sub-packages by replacing custom TOML-based version parsing with importlib.metadata.version(). The changes are well-structured and follow Python packaging best practices.

✅ Strengths

  1. Simplified version retrieval: Using importlib.metadata is the recommended approach for Python 3.10+ and eliminates runtime dependencies on toml/tomllib
  2. Consistent fallback behavior: All packages now consistently fall back to "0.0.0" when not installed
  3. Cleaner __init__.py files: Removing boilerplate reduces maintenance burden
  4. Testing dependencies separated: Moving test deps to [testing] extra keeps the default install lighter
  5. find_namespace_packages: Proper use for flat-layout namespace packages

📝 Suggestions for Improvement

1. Dead code in isaaclab_newton/setup.py

The custom build_py class that bundles config/extension.toml into the wheel is now dead code:

class build_py(setuptools.command.build_py.build_py):
    """Custom build command that bundles config/extension.toml into the package."""
    def run(self):
        super().run()
        src = os.path.join(EXTENSION_PATH, "config", "extension.toml")
        dst_dir = os.path.join(self.build_lib, "isaaclab_newton", "config")
        os.makedirs(dst_dir, exist_ok=True)
        shutil.copy(src, os.path.join(dst_dir, "extension.toml"))

Since __init__.py no longer reads from extension.toml at runtime (it uses importlib.metadata instead), this bundling is unnecessary. The setup.py still reads the TOML at build time for metadata, but that happens before wheel creation and doesn't require bundling.

Recommendation: Remove the custom build_py class and the cmdclass={"build_py": build_py} line, along with the shutil import.

2. Consider documenting the [testing] extra

The new isaaclab[testing] extra is a nice addition. Users running tests will need to know to install it:

pip install "isaaclab[testing]"

Consider adding this to the developer documentation or CONTRIBUTING guide.

3. Minor: Unused IntEnum import removal

The PR correctly removes an unused from enum import IntEnum import in isaaclab_experimental/__init__.py. This was dead code that was never exposed or used.

🔍 Verification Checklist

  • All 14 packages use consistent importlib.metadata.version() pattern
  • Fallback to "0.0.0" is consistent across all packages
  • No remaining runtime toml imports in __init__.py files
  • find_namespace_packages is used correctly with explicit include patterns
  • Testing dependencies moved without loss
  • No breaking changes to public API (removed variables like ISAACLAB_*_EXT_DIR were not exported or documented)

⚠️ Potential Considerations

  1. Version during editable install: With importlib.metadata, the version is read from installed package metadata. For editable installs (pip install -e), this should work correctly since pip registers metadata. However, if someone imports the package without installing (e.g., just adding to PYTHONPATH), they'll get "0.0.0". This is acceptable behavior and matches the PR description.

  2. CI pipelines: Verify that CI workflows install isaaclab[testing] when running tests. Based on current workflows, test dependencies may have been implicitly available; this change makes them explicit.


Overall, this is a clean modernization that reduces complexity and aligns with current Python packaging standards. The main actionable item is removing the now-dead build_py code in isaaclab_newton/setup.py.


Update (a530236): Reviewed new commits. Changes include:

  • Dockerfile additions for Miniconda/conda CI testing
  • Extensive new test coverage for install workflows and command parsing
  • Test refactors (using Warp types for camera dtypes, .torch property access)
  • Import cleanups and removal of unnecessary AppLauncher dependencies in unit tests

The new commits are sound and don't introduce any issues. Previous suggestion about dead build_py code in isaaclab_newton/setup.py remains applicable but is non-blocking.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 15, 2026

Greptile Summary

This PR modernizes packaging across all 14 IsaacLab sub-packages by replacing toml-based version parsing in __init__.py files with importlib.metadata.version (stdlib since Python 3.8), switching all setup.py files from from setuptools import setup to import setuptools, and migrating hardcoded package lists to find_namespace_packages.

  • Version management: Every __init__.py now uses importlib.metadata.version(\"<pkg>\") with a \"0.0.0\" fallback, removing os/toml imports and the TOML-path lookup logic from each module's startup.
  • Package discovery: packages=[...] hardcoded lists (some 20+ entries for isaaclab_physx) are replaced with setuptools.find_namespace_packages(include=[\"<pkg>\", \"<pkg>.*\"]), reducing maintenance overhead.
  • Dependency hygiene: Testing dependencies previously in INSTALL_REQUIRES of isaaclab are moved to a new [testing] optional extra, lightening the default install footprint.

Confidence Score: 3/5

Safe to merge for most packages, but the removal of ISAACLAB_ASSETS_DATA_DIR breaks the documented public API for isaaclab_assets users.

The isaaclab_assets init.py removes ISAACLAB_ASSETS_DATA_DIR, a variable that the package's own README.md documents as the canonical way to locate local asset files. Users following that guide will get an ImportError immediately on import. The PR checklist confirms documentation has not been updated. All other changes are clean and consistent across the 14 sub-packages.

source/isaaclab_assets/isaaclab_assets/init.py and source/isaaclab_assets/docs/README.md — the removed ISAACLAB_ASSETS_DATA_DIR export conflicts with the still-published usage example in the README.

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/init.py Replaces toml-based version parsing with importlib.metadata.version; removes ISAACLAB_EXT_DIR and ISAACLAB_METADATA module-level variables (confirmed unused in the rest of the codebase)
source/isaaclab/setup.py Moves testing dependencies to [testing] extra and switches to find_namespace_packages; the new [testing] extra is not included in the [all] group, changing prior install behaviour
source/isaaclab_assets/isaaclab_assets/init.py Removes ISAACLAB_ASSETS_DATA_DIR, ISAACLAB_ASSETS_EXT_DIR and ISAACLAB_ASSETS_METADATA exports; ISAACLAB_ASSETS_DATA_DIR is still referenced in docs/README.md causing ImportError for users following the guide
source/isaaclab_newton/setup.py Switches to find_namespace_packages; the custom build_py TOML-bundling hook is now dead code since init.py no longer reads the bundled TOML
source/isaaclab_physx/setup.py Replaces a long hardcoded package list with find_namespace_packages; clean simplification with no functional change
source/isaaclab_ov/setup.py Adds TOML-based metadata loading (version, description, keywords, url) from extension.toml, replacing previously hardcoded values; consistent with other packages
source/isaaclab_experimental/isaaclab_experimental/init.py Removes toml/os imports and the unused top-level IntEnum import; no downstream consumers of these exports found in the codebase
source/isaaclab_mimic/isaaclab_mimic/init.py Replaces hardcoded version = "1.0.0" with importlib.metadata lookup; version is now driven by the installed package metadata

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Package __init__.py imported"] --> B{"importlib.metadata\n.version(pkg_name)"}
    B -- "Package installed" --> C["__version__ = real version"]
    B -- "PackageNotFoundError" --> D["__version__ = '0.0.0'"]
    subgraph "Old approach"
        E["import toml"] --> F["Load config/extension.toml"]
        F --> G["__version__ from toml"]
        E -- "ImportError" --> H["fallback to '0.0.0'"]
    end
    subgraph "setup.py"
        J["find_namespace_packages"] --> K["Auto-discovers sub-packages"]
        N["EXTRAS_REQUIRE['testing']"] --> O["pytest, coverage, etc."]
    end
Loading

Comments Outside Diff (3)

  1. source/isaaclab_assets/isaaclab_assets/__init__.py, line 1-17 (link)

    P1 Publicly documented symbol ISAACLAB_ASSETS_DATA_DIR silently removed

    The module-level variable ISAACLAB_ASSETS_DATA_DIR (and ISAACLAB_ASSETS_EXT_DIR, ISAACLAB_ASSETS_METADATA) were removed from isaaclab_assets/__init__.py, but source/isaaclab_assets/docs/README.md still shows the canonical usage pattern from isaaclab_assets import ISAACLAB_ASSETS_DATA_DIR. Any user following that guide will now get an ImportError. The PR checklist item for documentation updates is unchecked, confirming this was not yet addressed.

  2. source/isaaclab_newton/setup.py, line 16-68 (link)

    P2 build_py TOML-bundling hook is now dead code

    The custom build_py command copies config/extension.toml into the built wheel so isaaclab_newton/__init__.py can read it at runtime. After this PR, __init__.py no longer reads the TOML at all — it uses importlib.metadata.version. The cmdclass={"build_py": build_py} is still wired in, so every wheel build continues to run this copy step unnecessarily. The entire build_py class, import shutil, and import setuptools.command.build_py can be removed.

  3. source/isaaclab/setup.py, line 79-89 (link)

    P2 Testing extra not included in the all convenience group

    The new [testing] extra is added after the all key is assembled. EXTRAS_REQUIRE["all"] collects the sub-package extras but does not include testing. If users expect pip install isaaclab[all] to also pull in test dependencies (matching the previous behaviour where they were in INSTALL_REQUIRES), they will now need to additionally specify [all,testing].

Reviews (1): Last reviewed commit: "Read version from package metadata popul..." | Re-trigger Greptile

@diegoferigo-rai
Copy link
Copy Markdown
Author

diegoferigo-rai commented May 15, 2026

For reviewers: the agents correctly identified that ISAACLAB_ASSETS_DATA_DIR was removed, but the project still depends on it in a few places. I'd propose the following behavior:

  1. First, check whether the original in-source assets directory exists and use it if available. This would cover editable installations.
  2. For non-editable installations, read from a new ISAACLAB_ASSETS_DATA_DIR environment variable. If it is not set, fall back to a local directory such as pathlib.Path.home() / ".cache" / "isaaclab" / "assets".

@diegoferigo-rai diegoferigo-rai force-pushed the diegoferigo/isaaclab3 branch from 64d5b47 to a530236 Compare May 18, 2026 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asset New asset feature or request isaac-mimic Related to Isaac Mimic team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant