docsig 0.53.1__tar.gz → 0.53.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.53.1 → docsig-0.53.2}/PKG-INFO +6 -6
- {docsig-0.53.1 → docsig-0.53.2}/README.rst +5 -5
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_report.py +40 -7
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_stub.py +44 -6
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_version.py +1 -1
- {docsig-0.53.1 → docsig-0.53.2}/pyproject.toml +8 -6
- {docsig-0.53.1 → docsig-0.53.2}/LICENSE +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/__init__.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/__main__.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_config.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_core.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_decorators.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_directives.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_hooks.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_main.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_module.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/_utils.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/messages.py +0 -0
- {docsig-0.53.1 → docsig-0.53.2}/docsig/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: docsig
|
|
3
|
-
Version: 0.53.
|
|
3
|
+
Version: 0.53.2
|
|
4
4
|
Summary: Check signature params for proper documentation
|
|
5
5
|
Home-page: https://pypi.org/project/docsig/
|
|
6
6
|
License: MIT
|
|
@@ -90,7 +90,7 @@ Supports reStructuredText (``Sphinx``), ``NumPy``, and ``Google``
|
|
|
90
90
|
|
|
91
91
|
Contributing
|
|
92
92
|
------------
|
|
93
|
-
If you are interested in contributing to ``docsig`` please read about contributing `here <https://
|
|
93
|
+
If you are interested in contributing to ``docsig`` please read about contributing `here <https://docsig.readthedocs.io/en/latest/development/contributing.html>`__
|
|
94
94
|
|
|
95
95
|
Installation
|
|
96
96
|
------------
|
|
@@ -199,17 +199,17 @@ API
|
|
|
199
199
|
E102: includes parameters that do not exist (params-do-not-exist)
|
|
200
200
|
1
|
|
201
201
|
|
|
202
|
-
A full list of checks can be found `here <https://docsig.readthedocs.io/en/latest/
|
|
202
|
+
A full list of checks can be found `here <https://docsig.readthedocs.io/en/latest/usage/messages.html>`__
|
|
203
203
|
|
|
204
204
|
Message Control
|
|
205
205
|
***************
|
|
206
206
|
|
|
207
|
-
`Documentation on message control <https://
|
|
207
|
+
`Documentation on message control <https://docsig.readthedocs.io/en/latest/usage/message-control.html>`_
|
|
208
208
|
|
|
209
209
|
Classes
|
|
210
210
|
*******
|
|
211
211
|
|
|
212
|
-
`Documenting classes <https://
|
|
212
|
+
`Documenting classes <https://docsig.readthedocs.io/en/latest/usage/configuration.html#classes>`_
|
|
213
213
|
|
|
214
214
|
pre-commit
|
|
215
215
|
**********
|
|
@@ -222,7 +222,7 @@ It can be added to your .pre-commit-config.yaml as follows:
|
|
|
222
222
|
|
|
223
223
|
repos:
|
|
224
224
|
- repo: https://github.com/jshwi/docsig
|
|
225
|
-
rev: v0.53.
|
|
225
|
+
rev: v0.53.2
|
|
226
226
|
hooks:
|
|
227
227
|
- id: docsig
|
|
228
228
|
args:
|
|
@@ -62,7 +62,7 @@ Supports reStructuredText (``Sphinx``), ``NumPy``, and ``Google``
|
|
|
62
62
|
|
|
63
63
|
Contributing
|
|
64
64
|
------------
|
|
65
|
-
If you are interested in contributing to ``docsig`` please read about contributing `here <https://
|
|
65
|
+
If you are interested in contributing to ``docsig`` please read about contributing `here <https://docsig.readthedocs.io/en/latest/development/contributing.html>`__
|
|
66
66
|
|
|
67
67
|
Installation
|
|
68
68
|
------------
|
|
@@ -171,17 +171,17 @@ API
|
|
|
171
171
|
E102: includes parameters that do not exist (params-do-not-exist)
|
|
172
172
|
1
|
|
173
173
|
|
|
174
|
-
A full list of checks can be found `here <https://docsig.readthedocs.io/en/latest/
|
|
174
|
+
A full list of checks can be found `here <https://docsig.readthedocs.io/en/latest/usage/messages.html>`__
|
|
175
175
|
|
|
176
176
|
Message Control
|
|
177
177
|
***************
|
|
178
178
|
|
|
179
|
-
`Documentation on message control <https://
|
|
179
|
+
`Documentation on message control <https://docsig.readthedocs.io/en/latest/usage/message-control.html>`_
|
|
180
180
|
|
|
181
181
|
Classes
|
|
182
182
|
*******
|
|
183
183
|
|
|
184
|
-
`Documenting classes <https://
|
|
184
|
+
`Documenting classes <https://docsig.readthedocs.io/en/latest/usage/configuration.html#classes>`_
|
|
185
185
|
|
|
186
186
|
pre-commit
|
|
187
187
|
**********
|
|
@@ -194,7 +194,7 @@ It can be added to your .pre-commit-config.yaml as follows:
|
|
|
194
194
|
|
|
195
195
|
repos:
|
|
196
196
|
- repo: https://github.com/jshwi/docsig
|
|
197
|
-
rev: v0.53.
|
|
197
|
+
rev: v0.53.2
|
|
198
198
|
hooks:
|
|
199
199
|
- id: docsig
|
|
200
200
|
args:
|
|
@@ -11,6 +11,7 @@ import typing as _t
|
|
|
11
11
|
import click as _click
|
|
12
12
|
|
|
13
13
|
from ._module import Function as _Function
|
|
14
|
+
from ._stub import UNNAMED as _UNNAMED
|
|
14
15
|
from ._stub import Param as _Param
|
|
15
16
|
from ._stub import RetType as _RetType
|
|
16
17
|
from ._utils import almost_equal as _almost_equal
|
|
@@ -65,10 +66,14 @@ class Failure(_t.List[str]):
|
|
|
65
66
|
self._missing_class_docstring()
|
|
66
67
|
self._missing_func_docstring()
|
|
67
68
|
if func.docstring.string is not None:
|
|
68
|
-
|
|
69
|
+
# make sure these come first as they alter the function
|
|
70
|
+
# docstring object before it is analysed further
|
|
71
|
+
self._duplicates()
|
|
69
72
|
self._exists()
|
|
73
|
+
|
|
74
|
+
# all further analysis below
|
|
75
|
+
self._return_not_typed()
|
|
70
76
|
self._missing()
|
|
71
|
-
self._duplicates()
|
|
72
77
|
self._extra_return()
|
|
73
78
|
self._missing_return()
|
|
74
79
|
self._property_return()
|
|
@@ -78,9 +83,9 @@ class Failure(_t.List[str]):
|
|
|
78
83
|
doc = func.docstring.args.get(index)
|
|
79
84
|
self._description_syntax(doc)
|
|
80
85
|
self._indent_syntax(doc)
|
|
86
|
+
self._incorrect(doc)
|
|
81
87
|
if arg != doc:
|
|
82
88
|
self._order(arg, doc)
|
|
83
|
-
self._incorrect(arg, doc)
|
|
84
89
|
self._misspelled(arg, doc)
|
|
85
90
|
self._not_equal(arg, doc)
|
|
86
91
|
|
|
@@ -105,7 +110,16 @@ class Failure(_t.List[str]):
|
|
|
105
110
|
self._add(_E[101])
|
|
106
111
|
|
|
107
112
|
def _exists(self) -> None:
|
|
113
|
+
# pop the parameters that do not exist so that they are excluded
|
|
114
|
+
# from further analysis, that way there are no additional, and
|
|
115
|
+
# redundant, errors
|
|
116
|
+
# this will ensure that both signature and docstring are equal
|
|
117
|
+
# in length, with all parameters that do not exist accounted for
|
|
108
118
|
if len(self._func.docstring.args) > len(self._func.signature.args):
|
|
119
|
+
for count, __ in enumerate(self._func.docstring.args, 1):
|
|
120
|
+
if count > len(self._func.signature.args):
|
|
121
|
+
self._func.docstring.args.pop(count - 1)
|
|
122
|
+
|
|
109
123
|
self._add(_E[102])
|
|
110
124
|
|
|
111
125
|
def _missing_func_docstring(self) -> None:
|
|
@@ -121,7 +135,14 @@ class Failure(_t.List[str]):
|
|
|
121
135
|
self._add(_E[103])
|
|
122
136
|
|
|
123
137
|
def _duplicates(self) -> None:
|
|
138
|
+
# pop the duplicates so that they are considered a single
|
|
139
|
+
# parameter, that way there are no assumptions that the
|
|
140
|
+
# parameters must be out of order
|
|
124
141
|
if self._func.docstring.args.duplicated:
|
|
142
|
+
for count, arg in enumerate(self._func.docstring.args):
|
|
143
|
+
if arg in self._func.docstring.args.duplicates:
|
|
144
|
+
self._func.docstring.args.pop(count)
|
|
145
|
+
|
|
125
146
|
self._add(_E[106])
|
|
126
147
|
|
|
127
148
|
def _extra_return(self) -> None:
|
|
@@ -151,13 +172,25 @@ class Failure(_t.List[str]):
|
|
|
151
172
|
and not self._no_returns
|
|
152
173
|
):
|
|
153
174
|
docstring = self._func.docstring.string
|
|
154
|
-
|
|
155
|
-
|
|
175
|
+
# do more than just search the docstring for the word return
|
|
176
|
+
# as return statements come last, so only search the last
|
|
177
|
+
# line
|
|
178
|
+
# params can also come last, so make sure it is not a param
|
|
179
|
+
# declaration
|
|
180
|
+
if docstring is not None:
|
|
181
|
+
lines = docstring.splitlines()
|
|
182
|
+
if len(lines) > 1:
|
|
183
|
+
if "return" in lines[-1] and ":param" not in lines[-1]:
|
|
184
|
+
hint = True
|
|
156
185
|
|
|
157
186
|
self._add(_E[105], hint=hint)
|
|
158
187
|
|
|
159
|
-
def _incorrect(self,
|
|
160
|
-
if
|
|
188
|
+
def _incorrect(self, doc: _Param) -> None:
|
|
189
|
+
# if the parameter does not have a name, but exists, then it
|
|
190
|
+
# must be incorrectly documented
|
|
191
|
+
# prior implementation relied on the docstring parameter
|
|
192
|
+
# equalling the signature parameter
|
|
193
|
+
if doc.name == _UNNAMED:
|
|
161
194
|
self._add(_E[107])
|
|
162
195
|
|
|
163
196
|
# final catch-all
|
|
@@ -14,6 +14,9 @@ from enum import Enum as _Enum
|
|
|
14
14
|
import astroid as _ast
|
|
15
15
|
import sphinx.ext.napoleon as _s
|
|
16
16
|
|
|
17
|
+
# no function will accidentally have this name
|
|
18
|
+
UNNAMED = -1000
|
|
19
|
+
|
|
17
20
|
|
|
18
21
|
# noinspection PyTypeChecker
|
|
19
22
|
class _GoogleDocstring(str):
|
|
@@ -131,19 +134,22 @@ class Param(_t.NamedTuple):
|
|
|
131
134
|
class _Matches(_t.List[Param]):
|
|
132
135
|
_pattern = _re.compile(":(.*?):")
|
|
133
136
|
|
|
134
|
-
def __init__(self, string: str) -> None:
|
|
137
|
+
def __init__(self, string: str, indent_anomaly: bool) -> None:
|
|
135
138
|
super().__init__()
|
|
136
139
|
for line in string.splitlines():
|
|
137
140
|
strip_line = line.lstrip()
|
|
138
141
|
match = self._pattern.split(strip_line)[1:]
|
|
139
142
|
if match:
|
|
140
|
-
|
|
143
|
+
description = None
|
|
141
144
|
kinds = match[0].split()
|
|
142
145
|
if kinds:
|
|
143
146
|
kind = DocType.from_str(kinds[0])
|
|
144
147
|
|
|
145
148
|
if len(kinds) > 1:
|
|
146
149
|
name = kinds[1]
|
|
150
|
+
else:
|
|
151
|
+
# name could not be parsed
|
|
152
|
+
name = UNNAMED
|
|
147
153
|
|
|
148
154
|
if len(match) > 1:
|
|
149
155
|
description = match[1]
|
|
@@ -153,7 +159,7 @@ class _Matches(_t.List[Param]):
|
|
|
153
159
|
kind,
|
|
154
160
|
name,
|
|
155
161
|
description,
|
|
156
|
-
|
|
162
|
+
int(indent_anomaly),
|
|
157
163
|
)
|
|
158
164
|
)
|
|
159
165
|
|
|
@@ -165,6 +171,7 @@ class _Params(_t.List[Param]):
|
|
|
165
171
|
super().__init__()
|
|
166
172
|
self._ignore_args = ignore_args
|
|
167
173
|
self._ignore_kwargs = ignore_kwargs
|
|
174
|
+
self._duplicates: list[Param] = []
|
|
168
175
|
|
|
169
176
|
# pylint: disable=too-many-boolean-expressions
|
|
170
177
|
def append(self, value: Param) -> None:
|
|
@@ -195,8 +202,26 @@ class _Params(_t.List[Param]):
|
|
|
195
202
|
|
|
196
203
|
@property
|
|
197
204
|
def duplicated(self) -> bool:
|
|
198
|
-
"""Boolean value for whether there are duplicate parameters.
|
|
199
|
-
|
|
205
|
+
"""Boolean value for whether there are duplicate parameters.
|
|
206
|
+
|
|
207
|
+
Ensure only the names of the parameters are needed to be
|
|
208
|
+
considered duplicates. It is not relevant whether the
|
|
209
|
+
descriptions match.
|
|
210
|
+
"""
|
|
211
|
+
for k, v in _Counter(i.name for i in self).items():
|
|
212
|
+
if v > 1:
|
|
213
|
+
for i in self:
|
|
214
|
+
if i.name == k:
|
|
215
|
+
# record the duplicates for later analysis
|
|
216
|
+
self._duplicates.append(i)
|
|
217
|
+
return True
|
|
218
|
+
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
@property
|
|
222
|
+
def duplicates(self) -> list[Param]:
|
|
223
|
+
"""Duplicated parameters."""
|
|
224
|
+
return self._duplicates
|
|
200
225
|
|
|
201
226
|
|
|
202
227
|
class _Stub:
|
|
@@ -288,6 +313,19 @@ class Docstring(_Stub):
|
|
|
288
313
|
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
289
314
|
"""
|
|
290
315
|
|
|
316
|
+
@staticmethod
|
|
317
|
+
def _indent_anomaly(string: str) -> bool:
|
|
318
|
+
leading_spaces = []
|
|
319
|
+
for line in string.splitlines():
|
|
320
|
+
match = _re.match(r"^\s*", line)
|
|
321
|
+
if match is not None:
|
|
322
|
+
spaces = len(match.group())
|
|
323
|
+
if spaces > 0:
|
|
324
|
+
leading_spaces.append(spaces)
|
|
325
|
+
|
|
326
|
+
# look for spaces in odd intervals
|
|
327
|
+
return bool(any(i % 2 != 0 for i in leading_spaces))
|
|
328
|
+
|
|
291
329
|
def __init__(
|
|
292
330
|
self,
|
|
293
331
|
node: _ast.Const | None = None,
|
|
@@ -298,7 +336,7 @@ class Docstring(_Stub):
|
|
|
298
336
|
self._string = None
|
|
299
337
|
if node is not None:
|
|
300
338
|
self._string = _RawDocstring(node.value)
|
|
301
|
-
for i in _Matches(self._string):
|
|
339
|
+
for i in _Matches(self._string, self._indent_anomaly(node.value)):
|
|
302
340
|
self._args.append(i)
|
|
303
341
|
|
|
304
342
|
self._returns = self._string is not None and bool(
|
|
@@ -27,6 +27,7 @@ fail_under = 100
|
|
|
27
27
|
|
|
28
28
|
[tool.coverage.run]
|
|
29
29
|
omit = [
|
|
30
|
+
"docs/conf.py",
|
|
30
31
|
"docsig/__main__.py",
|
|
31
32
|
"whitelist.py"
|
|
32
33
|
]
|
|
@@ -65,7 +66,7 @@ maintainers = [
|
|
|
65
66
|
name = "docsig"
|
|
66
67
|
readme = "README.rst"
|
|
67
68
|
repository = "https://github.com/jshwi/docsig"
|
|
68
|
-
version = "0.53.
|
|
69
|
+
version = "0.53.2"
|
|
69
70
|
|
|
70
71
|
[tool.poetry.dependencies]
|
|
71
72
|
Sphinx = "^7.0.0"
|
|
@@ -78,14 +79,16 @@ python = "^3.8"
|
|
|
78
79
|
[tool.poetry.dev-dependencies]
|
|
79
80
|
bump2version = "^1.0.1"
|
|
80
81
|
deptry = "^0.16.1"
|
|
82
|
+
furo = "^2024.4.27"
|
|
81
83
|
ipython = "^8.12.0"
|
|
84
|
+
myst-parser = "^3.0.1"
|
|
82
85
|
pre-commit = "^3.3.3"
|
|
83
86
|
pyaud = "^7.5.0"
|
|
84
87
|
pytest-randomly = "^3.13.0"
|
|
85
88
|
pytest-sugar = "^1.0.0"
|
|
86
89
|
pytest-xdist = "^3.6.1"
|
|
87
90
|
restview = "^3.0.0"
|
|
88
|
-
sphinx-
|
|
91
|
+
sphinx-copybutton = "^0.5.2"
|
|
89
92
|
sphinx-toolbox = "^3.5.0"
|
|
90
93
|
templatest = "^0.10.1"
|
|
91
94
|
tox = "^4.15.0"
|
|
@@ -95,10 +98,8 @@ docsig = "docsig.__main__:main"
|
|
|
95
98
|
|
|
96
99
|
[tool.pyaud]
|
|
97
100
|
audit = [
|
|
98
|
-
"about-tests",
|
|
99
101
|
"commit-policy",
|
|
100
102
|
"copyright-year",
|
|
101
|
-
"files",
|
|
102
103
|
"format",
|
|
103
104
|
"format-docs",
|
|
104
105
|
"format-str",
|
|
@@ -106,13 +107,14 @@ audit = [
|
|
|
106
107
|
"lint",
|
|
107
108
|
"test",
|
|
108
109
|
"typecheck",
|
|
109
|
-
"unused"
|
|
110
|
+
"unused",
|
|
111
|
+
"whitelist"
|
|
110
112
|
]
|
|
111
113
|
exclude = '''
|
|
112
114
|
(?x)^(
|
|
113
115
|
| docs\/conf\.py
|
|
114
116
|
| whitelist\.py
|
|
115
|
-
| scripts
|
|
117
|
+
| scripts\/.*
|
|
116
118
|
)$
|
|
117
119
|
'''
|
|
118
120
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|