コード例 #1
0
def _GetArgsAndFlagsString(spec, metadata):
    """The args and flags string for showing how to call a function.

  If positional arguments are accepted, the args will be shown as positional.
  E.g. "ARG1 ARG2 [--flag=FLAG]"

  If positional arguments are disallowed, the args will be shown with flags
  syntax.
  E.g. "--arg1=ARG1 [--flag=FLAG]"

  Args:
    spec: The full arg spec for the component to construct the args and flags
      string for.
    metadata: Metadata for the component, including whether it accepts
      positional arguments.

  Returns:
    The constructed args and flags string.
  """
    args_with_no_defaults = spec.args[:len(spec.args) - len(spec.defaults)]
    args_with_defaults = spec.args[len(spec.args) - len(spec.defaults):]

    # Check if positional args are allowed. If not, require flag syntax for args.
    accepts_positional_args = metadata.get(decorators.ACCEPTS_POSITIONAL_ARGS)

    arg_and_flag_strings = []
    if args_with_no_defaults:
        if accepts_positional_args:
            arg_strings = [
                formatting.Underline(arg.upper())
                for arg in args_with_no_defaults
            ]
        else:
            arg_strings = [
                '--{arg}={arg_upper}'.format(arg=arg,
                                             arg_upper=formatting.Underline(
                                                 arg.upper()))
                for arg in args_with_no_defaults
            ]
        arg_and_flag_strings.extend(arg_strings)

    # If there are any arguments that are treated as flags:
    if args_with_defaults or spec.kwonlyargs or spec.varkw:
        arg_and_flag_strings.append('<flags>')

    if spec.varargs:
        varargs_string = '[{varargs}]...'.format(
            varargs=formatting.Underline(spec.varargs.upper()))
        arg_and_flag_strings.append(varargs_string)

    return ' '.join(arg_and_flag_strings)
コード例 #2
0
def _NewChoicesSection(name, choices):
    return _CreateItem(
        "{name} is one of the following:".format(
            name=formatting.Bold(formatting.Underline(name))),
        "\n" + "\n\n".join(choices),
        indent=1,
    )
コード例 #3
0
def _CreateFlagItem(flag,
                    docstring_info,
                    spec,
                    required=False,
                    flag_string=None):
    """Returns a string describing a flag using docstring and FullArgSpec info.

    Args:
      flag: The name of the flag.
      docstring_info: A docstrings.DocstringInfo namedtuple with information about
        the containing function's docstring.
      spec: An instance of fire.inspectutils.FullArgSpec, containing type and
       default information about the arguments to a callable.
      required: Whether the flag is required.
      flag_string: If provided, use this string for the flag, rather than
        constructing one from the flag name.
    Returns:
      A string to be used in constructing the help screen for the function.
    """
    # pylint: disable=g-bad-todo
    # TODO(MichaelCG8): Get type and default information from docstrings if it is
    # not available in FullArgSpec. This will require updating
    # fire.docstrings.parser().

    # The help string is indented, so calculate the maximum permitted length
    # before indentation to avoid exceeding the maximum line length.
    max_str_length = LINE_LENGTH - SECTION_INDENTATION - SUBSECTION_INDENTATION

    description = _GetArgDescription(flag, docstring_info)

    if not flag_string:
        flag_string_template = "--{flag_name}={flag_name_upper}"
        flag_string = flag_string_template.format(
            flag_name=flag, flag_name_upper=formatting.Underline(flag.upper()))
    if required:
        flag_string += " (required)"

    arg_type = _GetArgType(flag, spec)
    arg_default = _GetArgDefault(flag, spec)

    # We need to handle the case where there is a default of None, but otherwise
    # the argument has another type.
    if arg_default == "None":
        arg_type = "Optional[{}]".format(arg_type)

    arg_type = "Type: {}".format(arg_type) if arg_type else ""
    available_space = max_str_length - len(arg_type)
    arg_type = formatting.EllipsisTruncate(arg_type, available_space,
                                           max_str_length)

    arg_default = "Default: {}".format(arg_default) if arg_default else ""
    available_space = max_str_length - len(arg_default)
    arg_default = formatting.EllipsisTruncate(arg_default, available_space,
                                              max_str_length)

    description = "\n".join(part
                            for part in (arg_type, arg_default, description)
                            if part)

    return _CreateItem(flag_string, description, indent=SUBSECTION_INDENTATION)
