docsig 0.47.0__tar.gz → 0.49.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {docsig-0.47.0 → docsig-0.49.0}/PKG-INFO +8 -18
- {docsig-0.47.0 → docsig-0.49.0}/README.rst +6 -15
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_config.py +3 -2
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_core.py +6 -6
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_decorators.py +1 -1
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_directives.py +1 -3
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_display.py +43 -72
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_hooks.py +2 -2
- docsig-0.49.0/docsig/_main.py +45 -0
- docsig-0.49.0/docsig/_report.py +196 -0
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_stub.py +4 -0
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_utils.py +3 -1
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_version.py +1 -1
- {docsig-0.47.0 → docsig-0.49.0}/pyproject.toml +3 -3
- docsig-0.47.0/docsig/_main.py +0 -47
- docsig-0.47.0/docsig/_report.py +0 -275
- {docsig-0.47.0 → docsig-0.49.0}/LICENSE +0 -0
- {docsig-0.47.0 → docsig-0.49.0}/docsig/__init__.py +0 -0
- {docsig-0.47.0 → docsig-0.49.0}/docsig/__main__.py +0 -0
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_message.py +0 -0
- {docsig-0.47.0 → docsig-0.49.0}/docsig/_module.py +0 -0
- {docsig-0.47.0 → docsig-0.49.0}/docsig/messages.py +0 -0
- {docsig-0.47.0 → docsig-0.49.0}/docsig/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: docsig
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.49.0
|
|
4
4
|
Summary: Check signature params for proper documentation
|
|
5
5
|
Home-page: https://pypi.org/project/docsig/
|
|
6
6
|
License: MIT
|
|
@@ -21,8 +21,7 @@ Requires-Dist: Pygments (>=2.13.0,<3.0.0)
|
|
|
21
21
|
Requires-Dist: Sphinx (>=7.0.0,<8.0.0)
|
|
22
22
|
Requires-Dist: arcon (>=0.4.0)
|
|
23
23
|
Requires-Dist: astroid (>=3.0.1,<4.0.0)
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist: typing-extensions (>=4.8.0,<5.0.0)
|
|
24
|
+
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
26
25
|
Project-URL: Documentation, https://docsig.readthedocs.io/en/latest
|
|
27
26
|
Project-URL: Repository, https://github.com/jshwi/docsig
|
|
28
27
|
Description-Content-Type: text/x-rst
|
|
@@ -139,7 +138,7 @@ Commandline
|
|
|
139
138
|
-s STR, --string STR string to parse instead of files
|
|
140
139
|
-d LIST, --disable LIST comma separated list of rules to disable
|
|
141
140
|
-t LIST, --target LIST comma separated list of rules to target
|
|
142
|
-
-e
|
|
141
|
+
-e PATTERN, --exclude PATTERN regular expression of files or dirs to exclude
|
|
143
142
|
from checks
|
|
144
143
|
|
|
145
144
|
Options can also be configured with the pyproject.toml file
|
|
@@ -182,7 +181,7 @@ API
|
|
|
182
181
|
... :param param3: About param3.
|
|
183
182
|
... '''
|
|
184
183
|
... """
|
|
185
|
-
>>> docsig(string=string)
|
|
184
|
+
>>> docsig(string=string, summary=True, no_ansi=True)
|
|
186
185
|
0
|
|
187
186
|
|
|
188
187
|
.. code-block:: python
|
|
@@ -196,18 +195,9 @@ API
|
|
|
196
195
|
... :param param3: About param3.
|
|
197
196
|
... '''
|
|
198
197
|
... """
|
|
199
|
-
>>> docsig(string=string)
|
|
200
|
-
2
|
|
201
|
-
|
|
202
|
-
def function(✓param1, ✓param2, ✖None) -> ✓None:
|
|
203
|
-
"""
|
|
204
|
-
:param param1: ✓
|
|
205
|
-
:param param2: ✓
|
|
206
|
-
:param param3: ✖
|
|
207
|
-
"""
|
|
208
|
-
<BLANKLINE>
|
|
209
|
-
E102: includes parameters that do not exist (params-do-not-exist)
|
|
210
|
-
<BLANKLINE>
|
|
198
|
+
>>> docsig(string=string, summary=True, no_ansi=True)
|
|
199
|
+
2 in function
|
|
200
|
+
E102: includes parameters that do not exist (params-do-not-exist)
|
|
211
201
|
1
|
|
212
202
|
|
|
213
203
|
A full list of checks can be found `here <https://docsig.readthedocs.io/en/latest/docsig.html#docsig-messages>`__
|
|
@@ -233,7 +223,7 @@ It can be added to your .pre-commit-config.yaml as follows:
|
|
|
233
223
|
|
|
234
224
|
repos:
|
|
235
225
|
- repo: https://github.com/jshwi/docsig
|
|
236
|
-
rev: v0.
|
|
226
|
+
rev: v0.49.0
|
|
237
227
|
hooks:
|
|
238
228
|
- id: docsig
|
|
239
229
|
args:
|
|
@@ -110,7 +110,7 @@ Commandline
|
|
|
110
110
|
-s STR, --string STR string to parse instead of files
|
|
111
111
|
-d LIST, --disable LIST comma separated list of rules to disable
|
|
112
112
|
-t LIST, --target LIST comma separated list of rules to target
|
|
113
|
-
-e
|
|
113
|
+
-e PATTERN, --exclude PATTERN regular expression of files or dirs to exclude
|
|
114
114
|
from checks
|
|
115
115
|
|
|
116
116
|
Options can also be configured with the pyproject.toml file
|
|
@@ -153,7 +153,7 @@ API
|
|
|
153
153
|
... :param param3: About param3.
|
|
154
154
|
... '''
|
|
155
155
|
... """
|
|
156
|
-
>>> docsig(string=string)
|
|
156
|
+
>>> docsig(string=string, summary=True, no_ansi=True)
|
|
157
157
|
0
|
|
158
158
|
|
|
159
159
|
.. code-block:: python
|
|
@@ -167,18 +167,9 @@ API
|
|
|
167
167
|
... :param param3: About param3.
|
|
168
168
|
... '''
|
|
169
169
|
... """
|
|
170
|
-
>>> docsig(string=string)
|
|
171
|
-
2
|
|
172
|
-
|
|
173
|
-
def function(✓param1, ✓param2, ✖None) -> ✓None:
|
|
174
|
-
"""
|
|
175
|
-
:param param1: ✓
|
|
176
|
-
:param param2: ✓
|
|
177
|
-
:param param3: ✖
|
|
178
|
-
"""
|
|
179
|
-
<BLANKLINE>
|
|
180
|
-
E102: includes parameters that do not exist (params-do-not-exist)
|
|
181
|
-
<BLANKLINE>
|
|
170
|
+
>>> docsig(string=string, summary=True, no_ansi=True)
|
|
171
|
+
2 in function
|
|
172
|
+
E102: includes parameters that do not exist (params-do-not-exist)
|
|
182
173
|
1
|
|
183
174
|
|
|
184
175
|
A full list of checks can be found `here <https://docsig.readthedocs.io/en/latest/docsig.html#docsig-messages>`__
|
|
@@ -204,7 +195,7 @@ It can be added to your .pre-commit-config.yaml as follows:
|
|
|
204
195
|
|
|
205
196
|
repos:
|
|
206
197
|
- repo: https://github.com/jshwi/docsig
|
|
207
|
-
rev: v0.
|
|
198
|
+
rev: v0.49.0
|
|
208
199
|
hooks:
|
|
209
200
|
- id: docsig
|
|
210
201
|
args:
|
|
@@ -6,9 +6,9 @@ docsig._config
|
|
|
6
6
|
from argparse import HelpFormatter as _HelpFormatter
|
|
7
7
|
from pathlib import Path as _Path
|
|
8
8
|
|
|
9
|
+
import click as _click
|
|
9
10
|
from arcon import ArgumentParser as _ArgumentParser
|
|
10
11
|
|
|
11
|
-
from ._display import color as _color
|
|
12
12
|
from ._version import __version__
|
|
13
13
|
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ class Parser(_ArgumentParser):
|
|
|
18
18
|
def __init__(self) -> None:
|
|
19
19
|
super().__init__(
|
|
20
20
|
version=__version__,
|
|
21
|
-
prog=
|
|
21
|
+
prog=_click.style(__package__, fg="cyan"),
|
|
22
22
|
formatter_class=lambda prog: _HelpFormatter(
|
|
23
23
|
prog, max_help_position=45
|
|
24
24
|
),
|
|
@@ -149,5 +149,6 @@ class Parser(_ArgumentParser):
|
|
|
149
149
|
self.add_argument(
|
|
150
150
|
"-e",
|
|
151
151
|
"--exclude",
|
|
152
|
+
metavar="PATTERN",
|
|
152
153
|
help="regular expression of files or dirs to exclude from checks",
|
|
153
154
|
)
|
|
@@ -7,6 +7,8 @@ from __future__ import annotations as _
|
|
|
7
7
|
|
|
8
8
|
from pathlib import Path as _Path
|
|
9
9
|
|
|
10
|
+
import click as _click
|
|
11
|
+
|
|
10
12
|
from . import _decorators
|
|
11
13
|
from ._display import Display as _Display
|
|
12
14
|
from ._display import Failure as _Failure
|
|
@@ -16,7 +18,7 @@ from ._message import Message as _Message
|
|
|
16
18
|
from ._module import Function as _Function
|
|
17
19
|
from ._module import Modules as _Modules
|
|
18
20
|
from ._module import Parent as _Parent
|
|
19
|
-
from ._report import
|
|
21
|
+
from ._report import Report as _Report
|
|
20
22
|
from .messages import TEMPLATE as _TEMPLATE
|
|
21
23
|
from .messages import E as _E
|
|
22
24
|
|
|
@@ -42,7 +44,7 @@ _DEFAULT_EXCLUDES = """\
|
|
|
42
44
|
|
|
43
45
|
def _print_checks() -> None:
|
|
44
46
|
for msg in _E.values():
|
|
45
|
-
|
|
47
|
+
_click.echo(msg.fstring(_TEMPLATE))
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
def _run_check( # pylint: disable=too-many-arguments
|
|
@@ -73,13 +75,11 @@ def _run_check( # pylint: disable=too-many-arguments
|
|
|
73
75
|
and not (child.isdunder and not check_dunders)
|
|
74
76
|
and not (child.docstring.bare and ignore_no_params)
|
|
75
77
|
):
|
|
76
|
-
report =
|
|
78
|
+
report = _Report(
|
|
77
79
|
child, targets, child.disabled, check_property_returns
|
|
78
80
|
)
|
|
79
81
|
if report:
|
|
80
|
-
failures.append(
|
|
81
|
-
_Failure(child, _FuncStr(child, no_ansi), report)
|
|
82
|
-
)
|
|
82
|
+
failures.append(_Failure(child, _FuncStr(child), report))
|
|
83
83
|
|
|
84
84
|
if check_nested:
|
|
85
85
|
for func in child:
|
|
@@ -59,7 +59,7 @@ def validate_args(func: _FuncType) -> _WrappedFuncType:
|
|
|
59
59
|
for message in kwargs.get("targets") or []:
|
|
60
60
|
if not message.isknown:
|
|
61
61
|
stderr.append(
|
|
62
|
-
f"unknown option to target '{message.description}'"
|
|
62
|
+
f"unknown option to target '{message.description}'"
|
|
63
63
|
)
|
|
64
64
|
|
|
65
65
|
if kwargs.get("check_class") and kwargs.get(
|
|
@@ -10,8 +10,6 @@ import tokenize as _tokenize
|
|
|
10
10
|
import typing as _t
|
|
11
11
|
from io import StringIO as _StringIO
|
|
12
12
|
|
|
13
|
-
from typing_extensions import Self as _Self
|
|
14
|
-
|
|
15
13
|
from ._message import Message as _Message
|
|
16
14
|
from .messages import E as _E
|
|
17
15
|
|
|
@@ -96,7 +94,7 @@ class Directive:
|
|
|
96
94
|
return self._kind == self._valid_kinds[1]
|
|
97
95
|
|
|
98
96
|
@classmethod
|
|
99
|
-
def parse(cls, comment: str, col: int) ->
|
|
97
|
+
def parse(cls, comment: str, col: int) -> Directive | None:
|
|
100
98
|
"""Parse string into directive object if possible.
|
|
101
99
|
|
|
102
100
|
:param comment: Comment to parse.
|
|
@@ -8,7 +8,7 @@ from __future__ import annotations as _
|
|
|
8
8
|
import typing as _t
|
|
9
9
|
from collections import UserString as _UserString
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
import click as _click
|
|
12
12
|
from pygments import highlight as _highlight
|
|
13
13
|
from pygments.formatters.terminal256 import (
|
|
14
14
|
Terminal256Formatter as _Terminal256Formatter,
|
|
@@ -23,39 +23,18 @@ from ._stub import ARG as _ARG
|
|
|
23
23
|
from ._stub import KEY as _KEY
|
|
24
24
|
from ._stub import Param as _Param
|
|
25
25
|
|
|
26
|
-
color = _Color()
|
|
27
|
-
|
|
28
|
-
color.populate_colors()
|
|
29
|
-
|
|
30
26
|
TAB = " "
|
|
31
27
|
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
self._no_ansi = no_ansi
|
|
36
|
-
|
|
37
|
-
def color(self, obj: _t.Any, color_obj: _Color) -> str:
|
|
38
|
-
"""Get string with selected color.
|
|
39
|
-
|
|
40
|
-
:param obj: Any object, represented as ``__str__``.
|
|
41
|
-
:param color_obj: Instantiated ``Color`` object.
|
|
42
|
-
:return: Colored string or string as was supplied.
|
|
43
|
-
"""
|
|
44
|
-
return str(obj) if self._no_ansi else color_obj.get(obj)
|
|
45
|
-
|
|
46
|
-
def syntax(self, obj: _t.Any) -> str:
|
|
47
|
-
"""Get code representation with syntax highlighting.
|
|
29
|
+
def syntax(obj: _t.Any) -> str:
|
|
30
|
+
"""Get code representation with syntax highlighting.
|
|
48
31
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
else _highlight(
|
|
56
|
-
obj, _PythonLexer(), _Terminal256Formatter(style="monokai")
|
|
57
|
-
).strip()
|
|
58
|
-
)
|
|
32
|
+
:param obj: Any object, represented as ``__str__``.
|
|
33
|
+
:return: Colored string or string as was supplied.
|
|
34
|
+
"""
|
|
35
|
+
return _highlight(
|
|
36
|
+
obj, _PythonLexer(), _Terminal256Formatter(style="monokai")
|
|
37
|
+
).strip()
|
|
59
38
|
|
|
60
39
|
|
|
61
40
|
class FuncStr(_UserString):
|
|
@@ -63,16 +42,14 @@ class FuncStr(_UserString):
|
|
|
63
42
|
|
|
64
43
|
:param func: Represents a function with signature and docstring
|
|
65
44
|
parameters.
|
|
66
|
-
:param no_ansi: Disable ANSI output.
|
|
67
45
|
"""
|
|
68
46
|
|
|
69
47
|
CHECK = "\u2713"
|
|
70
48
|
CROSS = "\u2716"
|
|
71
49
|
TRIPLE_QUOTES = '"""'
|
|
72
50
|
|
|
73
|
-
def __init__(self, func: _Function
|
|
51
|
+
def __init__(self, func: _Function) -> None:
|
|
74
52
|
super().__init__(func.name)
|
|
75
|
-
self._ansi = _ANSI(no_ansi)
|
|
76
53
|
self._parent_name = func.parent.name
|
|
77
54
|
self._isinit = func.isinit
|
|
78
55
|
self.data = ""
|
|
@@ -80,13 +57,13 @@ class FuncStr(_UserString):
|
|
|
80
57
|
if self._isinit:
|
|
81
58
|
self.data += TAB
|
|
82
59
|
|
|
83
|
-
self.data +=
|
|
60
|
+
self.data += syntax(f"def {func.name}(")
|
|
84
61
|
if self._is_string:
|
|
85
|
-
self._docstring =
|
|
62
|
+
self._docstring = syntax(f"{TAB}{self.TRIPLE_QUOTES}")
|
|
86
63
|
else:
|
|
87
|
-
self._docstring = f"{TAB}{
|
|
64
|
+
self._docstring = f"{TAB}{_click.style('...', fg='red')}\n"
|
|
88
65
|
|
|
89
|
-
self._mark =
|
|
66
|
+
self._mark = _click.style(self.CHECK, fg="green")
|
|
90
67
|
for index in range(len(func)):
|
|
91
68
|
arg = func.signature.args.get(index)
|
|
92
69
|
doc = func.docstring.args.get(index)
|
|
@@ -119,9 +96,9 @@ class FuncStr(_UserString):
|
|
|
119
96
|
:param failed: Boolean to test that check failed.
|
|
120
97
|
"""
|
|
121
98
|
self._mark = (
|
|
122
|
-
|
|
99
|
+
_click.style(self.CROSS, fg="red")
|
|
123
100
|
if failed
|
|
124
|
-
else
|
|
101
|
+
else _click.style(self.CHECK, fg="green")
|
|
125
102
|
)
|
|
126
103
|
|
|
127
104
|
def add_param(
|
|
@@ -162,34 +139,27 @@ class FuncStr(_UserString):
|
|
|
162
139
|
:param arg: Signature argument.
|
|
163
140
|
"""
|
|
164
141
|
if arg is not None:
|
|
165
|
-
self.data += "{}{}{}{}"
|
|
166
|
-
self._ansi.syntax(") -> "),
|
|
167
|
-
self._mark,
|
|
168
|
-
arg,
|
|
169
|
-
self._ansi.syntax(":"),
|
|
170
|
-
)
|
|
142
|
+
self.data += f"{syntax(') -> ')}{self._mark}{arg}{syntax(':')}"
|
|
171
143
|
else:
|
|
172
144
|
self.data += "{}{}{}".format(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
145
|
+
syntax(")"),
|
|
146
|
+
_click.style("?", fg="red"),
|
|
147
|
+
syntax(":"),
|
|
176
148
|
)
|
|
177
149
|
|
|
178
150
|
def add_comma(self) -> None:
|
|
179
151
|
"""Add comma between parenthesis."""
|
|
180
|
-
self.data +=
|
|
152
|
+
self.data += syntax(", ")
|
|
181
153
|
|
|
182
154
|
def close_docstring(self) -> None:
|
|
183
155
|
"""Close docstring."""
|
|
184
|
-
self._cat_docstring(
|
|
185
|
-
f"\n{TAB}{self._ansi.syntax(self.TRIPLE_QUOTES)}\n"
|
|
186
|
-
)
|
|
156
|
+
self._cat_docstring(f"\n{TAB}{syntax(self.TRIPLE_QUOTES)}\n")
|
|
187
157
|
|
|
188
158
|
def render(self) -> None:
|
|
189
159
|
"""Render final string by adding docstring to function."""
|
|
190
160
|
if self._isinit:
|
|
191
161
|
self.data = (
|
|
192
|
-
|
|
162
|
+
syntax(f"class {self._parent_name}:")
|
|
193
163
|
+ f"\n{self._docstring}"
|
|
194
164
|
+ f"\n{self.data}\n"
|
|
195
165
|
)
|
|
@@ -209,15 +179,7 @@ class Failures(_t.List[Failure]):
|
|
|
209
179
|
"""Sequence of failed functions."""
|
|
210
180
|
|
|
211
181
|
|
|
212
|
-
class
|
|
213
|
-
def __getitem__(self, key: str) -> list[Failures]:
|
|
214
|
-
if key not in super().__iter__():
|
|
215
|
-
super().__setitem__(key, [])
|
|
216
|
-
|
|
217
|
-
return super().__getitem__(key)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
class Display(_DisplaySequence):
|
|
182
|
+
class Display(_t.Dict[str, _t.List[Failures]]):
|
|
221
183
|
"""Collect and display report.
|
|
222
184
|
|
|
223
185
|
:param no_ansi: Disable ANSI output.
|
|
@@ -225,7 +187,13 @@ class Display(_DisplaySequence):
|
|
|
225
187
|
|
|
226
188
|
def __init__(self, no_ansi: bool = False) -> None:
|
|
227
189
|
super().__init__()
|
|
228
|
-
self._ansi =
|
|
190
|
+
self._ansi = not no_ansi
|
|
191
|
+
|
|
192
|
+
def __getitem__(self, key: str) -> list[Failures]:
|
|
193
|
+
if key not in super().__iter__():
|
|
194
|
+
super().__setitem__(key, [])
|
|
195
|
+
|
|
196
|
+
return super().__getitem__(key)
|
|
229
197
|
|
|
230
198
|
def report(self) -> None:
|
|
231
199
|
"""Display report if any checks have failed."""
|
|
@@ -236,10 +204,12 @@ class Display(_DisplaySequence):
|
|
|
236
204
|
if failure.func.parent.name:
|
|
237
205
|
header += f" in {failure.func.parent.name}"
|
|
238
206
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
207
|
+
_click.echo(
|
|
208
|
+
_click.style(header, fg="magenta"), color=self._ansi
|
|
209
|
+
)
|
|
210
|
+
_click.echo(len(header) * "-", color=self._ansi)
|
|
211
|
+
_click.echo(failure.func_str, color=self._ansi)
|
|
212
|
+
_click.echo(failure.report.get_report(), color=self._ansi)
|
|
243
213
|
|
|
244
214
|
def summarise(self) -> None:
|
|
245
215
|
"""Display report summary if any checks have failed."""
|
|
@@ -252,9 +222,10 @@ class Display(_DisplaySequence):
|
|
|
252
222
|
function = f"{failure.func.parent.name}.{function}"
|
|
253
223
|
|
|
254
224
|
header += f" in {function}"
|
|
255
|
-
|
|
256
|
-
"{}\n
|
|
257
|
-
|
|
258
|
-
failure.report.get_report("
|
|
259
|
-
)
|
|
225
|
+
_click.echo(
|
|
226
|
+
"{}\n {}".format(
|
|
227
|
+
_click.style(header, fg="magenta"),
|
|
228
|
+
failure.report.get_report(" ").strip(),
|
|
229
|
+
),
|
|
230
|
+
color=self._ansi,
|
|
260
231
|
)
|
|
@@ -6,12 +6,12 @@ docsig._hooks
|
|
|
6
6
|
import sys as _sys
|
|
7
7
|
from os import environ as _e
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
import click as _click
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def pretty_print_error() -> None:
|
|
13
13
|
"""Print user friendly commandline error if debug not enabled."""
|
|
14
14
|
if _e.get("DOCSIG_DEBUG", None) != "1":
|
|
15
15
|
_sys.excepthook = lambda x, y, _: print(
|
|
16
|
-
f"{
|
|
16
|
+
f"{_click.style(x.__name__, fg='red', bold=True)}: {y}"
|
|
17
17
|
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""
|
|
2
|
+
docsig._main
|
|
3
|
+
============
|
|
4
|
+
|
|
5
|
+
Contains package entry point.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations as _
|
|
9
|
+
|
|
10
|
+
from ._config import Parser as _Parser
|
|
11
|
+
from ._core import docsig as _docsig
|
|
12
|
+
from ._hooks import pretty_print_error as _pretty_print_error
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main() -> str | int:
|
|
16
|
+
"""Main function for package.
|
|
17
|
+
|
|
18
|
+
Collect config and arguments for the commandline.
|
|
19
|
+
|
|
20
|
+
:return: Exit status for whether test failed or not.
|
|
21
|
+
"""
|
|
22
|
+
p = _Parser()
|
|
23
|
+
_pretty_print_error()
|
|
24
|
+
return _docsig(
|
|
25
|
+
*p.args.path,
|
|
26
|
+
string=p.args.string,
|
|
27
|
+
list_checks=p.args.list_checks,
|
|
28
|
+
check_class=p.args.check_class,
|
|
29
|
+
check_class_constructor=p.args.check_class_constructor,
|
|
30
|
+
check_dunders=p.args.check_dunders,
|
|
31
|
+
check_protected_class_methods=p.args.check_protected_class_methods,
|
|
32
|
+
check_nested=p.args.check_nested,
|
|
33
|
+
check_overridden=p.args.check_overridden,
|
|
34
|
+
check_protected=p.args.check_protected,
|
|
35
|
+
check_property_returns=p.args.check_property_returns,
|
|
36
|
+
ignore_no_params=p.args.ignore_no_params,
|
|
37
|
+
ignore_args=p.args.ignore_args,
|
|
38
|
+
ignore_kwargs=p.args.ignore_kwargs,
|
|
39
|
+
no_ansi=p.args.no_ansi,
|
|
40
|
+
summary=p.args.summary,
|
|
41
|
+
verbose=p.args.verbose,
|
|
42
|
+
targets=p.args.target,
|
|
43
|
+
disable=p.args.disable,
|
|
44
|
+
exclude=p.args.exclude,
|
|
45
|
+
)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""
|
|
2
|
+
docsig._report
|
|
3
|
+
==============
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations as _
|
|
7
|
+
|
|
8
|
+
import typing as _t
|
|
9
|
+
|
|
10
|
+
from ._message import Message as _Message
|
|
11
|
+
from ._module import Function as _Function
|
|
12
|
+
from ._stub import RETURN as _RETURN
|
|
13
|
+
from ._stub import Param as _Param
|
|
14
|
+
from ._utils import almost_equal as _almost_equal
|
|
15
|
+
from .messages import TEMPLATE as _TEMPLATE
|
|
16
|
+
from .messages import E as _E
|
|
17
|
+
|
|
18
|
+
_MIN_MATCH = 0.8
|
|
19
|
+
_MAX_MATCH = 1.0
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Report(_t.List[str]):
|
|
23
|
+
"""Compile and produce report.
|
|
24
|
+
|
|
25
|
+
:param func: Function object.
|
|
26
|
+
:param targets: List of errors to target.
|
|
27
|
+
:param disable: List of errors to disable.
|
|
28
|
+
:param check_property_returns: Run return checks on properties.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
func: _Function,
|
|
34
|
+
targets: list[_Message],
|
|
35
|
+
disable: list[_Message],
|
|
36
|
+
check_property_returns: bool,
|
|
37
|
+
) -> None:
|
|
38
|
+
super().__init__()
|
|
39
|
+
self._disable = list(disable)
|
|
40
|
+
if targets:
|
|
41
|
+
errors = list(_E.all(1))
|
|
42
|
+
for target in targets:
|
|
43
|
+
errors.remove(target)
|
|
44
|
+
|
|
45
|
+
self._disable.extend(errors)
|
|
46
|
+
|
|
47
|
+
self._errors: list[_Message] = []
|
|
48
|
+
self._func = func
|
|
49
|
+
self._no_prop_return = func.isproperty and not check_property_returns
|
|
50
|
+
self._no_returns = func.isinit or self._no_prop_return
|
|
51
|
+
self._invalid_directive()
|
|
52
|
+
self._invalid_directive_options()
|
|
53
|
+
self._missing_class_docstring()
|
|
54
|
+
self._missing_func_docstring()
|
|
55
|
+
if func.docstring.string is not None:
|
|
56
|
+
self._return_not_typed()
|
|
57
|
+
self._exists()
|
|
58
|
+
self._missing()
|
|
59
|
+
self._duplicates()
|
|
60
|
+
self._extra_return()
|
|
61
|
+
self._missing_return()
|
|
62
|
+
self._property_return()
|
|
63
|
+
self._class_return()
|
|
64
|
+
for index in range(len(func)):
|
|
65
|
+
arg = func.signature.args.get(index)
|
|
66
|
+
doc = func.docstring.args.get(index)
|
|
67
|
+
self._description_syntax(doc)
|
|
68
|
+
self._indent_syntax(doc)
|
|
69
|
+
if arg != doc:
|
|
70
|
+
self._order(arg, doc)
|
|
71
|
+
self._incorrect(arg, doc)
|
|
72
|
+
self._misspelled(arg, doc)
|
|
73
|
+
self._not_equal(arg, doc)
|
|
74
|
+
|
|
75
|
+
self.sort()
|
|
76
|
+
|
|
77
|
+
def _add(self, value: _Message, hint: bool = False, **kwargs) -> None:
|
|
78
|
+
self._errors.append(value)
|
|
79
|
+
message = value.fstring(_TEMPLATE)
|
|
80
|
+
if kwargs:
|
|
81
|
+
message = message.format(**kwargs)
|
|
82
|
+
|
|
83
|
+
if hint:
|
|
84
|
+
message += f"\nhint: {value.hint}"
|
|
85
|
+
|
|
86
|
+
if value not in self._disable and message not in self:
|
|
87
|
+
super().append(message)
|
|
88
|
+
|
|
89
|
+
def _order(self, sig: _Param, doc: _Param) -> None:
|
|
90
|
+
if any(sig.name == i.name for i in self._func.docstring.args) or any(
|
|
91
|
+
doc.name == i.name for i in self._func.signature.args
|
|
92
|
+
):
|
|
93
|
+
self._add(_E[101])
|
|
94
|
+
|
|
95
|
+
def _exists(self) -> None:
|
|
96
|
+
if len(self._func.docstring.args) > len(self._func.signature.args):
|
|
97
|
+
self._add(_E[102])
|
|
98
|
+
|
|
99
|
+
def _missing_func_docstring(self) -> None:
|
|
100
|
+
if not self._func.isinit and self._func.docstring.string is None:
|
|
101
|
+
self._add(_E[113])
|
|
102
|
+
|
|
103
|
+
def _missing_class_docstring(self) -> None:
|
|
104
|
+
if self._func.isinit and self._func.docstring.string is None:
|
|
105
|
+
self._add(_E[114])
|
|
106
|
+
|
|
107
|
+
def _missing(self) -> None:
|
|
108
|
+
if len(self._func.signature.args) > len(self._func.docstring.args):
|
|
109
|
+
self._add(_E[103])
|
|
110
|
+
|
|
111
|
+
def _duplicates(self) -> None:
|
|
112
|
+
if self._func.docstring.args.duplicated:
|
|
113
|
+
self._add(_E[106])
|
|
114
|
+
|
|
115
|
+
def _extra_return(self) -> None:
|
|
116
|
+
if (
|
|
117
|
+
self._func.docstring.returns
|
|
118
|
+
and self._func.signature.rettype == "None"
|
|
119
|
+
and not self._no_returns
|
|
120
|
+
):
|
|
121
|
+
self._add(_E[104])
|
|
122
|
+
|
|
123
|
+
def _property_return(self) -> None:
|
|
124
|
+
if self._func.docstring.returns and self._no_prop_return:
|
|
125
|
+
self._add(_E[108], hint=True)
|
|
126
|
+
|
|
127
|
+
def _return_not_typed(self) -> None:
|
|
128
|
+
if self._func.signature.rettype is None and not self._no_returns:
|
|
129
|
+
self._add(_E[109])
|
|
130
|
+
|
|
131
|
+
def _missing_return(self) -> None:
|
|
132
|
+
hint = False
|
|
133
|
+
if (
|
|
134
|
+
self._func.signature.returns
|
|
135
|
+
and not self._func.docstring.returns
|
|
136
|
+
and not self._no_returns
|
|
137
|
+
):
|
|
138
|
+
docstring = self._func.docstring.string
|
|
139
|
+
if docstring is not None and _RETURN in docstring:
|
|
140
|
+
hint = True
|
|
141
|
+
|
|
142
|
+
self._add(_E[105], hint=hint)
|
|
143
|
+
|
|
144
|
+
def _incorrect(self, sig: _Param, doc: _Param) -> None:
|
|
145
|
+
if sig.name is None and doc.name is None:
|
|
146
|
+
self._add(_E[107])
|
|
147
|
+
|
|
148
|
+
# final catch-all
|
|
149
|
+
def _not_equal(self, sig: _Param, doc: _Param) -> None:
|
|
150
|
+
if sig.name is not None and doc.name is not None and not self._errors:
|
|
151
|
+
self._add(_E[110])
|
|
152
|
+
|
|
153
|
+
def _class_return(self) -> None:
|
|
154
|
+
if self._func.docstring.returns and self._func.isinit:
|
|
155
|
+
self._add(_E[111], hint=True)
|
|
156
|
+
|
|
157
|
+
def _misspelled(self, sig: _Param, doc: _Param) -> None:
|
|
158
|
+
if (
|
|
159
|
+
sig.name is not None
|
|
160
|
+
and doc.name is not None
|
|
161
|
+
and not self._errors
|
|
162
|
+
and _almost_equal(sig.name, doc.name, _MIN_MATCH, _MAX_MATCH)
|
|
163
|
+
):
|
|
164
|
+
self._add(_E[112])
|
|
165
|
+
|
|
166
|
+
def _description_syntax(self, doc: _Param) -> None:
|
|
167
|
+
if doc.description is not None and not doc.description.startswith(" "):
|
|
168
|
+
self._add(_E[115])
|
|
169
|
+
|
|
170
|
+
def _indent_syntax(self, doc: _Param) -> None:
|
|
171
|
+
if doc.indent > 0:
|
|
172
|
+
self._add(_E[116])
|
|
173
|
+
|
|
174
|
+
def _invalid_directive(self) -> None:
|
|
175
|
+
for directive in self._func.directives:
|
|
176
|
+
if not directive.isvalid:
|
|
177
|
+
err = _E[int(f"20{1 if directive.ismodule else 2}")]
|
|
178
|
+
self._add(err, directive=directive.kind)
|
|
179
|
+
|
|
180
|
+
def _invalid_directive_options(self) -> None:
|
|
181
|
+
for directive in self._func.directives:
|
|
182
|
+
if directive.rules.unknown:
|
|
183
|
+
err = _E[int(f"20{3 if directive.ismodule else 4}")]
|
|
184
|
+
for rule in directive.rules.unknown:
|
|
185
|
+
self._add(
|
|
186
|
+
err, directive=directive.kind, option=rule.description
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
def get_report(self, prefix: str = "") -> str:
|
|
190
|
+
"""Get report compiled as a string.
|
|
191
|
+
|
|
192
|
+
:param prefix: Prefix report.
|
|
193
|
+
:return: Current report.
|
|
194
|
+
"""
|
|
195
|
+
report = f"\n{prefix}".join(self)
|
|
196
|
+
return f"{report}\n"
|
|
@@ -20,16 +20,19 @@ RETURN = "return"
|
|
|
20
20
|
ARG = "arg"
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
# noinspection PyTypeChecker
|
|
23
24
|
class _GoogleDocstring(str):
|
|
24
25
|
def __new__(cls, string: str) -> _GoogleDocstring:
|
|
25
26
|
return super().__new__(cls, str(_s.GoogleDocstring(string)))
|
|
26
27
|
|
|
27
28
|
|
|
29
|
+
# noinspection PyTypeChecker
|
|
28
30
|
class _NumpyDocstring(str):
|
|
29
31
|
def __new__(cls, string: str) -> _NumpyDocstring:
|
|
30
32
|
return super().__new__(cls, str(_s.NumpyDocstring(string)))
|
|
31
33
|
|
|
32
34
|
|
|
35
|
+
# noinspection PyTypeChecker
|
|
33
36
|
class _DocFmt(str):
|
|
34
37
|
def __new__(cls, string: str) -> _DocFmt:
|
|
35
38
|
return super().__new__(
|
|
@@ -40,6 +43,7 @@ class _DocFmt(str):
|
|
|
40
43
|
)
|
|
41
44
|
|
|
42
45
|
|
|
46
|
+
# noinspection PyTypeChecker
|
|
43
47
|
class _RawDocstring(str):
|
|
44
48
|
def __new__(cls, string: str) -> _RawDocstring:
|
|
45
49
|
return super().__new__(
|
|
@@ -7,6 +7,8 @@ from __future__ import annotations as _
|
|
|
7
7
|
|
|
8
8
|
from difflib import SequenceMatcher as _SequenceMatcher
|
|
9
9
|
|
|
10
|
+
import click as _click
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
def almost_equal(str1: str, str2: str, mini: float, maxi: float) -> bool:
|
|
12
14
|
"""Show result for more than the minimum but less than the maximum.
|
|
@@ -28,4 +30,4 @@ def vprint(msg: str, verbose: bool = False) -> None:
|
|
|
28
30
|
:param verbose: Whether verbose mode is enabled.
|
|
29
31
|
"""
|
|
30
32
|
if verbose:
|
|
31
|
-
|
|
33
|
+
_click.echo(msg)
|
|
@@ -19,6 +19,7 @@ line-length = 79
|
|
|
19
19
|
[tool.constcheck]
|
|
20
20
|
ignore_strings = [
|
|
21
21
|
"disable",
|
|
22
|
+
"red",
|
|
22
23
|
"store",
|
|
23
24
|
"store_true",
|
|
24
25
|
"targets",
|
|
@@ -72,16 +73,15 @@ maintainers = [
|
|
|
72
73
|
name = "docsig"
|
|
73
74
|
readme = "README.rst"
|
|
74
75
|
repository = "https://github.com/jshwi/docsig"
|
|
75
|
-
version = "0.
|
|
76
|
+
version = "0.49.0"
|
|
76
77
|
|
|
77
78
|
[tool.poetry.dependencies]
|
|
78
79
|
Pygments = "^2.13.0"
|
|
79
80
|
Sphinx = "^7.0.0"
|
|
80
81
|
arcon = ">=0.4.0"
|
|
81
82
|
astroid = "^3.0.1"
|
|
82
|
-
|
|
83
|
+
click = "^8.1.7"
|
|
83
84
|
python = "^3.8"
|
|
84
|
-
typing-extensions = "^4.8.0"
|
|
85
85
|
|
|
86
86
|
[tool.poetry.dev-dependencies]
|
|
87
87
|
bump2version = "^1.0.1"
|
docsig-0.47.0/docsig/_main.py
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
docsig._main
|
|
3
|
-
============
|
|
4
|
-
|
|
5
|
-
Contains package entry point.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations as _
|
|
9
|
-
|
|
10
|
-
from ._config import Parser as _Parser
|
|
11
|
-
from ._core import docsig as _docsig
|
|
12
|
-
from ._hooks import pretty_print_error as _pretty_print_error
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def main() -> str | int:
|
|
16
|
-
"""Main function for package.
|
|
17
|
-
|
|
18
|
-
Collect config and arguments for the commandline.
|
|
19
|
-
|
|
20
|
-
:return: Exit status for whether test failed or not.
|
|
21
|
-
"""
|
|
22
|
-
parser = _Parser()
|
|
23
|
-
_pretty_print_error()
|
|
24
|
-
return _docsig(
|
|
25
|
-
*parser.args.path,
|
|
26
|
-
string=parser.args.string,
|
|
27
|
-
list_checks=parser.args.list_checks,
|
|
28
|
-
check_class=parser.args.check_class,
|
|
29
|
-
check_class_constructor=parser.args.check_class_constructor,
|
|
30
|
-
check_dunders=parser.args.check_dunders,
|
|
31
|
-
check_protected_class_methods=(
|
|
32
|
-
parser.args.check_protected_class_methods
|
|
33
|
-
),
|
|
34
|
-
check_nested=parser.args.check_nested,
|
|
35
|
-
check_overridden=parser.args.check_overridden,
|
|
36
|
-
check_protected=parser.args.check_protected,
|
|
37
|
-
check_property_returns=parser.args.check_property_returns,
|
|
38
|
-
ignore_no_params=parser.args.ignore_no_params,
|
|
39
|
-
ignore_args=parser.args.ignore_args,
|
|
40
|
-
ignore_kwargs=parser.args.ignore_kwargs,
|
|
41
|
-
no_ansi=parser.args.no_ansi,
|
|
42
|
-
summary=parser.args.summary,
|
|
43
|
-
verbose=parser.args.verbose,
|
|
44
|
-
targets=parser.args.target,
|
|
45
|
-
disable=parser.args.disable,
|
|
46
|
-
exclude=parser.args.exclude,
|
|
47
|
-
)
|
docsig-0.47.0/docsig/_report.py
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
docsig._report
|
|
3
|
-
==============
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from __future__ import annotations as _
|
|
7
|
-
|
|
8
|
-
import typing as _t
|
|
9
|
-
|
|
10
|
-
from ._message import Message as _Message
|
|
11
|
-
from ._module import Function as _Function
|
|
12
|
-
from ._stub import RETURN as _RETURN
|
|
13
|
-
from ._stub import Param as _Param
|
|
14
|
-
from ._utils import almost_equal as _almost_equal
|
|
15
|
-
from .messages import TEMPLATE as _TEMPLATE
|
|
16
|
-
from .messages import E as _E
|
|
17
|
-
|
|
18
|
-
_MIN_MATCH = 0.8
|
|
19
|
-
_MAX_MATCH = 1.0
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class _MessageSequence(_t.List[str]):
|
|
23
|
-
def __init__(
|
|
24
|
-
self,
|
|
25
|
-
targets: list[_Message],
|
|
26
|
-
disable: list[_Message],
|
|
27
|
-
) -> None:
|
|
28
|
-
super().__init__()
|
|
29
|
-
self._disable = list(disable)
|
|
30
|
-
if targets:
|
|
31
|
-
errors = list(_E.all(1))
|
|
32
|
-
for target in targets:
|
|
33
|
-
errors.remove(target)
|
|
34
|
-
|
|
35
|
-
self._disable.extend(errors)
|
|
36
|
-
|
|
37
|
-
self._errors: list[_Message] = []
|
|
38
|
-
|
|
39
|
-
def add(self, value: _Message, hint: bool = False, **kwargs) -> None:
|
|
40
|
-
"""Add an error to the container.
|
|
41
|
-
|
|
42
|
-
:param value: Value to add.
|
|
43
|
-
:param hint: Whether to print a hint or not.
|
|
44
|
-
:param kwargs: Variable(s) if format string.
|
|
45
|
-
"""
|
|
46
|
-
self._errors.append(value)
|
|
47
|
-
message = value.fstring(_TEMPLATE)
|
|
48
|
-
if kwargs:
|
|
49
|
-
message = message.format(**kwargs)
|
|
50
|
-
|
|
51
|
-
if hint:
|
|
52
|
-
message += f"\nhint: {value.hint}"
|
|
53
|
-
|
|
54
|
-
if value not in self._disable and message not in self:
|
|
55
|
-
super().append(message)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class Report(_MessageSequence):
|
|
59
|
-
"""Compile and produce report.
|
|
60
|
-
|
|
61
|
-
:param func: Function object.
|
|
62
|
-
:param targets: List of errors to target.
|
|
63
|
-
:param disable: List of errors to disable.
|
|
64
|
-
:param check_property_returns: Run return checks on properties.
|
|
65
|
-
"""
|
|
66
|
-
|
|
67
|
-
def __init__(
|
|
68
|
-
self,
|
|
69
|
-
func: _Function,
|
|
70
|
-
targets: list[_Message],
|
|
71
|
-
disable: list[_Message],
|
|
72
|
-
check_property_returns: bool,
|
|
73
|
-
) -> None:
|
|
74
|
-
super().__init__(targets, disable)
|
|
75
|
-
self._func = func
|
|
76
|
-
self._no_prop_return = func.isproperty and not check_property_returns
|
|
77
|
-
self._no_returns = func.isinit or self._no_prop_return
|
|
78
|
-
|
|
79
|
-
def order(self, sig: _Param, doc: _Param) -> None:
|
|
80
|
-
"""Test for documented parameters and their order.
|
|
81
|
-
|
|
82
|
-
:param sig: Signature argument.
|
|
83
|
-
:param doc: Docstring argument.
|
|
84
|
-
"""
|
|
85
|
-
if any(sig.name == i.name for i in self._func.docstring.args) or any(
|
|
86
|
-
doc.name == i.name for i in self._func.signature.args
|
|
87
|
-
):
|
|
88
|
-
self.add(_E[101])
|
|
89
|
-
|
|
90
|
-
def exists(self) -> None:
|
|
91
|
-
"""Test that non-existing parameter is not documented."""
|
|
92
|
-
if len(self._func.docstring.args) > len(self._func.signature.args):
|
|
93
|
-
self.add(_E[102])
|
|
94
|
-
|
|
95
|
-
def missing_func_docstring(self) -> None:
|
|
96
|
-
"""Test that docstring is not missing from func."""
|
|
97
|
-
if not self._func.isinit and self._func.docstring.string is None:
|
|
98
|
-
self.add(_E[113])
|
|
99
|
-
|
|
100
|
-
def missing_class_docstring(self) -> None:
|
|
101
|
-
"""Test that docstring is not missing from class."""
|
|
102
|
-
if self._func.isinit and self._func.docstring.string is None:
|
|
103
|
-
self.add(_E[114])
|
|
104
|
-
|
|
105
|
-
def missing(self) -> None:
|
|
106
|
-
"""Test that parameter is not missing from documentation."""
|
|
107
|
-
if len(self._func.signature.args) > len(self._func.docstring.args):
|
|
108
|
-
self.add(_E[103])
|
|
109
|
-
|
|
110
|
-
def duplicates(self) -> None:
|
|
111
|
-
"""Test that there are no duplicate parameters in docstring."""
|
|
112
|
-
if self._func.docstring.args.duplicated:
|
|
113
|
-
self.add(_E[106])
|
|
114
|
-
|
|
115
|
-
def extra_return(self) -> None:
|
|
116
|
-
"""Check that return is not documented when there is none."""
|
|
117
|
-
if (
|
|
118
|
-
self._func.docstring.returns
|
|
119
|
-
and self._func.signature.rettype == "None"
|
|
120
|
-
and not self._no_returns
|
|
121
|
-
):
|
|
122
|
-
self.add(_E[104])
|
|
123
|
-
|
|
124
|
-
def property_return(self) -> None:
|
|
125
|
-
"""Check that return is not documented for property."""
|
|
126
|
-
if self._func.docstring.returns and self._no_prop_return:
|
|
127
|
-
self.add(_E[108], hint=True)
|
|
128
|
-
|
|
129
|
-
def return_not_typed(self) -> None:
|
|
130
|
-
"""Check that return is not documented when no type provided."""
|
|
131
|
-
if self._func.signature.rettype is None and not self._no_returns:
|
|
132
|
-
self.add(_E[109])
|
|
133
|
-
|
|
134
|
-
def missing_return(self) -> None:
|
|
135
|
-
"""Check that return is documented when func returns value."""
|
|
136
|
-
hint = False
|
|
137
|
-
if (
|
|
138
|
-
self._func.signature.returns
|
|
139
|
-
and not self._func.docstring.returns
|
|
140
|
-
and not self._no_returns
|
|
141
|
-
):
|
|
142
|
-
docstring = self._func.docstring.string
|
|
143
|
-
if docstring is not None and _RETURN in docstring:
|
|
144
|
-
hint = True
|
|
145
|
-
|
|
146
|
-
self.add(_E[105], hint=hint)
|
|
147
|
-
|
|
148
|
-
def incorrect(self, sig: _Param, doc: _Param) -> None:
|
|
149
|
-
"""Test that proper syntax is used when documenting parameters.
|
|
150
|
-
|
|
151
|
-
:param sig: Signature argument.
|
|
152
|
-
:param doc: Docstring argument.
|
|
153
|
-
"""
|
|
154
|
-
if sig.name is None and doc.name is None:
|
|
155
|
-
self.add(_E[107])
|
|
156
|
-
|
|
157
|
-
def not_equal(self, sig: _Param, doc: _Param) -> None:
|
|
158
|
-
"""Final catch-all.
|
|
159
|
-
|
|
160
|
-
Only applies if no other errors, including disabled, have been
|
|
161
|
-
triggered
|
|
162
|
-
|
|
163
|
-
:param sig: Signature argument.
|
|
164
|
-
:param doc: Docstring argument.
|
|
165
|
-
"""
|
|
166
|
-
if sig.name is not None and doc.name is not None and not self._errors:
|
|
167
|
-
self.add(_E[110])
|
|
168
|
-
|
|
169
|
-
def class_return(self) -> None:
|
|
170
|
-
"""Check that return is not documented for __init__."""
|
|
171
|
-
if self._func.docstring.returns and self._func.isinit:
|
|
172
|
-
self.add(_E[111], hint=True)
|
|
173
|
-
|
|
174
|
-
def misspelled(self, sig: _Param, doc: _Param) -> None:
|
|
175
|
-
"""Test whether there is a spelling error in documentation.
|
|
176
|
-
|
|
177
|
-
To avoid false positives also check whether doc param is almost
|
|
178
|
-
equal amongst its sibling params. If params are too similarly
|
|
179
|
-
named then this error won't be raised.
|
|
180
|
-
|
|
181
|
-
:param sig: Signature argument.
|
|
182
|
-
:param doc: Docstring argument.
|
|
183
|
-
"""
|
|
184
|
-
if (
|
|
185
|
-
sig.name is not None
|
|
186
|
-
and doc.name is not None
|
|
187
|
-
and not self._errors
|
|
188
|
-
and _almost_equal(sig.name, doc.name, _MIN_MATCH, _MAX_MATCH)
|
|
189
|
-
):
|
|
190
|
-
self.add(_E[112])
|
|
191
|
-
|
|
192
|
-
def description_syntax(self, doc: _Param) -> None:
|
|
193
|
-
"""Test whether docstring description has correct spacing.
|
|
194
|
-
|
|
195
|
-
:param doc: Docstring argument.
|
|
196
|
-
"""
|
|
197
|
-
if doc.description is not None and not doc.description.startswith(" "):
|
|
198
|
-
self.add(_E[115])
|
|
199
|
-
|
|
200
|
-
def indent_syntax(self, doc: _Param) -> None:
|
|
201
|
-
"""Test whether docstring description is indented correctly.
|
|
202
|
-
|
|
203
|
-
:param doc: Docstring argument.
|
|
204
|
-
"""
|
|
205
|
-
if doc.indent > 0:
|
|
206
|
-
self.add(_E[116])
|
|
207
|
-
|
|
208
|
-
def invalid_directive(self) -> None:
|
|
209
|
-
"""Report on any invalid directives belonging to this func."""
|
|
210
|
-
for directive in self._func.directives:
|
|
211
|
-
if not directive.isvalid:
|
|
212
|
-
err = _E[int(f"20{1 if directive.ismodule else 2}")]
|
|
213
|
-
self.add(err, directive=directive.kind)
|
|
214
|
-
|
|
215
|
-
def invalid_directive_options(self) -> None:
|
|
216
|
-
"""Report on any invalid directive options belonging to this."""
|
|
217
|
-
for directive in self._func.directives:
|
|
218
|
-
if directive.rules.unknown:
|
|
219
|
-
err = _E[int(f"20{3 if directive.ismodule else 4}")]
|
|
220
|
-
for rule in directive.rules.unknown:
|
|
221
|
-
self.add(
|
|
222
|
-
err, directive=directive.kind, option=rule.description
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
def get_report(self, prefix: str = "") -> str:
|
|
226
|
-
"""Get report compiled as a string.
|
|
227
|
-
|
|
228
|
-
:param prefix: Prefix report.
|
|
229
|
-
:return: Current report.
|
|
230
|
-
"""
|
|
231
|
-
report = f"\n{prefix}".join(self)
|
|
232
|
-
return f"{report}\n"
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
def generate_report(
|
|
236
|
-
func: _Function,
|
|
237
|
-
targets: list[_Message],
|
|
238
|
-
disable: list[_Message],
|
|
239
|
-
check_property_returns: bool,
|
|
240
|
-
) -> Report:
|
|
241
|
-
"""Generate report if function or method has failed.
|
|
242
|
-
|
|
243
|
-
:param func: Function object.
|
|
244
|
-
:param targets: List of errors to target.
|
|
245
|
-
:param disable: List of errors to disable.
|
|
246
|
-
:param check_property_returns: Run return checks on properties.
|
|
247
|
-
:return: Compiled report.
|
|
248
|
-
"""
|
|
249
|
-
report = Report(func, targets, disable, check_property_returns)
|
|
250
|
-
report.invalid_directive()
|
|
251
|
-
report.invalid_directive_options()
|
|
252
|
-
report.missing_class_docstring()
|
|
253
|
-
report.missing_func_docstring()
|
|
254
|
-
if func.docstring.string is not None:
|
|
255
|
-
report.return_not_typed()
|
|
256
|
-
report.exists()
|
|
257
|
-
report.missing()
|
|
258
|
-
report.duplicates()
|
|
259
|
-
report.extra_return()
|
|
260
|
-
report.missing_return()
|
|
261
|
-
report.property_return()
|
|
262
|
-
report.class_return()
|
|
263
|
-
for index in range(len(func)):
|
|
264
|
-
arg = func.signature.args.get(index)
|
|
265
|
-
doc = func.docstring.args.get(index)
|
|
266
|
-
report.description_syntax(doc)
|
|
267
|
-
report.indent_syntax(doc)
|
|
268
|
-
if arg != doc:
|
|
269
|
-
report.order(arg, doc)
|
|
270
|
-
report.incorrect(arg, doc)
|
|
271
|
-
report.misspelled(arg, doc)
|
|
272
|
-
report.not_equal(arg, doc)
|
|
273
|
-
|
|
274
|
-
report.sort()
|
|
275
|
-
return report
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|