You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
432 lines
13 KiB
432 lines
13 KiB
"""
|
|
Test suite for the custom docstring parser implementation.
|
|
|
|
This module contains comprehensive tests to ensure the docstring parser
|
|
works correctly with various docstring formats and edge cases.
|
|
"""
|
|
|
|
import pytest
|
|
from swarms.utils.docstring_parser import (
|
|
parse,
|
|
DocstringParam,
|
|
)
|
|
|
|
|
|
class TestDocstringParser:
|
|
"""Test cases for the docstring parser functionality."""
|
|
|
|
def test_empty_docstring(self):
|
|
"""Test parsing of empty docstring."""
|
|
result = parse("")
|
|
assert result.short_description is None
|
|
assert result.params == []
|
|
|
|
def test_none_docstring(self):
|
|
"""Test parsing of None docstring."""
|
|
result = parse(None)
|
|
assert result.short_description is None
|
|
assert result.params == []
|
|
|
|
def test_whitespace_only_docstring(self):
|
|
"""Test parsing of whitespace-only docstring."""
|
|
result = parse(" \n \t \n ")
|
|
assert result.short_description is None
|
|
assert result.params == []
|
|
|
|
def test_simple_docstring_no_args(self):
|
|
"""Test parsing of simple docstring without Args section."""
|
|
docstring = """
|
|
This is a simple function.
|
|
|
|
Returns:
|
|
str: A simple string
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description == "This is a simple function."
|
|
)
|
|
assert result.params == []
|
|
|
|
def test_docstring_with_args(self):
|
|
"""Test parsing of docstring with Args section."""
|
|
docstring = """
|
|
This is a test function.
|
|
|
|
Args:
|
|
param1 (str): First parameter
|
|
param2 (int): Second parameter
|
|
param3 (bool, optional): Third parameter with default
|
|
|
|
Returns:
|
|
str: Return value description
|
|
"""
|
|
result = parse(docstring)
|
|
assert result.short_description == "This is a test function."
|
|
assert len(result.params) == 3
|
|
assert result.params[0] == DocstringParam(
|
|
"param1", "First parameter"
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"param2", "Second parameter"
|
|
)
|
|
assert result.params[2] == DocstringParam(
|
|
"param3", "Third parameter with default"
|
|
)
|
|
|
|
def test_docstring_with_parameters_section(self):
|
|
"""Test parsing of docstring with Parameters section."""
|
|
docstring = """
|
|
Another test function.
|
|
|
|
Parameters:
|
|
name (str): The name parameter
|
|
age (int): The age parameter
|
|
|
|
Returns:
|
|
None: Nothing is returned
|
|
"""
|
|
result = parse(docstring)
|
|
assert result.short_description == "Another test function."
|
|
assert len(result.params) == 2
|
|
assert result.params[0] == DocstringParam(
|
|
"name", "The name parameter"
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"age", "The age parameter"
|
|
)
|
|
|
|
def test_docstring_with_multiline_param_description(self):
|
|
"""Test parsing of docstring with multiline parameter descriptions."""
|
|
docstring = """
|
|
Function with multiline descriptions.
|
|
|
|
Args:
|
|
param1 (str): This is a very long description
|
|
that spans multiple lines and should be
|
|
properly concatenated.
|
|
param2 (int): Short description
|
|
|
|
Returns:
|
|
str: Result
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Function with multiline descriptions."
|
|
)
|
|
assert len(result.params) == 2
|
|
expected_desc = "This is a very long description that spans multiple lines and should be properly concatenated."
|
|
assert result.params[0] == DocstringParam(
|
|
"param1", expected_desc
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"param2", "Short description"
|
|
)
|
|
|
|
def test_docstring_without_type_annotations(self):
|
|
"""Test parsing of docstring without type annotations."""
|
|
docstring = """
|
|
Function without type annotations.
|
|
|
|
Args:
|
|
param1: First parameter without type
|
|
param2: Second parameter without type
|
|
|
|
Returns:
|
|
str: Result
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Function without type annotations."
|
|
)
|
|
assert len(result.params) == 2
|
|
assert result.params[0] == DocstringParam(
|
|
"param1", "First parameter without type"
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"param2", "Second parameter without type"
|
|
)
|
|
|
|
def test_pydantic_style_docstring(self):
|
|
"""Test parsing of Pydantic-style docstring."""
|
|
docstring = """
|
|
Convert a Pydantic model to a dictionary representation of functions.
|
|
|
|
Args:
|
|
pydantic_type (type[BaseModel]): The Pydantic model type to convert.
|
|
|
|
Returns:
|
|
dict[str, Any]: A dictionary representation of the functions.
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Convert a Pydantic model to a dictionary representation of functions."
|
|
)
|
|
assert len(result.params) == 1
|
|
assert result.params[0] == DocstringParam(
|
|
"pydantic_type", "The Pydantic model type to convert."
|
|
)
|
|
|
|
def test_docstring_with_various_sections(self):
|
|
"""Test parsing of docstring with multiple sections."""
|
|
docstring = """
|
|
Complex function with multiple sections.
|
|
|
|
Args:
|
|
input_data (dict): Input data dictionary
|
|
validate (bool): Whether to validate input
|
|
|
|
Returns:
|
|
dict: Processed data
|
|
|
|
Raises:
|
|
ValueError: If input is invalid
|
|
|
|
Note:
|
|
This is a note section
|
|
|
|
Example:
|
|
>>> result = complex_function({"key": "value"})
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Complex function with multiple sections."
|
|
)
|
|
assert len(result.params) == 2
|
|
assert result.params[0] == DocstringParam(
|
|
"input_data", "Input data dictionary"
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"validate", "Whether to validate input"
|
|
)
|
|
|
|
def test_docstring_with_see_also_section(self):
|
|
"""Test parsing of docstring with See Also section."""
|
|
docstring = """
|
|
Function with See Also section.
|
|
|
|
Args:
|
|
param1 (str): First parameter
|
|
|
|
See Also:
|
|
related_function: For related functionality
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Function with See Also section."
|
|
)
|
|
assert len(result.params) == 1
|
|
assert result.params[0] == DocstringParam(
|
|
"param1", "First parameter"
|
|
)
|
|
|
|
def test_docstring_with_see_also_underscore_section(self):
|
|
"""Test parsing of docstring with See_Also section (underscore variant)."""
|
|
docstring = """
|
|
Function with See_Also section.
|
|
|
|
Args:
|
|
param1 (str): First parameter
|
|
|
|
See_Also:
|
|
related_function: For related functionality
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Function with See_Also section."
|
|
)
|
|
assert len(result.params) == 1
|
|
assert result.params[0] == DocstringParam(
|
|
"param1", "First parameter"
|
|
)
|
|
|
|
def test_docstring_with_yields_section(self):
|
|
"""Test parsing of docstring with Yields section."""
|
|
docstring = """
|
|
Generator function.
|
|
|
|
Args:
|
|
items (list): List of items to process
|
|
|
|
Yields:
|
|
str: Processed item
|
|
"""
|
|
result = parse(docstring)
|
|
assert result.short_description == "Generator function."
|
|
assert len(result.params) == 1
|
|
assert result.params[0] == DocstringParam(
|
|
"items", "List of items to process"
|
|
)
|
|
|
|
def test_docstring_with_raises_section(self):
|
|
"""Test parsing of docstring with Raises section."""
|
|
docstring = """
|
|
Function that can raise exceptions.
|
|
|
|
Args:
|
|
value (int): Value to process
|
|
|
|
Raises:
|
|
ValueError: If value is negative
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Function that can raise exceptions."
|
|
)
|
|
assert len(result.params) == 1
|
|
assert result.params[0] == DocstringParam(
|
|
"value", "Value to process"
|
|
)
|
|
|
|
def test_docstring_with_examples_section(self):
|
|
"""Test parsing of docstring with Examples section."""
|
|
docstring = """
|
|
Function with examples.
|
|
|
|
Args:
|
|
x (int): Input value
|
|
|
|
Examples:
|
|
>>> result = example_function(5)
|
|
>>> print(result)
|
|
"""
|
|
result = parse(docstring)
|
|
assert result.short_description == "Function with examples."
|
|
assert len(result.params) == 1
|
|
assert result.params[0] == DocstringParam("x", "Input value")
|
|
|
|
def test_docstring_with_note_section(self):
|
|
"""Test parsing of docstring with Note section."""
|
|
docstring = """
|
|
Function with a note.
|
|
|
|
Args:
|
|
data (str): Input data
|
|
|
|
Note:
|
|
This function is deprecated
|
|
"""
|
|
result = parse(docstring)
|
|
assert result.short_description == "Function with a note."
|
|
assert len(result.params) == 1
|
|
assert result.params[0] == DocstringParam(
|
|
"data", "Input data"
|
|
)
|
|
|
|
def test_docstring_with_complex_type_annotations(self):
|
|
"""Test parsing of docstring with complex type annotations."""
|
|
docstring = """
|
|
Function with complex types.
|
|
|
|
Args:
|
|
data (List[Dict[str, Any]]): Complex data structure
|
|
callback (Callable[[str], int]): Callback function
|
|
optional (Optional[str], optional): Optional parameter
|
|
|
|
Returns:
|
|
Union[str, None]: Result or None
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description == "Function with complex types."
|
|
)
|
|
assert len(result.params) == 3
|
|
assert result.params[0] == DocstringParam(
|
|
"data", "Complex data structure"
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"callback", "Callback function"
|
|
)
|
|
assert result.params[2] == DocstringParam(
|
|
"optional", "Optional parameter"
|
|
)
|
|
|
|
def test_docstring_with_no_description(self):
|
|
"""Test parsing of docstring with no description, only Args."""
|
|
docstring = """
|
|
Args:
|
|
param1 (str): First parameter
|
|
param2 (int): Second parameter
|
|
"""
|
|
result = parse(docstring)
|
|
assert result.short_description is None
|
|
assert len(result.params) == 2
|
|
assert result.params[0] == DocstringParam(
|
|
"param1", "First parameter"
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"param2", "Second parameter"
|
|
)
|
|
|
|
def test_docstring_with_empty_args_section(self):
|
|
"""Test parsing of docstring with empty Args section."""
|
|
docstring = """
|
|
Function with empty Args section.
|
|
|
|
Args:
|
|
|
|
Returns:
|
|
str: Result
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Function with empty Args section."
|
|
)
|
|
assert result.params == []
|
|
|
|
def test_docstring_with_mixed_indentation(self):
|
|
"""Test parsing of docstring with mixed indentation."""
|
|
docstring = """
|
|
Function with mixed indentation.
|
|
|
|
Args:
|
|
param1 (str): First parameter
|
|
with continuation
|
|
param2 (int): Second parameter
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Function with mixed indentation."
|
|
)
|
|
assert len(result.params) == 2
|
|
assert result.params[0] == DocstringParam(
|
|
"param1", "First parameter with continuation"
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"param2", "Second parameter"
|
|
)
|
|
|
|
def test_docstring_with_tab_indentation(self):
|
|
"""Test parsing of docstring with tab indentation."""
|
|
docstring = """
|
|
Function with tab indentation.
|
|
|
|
Args:
|
|
param1 (str): First parameter
|
|
param2 (int): Second parameter
|
|
"""
|
|
result = parse(docstring)
|
|
assert (
|
|
result.short_description
|
|
== "Function with tab indentation."
|
|
)
|
|
assert len(result.params) == 2
|
|
assert result.params[0] == DocstringParam(
|
|
"param1", "First parameter"
|
|
)
|
|
assert result.params[1] == DocstringParam(
|
|
"param2", "Second parameter"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__])
|