コード例 #4
0
 def testHelpTextUnderlineFlag(self):
     component = tc.WithDefaults().triple
     t = trace.FireTrace(component, name="triple")
     help_screen = helptext.HelpText(component, t)
     self.assertIn(formatting.Bold("NAME") + "\n    triple", help_screen)
     self.assertIn(formatting.Bold("SYNOPSIS") + "\n    triple <flags>", help_screen)
     self.assertIn(
         formatting.Bold("FLAGS") + "\n    --" + formatting.Underline("count"),
         help_screen,
     )
コード例 #5
0
 def testHelpTextUnderlineFlag(self):
     component = tc.WithDefaults().triple
     t = trace.FireTrace(component, name='triple')
     help_screen = helptext.HelpText(component, t)
     self.assertIn(formatting.Bold('NAME') + '\n    triple', help_screen)
     self.assertIn(
         formatting.Bold('SYNOPSIS') + '\n    triple <flags>', help_screen)
     self.assertIn(
         formatting.Bold('FLAGS') + '\n    --' +
         formatting.Underline('count'), help_screen)
コード例 #6
0
ファイル: helptext.py プロジェクト: MichaelCG8/python-fire
def _CreateFlagItem(flag, docstring_info, spec, required=False):
    """Returns a string describing a flag using docstring and FullArgSpec info.

  Args:
    flag: The name of the flag.
    docstring_info: A docstrings.DocstringInfo namedtuple with information about
      the containing function's docstring.
    spec: An instance of fire.inspectutils.FullArgSpec, containing type and
     default information about the arguments to a callable.
    required: Whether the flag is required.
  Returns:
    A string to be used in constructing the help screen for the function.
  """
    # TODO(MichaelCG8): In future it would be good to be able to get type and
    #  default information out of docstrings if it is not available in
    #  FullArgSpec. This would require updating fire.docstrings.parser() and a
    #  decision would need to be made about which takes priority if the docstrings
    #  and function definition disagree.

    # The help string is indented, so calculate the maximum permitted length
    # before indentation to avoid exceeding the maximum line length.
    max_str_length = LINE_LENGTH - SECTION_INDENTATION - SUBSECTION_INDENTATION

    description = _GetArgDescription(flag, docstring_info)

    flag_string_template = '--{flag_name}={flag_name_upper}'
    flag_string = flag_string_template.format(
        flag_name=flag, flag_name_upper=formatting.Underline(flag.upper()))
    if required:
        flag_string += ' (required)'

    arg_type = _GetArgType(flag, spec)
    arg_default = _GetArgDefault(flag, spec)

    # We need to handle the case where there is a default
    # of None, but otherwise the argument has another type.
    if arg_default == 'None':
        arg_type = 'Optional[{}]'.format(arg_type)

    arg_type = 'Type: {}'.format(arg_type) if arg_type else ''
    available_space = max_str_length - len(arg_type)
    arg_type = \
      formatting.EllipsisTruncate(arg_type, available_space, max_str_length)

    arg_default = 'Default: {}'.format(arg_default) if arg_default else ''
    available_space = max_str_length - len(arg_default)
    arg_default = \
      formatting.EllipsisTruncate(arg_default, available_space, max_str_length)

    description = '\n'.join(part
                            for part in (arg_type, arg_default, description)
                            if part)

    return _CreateItem(flag_string, description, indent=SUBSECTION_INDENTATION)
コード例 #7
0
 def testHelpTextUnderlineFlag(self):
     component = tc.WithDefaults().triple
     info = inspectutils.Info(component)
     t = trace.FireTrace(component, name='triple')
     help_screen = helptext.HelpText(component, info, t)
     self.assertIn(formatting.Bold('NAME') + '\n    triple', help_screen)
     self.assertIn(
         formatting.Bold('SYNOPSIS') + '\n    triple [--count=COUNT]',
         help_screen)
     self.assertIn(
         formatting.Bold('FLAGS') + '\n    --' +
         formatting.Underline('count'), help_screen)
コード例 #8
0
def _GetPossibleActionsString(actions_grouped_by_kind):
  """A help screen string listing the possible action kinds available."""
  groups, commands, values, indexes = actions_grouped_by_kind

  possible_actions = []
  if groups:
    possible_actions.append('GROUP')
  if commands:
    possible_actions.append('COMMAND')
  if values:
    possible_actions.append('VALUE')
  if indexes:
    possible_actions.append('INDEX')

  possible_actions_string = ' | '.join(
      formatting.Underline(action) for action in possible_actions)
  return possible_actions_string
コード例 #9
0
def _CreateFlagItem(flag, docstring_info, required=False):
  """Returns a string describing a flag using information from the docstring.

  Args:
    flag: The name of the flag.
    docstring_info: A docstrings.DocstringInfo namedtuple with information about
      the containing function's docstring.
    required: Whether the flag is required.
  Returns:
    A string to be used in constructing the help screen for the function.
  """
  description = _GetArgDescription(flag, docstring_info)

  flag_string_template = '--{flag_name}={flag_name_upper}'
  flag = flag_string_template.format(
      flag_name=flag,
      flag_name_upper=formatting.Underline(flag.upper()))
  if required:
    flag += ' (required)'
  return _CreateItem(flag, description, indent=4)
コード例 #10
0
ファイル: helptext.py プロジェクト: loctv/python-fire
def _CreateFlagItem(flag, docstring_info):
    """Returns a string describing a flag using information from the docstring.

  Args:
    flag: The name of the flag.
    docstring_info: A docstrings.DocstringInfo namedtuple with information about
      the containing function's docstring.
  Returns:
    A string to be used in constructing the help screen for the function.
  """
    description = None
    if docstring_info.args:
        for arg_in_docstring in docstring_info.args:
            if arg_in_docstring.name == flag:
                description = arg_in_docstring.description
                break

    flag = '--{flag}'.format(flag=formatting.Underline(flag))
    if description:
        return _CreateItem(flag, description, indent=2)
    return flag
コード例 #11
0
def _NewChoicesSection(name, choices):
  return _CreateItem(
      '{name} is one of the following:'.format(
          name=formatting.Bold(formatting.Underline(name))),
      '\n' + '\n\n'.join(choices),
      indent=1)
コード例 #12
0
 def test_underline(self):
   text = formatting.Underline('hello')
   self.assertEqual('\x1b[4mhello\x1b[0m', text)
