[3.0.0-beta2] Forward AutoMate run_w_id downstream args#6136
Conversation
Greptile SummaryThis PR improves the
Confidence Score: 4/5Safe to merge; the change is narrow and well-contained, with no regressions to existing behaviour. The refactor is straightforward: command construction is correctly extracted, No files require special attention; Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant run_w_id.py
participant assembly_tasks_cfg.py
participant isaaclab.sh
User->>run_w_id.py: "python run_w_id.py --assembly_id=00004 --viz kit --headless"
run_w_id.py->>run_w_id.py: "parse_known_args()<br/>args.visualizer=kit<br/>downstream_args=[--headless]"
run_w_id.py->>assembly_tasks_cfg.py: update_task_param(cfg_path, 00004, ...)
run_w_id.py->>run_w_id.py: build_command(args, downstream_args)
run_w_id.py->>isaaclab.sh: "subprocess.run(command, check=True)"
Reviews (1): Last reviewed commit: "Forward Automate run_w_id downstream arg..." | Re-trigger Greptile |
There was a problem hiding this comment.
Code Review: PR #6136
Thanks for this contribution! This PR improves the run_w_id.py wrapper by enabling proper argument forwarding to downstream scripts. Here's my review:
✅ What Looks Good
-
Clean Refactoring: Extracting
build_command()as a separate function improves code organization and testability. -
Proper Argument Forwarding: Using
parse_known_args()withallow_abbrev=Falseis the correct pattern for wrapper scripts that need to pass through unknown arguments. -
Visualizer Support: Adding explicit
--visualizer/--vizsupport with proper forwarding to the downstream RL-Games script addresses the stated issue. -
Helpful Epilog: The parser epilog clearly communicates that additional arguments are forwarded, which improves UX.
-
Changelog Entry: The changelog entry is clear and follows project conventions.
💬 Suggestions (Non-blocking)
Consider using consistent argument style
The --visualizer argument uses space-separated syntax when forwarding:
command.extend(["--visualizer", args.visualizer])While other arguments use = syntax:
command.append(f"--checkpoint={args.checkpoint}")Both work, but consistency might be nice. This is purely stylistic and not a blocking concern.
Test coverage opportunity
The PR description mentions adding a unit test, but I only see 2 files in the changeset (changelog + run_w_id.py). If a test file was intended, it may not have been included in this commit. Consider adding tests for:
- The
build_command()function directly - Visualizer argument forwarding
- Downstream argument passthrough (e.g.,
--headless)
This would help prevent regressions and document expected behavior.
ℹ️ Notes
-
The file modification in
update_task_param()happens before subprocess execution. If the subprocess fails, the config file remains modified. This is existing behavior and may be intentional for debugging, but worth noting. -
Typos in known argument names (e.g.,
--assmbly_idinstead of--assembly_id) will now be silently passed through to the downstream script rather than raising an error. This is expected behavior withparse_known_args()but users should be aware.
Overall this is a clean, focused PR that solves a real usability issue.
Update (d1149f9): Reviewed new commits since c0cfc28. The diff is unchanged from the previous review — no new issues introduced. Previous suggestions (argument style consistency, test coverage) remain open but are non-blocking. LGTM.
Update (3ee9ea2): Reviewed incremental changes since d1149f9. No new issues introduced. Previous inline suggestions (use is not None for visualizer check, downstream_args ordering, test coverage) remain unaddressed but are non-blocking. LGTM.
| if args.checkpoint: | ||
| command.append(f"--checkpoint={args.checkpoint}") | ||
|
|
||
| if args.visualizer: |
There was a problem hiding this comment.
suggestion: if args.visualizer is not None: would be safer than truthiness — an empty string "" is falsy and would silently skip forwarding. Matches the default=None sentinel more precisely.
| if args.visualizer: | ||
| command.extend(["--visualizer", args.visualizer]) | ||
|
|
||
| command.extend(downstream_args) |
There was a problem hiding this comment.
note (low risk): Since --num_envs, --seed, etc. are emitted above from parsed defaults, a user who also passes --num_envs=64 as a "downstream" arg will produce a duplicate flag. Whether last-wins depends on the downstream argparser. Consider a brief comment noting this or placing downstream_args before the explicit flags.
| return module | ||
|
|
||
|
|
||
| def test_run_w_id_forwards_visualizer_and_downstream_args(monkeypatch): |
There was a problem hiding this comment.
suggestion: Consider adding a second test case (or parametrizing) with --train instead of --log_eval to cover the training script path (train.py vs play.py).
| def test_run_w_id_forwards_visualizer_and_downstream_args(monkeypatch): | ||
| module = _load_run_w_id_module() | ||
| captured = {} | ||
|
|
||
| monkeypatch.setattr( | ||
| sys, | ||
| "argv", | ||
| [ | ||
| "run_w_id.py", | ||
| "--assembly_id=00004", | ||
| "--checkpoint=checkpoint.pth", | ||
| "--log_eval", | ||
| "--viz", | ||
| "kit", | ||
| "--headless", | ||
| ], | ||
| ) | ||
| monkeypatch.setattr(module, "update_task_param", lambda *args: None) | ||
|
|
||
| def _fake_run(command, check): | ||
| captured["command"] = command | ||
| captured["check"] = check | ||
|
|
||
| monkeypatch.setattr(module.subprocess, "run", _fake_run) | ||
|
|
||
| module.main() | ||
|
|
||
| assert captured["check"] is True | ||
| assert "scripts/reinforcement_learning/rl_games/play.py" in captured["command"] | ||
| assert "--visualizer" in captured["command"] | ||
| visualizer_index = captured["command"].index("--visualizer") | ||
| assert captured["command"][visualizer_index + 1] == "kit" | ||
| assert "--headless" in captured["command"] |
There was a problem hiding this comment.
Missing negative and long-form visualizer test cases
The single test verifies --viz kit is forwarded correctly, but two cases are untested: (1) when neither --viz nor --visualizer is provided, the delegated command should contain no --visualizer entry at all (the default=None path through build_command); and (2) the --visualizer long-form alias. A future refactor that accidentally changes the default or the long-form dest would not be caught by the current suite.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| if args.assembly_id == "ASSEMBLY_ID": | ||
| parser.error("replace ASSEMBLY_ID with an AutoMate assembly ID, for example 00032") | ||
|
|
||
| update_task_param(args.cfg_path, args.assembly_id, args.train, args.log_eval) |
There was a problem hiding this comment.
--assembly_id can be None and silently corrupts the config
assembly_id has no required=True and no None guard — only the sentinel string "ASSEMBLY_ID" is caught. When --assembly_id is omitted entirely, args.assembly_id is None, update_task_param writes assembly_id = 'None' into assembly_tasks_cfg.py, and eval_filename becomes evaluation_None.h5, without any error being surfaced. This pre-dated the PR but the refactor is a natural point to add required=True or an explicit None check here.
c0cfc28 to
d1149f9
Compare
d1149f9 to
3ee9ea2
Compare
Summary
run_w_id.pyexplicitly accept--viz/--visualizerand forward it to the delegated RL-Games script--headlesscan pass throughrun_w_id.pyis a convenience wrapper for AutoMate Assembly runs: it updates the selected assembly ID in the AutoMate task config, then launches the normal RL-Games train/play script through./isaaclab.sh -p. Since the downstream script owns AppLauncher startup, visualizer selection should be forwarded rather than handled by the wrapper itself.Validation