Ejemplo n.º 1
0
    def testUsageOutputMethod(self):
        component = tc.NoDefaults().double
        t = trace.FireTrace(component, name='NoDefaults')
        t.AddAccessedProperty(component, 'double', ['double'], None, None)
        info = inspectutils.Info(component)
        usage_output = helptext.UsageText(component,
                                          info,
                                          trace=t,
                                          verbose=True)
        expected_output = '''
    Usage: NoDefaults double COUNT

    For detailed information on this command, run:
    NoDefaults double --help
    '''
        self.assertEqual(usage_output,
                         textwrap.dedent(expected_output).lstrip('\n'))
Ejemplo n.º 2
0
    def testUsageOutput(self):
        component = tc.NoDefaults()
        t = trace.FireTrace(component, name='NoDefaults')
        info = inspectutils.Info(component)
        usage_output = helptext.UsageText(component,
                                          info,
                                          trace=t,
                                          verbose=False)
        expected_output = '''
    Usage: NoDefaults <command>
      available commands:    double | triple

    For detailed information on this command, run:
      NoDefaults --help'''

        self.assertEqual(usage_output,
                         textwrap.dedent(expected_output).lstrip('\n'))
Ejemplo n.º 3
0
def HelpString(component, trace=None, verbose=False):
    """Returns a help string for a supplied component.

  The component can be any Python class, object, function, module, etc.

  Args:
    component: The component to determine the help string for.
    trace: The Fire trace leading to this component.
    verbose: Whether to include private members in the help string.
  Returns:
    String suitable for display giving information about the component.
  """
    info = inspectutils.Info(component)
    info['usage'] = UsageString(component, trace, verbose)
    info['docstring_info'] = docstrings.parse(info['docstring'])

    return _HelpText(info, trace)
Ejemplo n.º 4
0
def HelpString(component, trace=None, verbose=False):
    """Returns a help string for a supplied component.

  The component can be any Python class, object, function, module, etc.

  Args:
    component: The component to determine the help string for.
    trace: The Fire trace leading to this component.
    verbose: Whether to include private members in the help string.
  Returns:
    String suitable for display giving information about the component.
  """
    info = inspectutils.Info(component)
    info['usage'] = UsageString(component, trace, verbose)

    fields = [
        'type_name',
        'string_form',
        'file',
        'line',
        'docstring',
        'init_docstring',
        'class_docstring',
        'call_docstring',
        'length',
        'usage',
    ]

    max_size = max(
        len(_NormalizeField(field)) + 1 for field in fields
        if field in info and info[field])
    format_string = '{{field:{max_size}s}} {{value}}'.format(max_size=max_size)

    lines = []
    for field in fields:
        value = _DisplayValue(info, field, padding=max_size + 1)
        if value:
            if lines and field == 'usage':
                lines.append('')  # Ensure a blank line before usage.

            lines.append(
                format_string.format(
                    field=_NormalizeField(field) + ':',
                    value=value,
                ))
    return '\n'.join(lines)
Ejemplo n.º 5
0
def _ValuesUsageDetailsSection(component, values):
  """Creates a section tuple for the values section of the usage details."""
  value_item_strings = []
  for value_name, value in values.GetItems():
    del value
    init_info = inspectutils.Info(component.__class__.__init__)
    value_item = None
    if 'docstring_info' in init_info:
      init_docstring_info = init_info['docstring_info']
      if init_docstring_info.args:
        for arg_info in init_docstring_info.args:
          if arg_info.name == value_name:
            value_item = _CreateItem(value_name, arg_info.description)
    if value_item is None:
      value_item = str(value_name)
    value_item_strings.append(value_item)
  return ('VALUES', _NewChoicesSection('VALUE', value_item_strings))
Ejemplo n.º 6
0
 def testHelpTextObjectWithGroupAndValues(self):
     component = tc.TypedProperties()
     t = trace.FireTrace(component, name='TypedProperties')
     info = inspectutils.Info(component)
     help_screen = helptext.HelpText(component=component,
                                     info=info,
                                     trace=t,
                                     verbose=True)
     print(help_screen)
     self.assertIn('GROUPS', help_screen)
     self.assertIn('GROUP is one of the following:', help_screen)
     self.assertIn(
         'charlie\n       Class with functions that have default arguments.',
         help_screen)
     self.assertIn('VALUES', help_screen)
     self.assertIn('VALUE is one of the following:', help_screen)
     self.assertIn('alpha', help_screen)
