def _split(self, args_str, expected_scope_to_flags, expected_target_specs, expected_help=False): splitter = ArgSplitter(ArgSplitterTest._known_scopes) args = shlex.split(str(args_str)) scope_to_flags, target_specs = splitter.split_args(args) self.assertEquals(expected_scope_to_flags, scope_to_flags) self.assertEquals(expected_target_specs, target_specs) self.assertEquals(expected_help, splitter.is_help)
def _split(self, args_str, expected_goals, expected_scope_to_flags, expected_target_specs, expected_passthru=None, expected_passthru_owner=None, expected_is_help=False, expected_help_advanced=False, expected_help_all=False, expected_unknown_scopes=None): expected_passthru = expected_passthru or [] expected_unknown_scopes = expected_unknown_scopes or [] splitter = ArgSplitter(ArgSplitterTest._known_scope_infos) args = shlex.split(args_str) goals, scope_to_flags, target_specs, passthru, passthru_owner, unknown_scopes = splitter.split_args( args) self.assertEqual(expected_goals, goals) self.assertEqual(expected_scope_to_flags, scope_to_flags) self.assertEqual(expected_target_specs, target_specs) self.assertEqual(expected_passthru, passthru) self.assertEqual(expected_passthru_owner, passthru_owner) self.assertEqual(expected_is_help, splitter.help_request is not None) self.assertEqual(expected_help_advanced, (isinstance(splitter.help_request, OptionsHelp) and splitter.help_request.advanced)) self.assertEqual(expected_help_all, (isinstance(splitter.help_request, OptionsHelp) and splitter.help_request.all_scopes)) self.assertEqual(expected_unknown_scopes, unknown_scopes)
def assert_unknown_goal(args_str: str, unknown_goals: List[str]) -> None: splitter = ArgSplitter(ArgSplitterTest._known_scope_infos, buildroot=os.getcwd()) result = splitter.split_args(shlex.split(args_str)) assert isinstance(splitter.help_request, UnknownGoalHelp) assert set(unknown_goals) == set(splitter.help_request.unknown_goals) assert result.unknown_scopes == unknown_goals
def create(cls, env, config, known_scope_infos, args=None, bootstrap_option_values=None): """Create an Options instance. :param env: a dict of environment variables. :param :class:`pants.option.config.Config` config: data from a config file. :param known_scope_infos: ScopeInfos for all scopes that may be encountered. :param args: a list of cmd-line args; defaults to `sys.argv` if None is supplied. :param bootstrap_option_values: An optional namespace containing the values of bootstrap options. We can use these values when registering other options. """ # We need parsers for all the intermediate scopes, so inherited option values # can propagate through them. complete_known_scope_infos = cls.complete_scopes(known_scope_infos) splitter = ArgSplitter(complete_known_scope_infos) args = sys.argv if args is None else args goals, scope_to_flags, target_specs, passthru, passthru_owner, unknown_scopes = splitter.split_args(args) option_tracker = OptionTracker() if bootstrap_option_values: target_spec_files = bootstrap_option_values.target_spec_files if target_spec_files: for spec in target_spec_files: with open(spec, 'r') as f: target_specs.extend([line for line in [line.strip() for line in f] if line]) help_request = splitter.help_request parser_hierarchy = ParserHierarchy(env, config, complete_known_scope_infos, option_tracker) bootstrap_option_values = bootstrap_option_values known_scope_to_info = {s.scope: s for s in complete_known_scope_infos} return cls(goals, scope_to_flags, target_specs, passthru, passthru_owner, help_request, parser_hierarchy, bootstrap_option_values, known_scope_to_info, option_tracker, unknown_scopes)
def assert_valid_split( args_str: str, *, expected_goals: List[str], expected_scope_to_flags: Dict[str, List[str]], expected_specs: List[str], expected_passthru: Optional[List[str]] = None, expected_is_help: bool = False, expected_help_advanced: bool = False, expected_help_all: bool = False, ) -> None: expected_passthru = expected_passthru or [] splitter = ArgSplitter(ArgSplitterTest._known_scope_infos, buildroot=os.getcwd()) args = shlex.split(args_str) split_args = splitter.split_args(args) assert expected_goals == split_args.goals assert expected_scope_to_flags == split_args.scope_to_flags assert expected_specs == split_args.specs assert expected_passthru == split_args.passthru assert expected_is_help == (splitter.help_request is not None) assert expected_help_advanced == (isinstance(splitter.help_request, OptionsHelp) and splitter.help_request.advanced) assert expected_help_all == isinstance(splitter.help_request, AllHelp)
def __init__(self, env, config, known_scopes, args=sys.argv, bootstrap_option_values=None): """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file (must support config.get[list](section, name, default=)). :param known_scopes: a list of all possible scopes that may be encountered. :param args: a list of cmd-line args. :param bootstrap_option_values: An optional namespace containing the values of bootstrap options. We can use these values when registering other options. """ splitter = ArgSplitter(known_scopes) self._goals, self._scope_to_flags, self._target_specs, self._passthru, self._passthru_owner = \ splitter.split_args(args) if bootstrap_option_values: target_spec_files = bootstrap_option_values.target_spec_files if target_spec_files: for spec in target_spec_files: with open(spec) as f: self._target_specs.extend(filter(None, [line.strip() for line in f])) self._help_request = splitter.help_request self._parser_hierarchy = ParserHierarchy(env, config, known_scopes, self._help_request) self._values_by_scope = {} # Arg values, parsed per-scope on demand. self._bootstrap_option_values = bootstrap_option_values self._known_scopes = set(known_scopes)
def create(cls, env, config, known_scope_infos, args=None, bootstrap_option_values=None): """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file (must support config.get[list](section, name, default=)). :param known_scope_infos: ScopeInfos for all scopes that may be encountered. :param args: a list of cmd-line args; defaults to `sys.argv` if None is supplied. :param bootstrap_option_values: An optional namespace containing the values of bootstrap options. We can use these values when registering other options. """ # We need parsers for all the intermediate scopes, so inherited option values # can propagate through them. complete_known_scope_infos = cls.complete_scopes(known_scope_infos) splitter = ArgSplitter(complete_known_scope_infos) args = sys.argv if args is None else args goals, scope_to_flags, target_specs, passthru, passthru_owner = splitter.split_args(args) if bootstrap_option_values: target_spec_files = bootstrap_option_values.target_spec_files if target_spec_files: for spec in target_spec_files: with open(spec) as f: target_specs.extend(filter(None, [line.strip() for line in f])) help_request = splitter.help_request parser_hierarchy = ParserHierarchy(env, config, complete_known_scope_infos) values_by_scope = {} # Arg values, parsed per-scope on demand. bootstrap_option_values = bootstrap_option_values known_scope_to_info = {s.scope: s for s in complete_known_scope_infos} return cls(goals, scope_to_flags, target_specs, passthru, passthru_owner, help_request, parser_hierarchy, values_by_scope, bootstrap_option_values, known_scope_to_info)
def create( cls, env: Mapping[str, str], config: Config, known_scope_infos: Iterable[ScopeInfo], args: Sequence[str], bootstrap_option_values: OptionValueContainer | None = None, allow_unknown_options: bool = False, ) -> Options: """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file. :param known_scope_infos: ScopeInfos for all scopes that may be encountered. :param args: a list of cmd-line args; defaults to `sys.argv` if None is supplied. :param bootstrap_option_values: An optional namespace containing the values of bootstrap options. We can use these values when registering other options. :param allow_unknown_options: Whether to ignore or error on unknown cmd-line flags. """ # We need parsers for all the intermediate scopes, so inherited option values # can propagate through them. complete_known_scope_infos = cls.complete_scopes(known_scope_infos) splitter = ArgSplitter(complete_known_scope_infos, get_buildroot()) split_args = splitter.split_args(args) if split_args.passthru and len(split_args.goals) > 1: raise cls.AmbiguousPassthroughError( f"Specifying multiple goals (in this case: {split_args.goals}) " "along with passthrough args (args after `--`) is ambiguous.\n" "Try either specifying only a single goal, or passing the passthrough args " "directly to the relevant consumer via its associated flags.") if bootstrap_option_values: spec_files = bootstrap_option_values.spec_files if spec_files: for spec_file in spec_files: with open(spec_file) as f: split_args.specs.extend([ line for line in [line.strip() for line in f] if line ]) help_request = splitter.help_request parser_by_scope = { si.scope: Parser(env, config, si) for si in complete_known_scope_infos } known_scope_to_info = {s.scope: s for s in complete_known_scope_infos} return cls( goals=split_args.goals, scope_to_flags=split_args.scope_to_flags, specs=split_args.specs, passthru=split_args.passthru, help_request=help_request, parser_by_scope=parser_by_scope, bootstrap_option_values=bootstrap_option_values, known_scope_to_info=known_scope_to_info, allow_unknown_options=allow_unknown_options, )
def _split(self, args_str, expected_goals, expected_scope_to_flags, expected_target_specs, expected_passthru=None, expected_passthru_owner=None, expected_is_help=False, expected_help_advanced=False, expected_help_all=False): expected_passthru = expected_passthru or [] splitter = ArgSplitter(ArgSplitterTest._known_scope_infos) args = shlex.split(args_str) goals, scope_to_flags, target_specs, passthru, passthru_owner = splitter.split_args( args) self.assertEquals(expected_goals, goals) self.assertEquals(expected_scope_to_flags, scope_to_flags) self.assertEquals(expected_target_specs, target_specs) self.assertEquals(expected_passthru, passthru) self.assertEquals(expected_passthru_owner, passthru_owner) self.assertEquals(expected_is_help, splitter.help_request is not None) self.assertEquals( expected_help_advanced, splitter.help_request is not None and splitter.help_request.advanced) self.assertEquals( expected_help_all, splitter.help_request is not None and splitter.help_request.all_scopes) self.assertFalse(splitter.help_request is not None and splitter.help_request.version)
def __init__(self, env, config, known_scope_infos, args=sys.argv, bootstrap_option_values=None): """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file (must support config.get[list](section, name, default=)). :param known_scope_infos: ScopeInfos for all scopes that may be encountered. :param args: a list of cmd-line args. :param bootstrap_option_values: An optional namespace containing the values of bootstrap options. We can use these values when registering other options. """ # We need parsers for all the intermediate scopes, so inherited option values # can propagate through them. complete_known_scope_infos = self.complete_scopes(known_scope_infos) splitter = ArgSplitter(complete_known_scope_infos) self._goals, self._scope_to_flags, self._target_specs, self._passthru, self._passthru_owner = \ splitter.split_args(args) if bootstrap_option_values: target_spec_files = bootstrap_option_values.target_spec_files if target_spec_files: for spec in target_spec_files: with open(spec) as f: self._target_specs.extend(filter(None, [line.strip() for line in f])) self._help_request = splitter.help_request self._parser_hierarchy = ParserHierarchy(env, config, complete_known_scope_infos) self._values_by_scope = {} # Arg values, parsed per-scope on demand. self._bootstrap_option_values = bootstrap_option_values self._known_scopes = set([s[0] for s in known_scope_infos])
def _split_unknown_goal(self, args_str, unknown_goals): splitter = ArgSplitter(ArgSplitterTest._known_scope_infos) result = splitter.split_args(shlex.split(args_str)) self.assertTrue(isinstance(splitter.help_request, UnknownGoalHelp)) self.assertSetEqual(set(unknown_goals), set(splitter.help_request.unknown_goals)) self.assertEqual(result.unknown_scopes, unknown_goals)
def assert_valid_split( self, args_str: str, *, expected_goals: List[str], expected_scope_to_flags: Dict[str, List[str]], expected_positional_args: List[str], expected_passthru: Optional[List[str]] = None, expected_passthru_owner: Optional[str] = None, expected_is_help: bool = False, expected_help_advanced: bool = False, expected_help_all: bool = False, expected_unknown_scopes: Optional[List[str]] = None) -> None: expected_passthru = expected_passthru or [] expected_unknown_scopes = expected_unknown_scopes or [] splitter = ArgSplitter(ArgSplitterTest._known_scope_infos) args = shlex.split(args_str) split_args = splitter.split_args(args) self.assertEqual(expected_goals, split_args.goals) self.assertEqual(expected_scope_to_flags, split_args.scope_to_flags) self.assertEqual(expected_positional_args, split_args.positional_args) self.assertEqual(expected_passthru, split_args.passthru) self.assertEqual(expected_passthru_owner, split_args.passthru_owner) self.assertEqual(expected_is_help, splitter.help_request is not None) self.assertEqual(expected_help_advanced, (isinstance(splitter.help_request, OptionsHelp) and splitter.help_request.advanced)) self.assertEqual(expected_help_all, (isinstance(splitter.help_request, OptionsHelp) and splitter.help_request.all_scopes)) self.assertEqual(expected_unknown_scopes, split_args.unknown_scopes)
def create( cls, env: Mapping[str, str], config: Config, known_scope_infos: Iterable[ScopeInfo], args: Optional[Sequence[str]] = None, bootstrap_option_values: Optional[OptionValueContainer] = None, ) -> "Options": """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file. :param known_scope_infos: ScopeInfos for all scopes that may be encountered. :param args: a list of cmd-line args; defaults to `sys.argv` if None is supplied. :param bootstrap_option_values: An optional namespace containing the values of bootstrap options. We can use these values when registering other options. """ # We need parsers for all the intermediate scopes, so inherited option values # can propagate through them. complete_known_scope_infos = cls.complete_scopes(known_scope_infos) splitter = ArgSplitter(complete_known_scope_infos) args = sys.argv if args is None else args split_args = splitter.split_args(args) option_tracker = OptionTracker() if bootstrap_option_values: spec_files = bootstrap_option_values.spec_files if spec_files: for spec_file in spec_files: with open(spec_file, "r") as f: split_args.specs.extend([ line for line in [line.strip() for line in f] if line ]) help_request = splitter.help_request parser_hierarchy = ParserHierarchy(env, config, complete_known_scope_infos, option_tracker) known_scope_to_info = {s.scope: s for s in complete_known_scope_infos} return cls( goals=split_args.goals, scope_to_flags=split_args.scope_to_flags, specs=split_args.specs, passthru=split_args.passthru, passthru_owner=split_args.passthru_owner, help_request=help_request, parser_hierarchy=parser_hierarchy, bootstrap_option_values=bootstrap_option_values, known_scope_to_info=known_scope_to_info, option_tracker=option_tracker, unknown_scopes=split_args.unknown_scopes, )
def _split(self, args_str, expected_goals, expected_scope_to_flags, expected_target_specs, expected_passthru=None, expected_passthru_owner=None, expected_is_help=False): expected_passthru = expected_passthru or [] splitter = ArgSplitter(ArgSplitterTest._known_scopes) args = shlex.split(str(args_str)) goals, scope_to_flags, target_specs, passthru, passthru_owner = splitter.split_args(args) self.assertEquals(expected_goals, goals) self.assertEquals(expected_scope_to_flags, scope_to_flags) self.assertEquals(expected_target_specs, target_specs) self.assertEquals(expected_passthru, passthru) self.assertEquals(expected_passthru_owner, passthru_owner) self.assertEquals(expected_is_help, splitter.is_help)
def create( cls, env, config, known_scope_infos, args=None, bootstrap_option_values=None, option_tracker=None, ): """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file (must support config.get[list](section, name, default=)). :param known_scope_infos: ScopeInfos for all scopes that may be encountered. :param args: a list of cmd-line args; defaults to `sys.argv` if None is supplied. :param bootstrap_option_values: An optional namespace containing the values of bootstrap options. We can use these values when registering other options. :param :class:`pants.option.option_tracker.OptionTracker` option_tracker: option tracker instance to record how option values were assigned. """ # We need parsers for all the intermediate scopes, so inherited option values # can propagate through them. complete_known_scope_infos = cls.complete_scopes(known_scope_infos) splitter = ArgSplitter(complete_known_scope_infos) args = sys.argv if args is None else args goals, scope_to_flags, target_specs, passthru, passthru_owner = splitter.split_args( args) if not option_tracker: raise cls.OptionTrackerRequiredError() if bootstrap_option_values: target_spec_files = bootstrap_option_values.target_spec_files if target_spec_files: for spec in target_spec_files: with open(spec) as f: target_specs.extend( filter(None, [line.strip() for line in f])) help_request = splitter.help_request parser_hierarchy = ParserHierarchy(env, config, complete_known_scope_infos, option_tracker) values_by_scope = {} # Arg values, parsed per-scope on demand. bootstrap_option_values = bootstrap_option_values known_scope_to_info = {s.scope: s for s in complete_known_scope_infos} return cls(goals, scope_to_flags, target_specs, passthru, passthru_owner, help_request, parser_hierarchy, values_by_scope, bootstrap_option_values, known_scope_to_info, option_tracker)
def assert_valid_split( splitter: ArgSplitter, args_str: str, *, expected_goals: list[str], expected_scope_to_flags: dict[str, list[str]], expected_specs: list[str], expected_passthru: list[str] | None = None, expected_is_help: bool = False, expected_help_advanced: bool = False, expected_help_all: bool = False, ) -> None: expected_passthru = expected_passthru or [] args = shlex.split(args_str) split_args = splitter.split_args(args) assert expected_goals == split_args.goals assert expected_scope_to_flags == split_args.scope_to_flags assert expected_specs == split_args.specs assert expected_passthru == split_args.passthru assert expected_is_help == (split_args.builtin_goal in ("help", "help-advanced", "help-all", UNKNOWN_GOAL_NAME, NO_GOAL_NAME)) assert expected_help_advanced == ( "help-advanced" == split_args.builtin_goal) assert expected_help_all == ("help-all" == split_args.builtin_goal)
def __init__(self, env, config, known_scopes, args=sys.argv, legacy_parser=None): """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file (must support config.get(section, name, default=)). :param known_scopes: a list of all possible scopes that may be encountered. :param args: a list of cmd-line args. :param legacy_parser: optional instance of optparse.OptionParser, used to register and access the old-style flags during migration. """ splitter = ArgSplitter(known_scopes) self._scope_to_flags, self._target_specs, self._passthru = splitter.split_args(args) self._is_help = splitter.is_help self._parser_hierarchy = ParserHierarchy(env, config, known_scopes, legacy_parser) self._legacy_parser = legacy_parser # Old-style options, used temporarily during transition. self._legacy_values = None # Values parsed from old-stype options. self._values_by_scope = {} # Arg values, parsed per-scope on demand.
def _split(self, args_str, expected_goals, expected_scope_to_flags, expected_target_specs, expected_passthru=None, expected_passthru_owner=None, expected_is_help=False, expected_help_advanced=False, expected_help_all=False): expected_passthru = expected_passthru or [] splitter = ArgSplitter(ArgSplitterTest._known_scopes) args = shlex.split(str(args_str)) goals, scope_to_flags, target_specs, passthru, passthru_owner = splitter.split_args(args) self.assertEquals(expected_goals, goals) self.assertEquals(expected_scope_to_flags, scope_to_flags) self.assertEquals(expected_target_specs, target_specs) self.assertEquals(expected_passthru, passthru) self.assertEquals(expected_passthru_owner, passthru_owner) self.assertEquals(expected_is_help, splitter.help_request is not None) self.assertEquals(expected_help_advanced, splitter.help_request is not None and splitter.help_request.advanced) self.assertEquals(expected_help_all, splitter.help_request is not None and splitter.help_request.all_scopes)
def __init__(self, env, config, known_scopes, args=sys.argv, bootstrap_option_values=None): """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file (must support config.get[list](section, name, default=)). :param known_scopes: a list of all possible scopes that may be encountered. :param args: a list of cmd-line args. :param bootstrap_option_values: An optional namespace containing the values of bootstrap options. We can use these values when registering other options. """ splitter = ArgSplitter(known_scopes) self._goals, self._scope_to_flags, self._target_specs, self._passthru, self._passthru_owner = \ splitter.split_args(args) self._is_help = splitter.is_help self._parser_hierarchy = ParserHierarchy(env, config, known_scopes) self._values_by_scope = {} # Arg values, parsed per-scope on demand. self._bootstrap_option_values = bootstrap_option_values self._known_scopes = set(known_scopes)
def _split(self, args_str, expected_goals, expected_scope_to_flags, expected_target_specs, expected_passthru=None, expected_passthru_owner=None, expected_is_help=False): expected_passthru = expected_passthru or [] splitter = ArgSplitter(ArgSplitterTest._known_scopes) args = shlex.split(str(args_str)) goals, scope_to_flags, target_specs, passthru, passthru_owner = splitter.split_args( args) self.assertEquals(expected_goals, goals) self.assertEquals(expected_scope_to_flags, scope_to_flags) self.assertEquals(expected_target_specs, target_specs) self.assertEquals(expected_passthru, passthru) self.assertEquals(expected_passthru_owner, passthru_owner) self.assertEquals(expected_is_help, splitter.is_help)
def test_is_spec(splitter: ArgSplitter, known_scope_infos: list[ScopeInfo]) -> None: unambiguous_specs = [ "a/b/c", "a/b/c/", "a/b:c", "a/b/c.txt", ":c", "::", "a/", "./a.txt", ".", "*", "a/b/*.txt", "a/b/test*", "a/**/*", "!", "!a/b", "!a/b.txt", "a/b.txt:tgt", "a/b.txt:../tgt", "!a/b.txt:tgt", "dir#gen", "//:tgt#gen", "cache.java", "cache.tmp.java", ] directories_vs_goals = ["foo", "a_b_c"] # With no directories on disk to tiebreak. for spec in directories_vs_goals: assert splitter.likely_a_spec(spec) is False for s in unambiguous_specs: assert splitter.likely_a_spec(s) is True # With directories on disk to tiebreak. with temporary_dir() as tmpdir: splitter = ArgSplitter(known_scope_infos, tmpdir) for d in directories_vs_goals: Path(tmpdir, d).mkdir() assert splitter.likely_a_spec(d) is True
def __init__(self, env, config, known_scopes, args=sys.argv, legacy_parser=None): """Create an Options instance. :param env: a dict of environment variables. :param config: data from a config file (must support config.get(section, name, default=)). :param known_scopes: a list of all possible scopes that may be encountered. :param args: a list of cmd-line args. :param legacy_parser: optional instance of optparse.OptionParser, used to register and access the old-style flags during migration. """ splitter = ArgSplitter(known_scopes) self._scope_to_flags, self._target_specs = splitter.split_args(args) self._is_help = splitter.is_help self._parser_hierarchy = ParserHierarchy(env, config, known_scopes, legacy_parser) self._legacy_parser = legacy_parser # Old-style options, used temporarily during transition. self._legacy_values = None # Values parsed from old-stype options. self._values_by_scope = {} # Arg values, parsed per-scope on demand.
def test_is_spec(tmp_path: Path, splitter: ArgSplitter, known_scope_infos: list[ScopeInfo]) -> None: unambiguous_specs = [ "a/b/c", "a/b/c/", "a/b:c", "a/b/c.txt", ":c", "::", "a/", "./a.txt", ".", "*", "a/b/*.txt", "a/b/test*", "a/**/*", "a/b.txt:tgt", "a/b.txt:../tgt", "dir#gen", "//:tgt#gen", "cache.java", "cache.tmp.java", ] directories_vs_goals = ["foo", "a_b_c"] # With no directories on disk to tiebreak. for spec in directories_vs_goals: assert splitter.likely_a_spec(spec) is False assert splitter.likely_a_spec(f"-{spec}") is True for s in unambiguous_specs: assert splitter.likely_a_spec(s) is True assert splitter.likely_a_spec(f"-{s}") is True assert splitter.likely_a_spec("-") is True assert splitter.likely_a_spec("--") is False # With directories on disk to tiebreak. splitter = ArgSplitter(known_scope_infos, tmp_path.as_posix()) for d in directories_vs_goals: (tmp_path / d).mkdir() assert splitter.likely_a_spec(d) is True
def test_is_spec(self) -> None: unambiguous_specs = [ "a/b/c", "a/b/c/", "a/b:c", "a/b/c.txt", ":c", "::", "a/", "./a.txt", ".", "*", "a/b/*.txt", "a/b/test*", "a/**/*", "!", "!a/b", "!a/b.txt", "a/b.txt:tgt", "a/b.txt:../tgt", "!a/b.txt:tgt", ] directories_vs_goals = ["foo", "a_b_c"] # TODO: Once we properly ban scopes with dots in them, we can stop testing this case. files_vs_dotted_scopes = ["cache.java", "cache.tmp.java"] ambiguous_specs = [*directories_vs_goals, *files_vs_dotted_scopes] # With no files/directories on disk to tiebreak. splitter = ArgSplitter(ArgSplitterTest._known_scope_infos, buildroot=os.getcwd()) for spec in ambiguous_specs: assert splitter.likely_a_spec(spec) is False for s in unambiguous_specs: assert splitter.likely_a_spec(s) is True # With files/directories on disk to tiebreak. with temporary_dir() as tmpdir: splitter = ArgSplitter(ArgSplitterTest._known_scope_infos, tmpdir) for directory in directories_vs_goals: Path(tmpdir, directory).mkdir() for f in files_vs_dotted_scopes: Path(tmpdir, f).touch() for spec in ambiguous_specs: assert splitter.likely_a_spec(spec) is True
def test_is_spec(self) -> None: unambiguous_specs = [ "a/b/c", "a/b/c/", "a/b:c", "a/b/c.txt", ":c", "::", "a/", "./a.txt", ".", "*", "a/b/*.txt", "a/b/test*", "a/**/*", "!", "!/a/b", "!/a/b.txt", ] directories_vs_goals = ["foo", "a_b_c"] files_vs_subscopes = ["cache.java", "cache.tmp.java"] ambiguous_specs = [*directories_vs_goals, *files_vs_subscopes] # With no files/directories on disk to tiebreak. splitter = ArgSplitter(ArgSplitterTest._known_scope_infos, buildroot=os.getcwd()) for spec in ambiguous_specs: assert splitter.likely_a_spec(spec) is False for s in unambiguous_specs: assert splitter.likely_a_spec(s) is True # With files/directories on disk to tiebreak. with temporary_dir() as tmpdir: splitter = ArgSplitter(ArgSplitterTest._known_scope_infos, tmpdir) for dir in directories_vs_goals: Path(tmpdir, dir).mkdir() for f in files_vs_subscopes: Path(tmpdir, f).touch() for spec in ambiguous_specs: assert splitter.likely_a_spec(spec) is True
def assert_valid_split( splitter: ArgSplitter, args_str: str, *, expected_goals: list[str], expected_scope_to_flags: dict[str, list[str]], expected_specs: list[str], expected_passthru: list[str] | None = None, expected_is_help: bool = False, expected_help_advanced: bool = False, expected_help_all: bool = False, ) -> None: expected_passthru = expected_passthru or [] args = shlex.split(args_str) split_args = splitter.split_args(args) assert expected_goals == split_args.goals assert expected_scope_to_flags == split_args.scope_to_flags assert expected_specs == split_args.specs assert expected_passthru == split_args.passthru assert expected_is_help == (splitter.help_request is not None) assert expected_help_advanced == (isinstance( splitter.help_request, ThingHelp) and splitter.help_request.advanced) assert expected_help_all == isinstance(splitter.help_request, AllHelp)
def _split_no_goal(self, args_str): splitter = ArgSplitter(ArgSplitterTest._known_scope_infos) splitter.split_args(shlex.split(args_str)) self.assertTrue(isinstance(splitter.help_request, NoGoalHelp))
def test_no_goal_detection(self) -> None: splitter = ArgSplitter(ArgSplitterTest._known_scope_infos, buildroot=os.getcwd()) splitter.split_args(shlex.split("./pants foo/bar:baz")) self.assertTrue(isinstance(splitter.help_request, NoGoalHelp))
def assert_version_request(args_str: str) -> None: splitter = ArgSplitter(ArgSplitterTest._known_scope_infos, buildroot=os.getcwd()) splitter.split_args(shlex.split(args_str)) self.assertTrue(isinstance(splitter.help_request, VersionHelp))
def _split_version_request(self, args_str): splitter = ArgSplitter(ArgSplitterTest._known_scope_infos) splitter.split_args(shlex.split(args_str)) self.assertTrue(isinstance(splitter.help_request, VersionHelp))
def _split_version(self, args_str): splitter = ArgSplitter(ArgSplitterTest._known_scope_infos) args = shlex.split(args_str) splitter.split_args(args) self.assertTrue(splitter.help_request is not None and splitter.help_request.version)
def assert_not_spec(arg: str) -> None: assert ArgSplitter.likely_a_spec(arg) is False
def test_no_goal_detection(extra_args: str, splitter: ArgSplitter) -> None: splitter.split_args(shlex.split(f"./pants {extra_args}")) assert isinstance(splitter.help_request, NoGoalHelp)
def assert_spec(arg: str) -> None: assert ArgSplitter.spec(arg) is True
def _split_unknown_goal(self, args_str, unknown_goals): splitter = ArgSplitter(ArgSplitterTest._known_scope_infos) splitter.split_args(shlex.split(args_str)) self.assertTrue(isinstance(splitter.help_request, UnknownGoalHelp)) self.assertSetEqual(set(unknown_goals), set(splitter.help_request.unknown_goals))
def _error_split(self, args_str): parser = ArgSplitter(ArgSplitterTest._known_scopes) args = shlex.split(str(args_str)) with pytest.raises(ArgSplitterError): parser.split_args(args)
def assert_unknown_goal(splitter: ArgSplitter, args_str: str, unknown_goals: list[str]) -> None: splitter.split_args(shlex.split(args_str)) assert isinstance(splitter.help_request, UnknownGoalHelp) assert set(unknown_goals) == set(splitter.help_request.unknown_goals)