Esempio n. 1
0
    def test_ill_formed_docstring(self):
        docstring = """Docstring summary.

    args: raises ::
    :
    pathological docstrings should not fail, and ideally should behave
    reasonably.
    """
        docstrings.parse(docstring)
Esempio n. 2
0
    def test_numpy_colon_in_description(self):
        docstring = """
     Greets name.

     Arguments
     ---------
     name : str
         name, default : World
     arg2 : int
         arg2, default:None
     arg3 : bool
     """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary='Greets name.',
            description=None,
            args=[
                ArgInfo(name='name',
                        type='str',
                        description='name, default : World'),
                ArgInfo(name='arg2',
                        type='int',
                        description='arg2, default:None'),
                ArgInfo(name='arg3', type='bool', description=None),
            ])
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio 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)
    # TODO(dbieber): Stop using UsageString in favor of UsageText.
    info['usage'] = UsageString(component, trace, verbose)
    info['docstring_info'] = docstrings.parse(info['docstring'])

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

    if is_error_screen:
        # TODO(dbieber): Call UsageText instead of CommonHelpText once ready.
        return _CommonHelpText(info, trace)
    else:
        return _HelpText(info, trace)
Esempio n. 4
0
    def testHelpScreenWithLineBreak(self):
        component = tc.ClassWithMultilineDocstring.example_generator
        t = trace.FireTrace(component, name='example_generator')
        info = inspectutils.Info(component)
        info['docstring_info'] = docstrings.parse(info['docstring'])
        help_output = helputils.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).lstrip('\n'), help_output)
Esempio n. 5
0
    def test_google_format_typed_args_and_returns(self):
        docstring = """Docstring summary.

    This is a longer description of the docstring. It spans multiple lines, as
    is allowed.

    Args:
        param1 (int): The first parameter.
        param2 (str): The second parameter.

    Returns:
        bool: The return value. True for success, False otherwise.
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary='Docstring summary.',
            description=
            'This is a longer description of the docstring. It spans '
            'multiple lines, as\nis allowed.',
            args=[
                ArgInfo(name='param1',
                        type='int',
                        description='The first parameter.'),
                ArgInfo(name='param2',
                        type='str',
                        description='The second parameter.'),
            ],
            returns='bool: The return value. True for success, False otherwise.'
        )
        self.assertEqual(expected_docstring_info, docstring_info)
    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 = helputils.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)
Esempio n. 7
0
 def test_one_line_simple(self):
     docstring = """A simple one line docstring."""
     docstring_info = docstrings.parse(docstring)
     expected_docstring_info = DocstringInfo(
         summary="A simple one line docstring.",
     )
     self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 8
0
    def test_numpy_format_typed_args_and_returns(self):
        docstring = """Docstring summary.

    This is a longer description of the docstring. It spans across multiple
    lines.

    Parameters
    ----------
    param1 : int
        The first parameter.
    param2 : str
        The second parameter.

    Returns
    -------
    bool
        True if successful, False otherwise.
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary="Docstring summary.",
            description="This is a longer description of the docstring. It spans "
            "across multiple\nlines.",
            args=[
                ArgInfo(name="param1", type="int", description="The first parameter."),
                ArgInfo(name="param2", type="str", description="The second parameter."),
            ],
            # TODO(dbieber): Support return type.
            returns="bool True if successful, False otherwise.",
        )
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 9
0
    def test_numpy_format_multiline_arg_description(self):
        docstring = """Docstring summary.

    This is a longer description of the docstring. It spans across multiple
    lines.

    Parameters
    ----------
    param1 : int
        The first parameter.
    param2 : str
        The second parameter. This has a lot of text, enough to cover two
        lines.
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary="Docstring summary.",
            description="This is a longer description of the docstring. It spans "
            "across multiple\nlines.",
            args=[
                ArgInfo(name="param1", type="int", description="The first parameter."),
                ArgInfo(
                    name="param2",
                    type="str",
                    description="The second parameter. This has a lot of text, "
                    "enough to cover two lines.",
                ),
            ],
        )
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 10
0
    def test_rst_format_typed_args_and_returns(self):
        docstring = """Docstring summary.

    This is a longer description of the docstring. It spans across multiple
    lines.

    :param arg1: Description of arg1.
    :type arg1: str.
    :param arg2: Description of arg2.
    :type arg2: bool.
    :returns:  int -- description of the return value.
    :raises: AttributeError, KeyError
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary="Docstring summary.",
            description="This is a longer description of the docstring. It spans "
            "across multiple\nlines.",
            args=[
                ArgInfo(name="arg1", type="str", description="Description of arg1."),
                ArgInfo(name="arg2", type="bool", description="Description of arg2."),
            ],
            returns="int -- description of the return value.",
            raises="AttributeError, KeyError",
        )
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 11
0
    def test_google_format_multiline_arg_description(self):
        docstring = """Docstring summary.

    This is a longer description of the docstring. It spans multiple lines, as
    is allowed.

    Args:
        param1 (int): The first parameter.
        param2 (str): The second parameter. This has a lot of text, enough to
        cover two lines.
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary="Docstring summary.",
            description="This is a longer description of the docstring. It spans "
            "multiple lines, as\nis allowed.",
            args=[
                ArgInfo(name="param1", type="int", description="The first parameter."),
                ArgInfo(
                    name="param2",
                    type="str",
                    description="The second parameter. This has a lot of text, "
                    "enough to cover two lines.",
                ),
            ],
        )
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 12
0
  def testHelpScreen(self):
    component = tc.ClassWithDocstring()
    t = trace.FireTrace(component, name='ClassWithDocstring')
    info = inspectutils.Info(component)
    info['docstring_info'] = docstrings.parse(info['docstring'])
    help_output = helptext.HelpText(component, info, t)
    expected_output = """
