Skip to content

Stringfies class-type that prevent Cfg file eager imports implementation files dependencies#4732

Open
ooctipus wants to merge 2 commits intoisaac-sim:developfrom
ooctipus:feature/develop/stringfy_class_type
Open

Stringfies class-type that prevent Cfg file eager imports implementation files dependencies#4732
ooctipus wants to merge 2 commits intoisaac-sim:developfrom
ooctipus:feature/develop/stringfy_class_type

Conversation

@ooctipus
Copy link
Collaborator

Description

This PR changes all class-type value from a direct import to string import.
this make sure the implementation files dependencies are not loaded during config reading stage.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots

Please attach before and after screenshots of the change if applicable.

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

@github-actions github-actions bot added documentation Improvements or additions to documentation enhancement New feature or request asset New asset feature or request isaac-mimic Related to Isaac Mimic team labels Feb 25, 2026
@ooctipus ooctipus force-pushed the feature/develop/stringfy_class_type branch from b75d121 to 076b91d Compare February 26, 2026 08:25
@ooctipus ooctipus marked this pull request as ready for review February 26, 2026 08:25
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 26, 2026

Greptile Summary

Implements lazy loading for config class types by converting direct imports to string-based references that resolve on first use.

Key Changes

  • Adds ResolvableString class in string.py that wraps callable-like strings (format: module:ClassName) and lazily resolves them when accessed
  • Updates configclass.py to automatically wrap string values matching callable patterns during __post_init__
  • Introduces {DIR} placeholder support that expands to the declaring config module's parent package path
  • Converts class_type, func, function, and object_type fields across 71 config files from direct imports to string format
  • Moves implementation imports to TYPE_CHECKING blocks to prevent eager loading during config reads
  • Refactors several implementation files (asset_base.py, sensor_base.py) to delay imports

Architecture Impact

This change significantly improves config loading performance by preventing the entire dependency tree from being imported when just reading config values. The ResolvableString approach maintains backward compatibility - code accessing class_type fields works transparently whether the value is a string or the actual class.

Pattern Used

  • Before: class_type: type[Foo] = foo_module.Foo (eager import)
  • After: class_type: type[Foo] | str = "{DIR}.foo_module:Foo" (lazy string)

The type annotation preserves IDE autocomplete and type checking while the runtime value is a string that resolves lazily.

Confidence Score: 4/5

  • Safe to merge with standard testing - well-executed refactoring with consistent patterns
  • Score reflects thorough and systematic implementation across 71 files with no critical issues found. The pattern is simple, mechanical, and well-documented. Minor score reduction due to broad scope requiring runtime validation that lazy resolution works correctly across all use cases.
  • Check that ResolvableString resolution works correctly in edge cases like nested configs, serialization, and dynamic config construction

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/utils/string.py Adds ResolvableString class for lazy callable resolution - clean implementation
source/isaaclab/isaaclab/utils/configclass.py Implements automatic ResolvableString wrapping during config initialization with {DIR} placeholder support
source/isaaclab/isaaclab/envs/mdp/actions/actions_cfg.py Converts all class_type fields to string format with {DIR} prefix, moves imports to TYPE_CHECKING
source/isaaclab/isaaclab/assets/asset_base.py Refactors to avoid eager import of PhysicsManager by using SimulationContext.instance()
source/isaaclab/isaaclab/sensors/sensor_base.py Moves PhysX-specific imports inside functions to delay loading
source/isaaclab/isaaclab/terrains/trimesh/mesh_terrains_cfg.py Converts all function and object_type fields from direct imports to string paths with {DIR}
source/isaaclab/isaaclab/actuators/actuator_pd_cfg.py Converts actuator class_type fields to strings, uses TYPE_CHECKING for imports
source/isaaclab/isaaclab/sim/spawners/from_files/from_files_cfg.py Converts all spawner func fields to string format with {DIR} placeholder

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Config File Loaded] --> B{Field value matches<br/>callable pattern?}
    B -->|No| C[Value used as-is]
    B -->|Yes| D[Wrap in ResolvableString]
    D --> E{Contains DIR<br/>placeholder?}
    E -->|Yes| F[Replace DIR with<br/>module parent path]
    E -->|No| G[Keep string as-is]
    F --> H[ResolvableString created]
    G --> H
    H --> I[Config object ready]
    I --> J[Runtime: Field accessed]
    J --> K{First access?}
    K -->|Yes| L[Parse module:Class format]
    L --> M[Import module dynamically]
    M --> N[Get class attribute]
    N --> O[Cache resolved class]
    O --> P[Return class]
    K -->|No| Q[Return cached class]
    P --> R[Class used normally]
    Q --> R
    
    style D fill:#e1f5ff
    style H fill:#e1f5ff
    style O fill:#d4edda
    style Q fill:#d4edda
Loading

Last reviewed commit: 076b91d

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

71 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copy link
Collaborator

@AntoineRichard AntoineRichard left a comment

Choose a reason for hiding this comment

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

Makes sense to me, I'm a bit concerned with the verbosiness of the changes, but other than that it looks good!

Comment on lines 288 to 323
@@ -318,6 +318,8 @@ def _initialize_callback(self, event):
self._is_initialized = True
except Exception as e:
# Store exception to be raised after callback completes
from isaaclab_physx.physics import PhysxManager # noqa: PLC0415

PhysxManager.store_callback_exception(e)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't that be non physx specific? It feels odd to have this import here.


class_type: type[ActionTerm] = AgileBasedLowerBodyAction
class_type: type["AgileBasedLowerBodyAction"] | str = (
"isaaclab_tasks.manager_based.locomanipulation.pick_place.mdp.actions:AgileBasedLowerBodyAction"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you think we could add a feature so that we could do {..DIR} ?

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 documentation Improvements or additions to documentation enhancement New feature or request isaac-mimic Related to Isaac Mimic team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants