diff --git a/docs/guides/cli.md b/docs/guides/cli.md index 226b7d5e..5ba82d46 100644 --- a/docs/guides/cli.md +++ b/docs/guides/cli.md @@ -346,7 +346,7 @@ Train a model using the specified configuration. │ --dryrun Print the scheduler request without submitting │ --factory -f TEXT Predefined factory to use [default: None] │ --load -l TEXT Load a factory from a directory [default: None] -│ --yaml -y TEXT Path to a YAML file to load [default: None] +│ --yaml TEXT Path to a YAML file to load [default: None] │ --repl -r Enter interactive mode │ --detach Detach from the run │ --yes,--no-confirm -y Skip confirmation before execution diff --git a/nemo_run/cli/api.py b/nemo_run/cli/api.py index e05b921f..6f0fe35e 100644 --- a/nemo_run/cli/api.py +++ b/nemo_run/cli/api.py @@ -891,7 +891,7 @@ def command( None, "--load", "-l", help="Load a factory from a directory" ), yaml: Optional[str] = typer.Option( - None, "--yaml", "-y", help="Path to a YAML file to load" + None, "--yaml", help="Path to a YAML file to load" ), repl: bool = typer.Option(False, "--repl", "-r", help="Enter interactive mode"), detach: bool = typer.Option(False, "--detach", help="Detach from the run"), diff --git a/test/cli/test_api.py b/test/cli/test_api.py index da359c12..6640b690 100644 --- a/test/cli/test_api.py +++ b/test/cli/test_api.py @@ -1918,3 +1918,59 @@ class TestExtractConstituentTypes: def test_various_type_hints(self, type_hint, expected_types): """Test get_underlying_types with various type hints.""" assert extract_constituent_types(type_hint) == expected_types + + +class TestShortFlagCollision: + """Regression test for issue #559: -y flag collision between --yaml and --yes.""" + + def test_yaml_flag_no_short_alias(self): + """Verify --yaml does not have -y short flag.""" + @run.cli.entrypoint + def dummy_task(yaml: Optional[str] = typer.Option(None, "--yaml", help="YAML file")): + return yaml + + app = typer.Typer() + RunContext.cli_command(app, "task", dummy_task) + + runner = CliRunner() + + # Test --yaml flag works + result = runner.invoke(app, ["task", "--yaml", "config.yaml"]) + assert result.exit_code == 0 + + # Verify help output doesn't show -y for --yaml + help_result = runner.invoke(app, ["task", "--help"]) + assert help_result.exit_code == 0 + assert "--yaml" in help_result.stdout + + def test_skip_confirmation_flag_has_short_alias(self): + """Verify --yes/-y flag works correctly for skip_confirmation.""" + @run.cli.entrypoint(skip_confirmation=False) + def dummy_task(): + return "success" + + app = typer.Typer() + RunContext.cli_command(app, "task", dummy_task) + + runner = CliRunner() + + # Test -y flag works for skip_confirmation + result = runner.invoke(app, ["task", "-y"], input="n") + assert result.exit_code == 0 + + def test_help_output_no_duplicate_flag_warnings(self): + """Verify help output doesn't generate warnings about duplicate -y flags.""" + @run.cli.entrypoint + def dummy_task( + yaml: Optional[str] = typer.Option(None, "--yaml", help="YAML file"), + ): + return yaml + + app = typer.Typer() + RunContext.cli_command(app, "task", dummy_task) + + runner = CliRunner() + result = runner.invoke(app, ["task", "--help"]) + + # Help should succeed with no errors + assert result.exit_code == 0