NAME
    ClassWithDocstring - Test class for testing help text output.

SYNOPSIS
    ClassWithDocstring COMMAND | VALUES

DESCRIPTION
    This is some detail description of this test class.

COMMANDS
    COMMAND is one of the followings:

        print_msg
            Prints a message.

VALUES
    VALUE is one of the followings:

        message
            The default message to print.

"""
    self.assertEqual(textwrap.dedent(expected_output).lstrip('\n'), help_output)
Esempio n. 13
0
    def test_rst_format_typed_args_and_returns(self):
        docstring = """Docstring summary.

    This is a longer description of the docstring. It spans across multiple
    lines.

    :param arg1: Description of arg1.
    :type arg1: str.
    :param arg2: Description of arg2.
    :type arg2: bool.
    :returns:  int -- description of the return value.
    :raises: AttributeError, KeyError
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary='Docstring summary.',
            description=
            'This is a longer description of the docstring. It spans '
            'across multiple\nlines.',
            args=[
                ArgInfo(name='arg1',
                        type='str',
                        description='Description of arg1.'),
                ArgInfo(name='arg2',
                        type='bool',
                        description='Description of arg2.'),
            ],
            returns='int -- description of the return value.',
            raises='AttributeError, KeyError',
        )
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 14
0
 def test_google_format_arg_named_args(self):
     docstring = """
 Args:
   args: arg_description
 """
     docstring_info = docstrings.parse(docstring)
     expected_docstring_info = DocstringInfo(args=[
         ArgInfo(name='args', description='arg_description'),
     ])
     self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 15
0
 def test_one_line_runs_over_whitespace(self):
     docstring = """
   A one line docstring thats both a little too verbose and a little too long
   so it runs onto a second line.
 """
     docstring_info = docstrings.parse(docstring)
     expected_docstring_info = DocstringInfo(
         summary='A one line docstring thats both a little too verbose and '
         'a little too long so it runs onto a second line.', )
     self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 16
0
 def test_one_line_runs_over(self):
     # pylint: disable=line-too-long
     docstring = """A one line docstring thats both a little too verbose and a little too long
 so it runs onto a second line.
 """
     # pylint: enable=line-too-long
     docstring_info = docstrings.parse(docstring)
     expected_docstring_info = DocstringInfo(
         summary='A one line docstring thats both a little too verbose and '
         'a little too long so it runs onto a second line.', )
     self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 17
0
 def test_one_line_too_long(self):
     # pylint: disable=line-too-long
     docstring = """A one line docstring thats both a little too verbose and a little too long so it keeps going well beyond a reasonable length for a one-liner.
 """
     # pylint: enable=line-too-long
     docstring_info = docstrings.parse(docstring)
     expected_docstring_info = DocstringInfo(
         summary='A one line docstring thats both a little too verbose and '
         'a little too long so it keeps going well beyond a reasonable length '
         'for a one-liner.', )
     self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 18
0
    def test_google_section_with_blank_first_line(self):
        docstring = """Inspired by requests HTTPAdapter docstring.

    :param x: Simple param.

    Usage:

      >>> import requests
    """
        docstring_info = docstrings.parse(docstring)
        self.assertEqual('Inspired by requests HTTPAdapter docstring.',
                         docstring_info.summary)
Esempio n. 19
0
 def testHelpTextNoDefaults(self):
   component = tc.NoDefaults
   # TODO(joejoevictor): We should have inspectutils.Info to generate
   # info['docstring_info'] as well.
   info = inspectutils.Info(component)
   info['docstring_info'] = docstrings.parse(info['docstring'])
   help_screen = helptext.HelpText(
       component=component,
       info=info,
       trace=trace.FireTrace(component, name='NoDefaults'))
   self.assertIn('NAME\n    NoDefaults', help_screen)
   self.assertIn('SYNOPSIS\n    NoDefaults', help_screen)
   self.assertNotIn('DESCRIPTION', help_screen)
   self.assertNotIn('NOTES', help_screen)
Esempio n. 20
0
    def test_google_format_args_only(self):
        docstring = """One line description.

    Args:
      arg1: arg1_description
      arg2: arg2_description
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary='One line description.',
            args=[
                ArgInfo(name='arg1', description='arg1_description'),
                ArgInfo(name='arg2', description='arg2_description'),
            ])
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 21
0
 def testHelpTextNoDefaultsObject(self):
   component = tc.NoDefaults()
   info = inspectutils.Info(component)
   info['docstring_info'] = docstrings.parse(info['docstring'])
   help_screen = helptext.HelpText(
       component=component,
       info=info,
       trace=trace.FireTrace(component, name='NoDefaults'))
   self.assertIn('NAME\n    NoDefaults', help_screen)
   self.assertIn('SYNOPSIS\n    NoDefaults COMMAND', help_screen)
   self.assertNotIn('DESCRIPTION', help_screen)
   self.assertIn('COMMANDS\n    COMMAND is one of the followings:',
                 help_screen)
   self.assertIn('double', help_screen)
   self.assertIn('triple', help_screen)
   self.assertNotIn('NOTES', help_screen)
Esempio n. 22
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)
Esempio n. 23
0
    def test_multisection_docstring(self):
        docstring = """Docstring summary.

    This is the first section of a docstring description.

    This is the second section of a docstring description. This docstring
    description has just two sections.
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary='Docstring summary.',
            description='This is the first section of a docstring description.'
            '\n\n'
            'This is the second section of a docstring description. This docstring'
            '\n'
            'description has just two sections.',
        )
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 24
0
def Info(component):
    """Returns a dict with information about the given component.

    The dict will have at least some of the following fields.
      type_name: The type of `component`.
      string_form: A string representation of `component`.
      file: The file in which `component` is defined.
      line: The line number at which `component` is defined.
      docstring: The docstring of `component`.
      init_docstring: The init docstring of `component`.
      class_docstring: The class docstring of `component`.
      call_docstring: The call docstring of `component`.
      length: The length of `component`.

    Args:
      component: The component to analyze.
    Returns:
      A dict with information about the component.
    """
    try:
        from IPython.core import (
            oinspect, )  # pylint: disable=import-outside-toplevel,g-import-not-at-top

        inspector = oinspect.Inspector()
        info = inspector.info(component)

        # IPython's oinspect.Inspector.info may return '<no docstring>'
        if info["docstring"] == "<no docstring>":
            info["docstring"] = None
    except ImportError:
        info = _InfoBackup(component)

    try:
        unused_code, lineindex = inspect.findsource(component)
        info["line"] = lineindex + 1
    except (TypeError, IOError):
        info["line"] = None

    if "docstring" in info:
        info["docstring_info"] = docstrings.parse(info["docstring"])

    return info
Esempio n. 25
0
    def test_rst_format_typed_args_and_kwargs(self):
        docstring = """Docstring summary.

    :param arg1: Description of arg1.
    :type arg1: str.
    :key arg2: Description of arg2.
    :type arg2: bool.
    :key arg3: Description of arg3.
    :type arg3: str.
    """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary="Docstring summary.",
            args=[
                ArgInfo(name="arg1", type="str", description="Description of arg1."),
                KwargInfo(name="arg2", type="bool", description="Description of arg2."),
                KwargInfo(name="arg3", type="str", description="Description of arg3."),
            ],
        )
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 26
0
    def test_numpy_colon_in_description(self):
        docstring = """
     Greets name.

     Arguments
     ---------
     name : str
         name, default : World
     arg2 : int
         arg2, default:None
     arg3 : bool
     """
        docstring_info = docstrings.parse(docstring)
        expected_docstring_info = DocstringInfo(
            summary="Greets name.",
            description=None,
            args=[
                ArgInfo(name="name", type="str", description="name, default : World"),
                ArgInfo(name="arg2", type="int", description="arg2, default:None"),
                ArgInfo(name="arg3", type="bool", description=None),
            ],
        )
        self.assertEqual(expected_docstring_info, docstring_info)
Esempio n. 27
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)
    info['docstring_info'] = docstrings.parse(info['docstring'])

    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)
Esempio n. 28
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 ''
    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))

    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_docstring_info = docstrings.parse(
                inspectutils.Info(command)['docstring'])
            command_item_strings.append(
                _CreateItem(command_name, command_docstring_info.summary))
        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_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(
                        _CreateItem(value_name, arg_info.description))
        usage_details_sections.append(
            ('VALUES', _NewChoicesSection('VALUE', value_item_strings)))

    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)

    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)
Esempio n. 29
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)
 def test_fuzz_parse(self, value):
     docstrings.parse(value)