コード例 #13
0
ファイル: helptext.py プロジェクト: loctv/python-fire
def HelpTextForObject(component, info, trace=None, verbose=False):
    """Generates help text for python objects.

  Args:
    component: Current component to generate help text for.
    info: Info containing metadata of component.
    trace: FireTrace object that leads to current component.
    verbose: Whether to display help text in verbose mode.

  Returns:
    Formatted help text for display.
  """
    current_command = GetCurrentCommand(trace)
    current_command_without_separator = GetCurrentCommand(
        trace, include_separators=False)
    docstring_info = info['docstring_info']
    command_summary = docstring_info.summary if docstring_info.summary else ''
    command_description = GetDescriptionSectionText(docstring_info.summary,
                                                    docstring_info.description)
    groups = []
    commands = []
    values = []
    members = completion._Members(component, verbose)  # pylint: disable=protected-access
    for member_name, member in members:
        if value_types.IsGroup(member):
            groups.append((member_name, member))
        if value_types.IsCommand(member):
            commands.append((member_name, member))
        if value_types.IsValue(member):
            values.append((member_name, member))

    usage_details_sections = []
    possible_actions = []
    # TODO(joejoevictor): Add global flags to here. Also, if it's a callable,
    # there will be additional flags.
    possible_flags = ''

    if groups:
        possible_actions.append('GROUP')
        usage_details_section = GroupUsageDetailsSection(groups)
        usage_details_sections.append(usage_details_section)
    if commands:
        possible_actions.append('COMMAND')
        usage_details_section = CommandUsageDetailsSection(commands)
        usage_details_sections.append(usage_details_section)
    if values:
        possible_actions.append('VALUE')
        usage_details_section = ValuesUsageDetailsSection(component, values)
        usage_details_sections.append(usage_details_section)

    possible_actions_string = ' | '.join(
        formatting.Underline(action) for action in possible_actions)

    synopsis_template = '{current_command} {possible_actions}{possible_flags}'
    synopsis_string = synopsis_template.format(
        current_command=current_command,
        possible_actions=possible_actions_string,
        possible_flags=possible_flags)

    description_sections = []
    if command_description:
        description_sections.append(('DESCRIPTION', command_description))

    name_line = '{current_command} - {command_summary}'.format(
        current_command=current_command_without_separator,
        command_summary=command_summary)
    output_sections = [
        ('NAME', name_line),
        ('SYNOPSIS', synopsis_string),
    ] + description_sections + usage_details_sections

    return '\n\n'.join(
        _CreateOutputSection(name, content)
        for name, content in output_sections)
コード例 #14
0
ファイル: helptext.py プロジェクト: loctv/python-fire
def HelpTextForFunction(component, info, trace=None, verbose=False):
    """Returns detail help text for a function component.

  Args:
    component: Current component to generate help text for.
    info: Info containing metadata of component.
    trace: FireTrace object that leads to current component.
    verbose: Whether to display help text in verbose mode.

  Returns:
    Formatted help text for display.
  """
    # TODO(joejoevictor): Implement verbose related output
    del verbose

    current_command = GetCurrentCommand(trace)
    current_command_without_separator = GetCurrentCommand(
        trace, include_separators=False)
    summary, description = GetSummaryAndDescription(info['docstring_info'])

    args_with_no_defaults, args_with_defaults, flags = GetArgsAngFlags(
        component)
    del args_with_defaults

    # Name section
    name_section_template = '{current_command}{command_summary}'
    command_summary_str = ' - ' + summary if summary else ''
    name_section = name_section_template.format(
        current_command=current_command_without_separator,
        command_summary=command_summary_str)

    # Check if positional args are allowed. If not, require flag syntax for args.
    metadata = decorators.GetMetadata(component)
    accepts_positional_args = metadata.get(decorators.ACCEPTS_POSITIONAL_ARGS)

    arg_and_flag_strings = []
    if args_with_no_defaults:
        if accepts_positional_args:
            arg_strings = [
                formatting.Underline(arg.upper())
                for arg in args_with_no_defaults
            ]
        else:
            arg_strings = [
                '--{arg}={arg_upper}'.format(arg=arg,
                                             arg_upper=formatting.Underline(
                                                 arg.upper()))
                for arg in args_with_no_defaults
            ]
        arg_and_flag_strings.extend(arg_strings)

    flag_string_template = '[--{flag_name}={flag_name_upper}]'
    if flags:
        flag_strings = [
            flag_string_template.format(flag_name=formatting.Underline(flag),
                                        flag_name_upper=flag.upper())
            for flag in flags
        ]
        arg_and_flag_strings.extend(flag_strings)
    args_and_flags = ' '.join(arg_and_flag_strings)

    # Synopsis section
    synopsis_section_template = '{current_command} {args_and_flags}'
    synopsis_section = synopsis_section_template.format(
        current_command=current_command, args_and_flags=args_and_flags)

    # Description section
    command_description = GetDescriptionSectionText(summary, description)
    description_sections = []
    if command_description:
        description_sections.append(('DESCRIPTION', command_description))

    # Positional arguments and flags section
    docstring_info = info['docstring_info']
    args_and_flags_sections = []
    notes_sections = []

    arg_items = [
        _CreateArgItem(arg, docstring_info) for arg in args_with_no_defaults
    ]
    if arg_items:
        title = 'POSITIONAL ARGUMENTS' if accepts_positional_args else 'ARGUMENTS'
        arguments_section = (title, '\n'.join(arg_items).rstrip('\n'))
        args_and_flags_sections.append(arguments_section)
        if accepts_positional_args:
            notes_sections.append(
                ('NOTES',
                 'You can also use flags syntax for POSITIONAL ARGUMENTS'))

    flag_items = [_CreateFlagItem(flag, docstring_info) for flag in flags]

    if flag_items:
        flags_section = ('FLAGS', '\n'.join(flag_items))
        args_and_flags_sections.append(flags_section)

    output_sections = [
        ('NAME', name_section),
        ('SYNOPSIS', synopsis_section),
    ] + description_sections + args_and_flags_sections + notes_sections

    return '\n\n'.join(
        _CreateOutputSection(name, content)
        for name, content in output_sections)
コード例 #15
0
def _GetPossibleActionsString(possible_actions):
  """A help screen string listing the possible action kinds available."""
  return ' | '.join(formatting.Underline(action.upper())
                    for action in possible_actions)
コード例 #16
0
ファイル: helptext.py プロジェクト: normalC/python-fire
def HelpTextForObject(component, info, trace=None, verbose=False):
  """Generates help text for python objects.

  Args:
    component: Current component to generate help text for.
    info: Info containing metadata of component.
    trace: FireTrace object that leads to current component.
    verbose: Whether to display help text in verbose mode.

  Returns:
    Formatted help text for display.
  """
  current_command = GetCurrentCommand(trace)

  docstring_info = info['docstring_info']
  command_summary = docstring_info.summary if docstring_info.summary else ''
  command_description = GetDescriptionSectionText(docstring_info.summary,
                                                  docstring_info.description)
  groups = []
  commands = []
  values = []
  members = completion._Members(component, verbose)  # pylint: disable=protected-access
  for member_name, member in members:
    if value_types.IsGroup(member):
      groups.append((member_name, member))
    if value_types.IsCommand(member):
      commands.append((member_name, member))
    if value_types.IsValue(member):
      values.append((member_name, member))

  usage_details_sections = []
  possible_actions = []
  # TODO(joejoevictor): Add global flags to here. Also, if it's a callable,
  # there will be additional flags.
  possible_flags = ''

  if groups:
    # TODO(joejoevictor): Add missing GROUPS section handling
    possible_actions.append('GROUP')
  if commands:
    possible_actions.append('COMMAND')
    command_item_strings = []
    for command_name, command in commands:
      command_info = inspectutils.Info(command)
      command_item = command_name
      if 'docstring_info' in command_info:
        command_docstring_info = command_info['docstring_info']
        if command_docstring_info and command_docstring_info.summary:
          command_item = _CreateItem(command_name,
                                     command_docstring_info.summary)

      command_item_strings.append(command_item)
    usage_details_sections.append(
        ('COMMANDS', _NewChoicesSection('COMMAND', command_item_strings)))

  if values:
    possible_actions.append('VALUE')
    value_item_strings = []
    for value_name, value in values:
      del value
      init_info = inspectutils.Info(component.__class__.__init__)
      value_item = value_name
      if 'docstring_info' in init_info:
        init_docstring_info = init_info['docstring_info']
        for arg_info in init_docstring_info.args:
          if arg_info.name == value_name:
            value_item = _CreateItem(value_name, arg_info.description)
      value_item_strings.append(value_item)
    usage_details_sections.append(
        ('VALUES', _NewChoicesSection('VALUE', value_item_strings)))

  possible_actions_string = ' | '.join(
      formatting.Underline(action) for action in possible_actions)

  synopsis_template = '{current_command} {possible_actions}{possible_flags}'
  synopsis_string = synopsis_template.format(
      current_command=current_command,
      possible_actions=possible_actions_string,
      possible_flags=possible_flags)

  description_sections = []
  if command_description:
    description_sections.append(('DESCRIPTION', command_description))

  name_line = '{current_command} - {command_summary}'.format(
      current_command=current_command,
      command_summary=command_summary)
  output_sections = [
      ('NAME', name_line),
      ('SYNOPSIS', synopsis_string),
  ] + description_sections + usage_details_sections

  return '\n\n'.join(
      _CreateOutputSection(name, content)
      for name, content in output_sections
  )
