Skip to content

Commit 1fc5e13

Browse files
unvendor docstring_parser
1 parent d833f9f commit 1fc5e13

17 files changed

Lines changed: 73 additions & 396 deletions

File tree

.coveragerc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
[run]
22
branch = true
3-
omit =
4-
# don't measure our vendored packages
5-
*/vendor/*
63

.github/workflows/on_pull_request.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ jobs:
3131
env:
3232
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3333
run: |
34-
poetry run pylint -j 0 --ignore=vendor recline | reviewdog -reporter=github-pr-check -diff="git diff main" -efm="%f:%l:%c: %m"
34+
poetry run pylint -j 0 recline | reviewdog -reporter=github-pr-check -diff="git diff main" -efm="%f:%l:%c: %m"

CONTRIBUTING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ $ poetry run python examples/cake.py
3434
$ poetry run pytest --cov=recline tests
3535
```
3636

37+
### Running the linter
38+
```
39+
$ poetry run ruff check
40+
```
41+
3742
### Building the package
3843

3944
```

docs/conf.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939

4040
apidoc_module_dir = '../recline'
4141
apidoc_output_dir = 'api_reference'
42-
apidoc_excluded_paths = ['vendor']
4342
apidoc_separate_modules = True
4443
apidoc_extra_args = ["-H", "API Reference"]
4544

poetry.lock

Lines changed: 18 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ packages = [
2222

2323
[tool.poetry.dependencies]
2424
argcomplete = ">=3"
25+
docstring_parser = ">=0.16"
2526
python = ">=3.10.0,<4"
2627
windows-curses = {version = "^2.3.3", markers = "sys_platform == 'win32'"}
2728
pyreadline3 = {version = "^3.4.1", markers = "sys_platform == 'win32'"}
@@ -40,6 +41,4 @@ importlib-metadata = "^9.0.0"
4041
requires = ["poetry-core>=2.0.0,<3.0.0"]
4142
build-backend = "poetry.core.masonry.api"
4243

43-
[tool.ruff]
44-
exclude = ["recline/vendor"]
4544

recline/arg_types/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
This package contains the various custom type definitions for CLI command parameters.
55
If you are defining a CLI command function that takes input with restrictions,
66
you may want to use a type annotation to allow recline to do the checking for you
7-
before your function ever gets invoked. For example:
7+
before your function ever gets invoked. For example::
88
9-
from recline.arg_types import Choices
9+
from recline.arg_types import Choices
1010
11-
@recline.command
12-
def commit(branch: Choices.define(['dev', 'beta', 'stable'])) -> None:
13-
# the function can now assume that branch has already been validated to be
14-
# one of the options above before we got here
11+
@recline.command
12+
def commit(branch: Choices.define(['dev', 'beta', 'stable'])) -> None:
13+
# the function can now assume that branch has already been validated to be
14+
# one of the options above before we got here
1515
"""

recline/commands/cli_command.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from recline.arg_types.flag import Flag
2222
from recline.arg_types.remainder import Remainder
2323
from recline.formatters.output_formatter import OutputFormatter
24-
from recline.vendor import docstring_parser
24+
import docstring_parser
2525

2626

2727
LOGGER = logging.getLogger(__name__)

recline/commands/man_utils.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,45 @@
88

99
import curses
1010

11+
from docstring_parser.common import DocstringExample
12+
1113
from recline.arg_types.positional import Positional
1214
from recline.arg_types.remainder import Remainder
1315
from recline.commands.cli_command import get_annotation_type
1416

1517

18+
def _iter_examples(docstring):
19+
"""Yield (name, description) tuples from a parsed docstring.
20+
21+
Handles two input forms:
22+
- ``DocstringExample`` objects (google-style ``Examples:`` blocks), whose
23+
``description`` field contains lines like ``name:`` followed by indented
24+
body lines.
25+
- Generic ``DocstringMeta`` entries with ``args[0]`` in ``{"example",
26+
"examples"}`` and the example name in ``args[1]`` (rest-style ``:example
27+
name:`` entries).
28+
"""
29+
30+
for meta in docstring.meta:
31+
if isinstance(meta, DocstringExample):
32+
name = None
33+
body_lines = []
34+
for line in (meta.description or '').splitlines():
35+
stripped = line.rstrip()
36+
if stripped and not line[:1].isspace() and stripped.endswith(':'):
37+
if name is not None:
38+
yield name, '\n'.join(body_lines).strip('\n')
39+
name = stripped[:-1]
40+
body_lines = []
41+
else:
42+
dedented = line[4:] if line.startswith(' ') else line
43+
body_lines.append(dedented)
44+
if name is not None:
45+
yield name, '\n'.join(body_lines).strip('\n')
46+
elif meta.args and meta.args[0] in {'example', 'examples'} and len(meta.args) > 1:
47+
yield meta.args[1], meta.description or ''
48+
49+
1650
def wrapped_string(text, screen_width, prefix=0):
1751
"""This function will take a string and make sure it can fit within the
1852
given screen_width.
@@ -111,7 +145,7 @@ def generate_help_text(screen_width, command_class):
111145
help_text.append(('\n',))
112146

113147
# each command parameter with description, constraints, and defaults
114-
if command_class.docstring.params:
148+
if command_class.required_args or command_class.optional_args:
115149
def print_arg(arg):
116150
meta = command_class.get_arg_metavar(arg)
117151
description = command_class.get_arg_description(arg, indent=None)
@@ -139,15 +173,16 @@ def print_arg(arg):
139173
print_arg(arg)
140174

141175
# each command example
142-
if command_class.docstring.examples:
176+
examples = list(_iter_examples(command_class.docstring))
177+
if examples:
143178
help_text.append(('EXAMPLES\n', curses.A_BOLD))
144-
for example in command_class.docstring.examples:
179+
for name, description in examples:
145180
prefix = indent + ' '
146181
help_text.append((indent,))
147-
help_text.append((f'{example.name}:', curses.A_UNDERLINE))
182+
help_text.append((f'{name}:', curses.A_UNDERLINE))
148183
help_text.append((f'\n{prefix}',))
149184
description = wrapped_string(
150-
example.description, screen_width, prefix=len(prefix),
185+
description, screen_width, prefix=len(prefix),
151186
)
152187
for line in description.split('\n'):
153188
help_text.append((f'{line}\n',))

0 commit comments

Comments
 (0)