docsig 0.81.3__tar.gz → 0.82.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.81.3 → docsig-0.82.0}/PKG-INFO +4 -4
- {docsig-0.81.3 → docsig-0.82.0}/README.rst +3 -3
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_check.py +12 -12
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_core.py +12 -120
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_directives.py +41 -1
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_files.py +14 -21
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_module.py +22 -42
- docsig-0.82.0/docsig/_parsers.py +89 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_report.py +66 -12
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_stub.py +15 -27
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_version.py +1 -1
- {docsig-0.81.3 → docsig-0.82.0}/docsig/messages.py +10 -0
- {docsig-0.81.3 → docsig-0.82.0}/pyproject.toml +2 -2
- {docsig-0.81.3 → docsig-0.82.0}/LICENSE +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/__init__.py +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/__main__.py +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_config.py +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_decorators.py +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_hooks.py +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_main.py +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/_utils.py +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/plugin.py +0 -0
- {docsig-0.81.3 → docsig-0.82.0}/docsig/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docsig
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.82.0
|
|
4
4
|
Summary: Check signature params for proper documentation
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -184,7 +184,7 @@ ensure your installation has registered `docsig`
|
|
|
184
184
|
.. code-block:: console
|
|
185
185
|
|
|
186
186
|
$ flake8 --version
|
|
187
|
-
7.3.0 (docsig: 0.
|
|
187
|
+
7.3.0 (docsig: 0.82.0, mccabe: 0.7.0, pycodestyle: 2.14.0, pyflakes: 3.4.0) CPython 3.10.19 on Darwin
|
|
188
188
|
|
|
189
189
|
And now use `flake8` to lint your files
|
|
190
190
|
|
|
@@ -270,7 +270,7 @@ Standalone
|
|
|
270
270
|
|
|
271
271
|
repos:
|
|
272
272
|
- repo: https://github.com/jshwi/docsig
|
|
273
|
-
rev: v0.
|
|
273
|
+
rev: v0.82.0
|
|
274
274
|
hooks:
|
|
275
275
|
- id: docsig
|
|
276
276
|
args:
|
|
@@ -289,7 +289,7 @@ or integrated with ``flake8``
|
|
|
289
289
|
hooks:
|
|
290
290
|
- id: flake8
|
|
291
291
|
additional_dependencies:
|
|
292
|
-
- docsig==0.
|
|
292
|
+
- docsig==0.82.0
|
|
293
293
|
args:
|
|
294
294
|
- "--sig-check-class"
|
|
295
295
|
- "--sig-check-dunders"
|
|
@@ -155,7 +155,7 @@ ensure your installation has registered `docsig`
|
|
|
155
155
|
.. code-block:: console
|
|
156
156
|
|
|
157
157
|
$ flake8 --version
|
|
158
|
-
7.3.0 (docsig: 0.
|
|
158
|
+
7.3.0 (docsig: 0.82.0, mccabe: 0.7.0, pycodestyle: 2.14.0, pyflakes: 3.4.0) CPython 3.10.19 on Darwin
|
|
159
159
|
|
|
160
160
|
And now use `flake8` to lint your files
|
|
161
161
|
|
|
@@ -241,7 +241,7 @@ Standalone
|
|
|
241
241
|
|
|
242
242
|
repos:
|
|
243
243
|
- repo: https://github.com/jshwi/docsig
|
|
244
|
-
rev: v0.
|
|
244
|
+
rev: v0.82.0
|
|
245
245
|
hooks:
|
|
246
246
|
- id: docsig
|
|
247
247
|
args:
|
|
@@ -260,7 +260,7 @@ or integrated with ``flake8``
|
|
|
260
260
|
hooks:
|
|
261
261
|
- id: flake8
|
|
262
262
|
additional_dependencies:
|
|
263
|
-
- docsig==0.
|
|
263
|
+
- docsig==0.82.0
|
|
264
264
|
args:
|
|
265
265
|
- "--sig-check-class"
|
|
266
266
|
- "--sig-check-dunders"
|
|
@@ -13,23 +13,23 @@ from ._report import Failures as _Failures
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def _should_check_function(
|
|
16
|
-
|
|
16
|
+
function: _Function,
|
|
17
17
|
parent: _Parent,
|
|
18
18
|
config: _Config,
|
|
19
19
|
) -> bool:
|
|
20
|
-
if
|
|
20
|
+
if function.isoverridden and not config.check.overridden:
|
|
21
21
|
return False
|
|
22
22
|
|
|
23
|
-
if
|
|
23
|
+
if function.isprotected and not config.check.protected:
|
|
24
24
|
return False
|
|
25
25
|
|
|
26
|
-
if
|
|
26
|
+
if function.isdunder and not config.check.dunders:
|
|
27
27
|
return False
|
|
28
28
|
|
|
29
|
-
if
|
|
29
|
+
if function.docstring.bare and config.ignore.no_params:
|
|
30
30
|
return False
|
|
31
31
|
|
|
32
|
-
if
|
|
32
|
+
if function.isinit and (
|
|
33
33
|
not (config.check.class_ or config.check.class_constructor)
|
|
34
34
|
or (parent.isprotected and not config.check.protected)
|
|
35
35
|
):
|
|
@@ -49,14 +49,14 @@ def _run_check(
|
|
|
49
49
|
parent,
|
|
50
50
|
config,
|
|
51
51
|
):
|
|
52
|
-
failure = _Failure(child, config
|
|
52
|
+
failure = _Failure(child, config)
|
|
53
53
|
if failure:
|
|
54
54
|
failures.append(failure)
|
|
55
55
|
|
|
56
56
|
# recurse for either class methods or, if enabled, nested functions
|
|
57
57
|
if not isinstance(child, _Function) or config.check.nested:
|
|
58
|
-
for
|
|
59
|
-
_run_check(
|
|
58
|
+
for child_of_child in child.children:
|
|
59
|
+
_run_check(child_of_child, child, config, failures)
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
def run_checks(module: _Parent, config: _Config) -> _Failures:
|
|
@@ -71,12 +71,12 @@ def run_checks(module: _Parent, config: _Config) -> _Failures:
|
|
|
71
71
|
:return: A list of function and class failures.
|
|
72
72
|
"""
|
|
73
73
|
failures = _Failures()
|
|
74
|
-
for
|
|
74
|
+
for child in module.children:
|
|
75
75
|
if (
|
|
76
|
-
not
|
|
76
|
+
not child.isprotected
|
|
77
77
|
or config.check.protected
|
|
78
78
|
or config.check.protected_class_methods
|
|
79
79
|
):
|
|
80
|
-
_run_check(
|
|
80
|
+
_run_check(child, module, config, failures)
|
|
81
81
|
|
|
82
82
|
return failures
|
|
@@ -8,29 +8,21 @@ Entry point and orchestration for running docstring/signature checks.
|
|
|
8
8
|
from __future__ import annotations as _
|
|
9
9
|
|
|
10
10
|
import logging as _logging
|
|
11
|
-
import os as _os
|
|
12
11
|
import sys as _sys
|
|
13
12
|
import warnings as _warnings
|
|
14
13
|
from pathlib import Path as _Path
|
|
15
|
-
from tokenize import TokenError as _TokenError
|
|
16
|
-
from warnings import warn as _warn
|
|
17
|
-
|
|
18
|
-
import astroid as _ast
|
|
19
14
|
|
|
20
15
|
from . import _decorators
|
|
21
16
|
from ._check import run_checks as _run_checks
|
|
22
17
|
from ._config import Check as _Check
|
|
23
18
|
from ._config import Config as _Config
|
|
24
19
|
from ._config import Ignore as _Ignore
|
|
25
|
-
from .
|
|
26
|
-
from .
|
|
27
|
-
from .
|
|
28
|
-
from ._module import Error as _Error
|
|
29
|
-
from ._module import Parent as _Parent
|
|
20
|
+
from ._files import Files as _Files
|
|
21
|
+
from ._parsers import parse_from_file as _parse_from_file
|
|
22
|
+
from ._parsers import parse_from_string as _parse_from_string
|
|
30
23
|
from ._report import Failures as _Failures
|
|
24
|
+
from ._report import report as _report
|
|
31
25
|
from ._utils import print_checks as _print_checks
|
|
32
|
-
from .messages import NEW as _NEW
|
|
33
|
-
from .messages import TEMPLATE as _TEMPLATE
|
|
34
26
|
from .messages import E as _E
|
|
35
27
|
from .messages import Messages as _Messages
|
|
36
28
|
|
|
@@ -69,102 +61,6 @@ def setup_logger(verbose: bool) -> None:
|
|
|
69
61
|
logger.addHandler(stream_handler)
|
|
70
62
|
|
|
71
63
|
|
|
72
|
-
def _parse_from_file(path: _Path, config: _Config) -> _Parent:
|
|
73
|
-
try:
|
|
74
|
-
code = path.read_text(encoding="utf-8")
|
|
75
|
-
parent = _parse_from_string(
|
|
76
|
-
code,
|
|
77
|
-
config,
|
|
78
|
-
str(path)[:-3].replace(_os.sep, ".").replace("-", "_"),
|
|
79
|
-
path,
|
|
80
|
-
)
|
|
81
|
-
except UnicodeDecodeError as err:
|
|
82
|
-
logger = _logging.getLogger(__package__)
|
|
83
|
-
logger.debug(_FILE_INFO, path, str(err).replace("\n", " "))
|
|
84
|
-
parent = _Parent(error=_Error.UNICODE)
|
|
85
|
-
|
|
86
|
-
if parent.error is not None and not path.name.endswith(".py"):
|
|
87
|
-
parent = _Parent()
|
|
88
|
-
|
|
89
|
-
return parent
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def _parse_from_string(
|
|
93
|
-
code: str,
|
|
94
|
-
config: _Config,
|
|
95
|
-
module_name: str = "",
|
|
96
|
-
path: _Path | None = None,
|
|
97
|
-
) -> _Parent:
|
|
98
|
-
logger = _logging.getLogger(__package__)
|
|
99
|
-
source_name = path or "stdin"
|
|
100
|
-
try:
|
|
101
|
-
node = _ast.parse(code, module_name, str(path))
|
|
102
|
-
try:
|
|
103
|
-
directives = _Directives.from_text(code, config.disable)
|
|
104
|
-
except _TokenError as err:
|
|
105
|
-
directives = _Directives()
|
|
106
|
-
logger.debug(
|
|
107
|
-
_FILE_INFO,
|
|
108
|
-
source_name,
|
|
109
|
-
f"error parsing comments {err}".lower(),
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
parent = _Parent(
|
|
113
|
-
node,
|
|
114
|
-
directives,
|
|
115
|
-
path,
|
|
116
|
-
config.ignore.args,
|
|
117
|
-
config.ignore.kwargs,
|
|
118
|
-
config.check.class_constructor,
|
|
119
|
-
)
|
|
120
|
-
logger.debug(_FILE_INFO, source_name, "Parsing Python code successful")
|
|
121
|
-
except _ast.AstroidSyntaxError as err:
|
|
122
|
-
logger.debug(_FILE_INFO, source_name, str(err).replace("\n", " "))
|
|
123
|
-
parent = _Parent(error=_Error.SYNTAX)
|
|
124
|
-
except RecursionError as err:
|
|
125
|
-
logger.debug(_FILE_INFO, source_name, str(err).replace("\n", " "))
|
|
126
|
-
parent = _Parent(error=_Error.RECURSION)
|
|
127
|
-
|
|
128
|
-
return parent
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def _report(
|
|
132
|
-
failures: _Failures,
|
|
133
|
-
config: _Config,
|
|
134
|
-
path: str | None = None,
|
|
135
|
-
) -> int:
|
|
136
|
-
retcodes = [0]
|
|
137
|
-
for failure in failures:
|
|
138
|
-
retcodes.append(failure.retcode)
|
|
139
|
-
path_prefix = f"{path}:" if path is not None else ""
|
|
140
|
-
header = f"{path_prefix}{failure.lineno} in {failure.name}"
|
|
141
|
-
if not config.no_ansi and _sys.stdout.isatty():
|
|
142
|
-
header = f"\033[35m{header}\033[0m"
|
|
143
|
-
|
|
144
|
-
print(header)
|
|
145
|
-
for item in failure:
|
|
146
|
-
extra = None
|
|
147
|
-
if item.hint:
|
|
148
|
-
extra = f"hint: {item.hint}"
|
|
149
|
-
|
|
150
|
-
if item.new:
|
|
151
|
-
extra = "warning: please remember to fix this or disable it"
|
|
152
|
-
_warn(_NEW.format(ref=item.ref), FutureWarning, stacklevel=3)
|
|
153
|
-
|
|
154
|
-
print(
|
|
155
|
-
" "
|
|
156
|
-
+ _TEMPLATE.format(
|
|
157
|
-
ref=item.ref,
|
|
158
|
-
description=item.description,
|
|
159
|
-
symbolic=item.symbolic,
|
|
160
|
-
),
|
|
161
|
-
)
|
|
162
|
-
if extra is not None:
|
|
163
|
-
print(f" {extra}")
|
|
164
|
-
|
|
165
|
-
return max(retcodes)
|
|
166
|
-
|
|
167
|
-
|
|
168
64
|
def handle_deprecations(
|
|
169
65
|
ignore_typechecker: bool,
|
|
170
66
|
disable: list,
|
|
@@ -187,14 +83,14 @@ def handle_deprecations(
|
|
|
187
83
|
disable.extend(messages)
|
|
188
84
|
|
|
189
85
|
|
|
190
|
-
def runner(
|
|
86
|
+
def runner(file: _Path, config: _Config) -> _Failures:
|
|
191
87
|
"""Run checks for a single file and return collected failures.
|
|
192
88
|
|
|
193
|
-
:param
|
|
89
|
+
:param file: Path to the file to check.
|
|
194
90
|
:param config: Configuration object.
|
|
195
91
|
:return: Collected failures for the file.
|
|
196
92
|
"""
|
|
197
|
-
module = _parse_from_file(
|
|
93
|
+
module = _parse_from_file(file, config)
|
|
198
94
|
return _run_checks(module, config)
|
|
199
95
|
|
|
200
96
|
|
|
@@ -315,14 +211,10 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
|
315
211
|
return _report(failures, config)
|
|
316
212
|
|
|
317
213
|
retcodes = [0]
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
)
|
|
324
|
-
for path_ in paths:
|
|
325
|
-
failures = runner(path_, config)
|
|
326
|
-
retcodes.append(_report(failures, config, str(path_)))
|
|
214
|
+
files = _Files(path, config)
|
|
215
|
+
for file in files:
|
|
216
|
+
failures = runner(file, config)
|
|
217
|
+
retcode = _report(failures, config, str(file))
|
|
218
|
+
retcodes.append(retcode)
|
|
327
219
|
|
|
328
220
|
return max(retcodes)
|
|
@@ -27,12 +27,16 @@ class Comment(_Messages):
|
|
|
27
27
|
"""
|
|
28
28
|
|
|
29
29
|
_valid_kinds = "enable", "disable"
|
|
30
|
+
_valid_flags = ("next",)
|
|
30
31
|
|
|
31
32
|
def __init__(self, string: str, col: int) -> None:
|
|
32
33
|
super().__init__()
|
|
33
34
|
self._ismodule = col == 0
|
|
34
35
|
parts = string.split("=")
|
|
35
|
-
|
|
36
|
+
subparts = parts[0].split("-")
|
|
37
|
+
self._kind = subparts[0]
|
|
38
|
+
self._flag = None if len(subparts) == 1 else subparts[1]
|
|
39
|
+
self._isnext = self._flag == "next"
|
|
36
40
|
if len(parts) == 1:
|
|
37
41
|
self.extend(_E.all)
|
|
38
42
|
else:
|
|
@@ -63,6 +67,21 @@ class Comment(_Messages):
|
|
|
63
67
|
"""Whether this is a disable directive."""
|
|
64
68
|
return self._kind == self._valid_kinds[1]
|
|
65
69
|
|
|
70
|
+
@property
|
|
71
|
+
def isnext(self) -> bool:
|
|
72
|
+
"""Whether this directive applies to the next line only."""
|
|
73
|
+
return self._isnext
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def isvalidflag(self) -> bool:
|
|
77
|
+
"""Whether the directive flag (if any) is valid."""
|
|
78
|
+
return self._flag is None or self._flag in self._valid_flags
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def flag(self) -> str | None:
|
|
82
|
+
"""Flag for this directive (e.g. next), or None."""
|
|
83
|
+
return self._flag
|
|
84
|
+
|
|
66
85
|
@classmethod
|
|
67
86
|
def parse(cls, comment: str, col: int) -> Comment | None:
|
|
68
87
|
"""Parse a comment into a docsig directive when present.
|
|
@@ -96,6 +115,9 @@ class Directives(_t.Dict[int, _t.Tuple[Comments, _Messages]]):
|
|
|
96
115
|
directives = cls()
|
|
97
116
|
fin = _StringIO(text)
|
|
98
117
|
comments = Comments()
|
|
118
|
+
enable_next = False
|
|
119
|
+
next_comments = Comments(comments)
|
|
120
|
+
next_messages = _Messages(messages)
|
|
99
121
|
for line in _tokenize.generate_tokens(fin.readline):
|
|
100
122
|
# do nothing for these line types
|
|
101
123
|
if line.type in (_tokenize.NAME, _tokenize.OP, _tokenize.DEDENT):
|
|
@@ -119,12 +141,30 @@ class Directives(_t.Dict[int, _t.Tuple[Comments, _Messages]]):
|
|
|
119
141
|
i for i in messages if i not in comment
|
|
120
142
|
)
|
|
121
143
|
|
|
144
|
+
# if directive has a 'next' flag then alter the
|
|
145
|
+
# module level scope, not the inline scope (which
|
|
146
|
+
# behaves similar to next), so that inline
|
|
147
|
+
# directives are included and not overwritten
|
|
148
|
+
if comment.isnext and not enable_next:
|
|
149
|
+
enable_next = True
|
|
150
|
+
next_comments = Comments(comments)
|
|
151
|
+
next_messages = _Messages(messages)
|
|
152
|
+
|
|
122
153
|
# if module level directive, then make changes
|
|
123
154
|
# globally
|
|
124
155
|
if comment.ismodule:
|
|
125
156
|
comments = scoped_comments
|
|
126
157
|
messages = scoped_messages
|
|
127
158
|
|
|
159
|
+
# if in a 'next' module level scope and the line type is a
|
|
160
|
+
# newline (not a comment to allow 'next' directives to be
|
|
161
|
+
# stacked) then leave the 'next' module level scope and
|
|
162
|
+
# reset the global messages to before the 'next' directive
|
|
163
|
+
elif enable_next and line.type != _tokenize.NL:
|
|
164
|
+
enable_next = False
|
|
165
|
+
comments = next_comments
|
|
166
|
+
messages = next_messages
|
|
167
|
+
|
|
128
168
|
# check that a scoped message has not updated this first, as
|
|
129
169
|
# they take precedence over global messages
|
|
130
170
|
if lineno not in directives:
|
|
@@ -17,6 +17,8 @@ from pathspec import PathSpec as _PathSpec
|
|
|
17
17
|
from pathspec.patterns import GitWildMatchPattern as _GitWildMatchPattern
|
|
18
18
|
from wcmatch.pathlib import Path as _WcPath
|
|
19
19
|
|
|
20
|
+
from ._config import Config as _Config
|
|
21
|
+
|
|
20
22
|
FILE_INFO = "%s: %s"
|
|
21
23
|
|
|
22
24
|
|
|
@@ -69,55 +71,46 @@ def _glob(path: _Path, pattern: str) -> bool:
|
|
|
69
71
|
return _WcPath(str(path)).globmatch(pattern) # type: ignore
|
|
70
72
|
|
|
71
73
|
|
|
72
|
-
class
|
|
74
|
+
class Files(_t.List[_Path]):
|
|
73
75
|
"""Collect paths to check (gitignore and exclude applied).
|
|
74
76
|
|
|
75
77
|
:param paths: Path(s) to collect (files or directories).
|
|
76
|
-
:param
|
|
77
|
-
exclude from checks.
|
|
78
|
-
:param excludes: Files or dirs to exclude from checks.
|
|
79
|
-
:param include_ignored: Check files even if they match a gitignore
|
|
80
|
-
pattern.
|
|
78
|
+
:param config: Configuration object.
|
|
81
79
|
"""
|
|
82
80
|
|
|
83
81
|
def __init__(
|
|
84
82
|
self,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
excludes: list[str] | None = None,
|
|
88
|
-
include_ignored: bool = False,
|
|
83
|
+
paths: tuple[str | _Path, ...],
|
|
84
|
+
config: _Config,
|
|
89
85
|
) -> None:
|
|
90
86
|
super().__init__()
|
|
91
|
-
self._include_ignored = include_ignored
|
|
87
|
+
self._include_ignored = config.include_ignored
|
|
92
88
|
self._gitignore = _Gitignore()
|
|
93
|
-
|
|
89
|
+
logger = _logging.getLogger(__package__)
|
|
94
90
|
for path in paths:
|
|
95
91
|
self._populate(_Path(path))
|
|
96
92
|
|
|
97
93
|
for path in list(self):
|
|
98
94
|
if str(path) != "." and (
|
|
99
|
-
any(_re.match(i, str(path)) for i in
|
|
100
|
-
or any(_glob(path, i) for i in excludes or [])
|
|
95
|
+
any(_re.match(i, str(path)) for i in config.exclude)
|
|
96
|
+
or any(_glob(path, i) for i in config.excludes or [])
|
|
101
97
|
):
|
|
102
|
-
|
|
103
|
-
FILE_INFO,
|
|
104
|
-
path,
|
|
105
|
-
"in exclude list, skipping",
|
|
106
|
-
)
|
|
98
|
+
logger.debug(FILE_INFO, path, "in exclude list, skipping")
|
|
107
99
|
self.remove(path)
|
|
108
100
|
|
|
109
101
|
self.sort()
|
|
110
102
|
|
|
111
103
|
def _populate(self, root: _Path) -> None:
|
|
104
|
+
logger = _logging.getLogger(__package__)
|
|
112
105
|
if not root.exists():
|
|
113
106
|
if root.is_symlink():
|
|
114
|
-
|
|
107
|
+
logger.debug(FILE_INFO, root, "broken link, skipping")
|
|
115
108
|
return
|
|
116
109
|
|
|
117
110
|
raise FileNotFoundError(root)
|
|
118
111
|
|
|
119
112
|
if not self._include_ignored and self._gitignore.match_file(root):
|
|
120
|
-
|
|
113
|
+
logger.debug(FILE_INFO, root, "in gitignore, skipping")
|
|
121
114
|
return
|
|
122
115
|
|
|
123
116
|
if root.is_file():
|
|
@@ -14,6 +14,7 @@ from pathlib import Path as _Path
|
|
|
14
14
|
|
|
15
15
|
import astroid as _ast
|
|
16
16
|
|
|
17
|
+
from ._config import Config as _Config
|
|
17
18
|
from ._directives import Comments as _Comments
|
|
18
19
|
from ._directives import Directives as _Directives
|
|
19
20
|
from ._stub import Docstring as _Docstring
|
|
@@ -47,12 +48,8 @@ class Parent: # pylint: disable=too-many-instance-attributes
|
|
|
47
48
|
|
|
48
49
|
:param node: AST node for this scope.
|
|
49
50
|
:param directives: Directives and excluded errors per line.
|
|
50
|
-
:param
|
|
51
|
-
:param
|
|
52
|
-
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
53
|
-
:param check_class_constructor: Check the class constructor's
|
|
54
|
-
docstring. Otherwise, expect the constructor's documentation to
|
|
55
|
-
be on the class level docstring.
|
|
51
|
+
:param file: Path for this scope (or None).
|
|
52
|
+
:param config: Configuration object.
|
|
56
53
|
:param imports: Imports in this scope.
|
|
57
54
|
:param error: Unrecoverable error for this scope, if any.
|
|
58
55
|
"""
|
|
@@ -68,29 +65,25 @@ class Parent: # pylint: disable=too-many-instance-attributes
|
|
|
68
65
|
| None
|
|
69
66
|
) = None,
|
|
70
67
|
directives: _Directives | None = None,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
ignore_kwargs: bool = False,
|
|
74
|
-
check_class_constructor: bool = False,
|
|
68
|
+
file: _Path | None = None,
|
|
69
|
+
config: _Config | None = None,
|
|
75
70
|
imports: _Imports | None = None,
|
|
76
71
|
error: Error | None = None,
|
|
77
72
|
) -> None:
|
|
78
73
|
super().__init__()
|
|
79
74
|
self._error = error
|
|
80
75
|
self._directives = directives or _Directives()
|
|
81
|
-
self.
|
|
82
|
-
self._ignore_kwargs = ignore_kwargs
|
|
83
|
-
self._check_class_constructor = check_class_constructor
|
|
76
|
+
self._config = config or _Config()
|
|
84
77
|
self._children = _Children()
|
|
85
78
|
self._imports = imports or _Imports()
|
|
86
79
|
self._overloads = _Overloads()
|
|
87
80
|
if node is None:
|
|
88
81
|
self._name = "module"
|
|
89
82
|
if not isinstance(self, Function) and error is not None:
|
|
90
|
-
self._children.append(Function(
|
|
83
|
+
self._children.append(Function(file, error=error))
|
|
91
84
|
else:
|
|
92
85
|
self._name = node.name
|
|
93
|
-
self._parse_ast(node,
|
|
86
|
+
self._parse_ast(node, file)
|
|
94
87
|
|
|
95
88
|
def _parse_ast(
|
|
96
89
|
self,
|
|
@@ -100,7 +93,7 @@ class Parent: # pylint: disable=too-many-instance-attributes
|
|
|
100
93
|
| _ast.nodes.FunctionDef
|
|
101
94
|
| _ast.nodes.NodeNG
|
|
102
95
|
),
|
|
103
|
-
|
|
96
|
+
file: _Path | None = None,
|
|
104
97
|
) -> None:
|
|
105
98
|
# need to keep track of `comments` as, even though they are
|
|
106
99
|
# resolved in the directive object, they are needed to notify
|
|
@@ -130,10 +123,8 @@ class Parent: # pylint: disable=too-many-instance-attributes
|
|
|
130
123
|
comments,
|
|
131
124
|
self._directives,
|
|
132
125
|
disabled,
|
|
133
|
-
|
|
134
|
-
self.
|
|
135
|
-
self._ignore_kwargs,
|
|
136
|
-
self._check_class_constructor,
|
|
126
|
+
file,
|
|
127
|
+
self._config,
|
|
137
128
|
self._imports,
|
|
138
129
|
)
|
|
139
130
|
if func.isoverloaded:
|
|
@@ -155,15 +146,13 @@ class Parent: # pylint: disable=too-many-instance-attributes
|
|
|
155
146
|
Parent(
|
|
156
147
|
subnode,
|
|
157
148
|
self._directives,
|
|
158
|
-
|
|
159
|
-
self.
|
|
160
|
-
self._ignore_kwargs,
|
|
161
|
-
self._check_class_constructor,
|
|
149
|
+
file,
|
|
150
|
+
self._config,
|
|
162
151
|
self._imports,
|
|
163
152
|
),
|
|
164
153
|
)
|
|
165
154
|
else:
|
|
166
|
-
self._parse_ast(subnode,
|
|
155
|
+
self._parse_ast(subnode, file)
|
|
167
156
|
|
|
168
157
|
@property
|
|
169
158
|
def isprotected(self) -> bool:
|
|
@@ -188,12 +177,8 @@ class Function(Parent): # pylint: disable=too-many-instance-attributes
|
|
|
188
177
|
:param comments: Comment directives for this function.
|
|
189
178
|
:param directives: Directives keyed by line.
|
|
190
179
|
:param messages: Disabled checks for this function.
|
|
191
|
-
:param
|
|
192
|
-
:param
|
|
193
|
-
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
194
|
-
:param check_class_constructor: If the function is the class
|
|
195
|
-
constructor, use its own docstring. Otherwise, use the class
|
|
196
|
-
level docstring for the constructor function.
|
|
180
|
+
:param file: Path for this function (or None).
|
|
181
|
+
:param config: Configuration object.
|
|
197
182
|
:param imports: Imports in this scope.
|
|
198
183
|
:param error: Unrecoverable error for this function, if any.
|
|
199
184
|
"""
|
|
@@ -205,20 +190,16 @@ class Function(Parent): # pylint: disable=too-many-instance-attributes
|
|
|
205
190
|
comments: _Comments | None = None,
|
|
206
191
|
directives: _Directives | None = None,
|
|
207
192
|
messages: _Messages | None = None,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
ignore_kwargs: bool = False,
|
|
211
|
-
check_class_constructor: bool = False,
|
|
193
|
+
file: _Path | None = None,
|
|
194
|
+
config: _Config | None = None,
|
|
212
195
|
imports: _Imports | None = None,
|
|
213
196
|
error: Error | None = None,
|
|
214
197
|
) -> None:
|
|
215
198
|
super().__init__(
|
|
216
199
|
node,
|
|
217
200
|
directives or _Directives(),
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
ignore_kwargs,
|
|
221
|
-
check_class_constructor,
|
|
201
|
+
file,
|
|
202
|
+
config,
|
|
222
203
|
imports,
|
|
223
204
|
)
|
|
224
205
|
self._comments = comments or _Comments()
|
|
@@ -241,10 +222,9 @@ class Function(Parent): # pylint: disable=too-many-instance-attributes
|
|
|
241
222
|
|
|
242
223
|
self._signature = self._signature.from_ast(
|
|
243
224
|
node,
|
|
244
|
-
|
|
245
|
-
ignore_kwargs,
|
|
225
|
+
self._config.ignore,
|
|
246
226
|
)
|
|
247
|
-
if self.isinit and not
|
|
227
|
+
if self.isinit and not self._config.check.class_constructor:
|
|
248
228
|
# docstring for __init__ is expected on the class
|
|
249
229
|
# docstring
|
|
250
230
|
relevant_doc_node = self._parent.doc_node
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
docsig._parsers
|
|
3
|
+
===============
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations as _
|
|
7
|
+
|
|
8
|
+
import logging as _logging
|
|
9
|
+
import os as _os
|
|
10
|
+
from pathlib import Path as _Path
|
|
11
|
+
from tokenize import TokenError as _TokenError
|
|
12
|
+
|
|
13
|
+
import astroid as _ast
|
|
14
|
+
|
|
15
|
+
from ._config import Config as _Config
|
|
16
|
+
from ._directives import Directives as _Directives
|
|
17
|
+
from ._files import FILE_INFO as _FILE_INFO
|
|
18
|
+
from ._module import Error as _Error
|
|
19
|
+
from ._module import Parent as _Parent
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def parse_from_string(
|
|
23
|
+
code: str,
|
|
24
|
+
config: _Config,
|
|
25
|
+
module_name: str = "",
|
|
26
|
+
file: _Path | None = None,
|
|
27
|
+
) -> _Parent:
|
|
28
|
+
"""Build a Parent from a string of Python code.
|
|
29
|
+
|
|
30
|
+
Parses AST and comment directives (AST does not include comments,
|
|
31
|
+
so directives are parsed separately). On syntax error, returns a
|
|
32
|
+
Parent with an error set.
|
|
33
|
+
|
|
34
|
+
:param code: Python source to parse.
|
|
35
|
+
:param config: Configuration object.
|
|
36
|
+
:param module_name: Module name, or empty string.
|
|
37
|
+
:param file: Path for the source (or None for stdin).
|
|
38
|
+
:return: Parent for the parsed code or syntax error.
|
|
39
|
+
"""
|
|
40
|
+
logger = _logging.getLogger(__package__)
|
|
41
|
+
source_name = file or "stdin"
|
|
42
|
+
try:
|
|
43
|
+
node = _ast.parse(code, module_name, str(file))
|
|
44
|
+
try:
|
|
45
|
+
directives = _Directives.from_text(code, config.disable)
|
|
46
|
+
except _TokenError as err:
|
|
47
|
+
directives = _Directives()
|
|
48
|
+
logger.debug(
|
|
49
|
+
_FILE_INFO,
|
|
50
|
+
source_name,
|
|
51
|
+
f"error parsing comments {err}".lower(),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
parent = _Parent(node, directives, file, config)
|
|
55
|
+
logger.debug(_FILE_INFO, source_name, "Parsing Python code successful")
|
|
56
|
+
except _ast.AstroidSyntaxError as err:
|
|
57
|
+
logger.debug(_FILE_INFO, source_name, str(err).replace("\n", " "))
|
|
58
|
+
parent = _Parent(error=_Error.SYNTAX)
|
|
59
|
+
except RecursionError as err:
|
|
60
|
+
logger.debug(_FILE_INFO, source_name, str(err).replace("\n", " "))
|
|
61
|
+
parent = _Parent(error=_Error.RECURSION)
|
|
62
|
+
|
|
63
|
+
return parent
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def parse_from_file(file: _Path, config: _Config) -> _Parent:
|
|
67
|
+
"""Build a Parent from a file containing Python code.
|
|
68
|
+
|
|
69
|
+
Reads the file and delegates to parse_from_string. On UnicodeError,
|
|
70
|
+
returns a Parent with a Unicode error. On syntax error and a non-.py
|
|
71
|
+
path, returns an empty Parent (not treated as Python).
|
|
72
|
+
|
|
73
|
+
:param file: Path to the file to parse.
|
|
74
|
+
:param config: Configuration object.
|
|
75
|
+
:return: Parent for the parsed file or an error/empty Parent.
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
code = file.read_text(encoding="utf-8")
|
|
79
|
+
module_name = str(file)[:-3].replace(_os.sep, ".").replace("-", "_")
|
|
80
|
+
parent = parse_from_string(code, config, module_name, file)
|
|
81
|
+
except UnicodeDecodeError as err:
|
|
82
|
+
logger = _logging.getLogger(__package__)
|
|
83
|
+
logger.debug(_FILE_INFO, file, str(err).replace("\n", " "))
|
|
84
|
+
parent = _Parent(error=_Error.UNICODE)
|
|
85
|
+
|
|
86
|
+
if parent.error is not None and not file.name.endswith(".py"):
|
|
87
|
+
parent = _Parent()
|
|
88
|
+
|
|
89
|
+
return parent
|
|
@@ -11,10 +11,13 @@ return the highest exit code.
|
|
|
11
11
|
from __future__ import annotations as _
|
|
12
12
|
|
|
13
13
|
import contextlib as _contextlib
|
|
14
|
+
import sys as _sys
|
|
14
15
|
import typing as _t
|
|
16
|
+
from warnings import warn as _warn
|
|
15
17
|
|
|
16
18
|
from astroid.nodes.scoped_nodes import scoped_nodes as _scoped_nodes
|
|
17
19
|
|
|
20
|
+
from ._config import Config as _Config
|
|
18
21
|
from ._module import Error as _Error
|
|
19
22
|
from ._module import Function as _Function
|
|
20
23
|
from ._stub import UNNAMED as _UNNAMED
|
|
@@ -24,9 +27,10 @@ from ._stub import Params as _Params
|
|
|
24
27
|
from ._stub import RetType as _RetType
|
|
25
28
|
from ._utils import almost_equal as _almost_equal
|
|
26
29
|
from ._utils import sentence_tokenizer as _sentence_tokenizer
|
|
30
|
+
from .messages import NEW as _NEW
|
|
31
|
+
from .messages import TEMPLATE as _TEMPLATE
|
|
27
32
|
from .messages import E as _E
|
|
28
33
|
from .messages import Message as _Message
|
|
29
|
-
from .messages import Messages as _Messages
|
|
30
34
|
|
|
31
35
|
_MIN_MATCH = 0.8
|
|
32
36
|
_MAX_MATCH = 1.0
|
|
@@ -55,21 +59,17 @@ class Failure(_t.List[Failed]):
|
|
|
55
59
|
violation.
|
|
56
60
|
|
|
57
61
|
:param func: Function under check.
|
|
58
|
-
:param
|
|
59
|
-
:param check_property_returns: Run return checks on properties.
|
|
62
|
+
:param config: Configuration object.
|
|
60
63
|
"""
|
|
61
64
|
|
|
62
|
-
def __init__(
|
|
63
|
-
self,
|
|
64
|
-
func: _Function,
|
|
65
|
-
target: _Messages,
|
|
66
|
-
check_property_returns: bool,
|
|
67
|
-
) -> None:
|
|
65
|
+
def __init__(self, func: _Function, config: _Config) -> None:
|
|
68
66
|
super().__init__()
|
|
69
67
|
self._retcode = 0
|
|
70
68
|
self._func = func
|
|
71
|
-
if target:
|
|
72
|
-
self._func.messages.extend(
|
|
69
|
+
if config.target:
|
|
70
|
+
self._func.messages.extend(
|
|
71
|
+
i for i in _E.all if i not in config.target
|
|
72
|
+
)
|
|
73
73
|
|
|
74
74
|
self._name = self._func.name
|
|
75
75
|
if (
|
|
@@ -93,7 +93,7 @@ class Failure(_t.List[Failed]):
|
|
|
93
93
|
sig = self._func.signature.args.get(index)
|
|
94
94
|
self._sig4xx_parameters(doc, sig)
|
|
95
95
|
|
|
96
|
-
self._sig5xx_returns(
|
|
96
|
+
self._sig5xx_returns(config.check.property_returns)
|
|
97
97
|
|
|
98
98
|
self.sort()
|
|
99
99
|
|
|
@@ -161,6 +161,13 @@ class Failure(_t.List[Failed]):
|
|
|
161
161
|
else:
|
|
162
162
|
# unknown-inline-directive
|
|
163
163
|
self._add(_E[2], directive=comment.kind)
|
|
164
|
+
elif not comment.isvalidflag:
|
|
165
|
+
if comment.ismodule:
|
|
166
|
+
# unknown-module-directive-flag
|
|
167
|
+
self._add(_E[6], directive=comment.kind, flag=comment.flag)
|
|
168
|
+
else:
|
|
169
|
+
# unknown-inline-directive-flag
|
|
170
|
+
self._add(_E[7], directive=comment.kind, flag=comment.flag)
|
|
164
171
|
else:
|
|
165
172
|
for rule in comment:
|
|
166
173
|
if not rule.isknown:
|
|
@@ -337,3 +344,50 @@ class Failure(_t.List[Failed]):
|
|
|
337
344
|
def retcode(self) -> int:
|
|
338
345
|
"""Exit code (non-zero if any check failed)."""
|
|
339
346
|
return self._retcode
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def report(
|
|
350
|
+
failures: Failures,
|
|
351
|
+
config: _Config,
|
|
352
|
+
file: str | None = None,
|
|
353
|
+
) -> int:
|
|
354
|
+
"""Print failures to stdout and return the highest exit code.
|
|
355
|
+
|
|
356
|
+
Iterates over failures, prints each with path, line header, and
|
|
357
|
+
messages, then returns the maximum retcode (0 or non-zero).
|
|
358
|
+
|
|
359
|
+
:param failures: Failures to print (one Failure per function).
|
|
360
|
+
:param config: Config for ANSI and formatting.
|
|
361
|
+
:param file: Module path when failures came from a file (optional).
|
|
362
|
+
:return: Exit code (non-zero if any check failed).
|
|
363
|
+
"""
|
|
364
|
+
retcodes = [0]
|
|
365
|
+
for failure in failures:
|
|
366
|
+
retcodes.append(failure.retcode)
|
|
367
|
+
path_prefix = f"{file}:" if file is not None else ""
|
|
368
|
+
header = f"{path_prefix}{failure.lineno} in {failure.name}"
|
|
369
|
+
if not config.no_ansi and _sys.stdout.isatty():
|
|
370
|
+
header = f"\033[35m{header}\033[0m"
|
|
371
|
+
|
|
372
|
+
print(header)
|
|
373
|
+
for item in failure:
|
|
374
|
+
extra = None
|
|
375
|
+
if item.hint:
|
|
376
|
+
extra = f"hint: {item.hint}"
|
|
377
|
+
|
|
378
|
+
if item.new:
|
|
379
|
+
extra = "warning: please remember to fix this or disable it"
|
|
380
|
+
_warn(_NEW.format(ref=item.ref), FutureWarning, stacklevel=3)
|
|
381
|
+
|
|
382
|
+
print(
|
|
383
|
+
" "
|
|
384
|
+
+ _TEMPLATE.format(
|
|
385
|
+
ref=item.ref,
|
|
386
|
+
description=item.description,
|
|
387
|
+
symbolic=item.symbolic,
|
|
388
|
+
),
|
|
389
|
+
)
|
|
390
|
+
if extra is not None:
|
|
391
|
+
print(f" {extra}")
|
|
392
|
+
|
|
393
|
+
return max(retcodes)
|
|
@@ -16,6 +16,8 @@ from enum import Enum as _Enum
|
|
|
16
16
|
import astroid as _ast
|
|
17
17
|
import sphinx.ext.napoleon as _s
|
|
18
18
|
|
|
19
|
+
from ._config import Ignore as _Ignore
|
|
20
|
+
|
|
19
21
|
# no function will accidentally have this name
|
|
20
22
|
UNNAMED = "-1000"
|
|
21
23
|
|
|
@@ -154,29 +156,23 @@ class Param:
|
|
|
154
156
|
class Params(_t.List[Param]):
|
|
155
157
|
"""A list-like collection of params.
|
|
156
158
|
|
|
157
|
-
:param
|
|
158
|
-
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
159
|
+
:param ignore: Configuration object for what to ignore.
|
|
159
160
|
"""
|
|
160
161
|
|
|
161
|
-
def __init__(
|
|
162
|
-
self,
|
|
163
|
-
ignore_args: bool = False,
|
|
164
|
-
ignore_kwargs: bool = False,
|
|
165
|
-
) -> None:
|
|
162
|
+
def __init__(self, ignore: _Ignore) -> None:
|
|
166
163
|
super().__init__()
|
|
167
|
-
self.
|
|
168
|
-
self._ignore_kwargs = ignore_kwargs
|
|
164
|
+
self._ignore = ignore
|
|
169
165
|
self._duplicates: list[Param] = []
|
|
170
166
|
|
|
171
167
|
def append(self, value: Param) -> None:
|
|
172
168
|
if not value.isprotected and any(
|
|
173
169
|
(
|
|
174
170
|
value.kind == DocType.PARAM,
|
|
175
|
-
(value.kind == DocType.ARG and not self.
|
|
171
|
+
(value.kind == DocType.ARG and not self._ignore.args),
|
|
176
172
|
(
|
|
177
173
|
value.kind == DocType.KWARG
|
|
178
174
|
and not (
|
|
179
|
-
self.
|
|
175
|
+
self._ignore.kwargs
|
|
180
176
|
or any(i.kind == DocType.KWARG for i in self)
|
|
181
177
|
)
|
|
182
178
|
),
|
|
@@ -223,12 +219,8 @@ class Params(_t.List[Param]):
|
|
|
223
219
|
|
|
224
220
|
|
|
225
221
|
class _Stub:
|
|
226
|
-
def __init__(
|
|
227
|
-
self
|
|
228
|
-
ignore_args: bool = False,
|
|
229
|
-
ignore_kwargs: bool = False,
|
|
230
|
-
) -> None:
|
|
231
|
-
self._args = Params(ignore_args, ignore_kwargs)
|
|
222
|
+
def __init__(self, ignore: _Ignore | None = None) -> None:
|
|
223
|
+
self._args = Params(ignore or _Ignore())
|
|
232
224
|
self._returns = False
|
|
233
225
|
|
|
234
226
|
@property
|
|
@@ -247,18 +239,16 @@ class Signature(_Stub):
|
|
|
247
239
|
|
|
248
240
|
:param rettype: Kind of return (none, some, untyped).
|
|
249
241
|
:param returns: True if return is declared in the signature.
|
|
250
|
-
:param
|
|
251
|
-
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
242
|
+
:param ignore: Configuration object for what to ignore.
|
|
252
243
|
"""
|
|
253
244
|
|
|
254
245
|
def __init__(
|
|
255
246
|
self,
|
|
256
247
|
rettype: RetType = RetType.NONE,
|
|
257
248
|
returns: bool = False,
|
|
258
|
-
|
|
259
|
-
ignore_kwargs: bool = False,
|
|
249
|
+
ignore: _Ignore | None = None,
|
|
260
250
|
) -> None:
|
|
261
|
-
super().__init__(
|
|
251
|
+
super().__init__(ignore or _Ignore())
|
|
262
252
|
self._rettype = rettype
|
|
263
253
|
self._returns = returns
|
|
264
254
|
|
|
@@ -266,19 +256,17 @@ class Signature(_Stub):
|
|
|
266
256
|
def from_ast(
|
|
267
257
|
cls,
|
|
268
258
|
node: _ast.nodes.Module | _ast.nodes.ClassDef | _ast.nodes.FunctionDef,
|
|
269
|
-
|
|
270
|
-
ignore_kwargs: bool = False,
|
|
259
|
+
ignore: _Ignore,
|
|
271
260
|
) -> Signature:
|
|
272
261
|
"""Build Signature from a function or class AST node.
|
|
273
262
|
|
|
274
263
|
:param node: AST node (function, class, or module).
|
|
275
|
-
:param
|
|
276
|
-
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
264
|
+
:param ignore: Configuration object for what to ignore.
|
|
277
265
|
:return: Signature with args and return type.
|
|
278
266
|
"""
|
|
279
267
|
rettype = RetType.from_ast(node.returns)
|
|
280
268
|
returns = rettype == RetType.SOME
|
|
281
|
-
signature = cls(rettype, returns,
|
|
269
|
+
signature = cls(rettype, returns, ignore)
|
|
282
270
|
# noinspection PyUnresolvedReferences
|
|
283
271
|
for i in [
|
|
284
272
|
a if isinstance(a, Param) else Param(name=a.name)
|
|
@@ -125,6 +125,16 @@ E = MessageMap(
|
|
|
125
125
|
"both mutually exclusive class options configured",
|
|
126
126
|
"mutually-exclusive-options",
|
|
127
127
|
),
|
|
128
|
+
6: Message(
|
|
129
|
+
"SIG006",
|
|
130
|
+
"unknown module comment flag for {directive} '{flag}'",
|
|
131
|
+
"unknown-module-directive-flag",
|
|
132
|
+
),
|
|
133
|
+
7: Message(
|
|
134
|
+
"SIG007",
|
|
135
|
+
"unknown inline comment flag for {directive} '{flag}'",
|
|
136
|
+
"unknown-inline-directive-flag",
|
|
137
|
+
),
|
|
128
138
|
#: SIG1xx Missing
|
|
129
139
|
101: Message(
|
|
130
140
|
"SIG101",
|
|
@@ -11,7 +11,7 @@ line-length = 79
|
|
|
11
11
|
allow_dirty = true
|
|
12
12
|
commit = true
|
|
13
13
|
commit_args = "-sS"
|
|
14
|
-
current_version = "0.
|
|
14
|
+
current_version = "0.82.0"
|
|
15
15
|
message = "bump: version {current_version} → {new_version}"
|
|
16
16
|
sign_tags = true
|
|
17
17
|
tag = true
|
|
@@ -122,7 +122,7 @@ maintainers = [
|
|
|
122
122
|
name = "docsig"
|
|
123
123
|
readme = "README.rst"
|
|
124
124
|
repository = "https://github.com/jshwi/docsig"
|
|
125
|
-
version = "0.
|
|
125
|
+
version = "0.82.0"
|
|
126
126
|
|
|
127
127
|
[tool.poetry.dependencies]
|
|
128
128
|
Sphinx = ">=7,<9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|