diff --git a/src/tyro/_backends/_tyro_backend.py b/src/tyro/_backends/_tyro_backend.py index 0f4dafba..0eb823ad 100644 --- a/src/tyro/_backends/_tyro_backend.py +++ b/src/tyro/_backends/_tyro_backend.py @@ -328,7 +328,6 @@ def _recurse( add_help=add_help, console_outputs=console_outputs, seen_double_dash=True, - return_unknown_args=return_unknown_args, ) continue @@ -484,7 +483,6 @@ def _recurse( local_prog, add_help=add_help, console_outputs=console_outputs, - return_unknown_args=return_unknown_args, min_remaining_positional=self._min_positional_consumption( positional_args ), @@ -544,7 +542,6 @@ def _recurse( local_prog, add_help=add_help, console_outputs=console_outputs, - return_unknown_args=return_unknown_args, ) continue @@ -796,7 +793,6 @@ def _consume_argument( add_help: bool, console_outputs: bool, seen_double_dash: bool = False, - return_unknown_args: bool = False, min_remaining_positional: int = 0, ): arg_values: list[str] = [] @@ -838,13 +834,12 @@ def _consume_argument( break # To match argparse behavior, any flag-like string - # terminates when return_unknown_args is set. We check - # for a leading alpha character after stripping dashes - # to avoid treating negative numbers (like -2 or -3.14) + # terminates positional nargs consumption. We check for + # a leading alpha character after stripping dashes to + # avoid treating negative numbers (like -2 or -3.14) # as flags. if ( - return_unknown_args - and token_key.startswith("-") + token_key.startswith("-") and len(token_key) > 1 and token_key.lstrip("-")[:1].isalpha() ): diff --git a/tests/test_positional.py b/tests/test_positional.py index f7f0f240..dc49697f 100644 --- a/tests/test_positional.py +++ b/tests/test_positional.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pathlib from dataclasses import dataclass from typing import List, Optional, Sequence, Tuple @@ -373,3 +374,21 @@ class Config: result = tyro.cli(Config, args=["-x", "a", "--", "b", "c"]) assert result.pos == ("b", "c") assert result.var_len == ("a",) + + +def test_positional_varlen_rejects_unknown_flags() -> None: + """Regression test for #457: unknown flags should not be consumed as positional values. + + With tyro >= 1.0.9, --invalid was incorrectly accepted as a positional + path value instead of raising an unrecognized-options error. + """ + + @dataclass + class Arguments: + logfile_paths: tyro.conf.Positional[tuple[pathlib.Path, ...]] + cfg_file: Annotated[pathlib.Path, tyro.conf.arg(aliases=["-c"])] = pathlib.Path( + "config.yaml" + ) + + with pytest.raises(SystemExit): + tyro.cli(Arguments, args=["--invalid"]) diff --git a/tests/test_py311_generated/test_positional_generated.py b/tests/test_py311_generated/test_positional_generated.py index 47019da2..8cd9b90a 100644 --- a/tests/test_py311_generated/test_positional_generated.py +++ b/tests/test_py311_generated/test_positional_generated.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pathlib from dataclasses import dataclass from typing import Annotated, List, Optional, Sequence, Tuple @@ -372,3 +373,21 @@ class Config: result = tyro.cli(Config, args=["-x", "a", "--", "b", "c"]) assert result.pos == ("b", "c") assert result.var_len == ("a",) + + +def test_positional_varlen_rejects_unknown_flags() -> None: + """Regression test for #457: unknown flags should not be consumed as positional values. + + With tyro >= 1.0.9, --invalid was incorrectly accepted as a positional + path value instead of raising an unrecognized-options error. + """ + + @dataclass + class Arguments: + logfile_paths: tyro.conf.Positional[tuple[pathlib.Path, ...]] + cfg_file: Annotated[pathlib.Path, tyro.conf.arg(aliases=["-c"])] = pathlib.Path( + "config.yaml" + ) + + with pytest.raises(SystemExit): + tyro.cli(Arguments, args=["--invalid"])