docsig 0.85.0__tar.gz → 0.85.2__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.85.0 → docsig-0.85.2}/PKG-INFO +4 -4
- {docsig-0.85.0 → docsig-0.85.2}/README.rst +3 -3
- {docsig-0.85.0 → docsig-0.85.2}/docsig/__init__.py +6 -1
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_check.py +0 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_config.py +0 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_core.py +3 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_decorators.py +0 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_directives.py +44 -6
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_files.py +0 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_main.py +0 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_module.py +9 -3
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_parsers.py +5 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_report.py +3 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_utils.py +0 -2
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_version.py +1 -1
- {docsig-0.85.0 → docsig-0.85.2}/docsig/messages.py +2 -5
- {docsig-0.85.0 → docsig-0.85.2}/pyproject.toml +2 -2
- {docsig-0.85.0 → docsig-0.85.2}/LICENSE +0 -0
- {docsig-0.85.0 → docsig-0.85.2}/docsig/__main__.py +0 -0
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_hooks.py +0 -0
- {docsig-0.85.0 → docsig-0.85.2}/docsig/_stub.py +0 -0
- {docsig-0.85.0 → docsig-0.85.2}/docsig/plugin/__init__.py +0 -0
- {docsig-0.85.0 → docsig-0.85.2}/docsig/plugin/_flake8.py +0 -0
- {docsig-0.85.0 → docsig-0.85.2}/docsig/plugin/_validate_pyproject.py +0 -0
- {docsig-0.85.0 → docsig-0.85.2}/docsig/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docsig
|
|
3
|
-
Version: 0.85.
|
|
3
|
+
Version: 0.85.2
|
|
4
4
|
Summary: Check signature params for proper documentation
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -195,7 +195,7 @@ ensure your installation has registered `docsig`
|
|
|
195
195
|
.. code-block:: console
|
|
196
196
|
|
|
197
197
|
$ flake8 --version
|
|
198
|
-
7.3.0 (docsig: 0.85.
|
|
198
|
+
7.3.0 (docsig: 0.85.2, mccabe: 0.7.0, pycodestyle: 2.14.0, pyflakes: 3.4.0) CPython 3.10.19 on Darwin
|
|
199
199
|
|
|
200
200
|
And now use `flake8` to lint your files
|
|
201
201
|
|
|
@@ -281,7 +281,7 @@ Standalone
|
|
|
281
281
|
|
|
282
282
|
repos:
|
|
283
283
|
- repo: https://github.com/jshwi/docsig
|
|
284
|
-
rev: v0.85.
|
|
284
|
+
rev: v0.85.2
|
|
285
285
|
hooks:
|
|
286
286
|
- id: docsig
|
|
287
287
|
args:
|
|
@@ -300,7 +300,7 @@ or integrated with ``flake8``
|
|
|
300
300
|
hooks:
|
|
301
301
|
- id: flake8
|
|
302
302
|
additional_dependencies:
|
|
303
|
-
- docsig==0.85.
|
|
303
|
+
- docsig==0.85.2
|
|
304
304
|
args:
|
|
305
305
|
- "--sig-check-class"
|
|
306
306
|
- "--sig-check-dunders"
|
|
@@ -166,7 +166,7 @@ ensure your installation has registered `docsig`
|
|
|
166
166
|
.. code-block:: console
|
|
167
167
|
|
|
168
168
|
$ flake8 --version
|
|
169
|
-
7.3.0 (docsig: 0.85.
|
|
169
|
+
7.3.0 (docsig: 0.85.2, mccabe: 0.7.0, pycodestyle: 2.14.0, pyflakes: 3.4.0) CPython 3.10.19 on Darwin
|
|
170
170
|
|
|
171
171
|
And now use `flake8` to lint your files
|
|
172
172
|
|
|
@@ -252,7 +252,7 @@ Standalone
|
|
|
252
252
|
|
|
253
253
|
repos:
|
|
254
254
|
- repo: https://github.com/jshwi/docsig
|
|
255
|
-
rev: v0.85.
|
|
255
|
+
rev: v0.85.2
|
|
256
256
|
hooks:
|
|
257
257
|
- id: docsig
|
|
258
258
|
args:
|
|
@@ -271,7 +271,7 @@ or integrated with ``flake8``
|
|
|
271
271
|
hooks:
|
|
272
272
|
- id: flake8
|
|
273
273
|
additional_dependencies:
|
|
274
|
-
- docsig==0.85.
|
|
274
|
+
- docsig==0.85.2
|
|
275
275
|
args:
|
|
276
276
|
- "--sig-check-class"
|
|
277
277
|
- "--sig-check-dunders"
|
|
@@ -5,8 +5,6 @@ docsig._core
|
|
|
5
5
|
Entry point and orchestration for running docstring/signature checks.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from __future__ import annotations as _
|
|
9
|
-
|
|
10
8
|
import logging as _logging
|
|
11
9
|
import sys as _sys
|
|
12
10
|
import warnings as _warnings
|
|
@@ -175,6 +173,9 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
|
175
173
|
if exclude is not None:
|
|
176
174
|
exclude_.append(exclude)
|
|
177
175
|
|
|
176
|
+
# while some params could be taken out for one time use (such as
|
|
177
|
+
# verbose), bundling all the configuration together makes it easier
|
|
178
|
+
# to report what args were provided in verbose mode
|
|
178
179
|
check = _Check(
|
|
179
180
|
class_=check_class,
|
|
180
181
|
class_constructor=check_class_constructor,
|
|
@@ -36,10 +36,23 @@ class Comment(_Messages):
|
|
|
36
36
|
self._kind = subparts[0]
|
|
37
37
|
self._flag = None if len(subparts) == 1 else subparts[1]
|
|
38
38
|
self._isnext = self._flag == "next"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
|
|
40
|
+
# if the flag is not valid, the preceding directive is not valid
|
|
41
|
+
# either
|
|
42
|
+
# at first it seems like the directive should be valid, i.e.
|
|
43
|
+
# `docsig: disable-next: SIG101` should still at least disable
|
|
44
|
+
# `SIG101`, but this causes more problems than it solves, at the
|
|
45
|
+
# module level
|
|
46
|
+
# disabling the check for the whole file is likely
|
|
47
|
+
# unexpected, confusing, and the opposite of what was intended
|
|
48
|
+
# better not disable the commented function than disable the
|
|
49
|
+
# whole file
|
|
50
|
+
# note that no directive flag at all is still a valid flag
|
|
51
|
+
if self.isvalidflag:
|
|
52
|
+
if len(parts) == 1:
|
|
53
|
+
self.extend(_E.all)
|
|
54
|
+
else:
|
|
55
|
+
self.extend(_E.from_ref(i) for i in parts[1].split(","))
|
|
43
56
|
|
|
44
57
|
@property
|
|
45
58
|
def kind(self) -> str:
|
|
@@ -90,7 +103,7 @@ class Comment(_Messages):
|
|
|
90
103
|
:return: Comment instance if valid; None otherwise.
|
|
91
104
|
"""
|
|
92
105
|
if comment[1:].strip().startswith(f"{__package__}:"):
|
|
93
|
-
return cls(comment.split(":")[1].strip(), col)
|
|
106
|
+
return cls(comment.split(":", maxsplit=1)[1].strip(), col)
|
|
94
107
|
|
|
95
108
|
return None
|
|
96
109
|
|
|
@@ -104,7 +117,11 @@ class Directives(dict[int, tuple[Comments, _Messages]]):
|
|
|
104
117
|
"""
|
|
105
118
|
|
|
106
119
|
@classmethod
|
|
107
|
-
def from_text(
|
|
120
|
+
def from_text( # pylint: disable=too-many-locals
|
|
121
|
+
cls,
|
|
122
|
+
text: str,
|
|
123
|
+
messages: _Messages,
|
|
124
|
+
) -> Directives:
|
|
108
125
|
"""Build a directives map from docsig directives in the code.
|
|
109
126
|
|
|
110
127
|
:param text: Python source code to scan for directives.
|
|
@@ -117,6 +134,8 @@ class Directives(dict[int, tuple[Comments, _Messages]]):
|
|
|
117
134
|
enable_next = False
|
|
118
135
|
next_comments = Comments(comments)
|
|
119
136
|
next_messages = _Messages(messages)
|
|
137
|
+
pending_inline: tuple[Comments, _Messages] | None = None
|
|
138
|
+
pending_inline_lineno: int | None = None
|
|
120
139
|
for line in _tokenize.generate_tokens(fin.readline):
|
|
121
140
|
# do nothing for these line types
|
|
122
141
|
if line.type in (_tokenize.NAME, _tokenize.OP, _tokenize.DEDENT):
|
|
@@ -154,6 +173,14 @@ class Directives(dict[int, tuple[Comments, _Messages]]):
|
|
|
154
173
|
if comment.ismodule:
|
|
155
174
|
comments = scoped_comments
|
|
156
175
|
messages = scoped_messages
|
|
176
|
+
else:
|
|
177
|
+
# defer scoped state for the next line without
|
|
178
|
+
# changing module-level messages
|
|
179
|
+
pending_inline = (
|
|
180
|
+
Comments(scoped_comments),
|
|
181
|
+
_Messages(scoped_messages),
|
|
182
|
+
)
|
|
183
|
+
pending_inline_lineno = lineno
|
|
157
184
|
|
|
158
185
|
# if in a 'next' module level scope and the line type is a
|
|
159
186
|
# newline (not a comment to allow 'next' directives to be
|
|
@@ -164,6 +191,17 @@ class Directives(dict[int, tuple[Comments, _Messages]]):
|
|
|
164
191
|
comments = next_comments
|
|
165
192
|
messages = next_messages
|
|
166
193
|
|
|
194
|
+
# inherit deferred inline scope on the first line after
|
|
195
|
+
# the comment (e.g. an indented def on the following line)
|
|
196
|
+
if (
|
|
197
|
+
pending_inline is not None
|
|
198
|
+
and pending_inline_lineno is not None
|
|
199
|
+
and lineno > pending_inline_lineno
|
|
200
|
+
):
|
|
201
|
+
scoped_comments, scoped_messages = pending_inline
|
|
202
|
+
pending_inline = None
|
|
203
|
+
pending_inline_lineno = None
|
|
204
|
+
|
|
167
205
|
# check that a scoped message has not updated this first, as
|
|
168
206
|
# they take precedence over global messages
|
|
169
207
|
if lineno not in directives:
|
|
@@ -5,8 +5,6 @@ docsig._module
|
|
|
5
5
|
AST-backed modules, classes, and functions for docstring checking.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from __future__ import annotations as _
|
|
9
|
-
|
|
10
8
|
import re as _re
|
|
11
9
|
import typing as _t
|
|
12
10
|
from pathlib import Path as _Path
|
|
@@ -38,6 +36,8 @@ ERRORS = (
|
|
|
38
36
|
_ast.DuplicateBasesError,
|
|
39
37
|
)
|
|
40
38
|
|
|
39
|
+
_DEFAULT_NAME = "module"
|
|
40
|
+
|
|
41
41
|
|
|
42
42
|
class Parent: # pylint: disable=too-many-instance-attributes
|
|
43
43
|
"""Container for functions or methods (module, class, or function).
|
|
@@ -74,8 +74,14 @@ class Parent: # pylint: disable=too-many-instance-attributes
|
|
|
74
74
|
self._imports = imports or _Imports()
|
|
75
75
|
self._overloads = _Overloads()
|
|
76
76
|
if node is None:
|
|
77
|
-
|
|
77
|
+
# this is either an empty module object (name it module)
|
|
78
|
+
# or an error preventing the module from being parsed
|
|
79
|
+
self._name = _DEFAULT_NAME
|
|
78
80
|
if not isinstance(self, Function) and error is not None:
|
|
81
|
+
# the only "function" belonging to the module can be
|
|
82
|
+
# later inspected to report on the module error (the
|
|
83
|
+
# report doesn't analyze modules or classes - it
|
|
84
|
+
# analyzes functions)
|
|
79
85
|
self._children.append(Function(file, error=error))
|
|
80
86
|
else:
|
|
81
87
|
self._name = node.name
|
|
@@ -3,8 +3,6 @@ docsig._parsers
|
|
|
3
3
|
===============
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from __future__ import annotations as _
|
|
7
|
-
|
|
8
6
|
import logging as _logging
|
|
9
7
|
import os as _os
|
|
10
8
|
from pathlib import Path as _Path
|
|
@@ -79,11 +77,16 @@ def parse_from_file(file: _Path, config: _Config) -> _Parent:
|
|
|
79
77
|
code = file.read_text(encoding="utf-8")
|
|
80
78
|
module_name = str(file)[:-3].replace(_os.sep, ".").replace("-", "_")
|
|
81
79
|
parent = parse_from_string(code, config, module_name, file)
|
|
80
|
+
|
|
82
81
|
except UnicodeDecodeError as err:
|
|
83
82
|
logger = _logging.getLogger(__package__)
|
|
84
83
|
logger.debug(_FILE_INFO, file, str(err).replace("\n", " "))
|
|
85
84
|
parent = _Parent(error=type(err))
|
|
86
85
|
|
|
86
|
+
# not all python files end with .py, but considering this isn't a
|
|
87
|
+
# *.py file and there was an error parsing the file it's likely not
|
|
88
|
+
# meant to bea a python file
|
|
89
|
+
# return empty parent without the error
|
|
87
90
|
if parent.error is not None and not file.name.endswith(".py"):
|
|
88
91
|
parent = _Parent()
|
|
89
92
|
|
|
@@ -8,8 +8,6 @@ issue), Failures (sequence of failures), and report() to print them and
|
|
|
8
8
|
return the highest exit code.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
from __future__ import annotations as _
|
|
12
|
-
|
|
13
11
|
import contextlib as _contextlib
|
|
14
12
|
import sys as _sys
|
|
15
13
|
import typing as _t
|
|
@@ -324,10 +322,13 @@ class Failure(list[Failed]):
|
|
|
324
322
|
if self._func.error is _ast.AstroidSyntaxError:
|
|
325
323
|
self._add(_E[901])
|
|
326
324
|
self._retcode = 123
|
|
325
|
+
# unicode-decode-error
|
|
327
326
|
if self._func.error is UnicodeDecodeError:
|
|
328
327
|
self._add(_E[902])
|
|
328
|
+
# recursion-error
|
|
329
329
|
if self._func.error is RecursionError:
|
|
330
330
|
self._add(_E[903])
|
|
331
|
+
# duplicates-found-in-mros
|
|
331
332
|
if self._func.error is _ast.DuplicateBasesError:
|
|
332
333
|
self._add(_E[904])
|
|
333
334
|
|
|
@@ -6,8 +6,6 @@ Error message definitions (Message, MessageMap, E) and format templates
|
|
|
6
6
|
for docstring-check output.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from __future__ import annotations as _
|
|
10
|
-
|
|
11
9
|
import typing as _t
|
|
12
10
|
|
|
13
11
|
#: Error code for unknown errors.
|
|
@@ -19,9 +17,8 @@ TEMPLATE = "{ref}: {description} ({symbolic})"
|
|
|
19
17
|
#: Flake8 template to format message strings.
|
|
20
18
|
FLAKE8 = "{ref} {description} ({symbolic})"
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
{ref} is a new violation and will error in a future version
|
|
24
|
-
"""
|
|
20
|
+
#: Template for future messages that don't raise a violation yet
|
|
21
|
+
NEW = "{ref} is a new violation and will error in a future version"
|
|
25
22
|
|
|
26
23
|
|
|
27
24
|
class Messages(list["Message"]):
|
|
@@ -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.85.
|
|
14
|
+
current_version = "0.85.2"
|
|
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.85.
|
|
125
|
+
version = "0.85.2"
|
|
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
|