Ejemplo n.º 7
0
    def testUsageOutputFunctionWithHelp(self):
        component = tc.function_with_help
        t = trace.FireTrace(component, name='function_with_help')
        info = inspectutils.Info(component)
        usage_output = helptext.UsageText(component,
                                          info,
                                          trace=t,
                                          verbose=True)
        expected_output = '''
    Usage: function_with_help <flags>

    Available flags: --help

    For detailed information on this command, run:
    function_with_help -- --help
    '''
        self.assertEqual(usage_output,
                         textwrap.dedent(expected_output).lstrip('\n'))
Ejemplo n.º 8
0
    def testUsageOutputFunctionWithDocstring(self):
        component = tc.multiplier_with_docstring
        t = trace.FireTrace(component, name='multiplier_with_docstring')
        info = inspectutils.Info(component)
        usage_output = helptext.UsageText(component,
                                          info,
                                          trace=t,
                                          verbose=True)
        expected_output = '''
    Usage: multiplier_with_docstring NUM <flags>

    Available flags: --rate

    For detailed information on this command, run:
    multiplier_with_docstring --help
    '''
        self.assertEqual(usage_output,
                         textwrap.dedent(expected_output).lstrip('\n'))
Ejemplo n.º 9
0
def HelpText(component, trace=None, verbose=False):
  """Gets the help string for the current component, suitable for a help screen.

  Args:
    component: The component to construct the help string for.
    trace: The Fire trace of the command so far. The command executed so far
      can be extracted from this trace.
    verbose: Whether to include private members in the help screen.

  Returns:
    The full help screen as a string.
  """
  # Preprocessing needed to create the sections:
  info = inspectutils.Info(component)
  actions_grouped_by_kind = _GetActionsGroupedByKind(component, verbose=verbose)
  spec = inspectutils.GetFullArgSpec(component)
  metadata = decorators.GetMetadata(component)

  # Sections:
  name_section = _NameSection(component, info, trace=trace, verbose=verbose)
  synopsis_section = _SynopsisSection(
      component, actions_grouped_by_kind, spec, metadata, trace=trace)
  description_section = _DescriptionSection(component, info)
  # TODO(dbieber): Add returns and raises sections for functions.

  if callable(component):
    args_and_flags_sections, notes_sections = _ArgsAndFlagsSections(
        info, spec, metadata)
  else:
    args_and_flags_sections = []
    notes_sections = []
  usage_details_sections = _UsageDetailsSections(component,
                                                 actions_grouped_by_kind)

  sections = (
      [name_section, synopsis_section, description_section]
      + args_and_flags_sections
      + usage_details_sections
      + notes_sections
  )
  return '\n\n'.join(
      _CreateOutputSection(*section)
      for section in sections if section is not None
  )
Ejemplo n.º 10
0
    def testHelpTextShortList(self):
        component = [10]
        info = inspectutils.Info(component)
        help_screen = helptext.HelpText(component=component,
                                        info=info,
                                        trace=trace.FireTrace(
                                            component, 'list'))
        self.assertIn('NAME\n    list', help_screen)
        self.assertIn('SYNOPSIS\n    list COMMAND', help_screen)
        # We don't check description content here since the content could be python
        # version dependent.
        self.assertIn('DESCRIPTION\n', help_screen)

        # We don't check the listed commands comprehensively since the list API
        # could potentially change between Python versions. Check a few
        # functions(command) that we're confident likely remain available.
        self.assertIn('COMMANDS\n    COMMAND is one of the followings:\n',
                      help_screen)
        self.assertIn('     append\n', help_screen)
Ejemplo n.º 11
0
  def testUsageOutputCallable(self):
    # This is both a group and a command!
    component = tc.CallableWithKeywordArgument
    t = trace.FireTrace(component, name='CallableWithKeywordArgument')
    info = inspectutils.Info(component)
    usage_output = helptext.UsageText(component, info, trace=t, verbose=True)
    # TODO(zuhaohen): We need to handle the case for keyword args as well
    # i.e. __call__ method of CallableWithKeywordArgument
    expected_output = '''
    Usage: CallableWithKeywordArgument <command>

      Available commands:    print_msg

    For detailed information on this command, run:
      CallableWithKeywordArgument -- --help
    '''
    self.assertEqual(
        usage_output,
        textwrap.dedent(expected_output).lstrip('\n'))
Ejemplo n.º 12
0
def _MakeUsageDetailsSection(action_group):
  """Creates a usage details section for the provided action group."""
  item_strings = []
  for name, member in action_group.GetItems():
    info = inspectutils.Info(member)
    item = name
    docstring_info = info.get('docstring_info')
    if (docstring_info
        and not custom_descriptions.NeedsCustomDescription(member)):
      summary = docstring_info.summary
    elif custom_descriptions.NeedsCustomDescription(member):
      summary = custom_descriptions.GetSummary(
          member, LINE_LENGTH - SECTION_INDENTATION, LINE_LENGTH)
    else:
      summary = None
    item = _CreateItem(name, summary)
    item_strings.append(item)
  return (action_group.plural.upper(),
          _NewChoicesSection(action_group.name.upper(), item_strings))
Ejemplo n.º 13
0
    def testHelpScreenForFunctionFunctionWithDefaultArgs(self):
        component = tc.WithDefaults().double
        t = trace.FireTrace(component, name='double')
        info = inspectutils.Info(component)
        help_output = helptext.HelpText(component, info, t)
        expected_output = """
    NAME
        double - Returns the input multiplied by 2.

    SYNOPSIS
        double [--count=COUNT]

    DESCRIPTION
        Returns the input multiplied by 2.

    FLAGS
        --count
          Input number that you want to double."""
        self.assertEqual(
            textwrap.dedent(expected_output).strip(), help_output.strip())
Ejemplo n.º 14
0
def HelpString(component, trace=None, verbose=False):
  """Returns the text to show for a supplied component.

  The component can be any Python class, object, function, module, etc.

  Args:
    component: The component to determine the help string for.
    trace: The Fire trace leading to this component.
    verbose: Whether to include private members in the help string.
  Returns:
    String suitable for display giving information about the component.
  """
  info = inspectutils.Info(component)

  is_error_screen = False
  if trace:
    is_error_screen = trace.HasError()

  if is_error_screen:
    return UsageText(component, info, trace, verbose=verbose)
  else:
    return HelpText(component, info, trace, verbose=verbose)
Ejemplo n.º 15
0
    def testHelpScreenForFunctionDocstringWithLineBreak(self):
        component = tc.ClassWithMultilineDocstring.example_generator
        t = trace.FireTrace(component, name='example_generator')
        info = inspectutils.Info(component)
        help_output = helptext.HelpText(component, info, t)
        expected_output = """
    NAME
        example_generator - Generators have a ``Yields`` section instead of a ``Returns`` section.

    SYNOPSIS
        example_generator N

    DESCRIPTION
        Generators have a ``Yields`` section instead of a ``Returns`` section.

    POSITIONAL ARGUMENTS
        N
            The upper limit of the range to generate, from 0 to `n` - 1.

    NOTES
        You could also use flags syntax for POSITIONAL ARGUMENTS"""
        self.assertEqual(
            textwrap.dedent(expected_output).strip(), help_output.strip())
Ejemplo n.º 16
0
  def testHelpScreenForFunctionFunctionWithDefaultArgs(self):
    component = tc.WithDefaults().double
    t = trace.FireTrace(component, name='double')
    info = inspectutils.Info(component)
    info['docstring_info'] = docstrings.parse(info['docstring'])
    help_output = helptext.HelpText(component, info, t)
    expected_output = """
    NAME
        double - Returns the input multiplied by 2.

    SYNOPSIS
        double [--count=COUNT]

    DESCRIPTION
        Returns the input multiplied by 2.

    FLAGS
        --count
            Input number that you want to double.

    NOTES
        You could also use flags syntax for POSITIONAL ARGUMENTS
    """
    self.assertEqual(textwrap.dedent(expected_output).lstrip('\n'), help_output)
