ClickUp Operator
by noahvanhart
"""Tests for Google-style docstring routines."""
import typing as T
import pytest
from docstring_parser.common import ParseError, RenderingStyle
from docstring_parser.google import (
GoogleParser,
Section,
SectionType,
compose,
parse,
)
def test_google_parser_unknown_section() -> None:
"""Test parsing an unknown section with default GoogleParser
configuration.
"""
parser = GoogleParser()
docstring = parser.parse(
"""
Unknown:
spam: a
"""
)
assert docstring.short_description == "Unknown:"
assert docstring.long_description == "spam: a"
assert len(docstring.meta) == 0
def test_google_parser_custom_sections() -> None:
"""Test parsing an unknown section with custom GoogleParser
configuration.
"""
parser = GoogleParser(
[
Section("DESCRIPTION", "desc", SectionType.SINGULAR),
Section("ARGUMENTS", "param", SectionType.MULTIPLE),
Section("ATTRIBUTES", "attribute", SectionType.MULTIPLE),
Section("EXAMPLES", "examples", SectionType.SINGULAR),
],
title_colon=False,
)
docstring = parser.parse(
"""
DESCRIPTION
This is the description.
ARGUMENTS
arg1: first arg
arg2: second arg
ATTRIBUTES
attr1: first attribute
attr2: second attribute
EXAMPLES
Many examples
More examples
"""
)
assert docstring.short_description is None
assert docstring.long_description is None
assert len(docstring.meta) == 6
assert docstring.meta[0].args == ["desc"]
assert docstring.meta[0].description == "This is the description."
assert docstring.meta[1].args == ["param", "arg1"]
assert docstring.meta[1].description == "first arg"
assert docstring.meta[2].args == ["param", "arg2"]
assert docstring.meta[2].description == "second arg"
assert docstring.meta[3].args == ["attribute", "attr1"]
assert docstring.meta[3].description == "first attribute"
assert docstring.meta[4].args == ["attribute", "attr2"]
assert docstring.meta[4].description == "second attribute"
assert docstring.meta[5].args == ["examples"]
assert docstring.meta[5].description == "Many examples\nMore examples"
def test_google_parser_custom_sections_after() -> None:
"""Test parsing an unknown section with custom GoogleParser configuration
that was set at a runtime.
"""
parser = GoogleParser(title_colon=False)
parser.add_section(Section("Note", "note", SectionType.SINGULAR))
docstring = parser.parse(
"""
short description
Note:
a note
"""
)
assert docstring.short_description == "short description"
assert docstring.long_description == "Note:\n a note"
docstring = parser.parse(
"""
short description
Note a note
"""
)
assert docstring.short_description == "short description"
assert docstring.long_description == "Note a note"
docstring = parser.parse(
"""
short description
Note
a note
"""
)
assert len(docstring.meta) == 1
assert docstring.meta[0].args == ["note"]
assert docstring.meta[0].description == "a note"
@pytest.mark.parametrize(
"source, expected",
[
("", None),
("\n", None),
("Short description", "Short description"),
("\nShort description\n", "Short description"),
("\n Short description\n", "Short description"),
],
)
def test_short_description(source: str, expected: str) -> None:
"""Test parsing short description."""
docstring = parse(source)
assert docstring.short_description == expected
assert docstring.long_description is None
assert not docstring.meta
@pytest.mark.parametrize(
"source, expected_short_desc, expected_long_desc, expected_blank",
[
(
"Short description\n\nLong description",
"Short description",
"Long description",
True,
),
(
"""
Short description
Long description
""",
"Short description",
"Long description",
True,
),
(
"""
Short description
Long description
Second line
""",
"Short description",
"Long description\nSecond line",
True,
),
(
"Short description\nLong description",
"Short description",
"Long description",
False,
),
(
"""
Short description
Long description
""",
"Short description",
"Long description",
False,
),
(
"\nShort description\nLong description\n",
"Short description",
"Long description",
False,
),
(
"""
Short description
Long description
Second line
""",
"Short description",
"Long description\nSecond line",
False,
),
],
)
def test_long_description(
source: str,
expected_short_desc: str,
expected_long_desc: str,
expected_blank: bool,
) -> None:
"""Test parsing long description."""
docstring = parse(source)
assert docstring.short_description == expected_short_desc
assert docstring.long_description == expected_long_desc
assert docstring.blank_after_short_description == expected_blank
assert not docstring.meta
@pytest.mark.parametrize(
"source, expected_short_desc, expected_long_desc, "
"expected_blank_short_desc, expected_blank_long_desc",
[
(
"""
Short description
Args:
asd:
""",
"Short description",
None,
False,
False,
),
(
"""
Short description
Long description
Args:
asd:
""",
"Short description",
"Long description",
False,
False,
),
(
"""
Short description
First line
Second line
Args:
asd:
""",
"Short description",
"First line\n Second line",
False,
False,
),
(
"""
Short description
First line
Second line
Args:
asd:
""",
"Short description",
"First line\n Second line",
True,
False,
),
(
"""
Short description
First line
Second line
Args:
asd:
""",
"Short description",
"First line\n Second line",
True,
True,
),
(
"""
Args:
asd:
""",
None,
None,
False,
False,
),
],
)
def test_meta_newlines(
source: str,
expected_short_desc: T.Optional[str],
expected_long_desc: T.Optional[str],
expected_blank_short_desc: bool,
expected_blank_long_desc: bool,
) -> None:
"""Test parsing newlines around description sections."""
docstring = parse(source)
assert docstring.short_description == expected_short_desc
assert docstring.long_description == expected_long_desc
assert docstring.blank_after_short_description == expected_blank_short_desc
assert docstring.blank_after_long_description == expected_blank_long_desc
assert len(docstring.meta) == 1
def test_meta_with_multiline_description() -> None:
"""Test parsing multiline meta documentation."""
docstring = parse(
"""
Short description
Args:
spam: asd
1
2
3
"""
)
assert docstring.short_description == "Short description"
assert len(docstring.meta) == 1
assert docstring.meta[0].args == ["param", "spam"]
assert docstring.meta[0].arg_name == "spam"
assert docstring.meta[0].description == "asd\n1\n 2\n3"
def test_default_args() -> None:
"""Test parsing default arguments."""
docstring = parse(
"""A sample function
A function the demonstrates docstrings
Args:
arg1 (int): The firsty arg
arg2 (str): The second arg
arg3 (float, optional): The third arg. Defaults to 1.0.
arg4 (Optional[Dict[str, Any]], optional): The last arg. Defaults to None.
arg5 (str, optional): The fifth arg. Defaults to DEFAULT_ARG5.
Returns:
Mapping[str, Any]: The args packed in a mapping
"""
)
assert docstring is not None
assert len(docstring.params) == 5
arg4 = docstring.params[3]
assert arg4.arg_name == "arg4"
assert arg4.is_optional
assert arg4.type_name == "Optional[Dict[str, Any]]"
assert arg4.default == "None"
assert arg4.description == "The last arg. Defaults to None."
def test_multiple_meta() -> None:
"""Test parsing multiple meta."""
docstring = parse(
"""
Short description
Args:
spam: asd
1
2
3
Raises:
bla: herp
yay: derp
"""
)
assert docstring.short_description == "Short description"
assert len(docstring.meta) == 3
assert docstring.meta[0].args == ["param", "spam"]
assert docstring.meta[0].arg_name == "spam"
assert docstring.meta[0].description == "asd\n1\n 2\n3"
assert docstring.meta[1].args == ["raises", "bla"]
assert docstring.meta[1].type_name == "bla"
assert docstring.meta[1].description == "herp"
assert docstring.meta[2].args == ["raises", "yay"]
assert docstring.meta[2].type_name == "yay"
assert docstring.meta[2].description == "derp"
def test_params() -> None:
"""Test parsing params."""
docstring = parse("Short description")
assert len(docstring.params) == 0
docstring = parse(
"""
Short description
Args:
name: description 1
priority (int): description 2
sender (str?): description 3
ratio (Optional[float], optional): description 4
"""
)
assert len(docstring.params) == 4
assert docstring.params[0].arg_name == "name"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "description 1"
assert not docstring.params[0].is_optional
assert docstring.params[1].arg_name == "priority"
assert docstring.params[1].type_name == "int"
assert docstring.params[1].description == "description 2"
assert not docstring.params[1].is_optional
assert docstring.params[2].arg_name == "sender"
assert docstring.params[2].type_name == "str"
assert docstring.params[2].description == "description 3"
assert docstring.params[2].is_optional
assert docstring.params[3].arg_name == "ratio"
assert docstring.params[3].type_name == "Optional[float]"
assert docstring.params[3].description == "description 4"
assert docstring.params[3].is_optional
docstring = parse(
"""
Short description
Args:
name: description 1
with multi-line text
priority (int): description 2
"""
)
assert len(docstring.params) == 2
assert docstring.params[0].arg_name == "name"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == (
"description 1\nwith multi-line text"
)
assert docstring.params[1].arg_name == "priority"
assert docstring.params[1].type_name == "int"
assert docstring.params[1].description == "description 2"
def test_attributes() -> None:
"""Test parsing attributes."""
docstring = parse("Short description")
assert len(docstring.params) == 0
docstring = parse(
"""
Short description
Attributes:
name: description 1
priority (int): description 2
sender (str?): description 3
ratio (Optional[float], optional): description 4
"""
)
assert len(docstring.params) == 4
assert docstring.params[0].arg_name == "name"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "description 1"
assert not docstring.params[0].is_optional
assert docstring.params[1].arg_name == "priority"
assert docstring.params[1].type_name == "int"
assert docstring.params[1].description == "description 2"
assert not docstring.params[1].is_optional
assert docstring.params[2].arg_name == "sender"
assert docstring.params[2].type_name == "str"
assert docstring.params[2].description == "description 3"
assert docstring.params[2].is_optional
assert docstring.params[3].arg_name == "ratio"
assert docstring.params[3].type_name == "Optional[float]"
assert docstring.params[3].description == "description 4"
assert docstring.params[3].is_optional
docstring = parse(
"""
Short description
Attributes:
name: description 1
with multi-line text
priority (int): description 2
"""
)
assert len(docstring.params) == 2
assert docstring.params[0].arg_name == "name"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == (
"description 1\nwith multi-line text"
)
assert docstring.params[1].arg_name == "priority"
assert docstring.params[1].type_name == "int"
assert docstring.params[1].description == "description 2"
def test_returns() -> None:
"""Test parsing returns."""
docstring = parse(
"""
Short description
"""
)
assert docstring.returns is None
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 0
docstring = parse(
"""
Short description
Returns:
description
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name is None
assert docstring.returns.description == "description"
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
docstring = parse(
"""
Short description
Returns:
description with: a colon!
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name is None
assert docstring.returns.description == "description with: a colon!"
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
docstring = parse(
"""
Short description
Returns:
int: description
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name == "int"
assert docstring.returns.description == "description"
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
docstring = parse(
"""
Returns:
Optional[Mapping[str, List[int]]]: A description: with a colon
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name == "Optional[Mapping[str, List[int]]]"
assert docstring.returns.description == "A description: with a colon"
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
docstring = parse(
"""
Short description
Yields:
int: description
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name == "int"
assert docstring.returns.description == "description"
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
docstring = parse(
"""
Short description
Returns:
int: description
with much text
even some spacing
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name == "int"
assert docstring.returns.description == (
"description\nwith much text\n\neven some spacing"
)
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
def test_raises() -> None:
"""Test parsing raises."""
docstring = parse(
"""
Short description
"""
)
assert len(docstring.raises) == 0
docstring = parse(
"""
Short description
Raises:
ValueError: description
"""
)
assert len(docstring.raises) == 1
assert docstring.raises[0].type_name == "ValueError"
assert docstring.raises[0].description == "description"
def test_examples() -> None:
"""Test parsing examples."""
docstring = parse(
"""
Short description
Example:
example: 1
Examples:
long example
more here
"""
)
assert len(docstring.examples) == 2
assert docstring.examples[0].description == "example: 1"
assert docstring.examples[1].description == "long example\n\nmore here"
def test_broken_meta() -> None:
"""Test parsing broken meta."""
with pytest.raises(ParseError):
parse("Args:")
with pytest.raises(ParseError):
parse("Args:\n herp derp")
def test_unknown_meta() -> None:
"""Test parsing unknown meta."""
docstring = parse(
"""Short desc
Unknown 0:
title0: content0
Args:
arg0: desc0
arg1: desc1
Unknown1:
title1: content1
Unknown2:
title2: content2
"""
)
assert docstring.params[0].arg_name == "arg0"
assert docstring.params[0].description == "desc0"
assert docstring.params[1].arg_name == "arg1"
assert docstring.params[1].description == "desc1"
def test_broken_arguments() -> None:
"""Test parsing broken arguments."""
with pytest.raises(ParseError):
parse(
"""This is a test
Args:
param - poorly formatted
"""
)
def test_empty_example() -> None:
"""Test parsing empty examples section."""
docstring = parse(
"""Short description
Example:
Raises:
IOError: some error
"""
)
assert len(docstring.examples) == 1
assert docstring.examples[0].args == ["examples"]
assert docstring.examples[0].description == ""
@pytest.mark.parametrize(
"source, expected",
[
("", ""),
("\n", ""),
("Short description", "Short description"),
("\nShort description\n", "Short description"),
("\n Short description\n", "Short description"),
(
"Short description\n\nLong description",
"Short description\n\nLong description",
),
(
"""
Short description
Long description
""",
"Short description\n\nLong description",
),
(
"""
Short description
Long description
Second line
""",
"Short description\n\nLong description\nSecond line",
),
(
"Short description\nLong description",
"Short description\nLong description",
),
(
"""
Short description
Long description
""",
"Short description\nLong description",
),
(
"\nShort description\nLong description\n",
"Short description\nLong description",
),
(
"""
Short description
Long description
Second line
""",
"Short description\nLong description\nSecond line",
),
(
"""
Short description
Meta:
asd
""",
"Short description\nMeta:\n asd",
),
(
"""
Short description
Long description
Meta:
asd
""",
"Short description\nLong description\nMeta:\n asd",
),
(
"""
Short description
First line
Second line
Meta:
asd
""",
"Short description\n"
"First line\n"
" Second line\n"
"Meta:\n"
" asd",
),
(
"""
Short description
First line
Second line
Meta:
asd
""",
"Short description\n"
"\n"
"First line\n"
" Second line\n"
"Meta:\n"
" asd",
),
(
"""
Short description
First line
Second line
Meta:
asd
""",
"Short description\n"
"\n"
"First line\n"
" Second line\n"
"\n"
"Meta:\n"
" asd",
),
(
"""
Short description
Meta:
asd
1
2
3
""",
"Short description\n"
"\n"
"Meta:\n"
" asd\n"
" 1\n"
" 2\n"
" 3",
),
(
"""
Short description
Meta1:
asd
1
2
3
Meta2:
herp
Meta3:
derp
""",
"Short description\n"
"\n"
"Meta1:\n"
" asd\n"
" 1\n"
" 2\n"
" 3\n"
"Meta2:\n"
" herp\n"
"Meta3:\n"
" derp",
),
(
"""
Short description
Args:
name: description 1
priority (int): description 2
sender (str, optional): description 3
message (str, optional): description 4, defaults to 'hello'
multiline (str?):
long description 5,
defaults to 'bye'
""",
"Short description\n"
"\n"
"Args:\n"
" name: description 1\n"
" priority (int): description 2\n"
" sender (str?): description 3\n"
" message (str?): description 4, defaults to 'hello'\n"
" multiline (str?): long description 5,\n"
" defaults to 'bye'",
),
(
"""
Short description
Raises:
ValueError: description
""",
"Short description\nRaises:\n ValueError: description",
),
],
)
def test_compose(source: str, expected: str) -> None:
"""Test compose in default mode."""
assert compose(parse(source)) == expected
@pytest.mark.parametrize(
"source, expected",
[
(
"""
Short description
Args:
name: description 1
priority (int): description 2
sender (str, optional): description 3
message (str, optional): description 4, defaults to 'hello'
multiline (str?):
long description 5,
defaults to 'bye'
""",
"Short description\n"
"\n"
"Args:\n"
" name: description 1\n"
" priority (int): description 2\n"
" sender (str, optional): description 3\n"
" message (str, optional): description 4, defaults to 'hello'\n"
" multiline (str, optional): long description 5,\n"
" defaults to 'bye'",
),
],
)
def test_compose_clean(source: str, expected: str) -> None:
"""Test compose in clean mode."""
assert (
compose(parse(source), rendering_style=RenderingStyle.CLEAN)
== expected
)
@pytest.mark.parametrize(
"source, expected",
[
(
"""
Short description
Args:
name: description 1
priority (int): description 2
sender (str, optional): description 3
message (str, optional): description 4, defaults to 'hello'
multiline (str?):
long description 5,
defaults to 'bye'
""",
"Short description\n"
"\n"
"Args:\n"
" name:\n"
" description 1\n"
" priority (int):\n"
" description 2\n"
" sender (str, optional):\n"
" description 3\n"
" message (str, optional):\n"
" description 4, defaults to 'hello'\n"
" multiline (str, optional):\n"
" long description 5,\n"
" defaults to 'bye'",
),
],
)
def test_compose_expanded(source: str, expected: str) -> None:
"""Test compose in expanded mode."""
assert (
compose(parse(source), rendering_style=RenderingStyle.EXPANDED)
== expected
)