Пример #1
0
    def get_option_scope_help_info(self, description: str, parser: Parser, is_goal: bool):
        """Returns an OptionScopeHelpInfo for the options parsed by the given parser."""

        basic_options = []
        advanced_options = []
        deprecated_options = []
        for args, kwargs in parser.option_registrations_iter():
            history = parser.history(kwargs["dest"])
            ohi = self.get_option_help_info(args, kwargs)
            ohi = dataclasses.replace(ohi, value_history=history)
            if ohi.deprecation_active:
                deprecated_options.append(ohi)
            elif kwargs.get("advanced") or (
                kwargs.get("recursive") and not kwargs.get("recursive_root")
            ):
                # In order to keep the regular help output uncluttered, we treat recursive
                # options as advanced.  The concept of recursive options is not widely used
                # and not clear to the end user, so it's best not to expose it as a concept.
                advanced_options.append(ohi)
            else:
                basic_options.append(ohi)

        return OptionScopeHelpInfo(
            scope=self._scope,
            description=description,
            is_goal=is_goal,
            basic=tuple(basic_options),
            advanced=tuple(advanced_options),
            deprecated=tuple(deprecated_options),
        )
Пример #2
0
    def get_option_scope_help_info(
        self,
        description: str,
        parser: Parser,
        is_goal: bool,
        provider: str = "",
        deprecated_scope: Optional[str] = None,
    ) -> OptionScopeHelpInfo:
        """Returns an OptionScopeHelpInfo for the options parsed by the given parser."""

        basic_options = []
        advanced_options = []
        deprecated_options = []
        for args, kwargs in parser.option_registrations_iter():
            history = parser.history(kwargs["dest"])
            ohi = self.get_option_help_info(args, kwargs)
            ohi = dataclasses.replace(ohi, value_history=history)
            if ohi.deprecation_active:
                deprecated_options.append(ohi)
            elif kwargs.get("advanced"):
                advanced_options.append(ohi)
            else:
                basic_options.append(ohi)

        return OptionScopeHelpInfo(
            scope=self._scope,
            description=description,
            provider=provider,
            is_goal=is_goal,
            deprecated_scope=deprecated_scope,
            basic=tuple(basic_options),
            advanced=tuple(advanced_options),
            deprecated=tuple(deprecated_options),
        )
 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)
Пример #4
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)
Пример #5
0
 def from_dict(cls, alias: str, d: dict[str, Any]) -> DockerRegistryOptions:
     return cls(
         alias=alias,
         address=d["address"],
         default=Parser.ensure_bool(d.get("default", alias == "default")),
         skip_push=Parser.ensure_bool(
             d.get("skip_push", DockerRegistryOptions.skip_push)),
         extra_image_tags=tuple(
             d.get("extra_image_tags",
                   DockerRegistryOptions.extra_image_tags)),
     )
Пример #6
0
    def do_test(kwargs, expected_basic=False, expected_advanced=False):
        def exp_to_len(exp):
            return int(exp)  # True -> 1, False -> 0.

        parser = Parser(
            env={},
            config=Config.load([]),
            scope_info=GlobalOptions.get_scope_info(),
        )
        parser.register("--foo", **kwargs)
        oshi = HelpInfoExtracter("").get_option_scope_help_info(
            "", parser, False)
        assert exp_to_len(expected_basic) == len(oshi.basic)
        assert exp_to_len(expected_advanced) == len(oshi.advanced)
Пример #7
0
 def do_test(args, kwargs, expected_default_str):
     # 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=GlobalOptions.get_scope_info(),
     )
     parser.register(*args, **kwargs)
     oshi = HelpInfoExtracter(parser.scope).get_option_scope_help_info(
         "description", parser, False)
     assert oshi.description == "description"
     assert len(oshi.basic) == 1
     ohi = oshi.basic[0]
     assert to_help_str(ohi.default) == expected_default_str
