Skip to content

Commit 082d578

Browse files
committed
Allow changing the usage width
Signed-off-by: Bernát Gábor <[email protected]>
1 parent 8bbd1cd commit 082d578

File tree

6 files changed

+61
-19
lines changed

6 files changed

+61
-19
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## 1.3.0 (2021-02-13)
6+
7+
- Add support for changing the usage width
8+
59
## 1.2.0 (2021-02-05)
610

711
- Add support for changing (removing) the title via the `title` attribute of the directive.

README.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)
1212

1313
Render CLI arguments (sub-commands friendly) defined by the argparse module. For live demo checkout the documentation of
14-
[tox](https://tox.readthedocs.io/en/rewrite/cli_interface.html) and [mdpo](https://mdpo.readthedocs.io/en/latest/cli.html#command-line-interfaces).
14+
[tox](https://tox.readthedocs.io/en/rewrite/cli_interface.html) and
15+
[mdpo](https://mdpo.readthedocs.io/en/latest/cli.html#command-line-interfaces).
1516

1617
## installation
1718

@@ -30,12 +31,15 @@ extensions = ["sphinx_argparse_cli"]
3031

3132
Within the reStructuredText files use the `sphinx_argparse_cli` directive that takes, at least, two arguments:
3233

33-
- the module path to where the parser is defined,
34-
- a no argument function within that module that once called returns the constructed
35-
[argparse](https://docs.python.org/3/library/argparse.html) parser
36-
- (optional) a program name that overwrites the autodiscovered running argument parser
37-
- (optional) a `:title:` argument which, when provided, overwrites the `<prog> - CLI interface` title added by default
38-
and when empty, will not be included
34+
| Name | Description |
35+
| ----------- | ----------------------------------------------------------------------------------------------------------------------------- |
36+
| module | the module path to where the parser is defined |
37+
| func | the module path to where the parser is defined |
38+
| prog | (optional) the module path to where the parser is defined |
39+
| title | (optional) when provided, overwrites the `<prog> - CLI interface` title added by default and when empty, will not be included |
40+
| usage_width | (optional) how large should usage examples be - defaults to 100 character |
41+
42+
For example:
3943

4044
```rst
4145
.. sphinx_argparse_cli::

src/sphinx_argparse_cli/_logic.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class SphinxArgparseCli(SphinxDirective):
4747
"func": unchanged_required,
4848
"prog": unchanged,
4949
"title": unchanged,
50+
"usage_width": unchanged,
5051
}
5152

5253
def __init__(
@@ -185,7 +186,7 @@ def _mk_sub_command(self, aliases: list[str], help_msg: str, parser: ArgumentPar
185186
return group_section
186187

187188
def _mk_usage(self, parser: ArgumentParser) -> literal_block:
188-
parser.formatter_class = lambda prog: HelpFormatter(prog, width=100)
189+
parser.formatter_class = lambda prog: HelpFormatter(prog, width=int(self.options.get("usage_width", 100)))
189190
texts = parser.format_usage()[len("usage: ") :].splitlines()
190191
texts = [line if at == 0 else f"{' ' * (len(parser.prog) + 1)}{line.lstrip()}" for at, line in enumerate(texts)]
191192
return literal_block("", Text("\n".join(texts)))

tests/test_logic.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from __future__ import annotations
22

3+
import os
34
from pathlib import Path
5+
from typing import cast
46

57
import pytest
68
from _pytest.fixtures import SubRequest
@@ -9,39 +11,65 @@
911

1012
@pytest.fixture()
1113
def build_outcome(app: SphinxTestApp, request: SubRequest) -> str:
14+
prepare_marker = request.node.get_closest_marker("prepare")
15+
if prepare_marker:
16+
directive_args: list[str] | None = prepare_marker.kwargs.get("directive_args")
17+
if directive_args:
18+
index = Path(cast(str, app.confdir)) / "index.rst"
19+
if not any(i for i in directive_args if i.startswith(":module:")):
20+
directive_args.append(":module: parser")
21+
if not any(i for i in directive_args if i.startswith(":func:")):
22+
directive_args.append(":func: make")
23+
args = [f" {i}" for i in directive_args]
24+
index.write_text(os.linesep.join([".. sphinx_argparse_cli::"] + args))
25+
26+
ext_mapping = {"html": "html", "text": "txt"}
27+
sphinx_marker = request.node.get_closest_marker("sphinx")
28+
assert sphinx_marker is not None
29+
ext = ext_mapping[sphinx_marker.kwargs.get("buildername")]
30+
1231
app.build()
13-
ext = {"html": "html", "text": "txt"}
14-
ext = ext.get(request.node.get_closest_marker("sphinx").args[0])
15-
assert ext is not None
1632
return (Path(app.outdir) / f"index.{ext}").read_text()
1733

1834

19-
@pytest.mark.sphinx("html", testroot="basic")
35+
@pytest.mark.sphinx(buildername="html", testroot="basic")
2036
def test_basic_as_html(build_outcome: str) -> None:
2137
assert build_outcome
2238

2339

24-
@pytest.mark.sphinx("text", testroot="complex")
40+
@pytest.mark.sphinx(buildername="text", testroot="complex")
2541
def test_complex_as_text(build_outcome: str) -> None:
2642
expected = (Path(__file__).parent / "complex.txt").read_text()
2743
assert build_outcome == expected
2844

2945

30-
@pytest.mark.sphinx("html", testroot="complex")
46+
@pytest.mark.sphinx(buildername="html", testroot="complex")
3147
def test_complex_as_html(build_outcome: str) -> None:
3248
assert build_outcome
3349

3450

35-
@pytest.mark.sphinx("text", testroot="prog")
51+
@pytest.mark.sphinx(buildername="text", testroot="prog")
3652
def test_prog_as_text(build_outcome: str) -> None:
3753
assert build_outcome == "magic - CLI interface\n*********************\n\n magic\n"
3854

3955

40-
@pytest.mark.sphinx("text", testroot="title-set")
56+
@pytest.mark.sphinx(buildername="text", testroot="title-set")
4157
def test_set_title_as_text(build_outcome: str) -> None:
4258
assert build_outcome == "My own title\n************\n\n foo\n"
4359

4460

45-
@pytest.mark.sphinx("text", testroot="title-empty")
61+
@pytest.mark.sphinx(buildername="text", testroot="title-empty")
4662
def test_empty_title_as_text(build_outcome: str) -> None:
4763
assert build_outcome == " foo\n"
64+
65+
66+
@pytest.mark.sphinx(buildername="text", testroot="complex")
67+
@pytest.mark.prepare(directive_args=[":usage_width: 100"])
68+
def test_usage_width_default(build_outcome: str) -> None:
69+
assert "complex second [-h] [--flag] [--root] one pos_two\n" in build_outcome
70+
71+
72+
@pytest.mark.sphinx(buildername="text", testroot="complex")
73+
@pytest.mark.prepare(directive_args=[":usage_width: 50"])
74+
def test_usage_width_custom(build_outcome: str) -> None:
75+
assert "complex second [-h] [--flag] [--root]\n" in build_outcome

tox.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,5 @@ commands =
7878

7979
[pytest]
8080
junit_family = xunit2
81+
markers =
82+
prepare

whitelist.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
Formattter
2-
autouse
3-
subparsers
42
autosectionlabel
3+
autouse
4+
buildername
5+
confdir
56
desc
67
dest
78
docutils
89
formatter
910
fromlist
1011
func
1112
lineno
13+
linesep
1214
metavar
1315
nitpicky
1416
outdir
@@ -18,5 +20,6 @@ prog
1820
refid
1921
rst
2022
statemachine
23+
subparsers
2124
testroot
2225
util

0 commit comments

Comments
 (0)