Rename Newton preset to MJWarp#5488
Conversation
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot
Summary
This PR renames the Newton MJWarp physics preset from newton to mjwarp across the entire codebase to distinguish solver selection from the Newton backend/package/visualizer names. The implementation includes a deprecation path that maps legacy newton preset references to mjwarp with warnings. The change is comprehensive, touching 54 files including documentation, task configs, test utilities, and the core Hydra preset system.
Architecture Impact
This is a naming-only refactor with well-contained blast radius:
- Hydra preset system (
isaaclab_tasks/utils/hydra.py): Core changes to support legacy aliasing via_LEGACY_PRESET_ALIASESand_normalize_preset_name(). All downstream preset resolution flows through this module. - Task configs: All
PresetCfgsubclasses with physics presets now usemjwarpfield name instead ofnewton. - Test infrastructure: Updated to use
mjwarppreset name, includingenv_test_utils.pywhich drives parametrized environment tests. - Documentation: Comprehensive update of all user-facing docs to use
mjwarp.
The deprecation layer ensures backward compatibility — existing scripts using presets=newton will continue to work with a warning.
Implementation Verdict
Ship it — Minor suggestions below, but the implementation is correct and thorough.
Test Coverage
Thorough. The PR includes:
- New regression test file
test_mjwarp_preset_names.pythat grep-guards against stalenewtonpreset references - Updated
test_hydra.pywithtest_legacy_newton_attribute_alias_warns()to verify deprecation warnings - Updated
test_preset_kit_decision.pyto usemjwarp - All existing Newton CI tests updated to use
mjwarp
The test author explicitly ran 74+ tests across multiple test files per the PR description.
CI Status
No CI checks available yet.
Findings
🔵 Improvement: source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py:91 — Docstring references outdated field name
The PresetCfg docstring example still shows newton as a field name, which contradicts the PR's goal:
class PhysicsCfg(PresetCfg):
default: PhysxCfg = PhysxCfg()
mjwarp: NewtonCfg = NewtonCfg() # docstring says newtonThe docstring at line 91 should use mjwarp for consistency.
🔵 Improvement: source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py:80-89 — __getattr__ unconditionally raises for unknown attributes
The implementation is correct, but the AttributeError message uses {type(self).__name__!s} which is redundant — !s is the default conversion. Consider simplifying to:
raise AttributeError(f"{type(self).__name__} object has no attribute {name!r}")🔵 Improvement: source/isaaclab_tasks/test/test_mjwarp_preset_names.py:47-48 — Special-case pattern for environments.rst
The test has a special case checking docs/source/overview/environments.rst for bare `newton` strings. This is fragile because:
- The path is hardcoded as a string comparison
- The
_LEGACY_PRESET_PATTERNSalready handles most cases
Consider documenting why this special case exists (e.g., table formatting that can't use the regex patterns).
🔵 Improvement: source/isaaclab_tasks/test/rendering_test_utils.py:271-273 — Helper function placement
The _physics_preset_name() helper maps "newton" → "mjwarp" for golden image paths. This is correct, but the function is defined mid-file after _apply_overrides_to_env_cfg. For readability, consider moving it near other private helpers at the top of the file.
🔵 Improvement: source/isaaclab_tasks/isaaclab_tasks/direct/shadow_hand/shadow_hand_env_cfg.py:337 — Comment still references presets=newton
Line 337 comment says:
# scene — use ShadowHandSceneCfg so that presets=mjwarp disables clone_in_fabric automaticallyThis is correctly updated. ✓ (No issue here, just confirming.)
🔵 Improvement: source/isaaclab_tasks/changelog.d/antoiner-rename-newton-preset-mjwarp.rst — Changelog wording
The changelog entry is clear and appropriate. The "Changed" and "Deprecated" sections correctly document the migration path.
🟡 Warning: source/isaaclab_tasks/test/test_shadow_hand_vision_presets.py:298 — Hardcoded preset name "mjwarp"
In render_correctness_env, the physics preset is checked via:
if physics == "newton":
cfg.sim.physics = copy.deepcopy(shadow_hand_vision_presets["sim.physics"]["mjwarp"])The test parameter is "newton" (line 259-281 show id="newton-...") but accesses the preset dict with "mjwarp". This is intentional since the dict key changed, but the test parameter string "newton" is now misleading. Consider renaming the test parameter to "mjwarp" for consistency, or add a comment explaining the mismatch is intentional for golden image path compatibility.
🔵 Improvement: Documentation consistency verified — All docs now use mjwarp consistently. The changes in docs/source/overview/environments.rst (90 lines changed) correctly update all preset column references from newton to mjwarp.
Overall: This is a clean, well-tested refactoring PR. The deprecation layer in hydra.py ensures backward compatibility, and the new test_mjwarp_preset_names.py guards against regressions. The author has been thorough in updating all 54 files consistently.
Greptile SummaryThis PR renames the public Newton MJWarp physics preset identifier from Confidence Score: 4/5Safe to merge; the rename is systematic and well-tested, with only minor style observations. All findings are P2 (style/clarity). The deprecation logic is correct: no double-warnings are emitted, the fallback when source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py — Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["CLI arg: presets=newton / env.backend=newton"] --> B["register_task / parse_overrides"]
B --> C["_normalize_preset_name(name, known_names)"]
C --> D{"'mjwarp' in known_names\nAND 'newton' not in known_names?"}
D -- Yes --> E["emit DeprecationWarning\nreturn 'mjwarp'"]
D -- No --> F["return name as-is"]
E --> G["resolve_presets / apply_overrides\nuse 'mjwarp'"]
F --> G
H["cfg.newton (Python attr access)"] --> I["PresetCfg.__getattr__"]
I --> J{"'mjwarp' in dataclass fields\nAND 'newton' not in fields?"}
J -- Yes --> K["emit DeprecationWarning\nreturn self.mjwarp"]
J -- No --> L["raise AttributeError"]
|
| return name | ||
| warnings.warn( | ||
| f"Preset '{name}' is deprecated. Use '{replacement}' instead.", | ||
| DeprecationWarning, | ||
| stacklevel=3, | ||
| ) | ||
| return replacement |
There was a problem hiding this comment.
Hardcoded
stacklevel is incorrect for generator-expression call sites
_normalize_preset_name is called from at least three different depths: directly (e.g., in _pick_alternative's for loop), via a generator expression passed to list.extend (in parse_overrides), and from a simple assignment (in apply_overrides). A fixed stacklevel=3 produces a meaningful source location only for one of these cases; when called from inside a generator expression the reported warning frame points into CPython's generator machinery rather than user code.
Consider passing stacklevel as a parameter with a sensible default:
def _normalize_preset_name(name: str, known_names: set[str], stacklevel: int = 3) -> str:| avail = list(presets[sec][path].keys()) | ||
| raise ValueError(f"Unknown preset '{name}' for {sec}.{path}. Available: {avail}") | ||
| full_path = f"{sec}.{path}" if path else sec | ||
| resolved[full_path] = (sec, path, name) | ||
|
|
||
| applied_by: dict[str, str] = {} | ||
| known_names = _known_preset_names(presets) |
There was a problem hiding this comment.
Redundant normalization in
apply_overrides
Both global_presets (built by parse_overrides) and preset_sel tuples are already normalized before apply_overrides is called in the production flow through register_task. The extra _normalize_preset_name calls here are harmless but create the impression that un-normalized names can arrive at this point, and they trigger an extra _known_preset_names traversal. If the intent is to guard direct test-only call-sites, a brief comment would make the reasoning clear:
# Normalize again in case apply_overrides is called directly (e.g. from tests)
# without going through parse_overrides.
known_names = _known_preset_names(presets)
for name in global_presets:
name = _normalize_preset_name(name, known_names)| avail = list(presets[sec][path].keys()) | ||
| raise ValueError(f"Unknown preset '{name}' for {sec}.{path}. Available: {avail}") | ||
| full_path = f"{sec}.{path}" if path else sec | ||
| resolved[full_path] = (sec, path, name) | ||
|
|
||
| applied_by: dict[str, str] = {} | ||
| known_names = _known_preset_names(presets) |
There was a problem hiding this comment.
Redundant normalization in
apply_overrides
Both global_presets (built by parse_overrides) and preset_sel tuples are already normalized before apply_overrides is called in the production flow through register_task. The extra _normalize_preset_name calls here are harmless but create the impression that un-normalized names can arrive at this point, and they trigger an extra _known_preset_names traversal. If the intent is to guard direct test-only call-sites, a brief comment would make the reasoning clear:
# Normalize again in case apply_overrides is called directly (e.g. from tests)
# without going through parse_overrides.
known_names = _known_preset_names(presets)
for name in global_presets:
name = _normalize_preset_name(name, known_names)| avail = list(presets[sec][path].keys()) | ||
| raise ValueError(f"Unknown preset '{name}' for {sec}.{path}. Available: {avail}") | ||
| full_path = f"{sec}.{path}" if path else sec | ||
| resolved[full_path] = (sec, path, name) | ||
|
|
||
| applied_by: dict[str, str] = {} | ||
| known_names = _known_preset_names(presets) |
There was a problem hiding this comment.
Redundant normalization in
apply_overrides
Both global_presets (built by parse_overrides) and preset_sel tuples are already normalized before apply_overrides is called in the production flow through register_task. The extra _normalize_preset_name calls here are harmless but create the impression that un-normalized names can arrive at this point, and they trigger an extra _known_preset_names traversal. If the intent is to guard direct test-only call-sites, a brief comment would make the reasoning clear:
# Normalize again in case apply_overrides is called directly (e.g. from tests)
# without going through parse_overrides.
known_names = _known_preset_names(presets)
for name in global_presets:
name = _normalize_preset_name(name, known_names)Pivots the rename to group Newton-backend solver variants under a common prefix and addresses review feedback on PR isaac-sim#5488: - newton -> newton_mjwarp - kamino -> newton_kamino Both legacy names remain live as aliases that emit a FutureWarning (always shown, unlike DeprecationWarning) and resolve to the new names. _user_stacklevel() points warnings at user code rather than inside hydra.py. _format_unknown_presets_error explicitly calls out the rename when an unknown preset matches a legacy alias. Tests cover the alias path end-to-end through parse_overrides and apply_overrides, the shadow-guard for configs that legitimately keep the deprecated spelling, and an expanded regression scanner that catches both renames (with a fixed RST literal pattern that actually matches the realistic ``newton``,/``newton``... forms).
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot
Summary
This follow-up addresses the rename from mjwarp to newton_mjwarp (and kamino to newton_kamino), which is a better naming convention that groups Newton-backend presets together while maintaining distinctiveness from the backend/package/visualizer names.
Previous Findings Status
✅ All previous concerns have been addressed:
- The docstring in
PresetCfgnow correctly usesnewton_mjwarpas the example field name - The test parameter naming in
test_shadow_hand_vision_presets.pymaintains"newton"for golden image compatibility with clear code structure - Documentation is consistent throughout
New Observations
The new newton_mjwarp naming convention is cleaner than the previous mjwarp — it groups solver presets by backend prefix while still distinguishing them from the bare newton backend label. The deprecation aliases now correctly map both newton → newton_mjwarp and kamino → newton_kamino.
Implementation Verdict
Ship it — The implementation is thorough, the deprecation path is correct, and the naming convention improvement makes the preset system more intuitive.
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot
Summary
This is a follow-up review after the final commits. The PR is complete and ready to ship.
Previous Findings Status
✅ All previous concerns were already addressed in the prior review. No regressions introduced.
Implementation Verdict
Ship it — The rename from newton/kamino to newton_mjwarp/newton_kamino is complete with proper deprecation warnings, comprehensive test coverage (including the new test_newton_solver_preset_names.py scanner), and consistent documentation updates across 54 files.
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot
Summary
Follow-up review after final commits. The PR remains complete and ready to ship.
Previous Findings Status
✅ All previous concerns remain addressed. No new issues introduced in the latest commits.
Implementation Verdict
Ship it — The rename is comprehensive with proper deprecation warnings, test coverage including the test_newton_solver_preset_names.py scanner, and consistent documentation. The legacy alias system in hydra.py correctly maps newton → newton_mjwarp and kamino → newton_kamino with FutureWarning emissions.
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot
Summary
Follow-up review after commit 6708443. The PR remains complete and ready to ship.
Previous Findings Status
✅ All previous concerns remain addressed. No new issues were introduced in this commit.
Implementation Verdict
Ship it — The rename from newton to newton_mjwarp is comprehensive across 55 files with proper deprecation warnings via _LEGACY_PRESET_ALIASES, thorough test coverage including the regression scanner in test_newton_solver_preset_names.py, and consistent documentation updates. The CI results show core checks passing (pre-commit, wheels, labeler, changelog) with physics-dependent jobs still pending as expected.
Pivots the rename to group Newton-backend solver variants under a common prefix and addresses review feedback on PR isaac-sim#5488: - newton -> newton_mjwarp - kamino -> newton_kamino Both legacy names remain live as aliases that emit a FutureWarning (always shown, unlike DeprecationWarning) and resolve to the new names. _user_stacklevel() points warnings at user code rather than inside hydra.py. _format_unknown_presets_error explicitly calls out the rename when an unknown preset matches a legacy alias. Tests cover the alias path end-to-end through parse_overrides and apply_overrides, the shadow-guard for configs that legitimately keep the deprecated spelling, and an expanded regression scanner that catches both renames (with a fixed RST literal pattern that actually matches the realistic ``newton``,/``newton``... forms).
- Path-specific apply_overrides error now mentions the rename when
an unknown name matches a deprecated alias (matches the global
preset path, which already calls out the rename via
_format_unknown_presets_error).
- _user_stacklevel caps its frame walk and falls back to stacklevel=2
when no non-hydra.py frame is found, so warnings at minimum jump
out of the helper rather than landing inside hydra.py.
- Changelog "Changed" entry is tagged **Breaking:** per AGENTS.md
(the alias shim covers most users, but workflows treating
FutureWarning as an error or iterating __dataclass_fields__
directly see a hard rename).
- :class:`FutureWarning` -> :exc:`FutureWarning` in the changelog
(FutureWarning is a builtin exception).
- Aligned the deprecation lifetime wording in hydra.py with the
changelog ("removed in a future release").
- Reformatted _SCAN_EXCLUDE_FILES to match ruff format output so
pre-commit is clean on a fresh checkout.
Adds tests for previously untested paths:
- _format_unknown_presets_error deprecation hint branch.
- Real-config alias path through UnitreeGo1RoughEnvCfg
(presets=newton resolves to the newton_mjwarp field).
- PresetCfg.__getattr__ AttributeError branch (hasattr / pytest.raises).
- _user_stacklevel attributing warnings outside hydra.py.
The bulk rename `mjwarp` -> `newton_mjwarp` made cells in the Presets column overflow the 23-char column width, producing 'Malformed table' errors during Sphinx doc build. Widened the column to 30 chars across all 11 tables in the file (separator rows, header underlines, and data-row cell padding).
6708443 to
1f30078
Compare
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot
Summary
Follow-up review after commit 1f30078. The PR remains complete and ready to ship.
Previous Findings Status
✅ All previous concerns remain addressed. No new issues were introduced in this commit.
Implementation Verdict
Ship it — The latest commit (1f30078) contains only minor doc formatting fixes and changelog fragment updates. The comprehensive rename from newton to newton_mjwarp across 55 files remains correct with proper deprecation warnings, thorough regression testing, and consistent documentation. CI shows core checks passing with physics-dependent jobs pending as expected.
Update preset references in the Kamino tutorial after the rename in isaac-sim#5488 ("Rename Newton preset to MJWarp"): * ``presets=newton`` -> ``presets=newton_mjwarp`` * ``presets=kamino`` -> ``presets=newton_kamino`` * ``env.sim.physics=kamino`` -> ``env.sim.physics=newton_kamino`` * Backticked preset name references in prose updated to match. This brings the tutorial in line with the renamed preset keys and satisfies the regression check in ``test_newton_solver_preset_names.py``.
Description
Renames the public Newton MJWarp physics preset from
newtontomjwarpto distinguish solver selection from the Newton backend, Newton package, and Newton visualizer names.The change keeps legitimate Newton component names intact, including
isaaclab_newton,newton_renderer,--viz newton, backend labelnewton, and solver value"newton". Legacynewtonpreset selections now resolve tomjwarpwith a deprecation warning.Related to #5483.
No new dependencies are required.
Type of change
Screenshots
Not applicable.
Testing
./isaaclab.sh -p -m pytest source/isaaclab_tasks/test/test_mjwarp_preset_names.py source/isaaclab_tasks/test/test_hydra.py source/isaaclab_tasks/test/test_preset_kit_decision.py -q: 74 passed./isaaclab.sh -p -m pytest source/isaaclab_tasks/test/test_shadow_hand_vision_presets.py -q: 67 passed, 6 skipped, 2 xpassed./isaaclab.sh -p -m pytest "source/isaaclab_visualizers/test/test_visualizer_cartpole_integration.py::test_cartpole_newton_visualizer_tiled_camera_rgb_non_black[newton]" -q: 1 passed./isaaclab.sh -p -m pytest --collect-only -q source/isaaclab_tasks/test/test_environments_newton.py: 86 tests collectednewtonpreset references: passed./isaaclab.sh -f: passedgit diff --check: passedChecklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists thereNote: this PR adds changelog fragments under
changelog.d. The extension version is compiled by the nightly workflow, soconfig/extension.tomlis intentionally not edited directly.