Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add docstring automation to get help message to typer objects #436

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions tests/assets/cli/multiapp-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The end

Top command


**Usage**:

```console
Expand Down Expand Up @@ -57,6 +58,7 @@ $ multiapp sub [OPTIONS] COMMAND [ARGS]...

Say Hello


**Usage**:

```console
Expand All @@ -73,6 +75,7 @@ $ multiapp sub hello [OPTIONS]

Say Hi


**Usage**:

```console
Expand All @@ -91,6 +94,7 @@ $ multiapp sub hi [OPTIONS] [USER]

Say bye


**Usage**:

```console
Expand Down
74 changes: 74 additions & 0 deletions tests/test_docstring_automation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from typing import Optional

import typer


def function_to_test_docstring(
param1: str, param2: int, param3: Optional[str] = None
) -> str:
"""Used by docstring automation tests."""


SUMMARY = "Function to test docstring styles."
PARAMS = {
"param1": "A very detailed description.",
"param2": "A small one.",
"param3": "A description with default value.",
}
DOCSTRINGS = {
"NUMPY": """
Function to test docstring styles.

Parameters
----------
param1 : str
A very detailed description.
param2 : int
A small one
param3 : Optional[str], optional
A description with default value, by default None

Returns
-------
str
Return information.

""",
"GOOGLE": """
Function to test docstring styles.

Args:
param1 (str): A very detailed description.
param2 (int): A small one
param3 (Optional[str], optional): A description with default value.
Defaults to None.

Returns:
str: Return information.

""",
"SPHINX": """
Function to test docstring styles.

:param param1: A very detailed description.
:type param1: str
:param param2: A small one
:type param2: int
:param param3: A description with default value, defaults to None
:type param3: Optional[str], optional
:return: Return information.
:rtype: str

""",
}

PRIORITY_SUMMARY = "Not automated!"
PRIORITY_PARAM_DOC = "A complete different one."


def function_to_test_priority(
param1: str = typer.Argument(...),
param2: int = typer.Argument(..., help=PRIORITY_PARAM_DOC),
param3: Optional[str] = None,
) -> str:
"""Used to test if docstring automation respects priority."""
59 changes: 59 additions & 0 deletions tests/test_docstring_automation/test_google.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import typer
import typer.core
from typer.testing import CliRunner

from . import (
DOCSTRINGS,
PARAMS,
PRIORITY_PARAM_DOC,
PRIORITY_SUMMARY,
SUMMARY,
function_to_test_docstring,
function_to_test_priority,
)

runner = CliRunner()


def test_google_docstring_parsing():
app = typer.Typer()
function_to_test_docstring.__doc__ = DOCSTRINGS["GOOGLE"]
app.command()(function_to_test_docstring)

result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Args:" not in result.output
assert "Returns:" not in result.output
assert "(str" not in result.output
assert "(int" not in result.output
assert "optional" not in result.output
assert " Defaults to" not in result.output

assert SUMMARY in result.output
assert all(param_doc in result.output for param_doc in PARAMS.values())


def test_google_docstring_parsing_priority():
app = typer.Typer()
function_to_test_priority.__doc__ = DOCSTRINGS["GOOGLE"]
app.command(help=PRIORITY_SUMMARY)(function_to_test_priority)

result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Args:" not in result.output
assert "Returns:" not in result.output
assert "(str" not in result.output
assert "(int" not in result.output
assert "optional" not in result.output
assert " Defaults to" not in result.output

assert SUMMARY not in result.output
assert PRIORITY_SUMMARY in result.output

assert PARAMS["param1"] in result.output
assert PARAMS["param2"] not in result.output
assert PRIORITY_PARAM_DOC in result.output
assert PARAMS["param3"] in result.output


# TODO def test_google_docstring_parsing_with line_breaking_param_doc():
42 changes: 42 additions & 0 deletions tests/test_docstring_automation/test_no_style.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import Optional

import typer
import typer.core
from typer.testing import CliRunner


def function_to_test_no_style_docstring(
param1: str, param2: int, param3: Optional[str] = None
) -> str:
"""Function to test No style docstring."""


