示例#1
0
  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)
示例#2
0
  def test_env_type_int(self):
    options = Options.create(env={'PANTS_FOO_BAR': "['123','456']"},
                             config=self._create_config({}),
                             known_scope_infos=OptionsTest._known_scope_infos,
                             args=shlex.split('./pants'),
                             option_tracker=OptionTracker())
    options.register(GLOBAL_SCOPE, '--foo-bar', type=list, member_type=int)
    self.assertEqual([123, 456], options.for_global_scope().foo_bar)

    options = Options.create(env={'PANTS_FOO_BAR': '123'},
                             config=self._create_config({}),
                             known_scope_infos=OptionsTest._known_scope_infos,
                             args=shlex.split('./pants'),
                             option_tracker=OptionTracker())
    options.register(GLOBAL_SCOPE, '--foo-bar', type=int)
    self.assertEqual(123, options.for_global_scope().foo_bar)
示例#3
0
 def __init__(self, env=None, args=None):
     self._env = env if env is not None else os.environ.copy()
     self._post_bootstrap_config = None  # Will be set later.
     self._args = sys.argv if args is None else args
     self._bootstrap_options = None  # We memoize the bootstrap options here.
     self._full_options = {}  # We memoize the full options here.
     self._option_tracker = OptionTracker()
示例#4
0
    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)

        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."
            )

        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,
            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,
        )
示例#5
0
 def test_double_registration(self):
   options = Options.create(env={},
                            config=self._create_config({}),
                            known_scope_infos=OptionsTest._known_scope_infos,
                            args=shlex.split('./pants'),
                            option_tracker=OptionTracker())
   options.register(GLOBAL_SCOPE, '--foo-bar')
   self.assertRaises(OptionAlreadyRegistered, lambda: options.register(GLOBAL_SCOPE, '--foo-bar'))
示例#6
0
 def test_frozen_registration(self):
     options = Options.create(args=[],
                              env={},
                              config=self._create_config({}),
                              known_scope_infos=[task('foo')],
                              option_tracker=OptionTracker())
     options.register('foo', '--arg1')
     with self.assertRaises(FrozenRegistration):
         options.register(GLOBAL_SCOPE, '--arg2')
示例#7
0
 def assertError(expected_error, *args, **kwargs):
     with self.assertRaises(expected_error):
         options = Options.create(args=[],
                                  env={},
                                  config=self._create_config({}),
                                  known_scope_infos=[],
                                  option_tracker=OptionTracker())
         options.register(GLOBAL_SCOPE, *args, **kwargs)
         options.for_global_scope()
示例#8
0
 def _parse(self, args_str, env=None, config=None, bootstrap_option_values=None):
   args = shlex.split(str(args_str))
   options = Options.create(env=env or {},
                            config=self._create_config(config or {}),
                            known_scope_infos=OptionsTest._known_scope_infos,
                            args=args,
                            bootstrap_option_values=bootstrap_option_values,
                            option_tracker=OptionTracker())
   self._register(options)
   return options
示例#9
0
 def test_deprecated_option_past_removal(self):
   with self.assertRaises(PastRemovalVersionError):
     options = Options.create(env={},
                              config=self._create_config({}),
                              known_scope_infos=OptionsTest._known_scope_infos,
                              args='./pants',
                              option_tracker=OptionTracker())
     options.register(GLOBAL_SCOPE, '--too-old-option', deprecated_version='0.0.24',
                      deprecated_hint='The semver for this option has already passed.')
     options.for_global_scope()
示例#10
0
 def _parse_type_int(self, args_str, env=None, config=None, bootstrap_option_values=None,
                     action=None):
   args = shlex.split(str(args_str))
   options = Options.create(env=env or {},
                            config=self._create_config(config or {}),
                            known_scope_infos=OptionsTest._known_scope_infos,
                            args=args,
                            bootstrap_option_values=bootstrap_option_values,
                            option_tracker=OptionTracker())
   options.register(GLOBAL_SCOPE, '--config-override', action=action, type=int)
   return options
示例#11
0
 def do_test(args, kwargs, expected_default):
   # Defaults are computed in the parser and added into the kwargs, so we
   # must jump through this hoop in this test.
   parser = Parser(env={}, config=Config.load([]),
                   scope_info=GlobalOptionsRegistrar.get_scope_info(),
                   parent_parser=None, option_tracker=OptionTracker())
   parser.register(*args, **kwargs)
   oshi = HelpInfoExtracter.get_option_scope_help_info_from_parser(parser).basic
   self.assertEquals(1, len(oshi))
   ohi = oshi[0]
   self.assertEqual(expected_default, ohi.default)
示例#12
0
 def test_no_recursive_subsystem_options(self):
     options = Options.create(env={},
                              config=self._create_config({}),
                              known_scope_infos=[subsystem('foo')],
                              args='./pants',
                              option_tracker=OptionTracker())
     # All subsystem options are implicitly recursive (a subscope of subsystem scope represents
     # a separate instance of the subsystem, so it needs all the options).
     # We disallow explicit specification of recursive (even if set to True), to avoid confusion.
     with self.assertRaises(RecursiveSubsystemOption):
         options.register('foo', '--bar', recursive=False)
         options.for_scope('foo')
     with self.assertRaises(RecursiveSubsystemOption):
         options.register('foo', '--baz', recursive=True)
         options.for_scope('foo')
示例#13
0
 def test_shadowing(self):
   options = Options.create(env={},
                            config=self._create_config({}),
                            known_scope_infos=[task('bar'), intermediate('foo'), task('foo.bar')],
                            args='./pants',
                            option_tracker=OptionTracker())
   options.register('', '--opt1')
   options.register('foo', '-o', '--opt2')
   with self.assertRaises(Shadowing):
     options.register('bar', '--opt1')
   with self.assertRaises(Shadowing):
     options.register('foo.bar', '--opt1')
   with self.assertRaises(Shadowing):
     options.register('foo.bar', '--opt2')
   with self.assertRaises(Shadowing):
     options.register('foo.bar', '--opt1', '--opt3')
   with self.assertRaises(Shadowing):
     options.register('foo.bar', '--opt3', '--opt2')