コード例 #17
0
def HelpTextForFunction(component, info, trace=None, verbose=False):
    """Returns detail help text for a function component.

  Args:
    component: Current component to generate help text for.
    info: Info containing metadata of component.
    trace: FireTrace object that leads to current component.
    verbose: Whether to display help text in verbose mode.

  Returns:
    Formatted help text for display.
  """
    # TODO(joejoevictor): Implement verbose related output
    del verbose

    current_command = GetCurrentCommand(trace)
    summary, description = GetSummaryAndDescription(info['docstring_info'])
    spec = inspectutils.GetFullArgSpec(component)
    args = spec.args

    args_with_no_defaults, args_with_defaults, flags = GetArgsAngFlags(
        component)
    del args_with_defaults

    # Name section
    name_section_template = '{current_command}{command_summary}'
    command_summary_str = ' - ' + summary if summary else ''
    name_section = name_section_template.format(
        current_command=current_command, command_summary=command_summary_str)

    args_and_flags = ''
    if args_with_no_defaults:
        items = [
            formatting.Underline(arg.upper()) for arg in args_with_no_defaults
        ]
        args_and_flags = ' '.join(items)

    synopsis_flag_template = '[--{flag_name}={flag_name_upper}]'
    if flags:
        items = [
            synopsis_flag_template.format(flag_name=formatting.Underline(flag),
                                          flag_name_upper=flag.upper())
            for flag in flags
        ]
        args_and_flags = args_and_flags + ' '.join(items)

    # Synopsis section
    synopsis_section_template = '{current_command} {args_and_flags}'
    positional_arguments = '|'.join(args)
    if positional_arguments:
        positional_arguments = ' ' + positional_arguments
    synopsis_section = synopsis_section_template.format(
        current_command=current_command, args_and_flags=args_and_flags)

    # Description section
    command_description = GetDescriptionSectionText(summary, description)
    description_sections = []
    if command_description:
        description_sections.append(('DESCRIPTION', command_description))

    # Positional arguments and flags section
    docstring_info = info['docstring_info']
    args_and_flags_sections = []
    notes_sections = []

    pos_arg_items = []
    pos_arg_items = [
        _CreatePositionalArgItem(arg, docstring_info)
        for arg in args_with_no_defaults
    ]
    if pos_arg_items:
        positional_arguments_section = ('POSITIONAL ARGUMENTS',
                                        '\n'.join(pos_arg_items).rstrip('\n'))
        args_and_flags_sections.append(positional_arguments_section)
        notes_sections.append(
            ('NOTES',
             'You could also use flags syntax for POSITIONAL ARGUMENTS'))

    flag_items = [_CreateFlagItem(flag, docstring_info) for flag in flags]

    if flag_items:
        flags_section = ('FLAGS', '\n'.join(flag_items))
        args_and_flags_sections.append(flags_section)

    output_sections = [
        ('NAME', name_section),
        ('SYNOPSIS', synopsis_section),
    ] + description_sections + args_and_flags_sections + notes_sections

    return '\n\n'.join(
        _CreateOutputSection(name, content)
        for name, content in output_sections)
コード例 #18
0
 def test_underline(self):
     text = formatting.Underline("hello")
     self.assertEqual("\x1b[4mhello\x1b[0m", text)