Skip to content

Commit a222470

Browse files
committed
Moved documentation annotation stripping into utility function. Changed argparse decorator to automatically strip annotations.
1 parent 96acc5a commit a222470

File tree

5 files changed

+48
-21
lines changed

5 files changed

+48
-21
lines changed

cmd2/cmd2.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
from .utils import (
140140
Settable,
141141
get_defining_class,
142+
strip_doc_annotations,
142143
)
143144

144145
# Set up readline
@@ -3808,23 +3809,7 @@ def _print_topics(self, header: str, cmds: List[str], verbose: bool) -> None:
38083809
doc = cmd_func.__doc__
38093810

38103811
# Attempt to locate the first documentation block
3811-
cmd_desc = ''
3812-
if doc:
3813-
found_first = False
3814-
for doc_line in doc.splitlines():
3815-
stripped_line = doc_line.strip()
3816-
3817-
# Don't include :param type lines
3818-
if stripped_line.startswith(':'):
3819-
if found_first:
3820-
break
3821-
elif stripped_line:
3822-
if found_first:
3823-
cmd_desc += "\n"
3824-
cmd_desc += stripped_line
3825-
found_first = True
3826-
elif found_first:
3827-
break
3812+
cmd_desc = strip_doc_annotations(doc) if doc else ''
38283813

38293814
# Add this command to the table
38303815
table_row = topic_table.generate_data_row([command, cmd_desc])

cmd2/decorators.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
from .parsing import (
3030
Statement,
3131
)
32+
from .utils import (
33+
strip_doc_annotations,
34+
)
3235

3336
if TYPE_CHECKING: # pragma: no cover
3437
import cmd2
@@ -384,7 +387,7 @@ def cmd_wrapper(*args: Any, **kwargs: Dict[str, Any]) -> Optional[bool]:
384387

385388
# If the description has not been set, then use the method docstring if one exists
386389
if parser.description is None and func.__doc__:
387-
parser.description = func.__doc__
390+
parser.description = strip_doc_annotations(func.__doc__)
388391

389392
# Set the command's help text as argparser.description (which can be None)
390393
cmd_wrapper.__doc__ = parser.description

cmd2/utils.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,3 +1228,29 @@ def __init__(self, parser: argparse.ArgumentParser, *, preserve_quotes: bool = F
12281228
"""
12291229
self.parser = parser
12301230
self.preserve_quotes = preserve_quotes
1231+
1232+
1233+
def strip_doc_annotations(doc: str) -> str:
1234+
"""
1235+
Strip annotations from a docstring leaving only the text description
1236+
1237+
:param doc: documentation string
1238+
"""
1239+
# Attempt to locate the first documentation block
1240+
cmd_desc = ''
1241+
found_first = False
1242+
for doc_line in doc.splitlines():
1243+
stripped_line = doc_line.strip()
1244+
1245+
# Don't include :param type lines
1246+
if stripped_line.startswith(':'):
1247+
if found_first:
1248+
break
1249+
elif stripped_line:
1250+
if found_first:
1251+
cmd_desc += "\n"
1252+
cmd_desc += stripped_line
1253+
found_first = True
1254+
elif found_first:
1255+
break
1256+
return cmd_desc

examples/arg_decorators.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ def do_fsize(self, args: argparse.Namespace) -> None:
4848

4949
@cmd2.with_argparser(pow_parser)
5050
def do_pow(self, args: argparse.Namespace) -> None:
51-
"""Raise an integer to a small integer exponent, either positive or negative"""
51+
"""
52+
Raise an integer to a small integer exponent, either positive or negative
53+
54+
:param args: argparse arguments
55+
"""
5256
self.poutput('{} ** {} == {}'.format(args.base, args.exponent, args.base**args.exponent))
5357

5458

tests/test_argparse.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ def namespace_provider(self) -> argparse.Namespace:
3535

3636
@cmd2.with_argparser(say_parser)
3737
def do_say(self, args, *, keyword_arg: Optional[str] = None):
38-
"""Repeat what you tell me to."""
38+
"""
39+
Repeat what you
40+
tell me to.
41+
42+
:param args: argparse namespace
43+
:param keyword_arg: Optional keyword arguments
44+
"""
3945
words = []
4046
for word in args.words:
4147
if word is None:
@@ -198,7 +204,10 @@ def test_argparse_help_docstring(argparse_app):
198204
out, err = run_cmd(argparse_app, 'help say')
199205
assert out[0].startswith('Usage: say')
200206
assert out[1] == ''
201-
assert out[2] == 'Repeat what you tell me to.'
207+
assert out[2] == 'Repeat what you'
208+
assert out[3] == 'tell me to.'
209+
for line in out:
210+
assert not line.startswith(':')
202211

203212

204213
def test_argparse_help_description(argparse_app):

0 commit comments

Comments
 (0)