def function_to_test_priority(
param1: str = typer.Argument(...),
param2: int = typer.Argument(..., help="A complete different one."),
param3: Optional[str] = None,
) -> str:
"""Function to test No style docstring."""


runner = CliRunner()


def test_no_style_help():
app = typer.Typer()
app.command()(function_to_test_no_style_docstring)

result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Function to test No style docstring." in result.output


def test_help_priority():
app = typer.Typer()
app.command(help="Not automated!")(function_to_test_priority)

result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Function to test No style docstring." not in result.output
assert "Not automated!" in result.output
assert "A complete different one." in result.output
63 changes: 63 additions & 0 deletions tests/test_docstring_automation/test_numpy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import typer
import typer.core
from typer.testing import CliRunner

from . import (
DOCSTRINGS,
PARAMS,
PRIORITY_PARAM_DOC,
PRIORITY_SUMMARY,
SUMMARY,
function_to_test_docstring,
function_to_test_priority,
)

runner = CliRunner()


def test_numpy_docstring_parsing():
app = typer.Typer()
function_to_test_docstring.__doc__ = DOCSTRINGS["NUMPY"]
app.command()(function_to_test_docstring)

result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Parameters" not in result.output
assert "----------" not in result.output
assert "Returns" not in result.output
assert "-------" not in result.output
assert ": str" not in result.output
assert ": int" not in result.output
assert "optional" not in result.output
assert ", by default" not in result.output

assert SUMMARY in result.output
assert all(param_doc in result.output for param_doc in PARAMS.values())


def test_numpy_docstring_parsing_priority():
app = typer.Typer()
function_to_test_priority.__doc__ = DOCSTRINGS["NUMPY"]
app.command(help=PRIORITY_SUMMARY)(function_to_test_priority)

result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Parameters" not in result.output
assert "----------" not in result.output
assert "Returns" not in result.output
assert "-------" not in result.output
assert ": str" not in result.output
assert ": int" not in result.output
assert "optional" not in result.output
assert ", by default" not in result.output

assert SUMMARY not in result.output
assert PRIORITY_SUMMARY in result.output

assert PARAMS["param1"] in result.output
assert PARAMS["param2"] not in result.output
assert PRIORITY_PARAM_DOC in result.output
assert PARAMS["param3"] in result.output


# TODO def test_numpy_docstring_parsing_with line_breaking_param_doc():
63 changes: 63 additions & 0 deletions tests/test_docstring_automation/test_sphinx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import typer
import typer.core
from typer.testing import CliRunner

from . import (
DOCSTRINGS,
PARAMS,
PRIORITY_PARAM_DOC,
PRIORITY_SUMMARY,
SUMMARY,
function_to_test_docstring,
function_to_test_priority,
)

runner = CliRunner()


def test_sphinx_docstring_parsing():
app = typer.Typer()
function_to_test_docstring.__doc__ = DOCSTRINGS["SPHINX"]
app.command()(function_to_test_docstring)

result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert ":param" not in result.output
assert ":type" not in result.output
assert ":return:" not in result.output
assert ":rtype:" not in result.output
assert ": str" not in result.output
assert ": int" not in result.output
assert "optional" not in result.output
assert ", defaults to" not in result.output

assert SUMMARY in result.output
assert all(param_doc in result.output for param_doc in PARAMS.values())


def test_sphinx_docstring_parsing_priority():
app = typer.Typer()
function_to_test_priority.__doc__ = DOCSTRINGS["SPHINX"]
app.command(help=PRIORITY_SUMMARY)(function_to_test_priority)

result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert ":param" not in result.output
assert ":type" not in result.output
assert ":return:" not in result.output
assert ":rtype:" not in result.output
assert ": str" not in result.output
assert ": int" not in result.output
assert "optional" not in result.output
assert ", defaults to" not in result.output

assert SUMMARY not in result.output
assert PRIORITY_SUMMARY in result.output

assert PARAMS["param1"] in result.output
assert PARAMS["param2"] not in result.output
assert PRIORITY_PARAM_DOC in result.output
assert PARAMS["param3"] in result.output


# TODO def test_sphinx_docstring_parsing_with line_breaking_param_doc():
Loading
Loading