structure saas with tools

This commit is contained in:
Davidson Gomes
2025-04-25 15:30:54 -03:00
commit 1aef473937
16434 changed files with 6584257 additions and 0 deletions

View File

@@ -0,0 +1 @@
"""Tests for docstring parser."""

View File

@@ -0,0 +1,22 @@
"""Private pydoctor customization code in order to exclude the package
docstring_parser.tests from the API documentation. Based on Twisted code.
"""
# pylint: disable=invalid-name
try:
from pydoctor.model import Documentable, PrivacyClass, System
except ImportError:
pass
else:
class HidesTestsPydoctorSystem(System):
"""A PyDoctor "system" used to generate the docs."""
def privacyClass(self, documentable: Documentable) -> PrivacyClass:
"""Report the privacy level for an object. Hide the module
'docstring_parser.tests'.
"""
if documentable.fullName().startswith("docstring_parser.tests"):
return PrivacyClass.HIDDEN
return super().privacyClass(documentable)

View File

@@ -0,0 +1,723 @@
"""Tests for epydoc-style docstring routines."""
import typing as T
import pytest
from docstring_parser.common import ParseError, RenderingStyle
from docstring_parser.epydoc import compose, parse
@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
@meta: asd
""",
"Short description",
None,
False,
False,
),
(
"""
Short description
Long description
@meta: asd
""",
"Short description",
"Long description",
False,
False,
),
(
"""
Short description
First line
Second line
@meta: asd
""",
"Short description",
"First line\n Second line",
False,
False,
),
(
"""
Short description
First line
Second line
@meta: asd
""",
"Short description",
"First line\n Second line",
True,
False,
),
(
"""
Short description
First line
Second line
@meta: asd
""",
"Short description",
"First line\n Second line",
True,
True,
),
(
"""
@meta: 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
@meta: asd
1
2
3
"""
)
assert docstring.short_description == "Short description"
assert len(docstring.meta) == 1
assert docstring.meta[0].args == ["meta"]
assert docstring.meta[0].description == "asd\n1\n 2\n3"
def test_multiple_meta() -> None:
"""Test parsing multiple meta."""
docstring = parse(
"""
Short description
@meta1: asd
1
2
3
@meta2: herp
@meta3: derp
"""
)
assert docstring.short_description == "Short description"
assert len(docstring.meta) == 3
assert docstring.meta[0].args == ["meta1"]
assert docstring.meta[0].description == "asd\n1\n 2\n3"
assert docstring.meta[1].args == ["meta2"]
assert docstring.meta[1].description == "herp"
assert docstring.meta[2].args == ["meta3"]
assert docstring.meta[2].description == "derp"
def test_meta_with_args() -> None:
"""Test parsing meta with additional arguments."""
docstring = parse(
"""
Short description
@meta ene due rabe: asd
"""
)
assert docstring.short_description == "Short description"
assert len(docstring.meta) == 1
assert docstring.meta[0].args == ["meta", "ene", "due", "rabe"]
assert docstring.meta[0].description == "asd"
def test_params() -> None:
"""Test parsing params."""
docstring = parse("Short description")
assert len(docstring.params) == 0
docstring = parse(
"""
Short description
@param name: description 1
@param priority: description 2
@type priority: int
@param sender: description 3
@type sender: str?
@param message: description 4, defaults to 'hello'
@type message: str?
@param multiline: long description 5,
defaults to 'bye'
@type multiline: str?
"""
)
assert len(docstring.params) == 5
assert docstring.params[0].arg_name == "name"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "description 1"
assert docstring.params[0].default is None
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[1].default is None
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[2].default is None
assert docstring.params[3].arg_name == "message"
assert docstring.params[3].type_name == "str"
assert (
docstring.params[3].description == "description 4, defaults to 'hello'"
)
assert docstring.params[3].is_optional
assert docstring.params[3].default == "'hello'"
assert docstring.params[4].arg_name == "multiline"
assert docstring.params[4].type_name == "str"
assert (
docstring.params[4].description
== "long description 5,\ndefaults to 'bye'"
)
assert docstring.params[4].is_optional
assert docstring.params[4].default == "'bye'"
def test_returns() -> None:
"""Test parsing returns."""
docstring = parse(
"""
Short description
"""
)
assert docstring.returns is None
docstring = parse(
"""
Short description
@return: description
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name is None
assert docstring.returns.description == "description"
assert not docstring.returns.is_generator
docstring = parse(
"""
Short description
@return: description
@rtype: int
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name == "int"
assert docstring.returns.description == "description"
assert not docstring.returns.is_generator
def test_yields() -> None:
"""Test parsing yields."""
docstring = parse(
"""
Short description
"""
)
assert docstring.returns is None
docstring = parse(
"""
Short description
@yield: description
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name is None
assert docstring.returns.description == "description"
assert docstring.returns.is_generator
docstring = parse(
"""
Short description
@yield: description
@ytype: int
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name == "int"
assert docstring.returns.description == "description"
assert docstring.returns.is_generator
def test_raises() -> None:
"""Test parsing raises."""
docstring = parse(
"""
Short description
"""
)
assert len(docstring.raises) == 0
docstring = parse(
"""
Short description
@raise: description
"""
)
assert len(docstring.raises) == 1
assert docstring.raises[0].type_name is None
assert docstring.raises[0].description == "description"
docstring = parse(
"""
Short description
@raise ValueError: description
"""
)
assert len(docstring.raises) == 1
assert docstring.raises[0].type_name == "ValueError"
assert docstring.raises[0].description == "description"
def test_broken_meta() -> None:
"""Test parsing broken meta."""
with pytest.raises(ParseError):
parse("@")
with pytest.raises(ParseError):
parse("@param herp derp")
with pytest.raises(ParseError):
parse("@param: invalid")
with pytest.raises(ParseError):
parse("@param with too many args: desc")
# these should not raise any errors
parse("@sthstrange: desc")
@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\n@meta: asd",
),
(
"""
Short description
Long description
@meta: asd
""",
"Short description\nLong description\n@meta: asd",
),
(
"""
Short description
First line
Second line
@meta: asd
""",
"Short description\nFirst line\n Second line\n@meta: asd",
),
(
"""
Short description
First line
Second line
@meta: asd
""",
"Short description\n"
"\n"
"First line\n"
" Second line\n"
"@meta: asd",
),
(
"""
Short description
First line
Second line
@meta: asd
""",
"Short description\n"
"\n"
"First line\n"
" Second line\n"
"\n"
"@meta: asd",
),
(
"""
@meta: asd
""",
"@meta: asd",
),
(
"""
Short description
@meta: asd
1
2
3
""",
"Short description\n"
"\n"
"@meta: asd\n"
" 1\n"
" 2\n"
" 3",
),
(
"""
Short description
@meta1: asd
1
2
3
@meta2: herp
@meta3: derp
""",
"Short description\n"
"\n@meta1: asd\n"
" 1\n"
" 2\n"
" 3\n@meta2: herp\n"
"@meta3: derp",
),
(
"""
Short description
@meta ene due rabe: asd
""",
"Short description\n\n@meta ene due rabe: asd",
),
(
"""
Short description
@param name: description 1
@param priority: description 2
@type priority: int
@param sender: description 3
@type sender: str?
@type message: str?
@param message: description 4, defaults to 'hello'
@type multiline: str?
@param multiline: long description 5,
defaults to 'bye'
""",
"Short description\n"
"\n"
"@param name: description 1\n"
"@type priority: int\n"
"@param priority: description 2\n"
"@type sender: str?\n"
"@param sender: description 3\n"
"@type message: str?\n"
"@param message: description 4, defaults to 'hello'\n"
"@type multiline: str?\n"
"@param multiline: long description 5,\n"
" defaults to 'bye'",
),
(
"""
Short description
@raise: description
""",
"Short description\n@raise: description",
),
(
"""
Short description
@raise ValueError: description
""",
"Short description\n@raise 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
@param name: description 1
@param priority: description 2
@type priority: int
@param sender: description 3
@type sender: str?
@type message: str?
@param message: description 4, defaults to 'hello'
@type multiline: str?
@param multiline: long description 5,
defaults to 'bye'
""",
"Short description\n"
"\n"
"@param name:\n"
" description 1\n"
"@type priority: int\n"
"@param priority:\n"
" description 2\n"
"@type sender: str?\n"
"@param sender:\n"
" description 3\n"
"@type message: str?\n"
"@param message:\n"
" description 4, defaults to 'hello'\n"
"@type multiline: str?\n"
"@param multiline:\n"
" 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
@param name: description 1
@param priority: description 2
@type priority: int
@param sender: description 3
@type sender: str?
@type message: str?
@param message: description 4, defaults to 'hello'
@type multiline: str?
@param multiline: long description 5,
defaults to 'bye'
""",
"Short description\n"
"\n"
"@param name:\n"
" description 1\n"
"@type priority:\n"
" int\n"
"@param priority:\n"
" description 2\n"
"@type sender:\n"
" str?\n"
"@param sender:\n"
" description 3\n"
"@type message:\n"
" str?\n"
"@param message:\n"
" description 4, defaults to 'hello'\n"
"@type multiline:\n"
" str?\n"
"@param multiline:\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
)
def test_short_rtype() -> None:
"""Test abbreviated docstring with only return type information."""
string = "Short description.\n\n@rtype: float"
docstring = parse(string)
assert compose(docstring) == string

View File

@@ -0,0 +1,977 @@
"""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
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,109 @@
"""Tests for parse_from_object function and attribute docstrings."""
from unittest.mock import patch
from docstring_parser import parse_from_object
module_attr: int = 1
"""Description for module_attr"""
def test_from_module_attribute_docstrings() -> None:
"""Test the parse of attribute docstrings from a module."""
from . import test_parse_from_object # pylint: disable=C0415,W0406
docstring = parse_from_object(test_parse_from_object)
assert "parse_from_object" in docstring.short_description
assert len(docstring.params) == 1
assert docstring.params[0].arg_name == "module_attr"
assert docstring.params[0].type_name == "int"
assert docstring.params[0].description == "Description for module_attr"
def test_from_class_attribute_docstrings() -> None:
"""Test the parse of attribute docstrings from a class."""
class StandardCase:
"""Short description
Long description
"""
attr_one: str
"""Description for attr_one"""
attr_two: bool = False
"""Description for attr_two"""
docstring = parse_from_object(StandardCase)
assert docstring.short_description == "Short description"
assert docstring.long_description == "Long description"
assert docstring.description == "Short description\nLong description"
assert len(docstring.params) == 2
assert docstring.params[0].arg_name == "attr_one"
assert docstring.params[0].type_name == "str"
assert docstring.params[0].description == "Description for attr_one"
assert docstring.params[1].arg_name == "attr_two"
assert docstring.params[1].type_name == "bool"
assert docstring.params[1].description == "Description for attr_two"
def test_from_class_attribute_docstrings_without_type() -> None:
"""Test the parse of untyped attribute docstrings."""
class WithoutType: # pylint: disable=missing-class-docstring
attr_one = "value"
"""Description for attr_one"""
docstring = parse_from_object(WithoutType)
assert docstring.short_description is None
assert docstring.long_description is None
assert docstring.description is None
assert len(docstring.params) == 1
assert docstring.params[0].arg_name == "attr_one"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "Description for attr_one"
def test_from_class_without_source() -> None:
"""Test the parse of class when source is unavailable."""
class WithoutSource:
"""Short description"""
attr_one: str
"""Description for attr_one"""
with patch(
"inspect.getsource", side_effect=OSError("could not get source code")
):
docstring = parse_from_object(WithoutSource)
assert docstring.short_description == "Short description"
assert docstring.long_description is None
assert docstring.description == "Short description"
assert len(docstring.params) == 0
def test_from_function() -> None:
"""Test the parse of a function docstring."""
def a_function(param1: str, param2: int = 2):
"""Short description
Args:
param1: Description for param1
param2: Description for param2
"""
return f"{param1} {param2}"
docstring = parse_from_object(a_function)
assert docstring.short_description == "Short description"
assert docstring.description == "Short description"
assert len(docstring.params) == 2
assert docstring.params[0].arg_name == "param1"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "Description for param1"
assert docstring.params[1].arg_name == "param2"
assert docstring.params[1].type_name is None
assert docstring.params[1].description == "Description for param2"

View File

@@ -0,0 +1,222 @@
"""Tests for generic docstring routines."""
import pytest
from docstring_parser.common import DocstringStyle, ParseError
from docstring_parser.parser import parse
def test_rest() -> None:
"""Test ReST-style parser autodetection."""
docstring = parse(
"""
Short description
Long description
Causing people to indent:
A lot sometimes
:param spam: spam desc
:param int bla: bla desc
:param str yay:
:raises ValueError: exc desc
:returns tuple: ret desc
"""
)
assert docstring.style == DocstringStyle.REST
assert docstring.short_description == "Short description"
assert docstring.long_description == (
"Long description\n\n"
"Causing people to indent:\n\n"
" A lot sometimes"
)
assert docstring.description == (
"Short description\n\n"
"Long description\n\n"
"Causing people to indent:\n\n"
" A lot sometimes"
)
assert len(docstring.params) == 3
assert docstring.params[0].arg_name == "spam"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "spam desc"
assert docstring.params[1].arg_name == "bla"
assert docstring.params[1].type_name == "int"
assert docstring.params[1].description == "bla desc"
assert docstring.params[2].arg_name == "yay"
assert docstring.params[2].type_name == "str"
assert docstring.params[2].description == ""
assert len(docstring.raises) == 1
assert docstring.raises[0].type_name == "ValueError"
assert docstring.raises[0].description == "exc desc"
assert docstring.returns is not None
assert docstring.returns.type_name == "tuple"
assert docstring.returns.description == "ret desc"
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
def test_google() -> None:
"""Test Google-style parser autodetection."""
docstring = parse(
"""Short description
Long description
Causing people to indent:
A lot sometimes
Args:
spam: spam desc
bla (int): bla desc
yay (str):
Raises:
ValueError: exc desc
Returns:
tuple: ret desc
"""
)
assert docstring.style == DocstringStyle.GOOGLE
assert docstring.short_description == "Short description"
assert docstring.long_description == (
"Long description\n\n"
"Causing people to indent:\n\n"
" A lot sometimes"
)
assert docstring.description == (
"Short description\n\n"
"Long description\n\n"
"Causing people to indent:\n\n"
" A lot sometimes"
)
assert len(docstring.params) == 3
assert docstring.params[0].arg_name == "spam"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "spam desc"
assert docstring.params[1].arg_name == "bla"
assert docstring.params[1].type_name == "int"
assert docstring.params[1].description == "bla desc"
assert docstring.params[2].arg_name == "yay"
assert docstring.params[2].type_name == "str"
assert docstring.params[2].description == ""
assert len(docstring.raises) == 1
assert docstring.raises[0].type_name == "ValueError"
assert docstring.raises[0].description == "exc desc"
assert docstring.returns is not None
assert docstring.returns.type_name == "tuple"
assert docstring.returns.description == "ret desc"
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
def test_numpydoc() -> None:
"""Test numpydoc-style parser autodetection."""
docstring = parse(
"""Short description
Long description
Causing people to indent:
A lot sometimes
Parameters
----------
spam
spam desc
bla : int
bla desc
yay : str
Raises
------
ValueError
exc desc
Other Parameters
----------------
this_guy : int, optional
you know him
Returns
-------
tuple
ret desc
See Also
--------
multiple lines...
something else?
Warnings
--------
multiple lines...
none of this is real!
"""
)
assert docstring.style == DocstringStyle.NUMPYDOC
assert docstring.short_description == "Short description"
assert docstring.long_description == (
"Long description\n\n"
"Causing people to indent:\n\n"
" A lot sometimes"
)
assert docstring.description == (
"Short description\n\n"
"Long description\n\n"
"Causing people to indent:\n\n"
" A lot sometimes"
)
assert len(docstring.params) == 4
assert docstring.params[0].arg_name == "spam"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "spam desc"
assert docstring.params[1].arg_name == "bla"
assert docstring.params[1].type_name == "int"
assert docstring.params[1].description == "bla desc"
assert docstring.params[2].arg_name == "yay"
assert docstring.params[2].type_name == "str"
assert docstring.params[2].description is None
assert docstring.params[3].arg_name == "this_guy"
assert docstring.params[3].type_name == "int"
assert docstring.params[3].is_optional
assert docstring.params[3].description == "you know him"
assert len(docstring.raises) == 1
assert docstring.raises[0].type_name == "ValueError"
assert docstring.raises[0].description == "exc desc"
assert docstring.returns is not None
assert docstring.returns.type_name == "tuple"
assert docstring.returns.description == "ret desc"
assert docstring.many_returns is not None
assert len(docstring.many_returns) == 1
assert docstring.many_returns[0] == docstring.returns
def test_autodetection_error_detection() -> None:
"""Test autodection for the case where one of the parsers throws an error
and another one succeeds.
"""
source = """
Does something useless
:param 3 + 3 a: a param
"""
with pytest.raises(ParseError):
# assert that one of the parsers does raise
parse(source, DocstringStyle.REST)
# assert that autodetection still works
docstring = parse(source)
assert docstring
assert docstring.style == DocstringStyle.GOOGLE

View File

@@ -0,0 +1,541 @@
"""Tests for ReST-style docstring routines."""
import typing as T
import pytest
from docstring_parser.common import ParseError, RenderingStyle
from docstring_parser.rest import compose, parse
@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.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, "
"expected_full_desc",
[
(
"""
Short description
:meta: asd
""",
"Short description",
None,
False,
False,
"Short description",
),
(
"""
Short description
Long description
:meta: asd
""",
"Short description",
"Long description",
False,
False,
"Short description\nLong description",
),
(
"""
Short description
First line
Second line
:meta: asd
""",
"Short description",
"First line\n Second line",
False,
False,
"Short description\nFirst line\n Second line",
),
(
"""
Short description
First line
Second line
:meta: asd
""",
"Short description",
"First line\n Second line",
True,
False,
"Short description\n\nFirst line\n Second line",
),
(
"""
Short description
First line
Second line
:meta: asd
""",
"Short description",
"First line\n Second line",
True,
True,
"Short description\n\nFirst line\n Second line",
),
(
"""
:meta: asd
""",
None,
None,
False,
False,
None,
),
],
)
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,
expected_full_desc: T.Optional[str],
) -> 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 docstring.description == expected_full_desc
assert len(docstring.meta) == 1
def test_meta_with_multiline_description() -> None:
"""Test parsing multiline meta documentation."""
docstring = parse(
"""
Short description
:meta: asd
1
2
3
"""
)
assert docstring.short_description == "Short description"
assert len(docstring.meta) == 1
assert docstring.meta[0].args == ["meta"]
assert docstring.meta[0].description == "asd\n1\n 2\n3"
def test_multiple_meta() -> None:
"""Test parsing multiple meta."""
docstring = parse(
"""
Short description
:meta1: asd
1
2
3
:meta2: herp
:meta3: derp
"""
)
assert docstring.short_description == "Short description"
assert len(docstring.meta) == 3
assert docstring.meta[0].args == ["meta1"]
assert docstring.meta[0].description == "asd\n1\n 2\n3"
assert docstring.meta[1].args == ["meta2"]
assert docstring.meta[1].description == "herp"
assert docstring.meta[2].args == ["meta3"]
assert docstring.meta[2].description == "derp"
def test_meta_with_args() -> None:
"""Test parsing meta with additional arguments."""
docstring = parse(
"""
Short description
:meta ene due rabe: asd
"""
)
assert docstring.short_description == "Short description"
assert len(docstring.meta) == 1
assert docstring.meta[0].args == ["meta", "ene", "due", "rabe"]
assert docstring.meta[0].description == "asd"
def test_params() -> None:
"""Test parsing params."""
docstring = parse("Short description")
assert len(docstring.params) == 0
docstring = parse(
"""
Short description
:param name: description 1
:param int priority: description 2
:param str? sender: description 3
:param str? message: description 4, defaults to 'hello'
:param str? multiline: long description 5,
defaults to 'bye'
"""
)
assert len(docstring.params) == 5
assert docstring.params[0].arg_name == "name"
assert docstring.params[0].type_name is None
assert docstring.params[0].description == "description 1"
assert docstring.params[0].default is None
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[1].default is None
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[2].default is None
assert docstring.params[3].arg_name == "message"
assert docstring.params[3].type_name == "str"
assert (
docstring.params[3].description == "description 4, defaults to 'hello'"
)
assert docstring.params[3].is_optional
assert docstring.params[3].default == "'hello'"
assert docstring.params[4].arg_name == "multiline"
assert docstring.params[4].type_name == "str"
assert (
docstring.params[4].description
== "long description 5,\ndefaults to 'bye'"
)
assert docstring.params[4].is_optional
assert docstring.params[4].default == "'bye'"
docstring = parse(
"""
Short description
:param a: description a
:type a: int
:param int b: description b
"""
)
assert len(docstring.params) == 2
assert docstring.params[0].arg_name == "a"
assert docstring.params[0].type_name == "int"
assert docstring.params[0].description == "description a"
assert docstring.params[0].default is None
assert not docstring.params[0].is_optional
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 not docstring.returns.is_generator
assert docstring.many_returns == [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 not docstring.returns.is_generator
assert docstring.many_returns == [docstring.returns]
docstring = parse(
"""
Short description
:returns: description
:rtype: int
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name == "int"
assert docstring.returns.description == "description"
assert not docstring.returns.is_generator
assert docstring.many_returns == [docstring.returns]
def test_yields() -> None:
"""Test parsing yields."""
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
:yields: description
"""
)
assert docstring.returns is not None
assert docstring.returns.type_name is None
assert docstring.returns.description == "description"
assert docstring.returns.is_generator
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.returns.is_generator
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: description
"""
)
assert len(docstring.raises) == 1
assert docstring.raises[0].type_name is None
assert docstring.raises[0].description == "description"
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_broken_meta() -> None:
"""Test parsing broken meta."""
with pytest.raises(ParseError):
parse(":")
with pytest.raises(ParseError):
parse(":param herp derp")
with pytest.raises(ParseError):
parse(":param: invalid")
with pytest.raises(ParseError):
parse(":param with too many args: desc")
# these should not raise any errors
parse(":sthstrange: desc")
def test_deprecation() -> None:
"""Test parsing deprecation notes."""
docstring = parse(":deprecation: 1.1.0 this function will be removed")
assert docstring.deprecation is not None
assert docstring.deprecation.version == "1.1.0"
assert docstring.deprecation.description == "this function will be removed"
docstring = parse(":deprecation: this function will be removed")
assert docstring.deprecation is not None
assert docstring.deprecation.version is None
assert docstring.deprecation.description == "this function will be removed"
@pytest.mark.parametrize(
"rendering_style, expected",
[
(
RenderingStyle.COMPACT,
"Short description.\n"
"\n"
"Long description.\n"
"\n"
":param int foo: a description\n"
":param int bar: another description\n"
":returns float: a return",
),
(
RenderingStyle.CLEAN,
"Short description.\n"
"\n"
"Long description.\n"
"\n"
":param int foo: a description\n"
":param int bar: another description\n"
":returns float: a return",
),
(
RenderingStyle.EXPANDED,
"Short description.\n"
"\n"
"Long description.\n"
"\n"
":param foo:\n"
" a description\n"
":type foo: int\n"
":param bar:\n"
" another description\n"
":type bar: int\n"
":returns:\n"
" a return\n"
":rtype: float",
),
],
)
def test_compose(rendering_style: RenderingStyle, expected: str) -> None:
"""Test compose"""
docstring = parse(
"""
Short description.
Long description.
:param int foo: a description
:param int bar: another description
:return float: a return
"""
)
assert compose(docstring, rendering_style=rendering_style) == expected
def test_short_rtype() -> None:
"""Test abbreviated docstring with only return type information."""
string = "Short description.\n\n:rtype: float"
docstring = parse(string)
rendering_style = RenderingStyle.EXPANDED
assert compose(docstring, rendering_style=rendering_style) == string

View File

@@ -0,0 +1,64 @@
"""Test for utility functions."""
from docstring_parser.common import DocstringReturns
from docstring_parser.util import combine_docstrings
def test_combine_docstrings() -> None:
"""Test combine_docstrings wrapper."""
def fun1(arg_a, arg_b, arg_c, arg_d):
"""short_description: fun1
:param arg_a: fun1
:param arg_b: fun1
:return: fun1
"""
assert arg_a and arg_b and arg_c and arg_d
def fun2(arg_b, arg_c, arg_d, arg_e):
"""short_description: fun2
long_description: fun2
:param arg_b: fun2
:param arg_c: fun2
:param arg_e: fun2
"""
assert arg_b and arg_c and arg_d and arg_e
@combine_docstrings(fun1, fun2)
def decorated1(arg_a, arg_b, arg_c, arg_d, arg_e, arg_f):
"""
:param arg_e: decorated
:param arg_f: decorated
"""
assert arg_a and arg_b and arg_c and arg_d and arg_e and arg_f
assert decorated1.__doc__ == (
"short_description: fun2\n"
"\n"
"long_description: fun2\n"
"\n"
":param arg_a: fun1\n"
":param arg_b: fun1\n"
":param arg_c: fun2\n"
":param arg_e: fun2\n"
":param arg_f: decorated\n"
":returns: fun1"
)
@combine_docstrings(fun1, fun2, exclude=[DocstringReturns])
def decorated2(arg_a, arg_b, arg_c, arg_d, arg_e, arg_f):
assert arg_a and arg_b and arg_c and arg_d and arg_e and arg_f
assert decorated2.__doc__ == (
"short_description: fun2\n"
"\n"
"long_description: fun2\n"
"\n"
":param arg_a: fun1\n"
":param arg_b: fun1\n"
":param arg_c: fun2\n"
":param arg_e: fun2"
)