Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ All notable changes to this project will be documented in this file.
- Skip sub-commands added with `help=argparse.SUPPRESS` instead of rendering them with a `==SUPPRESS==` description.
- Use the description, or `arguments`, as the heading of an argument group without a title instead of rendering `None`
and emitting duplicate label warnings.
- Fix a crash on whitespace-only help text, render help that parses to lists or several paragraphs as blocks under the
argument instead of inside its paragraph, and drop the empty paragraph an empty `:description:` produced.

## 1.13.1

Expand Down
8 changes: 8 additions & 0 deletions roots/test-help-nodes/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from __future__ import annotations

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent))
extensions = ["sphinx_argparse_cli"]
nitpicky = True
4 changes: 4 additions & 0 deletions roots/test-help-nodes/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. sphinx_argparse_cli::
:module: parser
:func: make
:description:
11 changes: 11 additions & 0 deletions roots/test-help-nodes/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from __future__ import annotations

from argparse import ArgumentParser, RawTextHelpFormatter


def make() -> ArgumentParser:
parser = ArgumentParser(prog="prog", formatter_class=RawTextHelpFormatter, add_help=False)
parser.add_argument("--blank", help=" ")
parser.add_argument("--list", help="- item one\n- item two")
parser.add_argument("--two", help="first paragraph\n\nsecond paragraph")
return parser
23 changes: 14 additions & 9 deletions src/sphinx_argparse_cli/_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from sphinx.util.logging import getLogger

if TYPE_CHECKING:
from collections.abc import Callable, Iterator
from collections.abc import Callable, Iterator, Sequence

from sphinx.domains.std import StandardDomain
from sphinx.util.logging import SphinxLoggerAdapter
Expand Down Expand Up @@ -198,7 +198,7 @@ def run(self) -> list[Node]:
return [home_section]

def _pre_format(self, block: str | None) -> paragraph | literal_block | None:
if block is None:
if block is None or not block.strip():
return None
if self._raw_format and "\n" in block:
lit = literal_block("", Text(block), classes=["sphinx-argparse-cli-wrap"])
Expand Down Expand Up @@ -258,13 +258,17 @@ def _mk_option_line(self, action: Action, prefix: str) -> list_item:
else:
self._mk_option_name(line, prefix, as_key)

extra: Sequence[Node] = ()
if action.help:
help_text = load_help_text(action.help)
temp = paragraph()
self.state.nested_parse(StringList(help_text.split("\n")), 0, temp)
line += Text(" - ")
for content in cast("paragraph", temp.children[0]).children:
line += content
self.state.nested_parse(StringList(load_help_text(action.help).split("\n")), 0, temp)
# only a leading paragraph can share the option's line; anything else becomes a block under it
if temp.children and isinstance(temp.children[0], paragraph):
line += Text(" - ")
line += temp.children[0].children
extra = temp.children[1:]
else:
extra = temp.children
if (
"no_default_values" not in self.options
and action.default is not None
Expand All @@ -275,8 +279,9 @@ def _mk_option_line(self, action: Action, prefix: str) -> list_item:
line += Text(" (default: ")
line += literal(text=str(action.default).replace(str(Path.cwd()), "{cwd}"))
line += Text(")")
_protect_option_dashes(line)
return list_item("", line, ids=[])
item = list_item("", line, *extra, ids=[])
_protect_option_dashes(item)
return item

def _mk_option_name(self, line: paragraph, prefix: str, opt: str) -> None:
ref_id = self._make_id(f"{prefix}-{opt}")
Expand Down
38 changes: 36 additions & 2 deletions tests/test_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def test_set_description_as_text(build_outcome: str) -> None:

@pytest.mark.sphinx(buildername="text", testroot="description-empty")
def test_empty_description_as_text(build_outcome: str) -> None:
assert build_outcome == "foo - CLI interface\n*******************\n\n\n foo\n"
assert build_outcome == "foo - CLI interface\n*******************\n\n foo\n"


@pytest.mark.sphinx(buildername="html", testroot="description-multiline")
Expand All @@ -140,7 +140,7 @@ def test_set_epilog_as_text(build_outcome: str) -> None:

@pytest.mark.sphinx(buildername="text", testroot="epilog-empty")
def test_empty_epilog_as_text(build_outcome: str) -> None:
assert build_outcome == "foo - CLI interface\n*******************\n\n foo\n\n"
assert build_outcome == "foo - CLI interface\n*******************\n\n foo\n"


@pytest.mark.sphinx(buildername="html", testroot="epilog-multiline")
Expand Down Expand Up @@ -323,6 +323,40 @@ def test_usage_ignores_python_colors(build_outcome: str) -> None:
)


@pytest.mark.sphinx(buildername="text", testroot="help-nodes")
def test_help_nodes_as_text(build_outcome: str) -> None:
assert (
build_outcome
== """prog - CLI interface
********************

prog [--blank BLANK] [--list LIST] [--two TWO]


prog options
============

* **"--blank"** "BLANK"

* **"--list"** "LIST"

* item one

* item two

* **"--two"** "TWO" - first paragraph

second paragraph
"""
)


@pytest.mark.sphinx(buildername="html", testroot="help-nodes")
def test_help_nodes_as_html(build_outcome: str, warning: StringIO) -> None:
assert "<p></p>" not in build_outcome
assert not warning.getvalue()


@pytest.mark.sphinx(buildername="html", testroot="group-untitled")
def test_group_untitled(build_outcome: str, warning: StringIO) -> None:
headings = re.findall(r'<h2>(.*?)<a class="headerlink" href="(#[^"]+)"', build_outcome)
Expand Down