2018-12-04 13:36:56 -08:00
# Copyright (C) 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" Tests for fire docstrings module. """
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from fire import docstrings
from fire import testutils
2020-12-16 12:26:35 -08:00
# pylint: disable=invalid-name
DocstringInfo = docstrings . DocstringInfo
ArgInfo = docstrings . ArgInfo
KwargInfo = docstrings . KwargInfo
# pylint: enable=invalid-name
2018-12-04 13:36:56 -08:00
class DocstringsTest ( testutils . BaseTestCase ) :
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. ' ,
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
def test_one_line_simple_whitespace ( self ) :
docstring = """
A simple one line docstring.
"""
docstring_info = docstrings . parse ( docstring )
expected_docstring_info = DocstringInfo (
summary = ' A simple one line docstring. ' ,
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
def test_one_line_too_long ( self ) :
# pylint: disable=line-too-long
2023-02-13 14:20:46 -05:00
docstring = """ A one line docstring that is both a little too verbose and a little too long so it keeps going well beyond a reasonable length for a one-liner.
2018-12-04 13:36:56 -08:00
"""
# pylint: enable=line-too-long
docstring_info = docstrings . parse ( docstring )
expected_docstring_info = DocstringInfo (
2023-02-13 14:20:46 -05:00
summary = ' A one line docstring that is both a little too verbose and '
2018-12-04 13:36:56 -08:00
' a little too long so it keeps going well beyond a reasonable length '
' for a one-liner. ' ,
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
def test_one_line_runs_over ( self ) :
# pylint: disable=line-too-long
2023-02-13 14:20:46 -05:00
docstring = """ A one line docstring that is both a little too verbose and a little too long
2018-12-04 13:36:56 -08:00
so it runs onto a second line.
"""
# pylint: enable=line-too-long
docstring_info = docstrings . parse ( docstring )
expected_docstring_info = DocstringInfo (
2023-02-13 14:20:46 -05:00
summary = ' A one line docstring that is both a little too verbose and '
2018-12-04 13:36:56 -08:00
' a little too long so it runs onto a second line. ' ,
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
def test_one_line_runs_over_whitespace ( self ) :
docstring = """
2023-02-13 14:20:46 -05:00
A one line docstring that is both a little too verbose and a little too long
2018-12-04 13:36:56 -08:00
so it runs onto a second line.
"""
docstring_info = docstrings . parse ( docstring )
expected_docstring_info = DocstringInfo (
2023-02-13 14:20:46 -05:00
summary = ' A one line docstring that is both a little too verbose and '
2018-12-04 13:36:56 -08:00
' a little too long so it runs onto a second line. ' ,
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
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 ' ) ,
]
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
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 ' ) ,
]
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
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 '
2019-07-25 15:13:18 -07:00
' multiple lines, as \n is allowed. ' ,
2018-12-04 13:36:56 -08:00
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. '
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
2021-01-22 08:40:05 -08:00
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 \n is 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 )
2018-12-04 13:36:56 -08:00
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 '
2019-07-25 15:13:18 -07:00
' across multiple \n lines. ' ,
2018-12-04 13:36:56 -08:00
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 ' ,
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
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 '
2019-07-25 15:13:18 -07:00
' across multiple \n lines. ' ,
2018-12-04 13:36:56 -08:00
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. ' ,
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
2018-12-04 13:36:56 -08:00
2021-01-22 08:40:05 -08:00
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 \n lines. ' ,
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 )
2018-12-04 13:36:56 -08:00
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. ' ,
2019-07-25 15:54:50 -07:00
description = ' This is the first section of a docstring description. '
' \n \n '
' This is the second section of a docstring description. This docstring '
' \n '
2018-12-04 13:36:56 -08:00
' description has just two sections. ' ,
)
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_docstring_info , docstring_info )
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 )
2018-12-04 13:36:56 -08:00
def test_ill_formed_docstring ( self ) :
docstring = """ Docstring summary.
args: raises ::
:
pathological docstrings should not fail, and ideally should behave
reasonably.
"""
docstrings . parse ( docstring )
2019-07-25 15:13:18 -07:00
def test_strip_blank_lines ( self ) :
lines = [ ' ' , ' foo ' , ' ' ]
expected_output = [ ' foo ' ]
2019-07-29 15:32:39 -07:00
self . assertEqual ( expected_output , docstrings . _strip_blank_lines ( lines ) ) # pylint: disable=protected-access
2019-07-25 15:13:18 -07:00
2020-02-28 14:31:51 -08:00
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 )
2020-12-16 12:26:35 -08:00
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 )
2018-12-04 13:36:56 -08:00
if __name__ == ' __main__ ' :
testutils . main ( )