Ejemplo n.º 17
0
 def testInfoOne(self):
     info = inspectutils.Info(1)
     self.assertEqual(info.get("type_name"), "int")
     self.assertEqual(info.get("file"), None)
     self.assertEqual(info.get("line"), None)
     self.assertEqual(info.get("string_form"), "1")
Ejemplo n.º 18
0
 def testInfoClass(self):
     info = inspectutils.Info(tc.NoDefaults)
     self.assertEqual(info.get("type_name"), "type")
     self.assertIn(os.path.join("fire", "test_components.py"), info.get("file"))
     self.assertGreater(info.get("line"), 0)
Ejemplo n.º 19
0
 def testInfoOne(self):
   info = inspectutils.Info(1)
   self.assertEqual(info.get('type_name'), 'int')
   self.assertEqual(info.get('file'), None)
   self.assertEqual(info.get('line'), None)
   self.assertEqual(info.get('string_form'), '1')
Ejemplo n.º 20
0
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
  )
Ejemplo n.º 21
0
 def testInfoClass(self):
   info = inspectutils.Info(tc.NoDefaults)
   self.assertEqual(info.get('type_name'), 'type')
   self.assertIn('fire/test_components.py', info.get('file'))
   self.assertGreater(info.get('line'), 0)
Ejemplo n.º 22
0
def HelpText(component, trace=None, verbose=False):
  info = inspectutils.Info(component)
  if inspect.isroutine(component) or inspect.isclass(component):
    return HelpTextForFunction(component, info, trace=trace, verbose=verbose)
  else:
    return HelpTextForObject(component, info, trace=trace, verbose=verbose)
Ejemplo n.º 23
0
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.
  """

    output_template = """NAME
    {current_command} - {command_summary}

SYNOPSIS
    {synopsis}

DESCRIPTION
    {command_description}
{detail_section}
"""

    current_command = GetCurrentCommand(trace)

    docstring_info = info['docstring_info']
    command_summary = docstring_info.summary if docstring_info.summary else ''
    if docstring_info.description:
        command_description = docstring_info.description
    else:
        command_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))

    possible_actions = []
    # TODO(joejoevictor): Add global flags to here. Also, if it's a callable,
    # there will be additional flags.
    possible_flags = ''
    detail_section_string = ''
    item_template = """
        {name}
            {command_summary}
"""

    if groups:
        # TODO(joejoevictor): Add missing GROUPS section handling
        possible_actions.append('GROUP')
    if commands:
        possible_actions.append('COMMAND')
        commands_str_template = """
COMMANDS
    COMMAND is one of the followings:
{items}
"""
        command_item_strings = []
        for command_name, command in commands:
            command_docstring_info = docstrings.parse(
                inspectutils.Info(command)['docstring'])
            command_item_strings.append(
                item_template.format(
                    name=command_name,
                    command_summary=command_docstring_info.summary))
        detail_section_string += commands_str_template.format(
            items=('\n'.join(command_item_strings)).rstrip('\n'))

    if values:
        possible_actions.append('VALUES')
        values_str_template = """
VALUES
    VALUE is one of the followings:
{items}
"""
        value_item_strings = []
        for value_name, value in values:
            del value
            init_docstring_info = docstrings.parse(
                inspectutils.Info(component.__class__.__init__)['docstring'])
            for arg_info in init_docstring_info.args:
                if arg_info.name == value_name:
                    value_item_strings.append(
                        item_template.format(
                            name=value_name,
                            command_summary=arg_info.description))
        detail_section_string += values_str_template.format(
            items=('\n'.join(value_item_strings)).rstrip('\n'))

    possible_actions_string = ' ' + (' | '.join(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)

    return output_template.format(current_command=current_command,
                                  command_summary=command_summary,
                                  synopsis=synopsis_string,
                                  command_description=command_description,
                                  detail_section=detail_section_string)
Ejemplo n.º 24
0
 def testInfoNoDocstring(self):
     info = inspectutils.Info(tc.NoDefaults)
     self.assertEqual(info['docstring'], None, 'Docstring should be None')