Пример #8
0
def gen_tasks_options_reference_data():
  """Generate the template data for the options reference rst doc."""
  goal_dict = {}
  goal_names = []
  for goal in Goal.all():
    tasks = []
    for task_name in goal.ordered_task_names():
      task_type = goal.task_type_by_name(task_name)
      doc_rst = indent_docstring_by_n(task_type.__doc__ or '', 2)
      doc_html = rst_to_html(dedent_docstring(task_type.__doc__))
      option_parser = Parser(env={}, config={}, scope='', help_request=None, parent_parser=None)
      def register(*args, **kwargs):
        option_parser.register(*args, **kwargs)
      register.bootstrap = bootstrap_option_values()
      task_type.register_options(register)
      argparser = option_parser._help_argparser
      scope = Goal.scope(goal.name, task_name)
      # task_type may actually be a synthetic subclass of the authored class from the source code.
      # We want to display the authored class's name in the docs (but note that we must use the
      # subclass for registering options above)
      for authored_task_type in task_type.mro():
        if authored_task_type.__module__ != 'abc':
          break
      impl = '{0}.{1}'.format(authored_task_type.__module__, authored_task_type.__name__)
      tasks.append(TemplateData(
          impl=impl,
          doc_html=doc_html,
          doc_rst=doc_rst,
          ogroup=oref_template_data_from_options(scope, argparser)))
    goal_dict[goal.name] = TemplateData(goal=goal, tasks=tasks)
    goal_names.append(goal.name)

  goals = [goal_dict[name] for name in sorted(goal_names, key=lambda x: x.lower())]
  return goals
Пример #9
0
 def capture_the_flags(*args, **kwargs):
   for flag in Parser.expand_flags(*args, **kwargs):
     flags.add(flag.name)
     if len(flag.name) == 2:
       short_flags.add(flag.name)
     if flag.inverse_name:
       flags.add(flag.inverse_name)
Пример #10
0
 def capture_the_flags(*args, **kwargs):
   for flag in Parser.expand_flags(*args, **kwargs):
     flags.add(flag.name)
     if len(flag.name) == 2:
       short_flags.add(flag.name)
     if flag.inverse_name:
       flags.add(flag.inverse_name)
Пример #11
0
    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,
        )
Пример #12
0
 def _make_parse_args_request(
         self, flags_in_scope,
         namespace: OptionValueContainerBuilder) -> Parser.ParseArgsRequest:
     return Parser.ParseArgsRequest(
         flags_in_scope=flags_in_scope,
         namespace=namespace,
         passthrough_args=self._passthru,
     )
Пример #13
0
def gen_glopts_reference_data():
  option_parser = Parser(env={}, config={}, scope='', help_request=None, parent_parser=None)
  def register(*args, **kwargs):
    option_parser.register(*args, **kwargs)
  register.bootstrap = bootstrap_option_values()
  register_bootstrap_options(register, buildroot='<buildroot>')
  register_global_options(register)
  argparser = option_parser._help_argparser
  return oref_template_data_from_options(Options.GLOBAL_SCOPE, argparser)
Пример #14
0
 def __init__(self, env, config, all_scopes):
     # Sorting ensures that ancestors precede descendants.
     all_scopes = sorted(set(list(all_scopes) + [GLOBAL_SCOPE]))
     self._parser_by_scope = {}
     for scope in all_scopes:
         parent_parser = (None if scope == GLOBAL_SCOPE else
                          self._parser_by_scope[scope.rpartition('.')[0]])
         self._parser_by_scope[scope] = Parser(env, config, scope,
                                               parent_parser)
Пример #15
0
 def __init__(self, env, config, scope_infos):
   # Sorting ensures that ancestors precede descendants.
   scope_infos = sorted(set(list(scope_infos)), key=lambda si: si.scope)
   self._parser_by_scope = {}
   for scope_info in scope_infos:
     scope = scope_info.scope
     parent_parser = (None if scope == GLOBAL_SCOPE else
                      self._parser_by_scope[scope.rpartition('.')[0]])
     self._parser_by_scope[scope] = Parser(env, config, scope_info, parent_parser)
Пример #16
0
 def _make_parse_args_request(
         self, flags_in_scope,
         namespace: OptionValueContainer) -> Parser.ParseArgsRequest:
     return Parser.ParseArgsRequest(
         flags_in_scope=flags_in_scope,
         namespace=namespace,
         get_all_scoped_flag_names=lambda: self.
         _all_scoped_flag_names_for_fuzzy_matching,
         passthrough_args=self._passthru,
     )
Пример #17
0
 def _make_parse_args_request(self, flags_in_scope, namespace):
     levenshtein_max_distance = (
         self._bootstrap_option_values.option_name_check_distance
         if self._bootstrap_option_values else 0)
     return Parser.ParseArgsRequest(
         flags_in_scope=flags_in_scope,
         namespace=namespace,
         get_all_scoped_flag_names=lambda: self.
         _all_scoped_flag_names_for_fuzzy_matching,
         levenshtein_max_distance=levenshtein_max_distance,
     )
Пример #18
0
 def __init__(
     self,
     env: Mapping[str, str],
     config: Config,
     scope_infos: Iterable[ScopeInfo],
 ) -> None:
     # Sorting ensures that ancestors precede descendants.
     scope_infos = sorted(set(list(scope_infos)), key=lambda si: si.scope)
     self._parser_by_scope: Dict[str, Parser] = {}
     for scope_info in scope_infos:
         scope = scope_info.scope
         parent_parser = (None if scope == GLOBAL_SCOPE else
                          self._parser_by_scope[enclosing_scope(scope)])
         self._parser_by_scope[scope] = Parser(env, config, scope_info,
                                               parent_parser)
Пример #19
0
 def parse(cls, value: bool | str) -> bool:
     try:
         return Parser.ensure_bool(value)
     except BooleanConversionError:
         enum_value = cls(value)
         bool_value = enum_value is not cls.NEVER
         deprecated_conditional(
             lambda: True,
             removal_version="2.6.0.dev0",
             entity_description=
             "python-setup resolve_all_constraints non boolean values",
             hint_message=
             f"Instead of {enum_value.value!r} use {bool_value!r}.",
         )
         return bool_value
Пример #20
0
 def _format_for_global_scope(show_advanced, show_deprecated, args, kwargs):
     parser = Parser(
         env={},
         config=Config.load([]),
         scope_info=GlobalOptions.get_scope_info(),
         parent_parser=None,
     )
     parser.register(*args, **kwargs)
     # Force a parse to generate the derivation history.
     parser.parse_args(Parser.ParseArgsRequest((), OptionValueContainerBuilder(), [], False))
     oshi = HelpInfoExtracter("").get_option_scope_help_info("", parser, False)
     return HelpFormatter(
         show_advanced=show_advanced, show_deprecated=show_deprecated, color=False
     ).format_options(oshi)
Пример #21
0
    def register(*args, **kwargs):
        _, option_dest = Parser.parse_name_and_dest(*args, **kwargs)

        default = kwargs.get("default")
        if default is None:
            if kwargs.get("type") == bool:
                default = False
            if kwargs.get("type") == list:
                default = []
        defaults[option_dest] = RankedValue(Rank.HARDCODED, default)

        fingerprint = kwargs.get("fingerprint", False)
        if fingerprint:
            if is_list_option(kwargs):
                val_type = kwargs.get("member_type", str)
            else:
                val_type = kwargs.get("type", str)
            fingerprintables[option_dest] = val_type
Пример #22
0
  def register(*args, **kwargs):
    option_name = Parser.parse_dest(*args, **kwargs)

    default = kwargs.get(b'default')
    if default is None:
      if kwargs.get(b'type') == bool:
        default = False
      if kwargs.get(b'type') == list:
        default = []
    defaults[option_name] = RankedValue(RankedValue.HARDCODED, default)

    fingerprint = kwargs.get(b'fingerprint', False)
    if fingerprint:
      if is_list_option(kwargs):
        val_type = kwargs.get(b'member_type', str)
      else:
        val_type = kwargs.get(b'type', str)
      fingerprintables[option_name] = val_type
Пример #23
0
    def register(*args, **kwargs):
        option_name = Parser.parse_dest(*args, **kwargs)

        default = kwargs.get(b'default')
        if default is None:
            if kwargs.get(b'type') == bool:
                default = False
            if kwargs.get(b'type') == list:
                default = []
        defaults[option_name] = RankedValue(RankedValue.HARDCODED, default)

        fingerprint = kwargs.get(b'fingerprint', False)
        if fingerprint:
            if is_list_option(kwargs):
                val_type = kwargs.get(b'member_type', str)
            else:
                val_type = kwargs.get(b'type', str)
            fingerprintables[option_name] = val_type
Пример #24
0
    def _make_parse_args_request(
        self,
        flags_in_scope,
        namespace: OptionValueContainer,
        include_passive_options: bool = False,
    ) -> Parser.ParseArgsRequest:
        levenshtein_max_distance = (
            self._bootstrap_option_values.option_name_check_distance
            if self._bootstrap_option_values else 0)

        return Parser.ParseArgsRequest(
            flags_in_scope=flags_in_scope,
            namespace=namespace,
            get_all_scoped_flag_names=lambda: self.
            _all_scoped_flag_names_for_fuzzy_matching,
            levenshtein_max_distance=levenshtein_max_distance,
            passthrough_args=self._passthru,
            include_passive_options=include_passive_options,
        )
Пример #25
0
def parser() -> Parser:
    return Parser(
        env={},
        config=Config.load([]),
        scope_info=GlobalOptions.get_scope_info(),
    )
Пример #26
0
    def get_option_help_info(self, args, kwargs):
        """Returns an OptionHelpInfo for the option registered with the given (args, kwargs)."""
        display_args = []
        scoped_cmd_line_args = []
        unscoped_cmd_line_args = []

        for arg in args:
            is_short_arg = len(arg) == 2
            unscoped_cmd_line_args.append(arg)
            if self._scope_prefix:
                scoped_arg = f"--{self._scope_prefix}-{arg.lstrip('-')}"
            else:
                scoped_arg = arg
            scoped_cmd_line_args.append(scoped_arg)

            if Parser.is_bool(kwargs):
                if is_short_arg:
                    display_args.append(scoped_arg)
                else:
                    unscoped_cmd_line_args.append(f"--no-{arg[2:]}")
                    sa_2 = scoped_arg[2:]
                    scoped_cmd_line_args.append(f"--no-{sa_2}")
                    display_args.append(f"--[no-]{sa_2}")
            else:
                metavar = self.compute_metavar(kwargs)
                display_args.append(f"{scoped_arg}={metavar}")
                if kwargs.get("passthrough"):
                    type_str = self.stringify_type(kwargs.get("member_type", str))
                    display_args.append(f"... -- [{type_str} [{type_str} [...]]]")

        typ = kwargs.get("type", str)
        default = self.compute_default(**kwargs)
        help_msg = kwargs.get("help", "No help available.")
        deprecation_start_version = kwargs.get("deprecation_start_version")
        removal_version = kwargs.get("removal_version")
        deprecation_active = removal_version is not None and deprecated.is_deprecation_active(
            deprecation_start_version
        )
        deprecated_message = None
        if removal_version:
            deprecated_tense = deprecated.get_deprecated_tense(removal_version)
            message_start = (
                "Deprecated"
                if deprecation_active
                else f"Upcoming deprecation in version: {deprecation_start_version}"
            )
            deprecated_message = (
                f"{message_start}, {deprecated_tense} removed in version: {removal_version}."
            )
        removal_hint = kwargs.get("removal_hint")
        choices = self.compute_choices(kwargs)

        dest = Parser.parse_dest(*args, **kwargs)
        # Global options have three env var variants. The last one is the most human-friendly.
        env_var = Parser.get_env_var_names(self._scope, dest)[-1]

        ret = OptionHelpInfo(
            display_args=tuple(display_args),
            comma_separated_display_args=", ".join(display_args),
            scoped_cmd_line_args=tuple(scoped_cmd_line_args),
            unscoped_cmd_line_args=tuple(unscoped_cmd_line_args),
            env_var=env_var,
            config_key=dest,
            typ=typ,
            default=default,
            help=help_msg,
            deprecation_active=deprecation_active,
            deprecated_message=deprecated_message,
            removal_version=removal_version,
            removal_hint=removal_hint,
            choices=choices,
            comma_separated_choices=None if choices is None else ", ".join(choices),
            value_history=None,
        )
        return ret
 def recording_register(*args, **kwargs):
     _, dest = Parser.parse_name_and_dest(*args, **kwargs)
     option_names.append(dest)
     register(*args, **kwargs)
Пример #28
0
 def from_dict(cls, alias: str, d: dict[str, Any]) -> DockerRegistryOptions:
     return cls(
         alias=alias,
         address=d["address"],
         default=Parser.ensure_bool(d.get("default", alias == "default")),
     )
Пример #29
0
 def from_dict(cls, alias: str, d: dict[str, Any]) -> HelmRegistry:
     return cls(
         alias=alias,
         address=cast(str, d["address"]).rstrip("/"),
         default=Parser.ensure_bool(d.get("default", alias == "default")),
     )
Пример #30
0
 def recording_register(*args, **kwargs):
   option_names.append(Parser.parse_dest(*args, **kwargs))
   register(*args, **kwargs)
Пример #31
0
 def recording_register(*args, **kwargs):
     option_names.append(Parser.parse_dest(*args, **kwargs))
     register(*args, **kwargs)