docsig 0.57.0__tar.gz → 0.59.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.57.0 → docsig-0.59.0}/PKG-INFO +22 -4
- {docsig-0.57.0 → docsig-0.59.0}/README.rst +21 -2
- docsig-0.59.0/docsig/_core.py +419 -0
- docsig-0.59.0/docsig/_files.py +118 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_module.py +14 -201
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_report.py +35 -51
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_stub.py +18 -33
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_utils.py +7 -9
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_version.py +1 -1
- {docsig-0.57.0 → docsig-0.59.0}/docsig/plugin.py +44 -27
- {docsig-0.57.0 → docsig-0.59.0}/pyproject.toml +8 -3
- docsig-0.57.0/docsig/_core.py +0 -225
- {docsig-0.57.0 → docsig-0.59.0}/LICENSE +0 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/__init__.py +0 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/__main__.py +0 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_config.py +0 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_decorators.py +0 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_directives.py +0 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_hooks.py +0 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/_main.py +0 -0
- {docsig-0.57.0 → docsig-0.59.0}/docsig/messages.py +0 -0
- {docsig-0.57.0 → docsig-0.59.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.59.0
|
|
4
4
|
Summary: Check signature params for proper documentation
|
|
5
5
|
Home-page: https://pypi.org/project/docsig/
|
|
6
6
|
License: MIT
|
|
@@ -19,7 +19,6 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Requires-Dist: Sphinx (>=7.0.0,<8.0.0)
|
|
20
20
|
Requires-Dist: arcon (>=0.4.0)
|
|
21
21
|
Requires-Dist: astroid (>=3.0.1,<4.0.0)
|
|
22
|
-
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
23
22
|
Requires-Dist: pathspec (>=0.12.1,<0.13.0)
|
|
24
23
|
Project-URL: Documentation, https://docsig.readthedocs.io/en/latest
|
|
25
24
|
Project-URL: Repository, https://github.com/jshwi/docsig
|
|
@@ -170,7 +169,7 @@ ensure your installation has registered `docsig`
|
|
|
170
169
|
.. code-block:: console
|
|
171
170
|
|
|
172
171
|
$ flake8 --version
|
|
173
|
-
7.1.0 (docsig: 0.
|
|
172
|
+
7.1.0 (docsig: 0.59.0, mccabe: 0.7.0, pycodestyle: 2.12.0, pyflakes: 3.2.0) CPython 3.8.13 on Darwin
|
|
174
173
|
|
|
175
174
|
And now use `flake8` to lint your files
|
|
176
175
|
|
|
@@ -253,11 +252,13 @@ pre-commit
|
|
|
253
252
|
|
|
254
253
|
It can be added to your .pre-commit-config.yaml as follows:
|
|
255
254
|
|
|
255
|
+
Standalone
|
|
256
|
+
|
|
256
257
|
.. code-block:: yaml
|
|
257
258
|
|
|
258
259
|
repos:
|
|
259
260
|
- repo: https://github.com/jshwi/docsig
|
|
260
|
-
rev: v0.
|
|
261
|
+
rev: v0.59.0
|
|
261
262
|
hooks:
|
|
262
263
|
- id: docsig
|
|
263
264
|
args:
|
|
@@ -266,3 +267,20 @@ It can be added to your .pre-commit-config.yaml as follows:
|
|
|
266
267
|
- "--check-overridden"
|
|
267
268
|
- "--check-protected"
|
|
268
269
|
|
|
270
|
+
or integrated with ``flake8``
|
|
271
|
+
|
|
272
|
+
.. code-block:: yaml
|
|
273
|
+
|
|
274
|
+
repos:
|
|
275
|
+
- repo: https://github.com/PyCQA/flake8
|
|
276
|
+
rev: "7.1.0"
|
|
277
|
+
hooks:
|
|
278
|
+
- id: flake8
|
|
279
|
+
additional_dependencies:
|
|
280
|
+
- docsig==0.59.0
|
|
281
|
+
args:
|
|
282
|
+
- "--sig-check-class"
|
|
283
|
+
- "--sig-check-dunders"
|
|
284
|
+
- "--sig-check-overridden"
|
|
285
|
+
- "--sig-check-protected"
|
|
286
|
+
|
|
@@ -143,7 +143,7 @@ ensure your installation has registered `docsig`
|
|
|
143
143
|
.. code-block:: console
|
|
144
144
|
|
|
145
145
|
$ flake8 --version
|
|
146
|
-
7.1.0 (docsig: 0.
|
|
146
|
+
7.1.0 (docsig: 0.59.0, mccabe: 0.7.0, pycodestyle: 2.12.0, pyflakes: 3.2.0) CPython 3.8.13 on Darwin
|
|
147
147
|
|
|
148
148
|
And now use `flake8` to lint your files
|
|
149
149
|
|
|
@@ -226,11 +226,13 @@ pre-commit
|
|
|
226
226
|
|
|
227
227
|
It can be added to your .pre-commit-config.yaml as follows:
|
|
228
228
|
|
|
229
|
+
Standalone
|
|
230
|
+
|
|
229
231
|
.. code-block:: yaml
|
|
230
232
|
|
|
231
233
|
repos:
|
|
232
234
|
- repo: https://github.com/jshwi/docsig
|
|
233
|
-
rev: v0.
|
|
235
|
+
rev: v0.59.0
|
|
234
236
|
hooks:
|
|
235
237
|
- id: docsig
|
|
236
238
|
args:
|
|
@@ -238,3 +240,20 @@ It can be added to your .pre-commit-config.yaml as follows:
|
|
|
238
240
|
- "--check-dunders"
|
|
239
241
|
- "--check-overridden"
|
|
240
242
|
- "--check-protected"
|
|
243
|
+
|
|
244
|
+
or integrated with ``flake8``
|
|
245
|
+
|
|
246
|
+
.. code-block:: yaml
|
|
247
|
+
|
|
248
|
+
repos:
|
|
249
|
+
- repo: https://github.com/PyCQA/flake8
|
|
250
|
+
rev: "7.1.0"
|
|
251
|
+
hooks:
|
|
252
|
+
- id: flake8
|
|
253
|
+
additional_dependencies:
|
|
254
|
+
- docsig==0.59.0
|
|
255
|
+
args:
|
|
256
|
+
- "--sig-check-class"
|
|
257
|
+
- "--sig-check-dunders"
|
|
258
|
+
- "--sig-check-overridden"
|
|
259
|
+
- "--sig-check-protected"
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
"""
|
|
2
|
+
docsig._core
|
|
3
|
+
============
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations as _
|
|
7
|
+
|
|
8
|
+
import sys as _sys
|
|
9
|
+
from pathlib import Path as _Path
|
|
10
|
+
|
|
11
|
+
import astroid as _ast
|
|
12
|
+
|
|
13
|
+
from . import _decorators
|
|
14
|
+
from ._directives import Directives as _Directives
|
|
15
|
+
from ._files import FILE_INFO as _FILE_INFO
|
|
16
|
+
from ._files import Paths as _Paths
|
|
17
|
+
from ._module import Ast as _Ast
|
|
18
|
+
from ._module import Function as _Function
|
|
19
|
+
from ._module import Parent as _Parent
|
|
20
|
+
from ._report import Failure as _Failure
|
|
21
|
+
from ._report import Failures as _Failures
|
|
22
|
+
from ._utils import pretty_print_error as _pretty_print_error
|
|
23
|
+
from ._utils import print_checks as _print_checks
|
|
24
|
+
from ._utils import vprint as _vprint
|
|
25
|
+
from .messages import TEMPLATE as _TEMPLATE
|
|
26
|
+
from .messages import Messages as _Messages
|
|
27
|
+
|
|
28
|
+
_DEFAULT_EXCLUDES = """\
|
|
29
|
+
(?x)^(
|
|
30
|
+
|\\.?venv
|
|
31
|
+
|\\.git
|
|
32
|
+
|\\.hg
|
|
33
|
+
|\\.idea
|
|
34
|
+
|\\.mypy_cache
|
|
35
|
+
|\\.nox
|
|
36
|
+
|\\.pytest_cache
|
|
37
|
+
|\\.svn
|
|
38
|
+
|\\.tox
|
|
39
|
+
|\\.vscode
|
|
40
|
+
|_?build
|
|
41
|
+
|__pycache__
|
|
42
|
+
|dist
|
|
43
|
+
|node_modules
|
|
44
|
+
)$
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _run_check( # pylint: disable=too-many-arguments,too-many-locals
|
|
49
|
+
child: _Parent,
|
|
50
|
+
parent: _Parent,
|
|
51
|
+
check_class: bool,
|
|
52
|
+
check_class_constructor: bool,
|
|
53
|
+
check_dunders: bool,
|
|
54
|
+
check_nested: bool,
|
|
55
|
+
check_overridden: bool,
|
|
56
|
+
check_protected: bool,
|
|
57
|
+
check_property_returns: bool,
|
|
58
|
+
ignore_no_params: bool,
|
|
59
|
+
ignore_typechecker: bool,
|
|
60
|
+
no_ansi: bool,
|
|
61
|
+
target: _Messages,
|
|
62
|
+
failures: _Failures,
|
|
63
|
+
) -> None:
|
|
64
|
+
if isinstance(child, _Function):
|
|
65
|
+
if not (child.isoverridden and not check_overridden) and (
|
|
66
|
+
not (child.isprotected and not check_protected)
|
|
67
|
+
and not (
|
|
68
|
+
child.isinit
|
|
69
|
+
and not (
|
|
70
|
+
(check_class or check_class_constructor)
|
|
71
|
+
and not (parent.isprotected and not check_protected)
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
and not (child.isdunder and not check_dunders)
|
|
75
|
+
and not (child.docstring.bare and ignore_no_params)
|
|
76
|
+
):
|
|
77
|
+
failure = _Failure(
|
|
78
|
+
child, target, check_property_returns, ignore_typechecker
|
|
79
|
+
)
|
|
80
|
+
if failure:
|
|
81
|
+
failures.append(failure)
|
|
82
|
+
|
|
83
|
+
if check_nested:
|
|
84
|
+
for func in child:
|
|
85
|
+
_run_check(
|
|
86
|
+
func,
|
|
87
|
+
child,
|
|
88
|
+
check_class,
|
|
89
|
+
check_class_constructor,
|
|
90
|
+
check_dunders,
|
|
91
|
+
check_nested,
|
|
92
|
+
check_overridden,
|
|
93
|
+
check_protected,
|
|
94
|
+
check_property_returns,
|
|
95
|
+
ignore_no_params,
|
|
96
|
+
ignore_typechecker,
|
|
97
|
+
no_ansi,
|
|
98
|
+
target,
|
|
99
|
+
failures,
|
|
100
|
+
)
|
|
101
|
+
else:
|
|
102
|
+
# this is a class
|
|
103
|
+
for func in child:
|
|
104
|
+
_run_check(
|
|
105
|
+
func,
|
|
106
|
+
child,
|
|
107
|
+
check_class,
|
|
108
|
+
check_class_constructor,
|
|
109
|
+
check_dunders,
|
|
110
|
+
check_nested,
|
|
111
|
+
check_overridden,
|
|
112
|
+
check_protected,
|
|
113
|
+
check_property_returns,
|
|
114
|
+
ignore_no_params,
|
|
115
|
+
ignore_typechecker,
|
|
116
|
+
no_ansi,
|
|
117
|
+
target,
|
|
118
|
+
failures,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _get_failures( # pylint: disable=too-many-locals,too-many-arguments
|
|
123
|
+
module: _Parent,
|
|
124
|
+
check_class: bool,
|
|
125
|
+
check_class_constructor: bool,
|
|
126
|
+
check_dunders: bool,
|
|
127
|
+
check_nested: bool,
|
|
128
|
+
check_overridden: bool,
|
|
129
|
+
check_protected: bool,
|
|
130
|
+
check_property_returns: bool,
|
|
131
|
+
ignore_no_params: bool,
|
|
132
|
+
ignore_typechecker: bool,
|
|
133
|
+
check_protected_class_methods: bool,
|
|
134
|
+
no_ansi: bool,
|
|
135
|
+
target: _Messages,
|
|
136
|
+
) -> _Failures:
|
|
137
|
+
failures = _Failures()
|
|
138
|
+
for top_level in module:
|
|
139
|
+
if (
|
|
140
|
+
not top_level.isprotected
|
|
141
|
+
or check_protected
|
|
142
|
+
or check_protected_class_methods
|
|
143
|
+
):
|
|
144
|
+
_run_check(
|
|
145
|
+
top_level,
|
|
146
|
+
module,
|
|
147
|
+
check_class,
|
|
148
|
+
check_class_constructor,
|
|
149
|
+
check_dunders,
|
|
150
|
+
check_nested,
|
|
151
|
+
check_overridden,
|
|
152
|
+
check_protected,
|
|
153
|
+
check_property_returns,
|
|
154
|
+
ignore_no_params,
|
|
155
|
+
ignore_typechecker,
|
|
156
|
+
no_ansi,
|
|
157
|
+
target or _Messages(),
|
|
158
|
+
failures,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
return failures
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _report(
|
|
165
|
+
failures: _Failures, path: str | None = None, no_ansi: bool = False
|
|
166
|
+
) -> None:
|
|
167
|
+
for failure in failures:
|
|
168
|
+
module = f"{path}:" if path is not None else ""
|
|
169
|
+
header = f"{module}{failure.lineno} in {failure.name}"
|
|
170
|
+
if not no_ansi and _sys.stdout.isatty():
|
|
171
|
+
header = f"\033[35m{header}\033[0m"
|
|
172
|
+
|
|
173
|
+
print(header)
|
|
174
|
+
for item in failure:
|
|
175
|
+
print(
|
|
176
|
+
" "
|
|
177
|
+
+ _TEMPLATE.format(
|
|
178
|
+
ref=item.ref,
|
|
179
|
+
description=item.description,
|
|
180
|
+
symbolic=item.symbolic,
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
if item.hint:
|
|
184
|
+
print(f" hint: {item.hint}")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def runner( # pylint: disable=too-many-locals,too-many-arguments
|
|
188
|
+
file: str | _Path,
|
|
189
|
+
disable: _Messages | None = None,
|
|
190
|
+
check_class: bool = False,
|
|
191
|
+
check_class_constructor: bool = False,
|
|
192
|
+
check_dunders: bool = False,
|
|
193
|
+
check_nested: bool = False,
|
|
194
|
+
check_overridden: bool = False,
|
|
195
|
+
check_protected: bool = False,
|
|
196
|
+
check_property_returns: bool = False,
|
|
197
|
+
ignore_no_params: bool = False,
|
|
198
|
+
ignore_args: bool = False,
|
|
199
|
+
ignore_kwargs: bool = False,
|
|
200
|
+
ignore_typechecker: bool = False,
|
|
201
|
+
check_protected_class_methods: bool = False,
|
|
202
|
+
no_ansi: bool = False,
|
|
203
|
+
verbose: bool = False,
|
|
204
|
+
target: _Messages | None = None,
|
|
205
|
+
) -> tuple[_Failures, int]:
|
|
206
|
+
"""Per path runner.
|
|
207
|
+
|
|
208
|
+
:param file: Path to check.
|
|
209
|
+
:param disable: Messages to disable.
|
|
210
|
+
:param check_class: Check class docstrings.
|
|
211
|
+
:param check_class_constructor: Check ``__init__`` methods. Note that this
|
|
212
|
+
is mutually incompatible with check_class.
|
|
213
|
+
:param check_dunders: Check dunder methods
|
|
214
|
+
:param check_nested: Check nested functions and classes.
|
|
215
|
+
:param check_overridden: Check overridden methods
|
|
216
|
+
:param check_protected: Check protected functions and classes.
|
|
217
|
+
:param check_property_returns: Run return checks on properties.
|
|
218
|
+
:param ignore_no_params: Ignore docstrings where parameters are not
|
|
219
|
+
documented
|
|
220
|
+
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
221
|
+
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
222
|
+
:param ignore_typechecker: Ignore checking return values.
|
|
223
|
+
:param check_protected_class_methods: Check public methods belonging
|
|
224
|
+
to protected classes.
|
|
225
|
+
:param no_ansi: Disable ANSI output.
|
|
226
|
+
:param verbose: increase output verbosity.
|
|
227
|
+
:param target: List of errors to target.
|
|
228
|
+
:return: Exit status for whether test failed or not.
|
|
229
|
+
"""
|
|
230
|
+
failures = _Failures()
|
|
231
|
+
path = _Path(file)
|
|
232
|
+
string = path.read_text(encoding="utf-8")
|
|
233
|
+
ast = _Ast.parse(string)
|
|
234
|
+
if ast.success:
|
|
235
|
+
_vprint(
|
|
236
|
+
_FILE_INFO.format(path=path, msg="Parsing Python code successful"),
|
|
237
|
+
verbose,
|
|
238
|
+
)
|
|
239
|
+
module = _Parent(
|
|
240
|
+
ast.module,
|
|
241
|
+
_Directives(string, disable or _Messages()),
|
|
242
|
+
path,
|
|
243
|
+
ignore_args,
|
|
244
|
+
ignore_kwargs,
|
|
245
|
+
check_class_constructor,
|
|
246
|
+
)
|
|
247
|
+
failures = _get_failures(
|
|
248
|
+
module,
|
|
249
|
+
check_class,
|
|
250
|
+
check_class_constructor,
|
|
251
|
+
check_dunders,
|
|
252
|
+
check_nested,
|
|
253
|
+
check_overridden,
|
|
254
|
+
check_protected,
|
|
255
|
+
check_property_returns,
|
|
256
|
+
ignore_no_params,
|
|
257
|
+
ignore_typechecker,
|
|
258
|
+
check_protected_class_methods,
|
|
259
|
+
no_ansi,
|
|
260
|
+
target or _Messages(),
|
|
261
|
+
)
|
|
262
|
+
return failures, 0
|
|
263
|
+
|
|
264
|
+
if path.name.endswith(".py"):
|
|
265
|
+
# pass by silently for files that do not end with .py, may
|
|
266
|
+
# result in a 123 syntax error exit status in the future
|
|
267
|
+
print(path, file=_sys.stderr)
|
|
268
|
+
_pretty_print_error(type(ast.err), str(ast.err), no_ansi=no_ansi)
|
|
269
|
+
return failures, 1
|
|
270
|
+
|
|
271
|
+
_vprint(
|
|
272
|
+
_FILE_INFO.format(path=path, msg=str(ast.err)),
|
|
273
|
+
verbose,
|
|
274
|
+
)
|
|
275
|
+
return failures, 0
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@_decorators.parse_msgs
|
|
279
|
+
@_decorators.handle_deprecations
|
|
280
|
+
@_decorators.validate_args
|
|
281
|
+
def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
282
|
+
*path: str | _Path,
|
|
283
|
+
string: str | None = None,
|
|
284
|
+
list_checks: bool = False,
|
|
285
|
+
check_class: bool = False,
|
|
286
|
+
check_class_constructor: bool = False,
|
|
287
|
+
check_dunders: bool = False,
|
|
288
|
+
check_protected_class_methods: bool = False,
|
|
289
|
+
check_nested: bool = False,
|
|
290
|
+
check_overridden: bool = False,
|
|
291
|
+
check_protected: bool = False,
|
|
292
|
+
check_property_returns: bool = False,
|
|
293
|
+
include_ignored: bool = False,
|
|
294
|
+
ignore_no_params: bool = False,
|
|
295
|
+
ignore_args: bool = False,
|
|
296
|
+
ignore_kwargs: bool = False,
|
|
297
|
+
ignore_typechecker: bool = False,
|
|
298
|
+
no_ansi: bool = False,
|
|
299
|
+
verbose: bool = False,
|
|
300
|
+
target: _Messages | None = None,
|
|
301
|
+
disable: _Messages | None = None,
|
|
302
|
+
exclude: str | None = None,
|
|
303
|
+
) -> int:
|
|
304
|
+
"""Package's core functionality.
|
|
305
|
+
|
|
306
|
+
Populate a sequence of module objects before iterating over their
|
|
307
|
+
top-level functions and classes.
|
|
308
|
+
|
|
309
|
+
If any of the functions within the module - and methods within its
|
|
310
|
+
classes - fail, print the resulting function string representation
|
|
311
|
+
and report.
|
|
312
|
+
|
|
313
|
+
:param path: Path(s) to check.
|
|
314
|
+
:param string: String to check.
|
|
315
|
+
:param list_checks: Display a list of all checks and their messages.
|
|
316
|
+
:param check_class: Check class docstrings.
|
|
317
|
+
:param check_class_constructor: Check ``__init__`` methods. Note that this
|
|
318
|
+
is mutually incompatible with check_class.
|
|
319
|
+
:param check_dunders: Check dunder methods
|
|
320
|
+
:param check_protected_class_methods: Check public methods belonging
|
|
321
|
+
to protected classes.
|
|
322
|
+
:param check_nested: Check nested functions and classes.
|
|
323
|
+
:param check_overridden: Check overridden methods
|
|
324
|
+
:param check_protected: Check protected functions and classes.
|
|
325
|
+
:param check_property_returns: Run return checks on properties.
|
|
326
|
+
:param include_ignored: Check files even if they match a gitignore
|
|
327
|
+
pattern.
|
|
328
|
+
:param ignore_no_params: Ignore docstrings where parameters are not
|
|
329
|
+
documented
|
|
330
|
+
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
331
|
+
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
332
|
+
:param ignore_typechecker: Ignore checking return values.
|
|
333
|
+
:param no_ansi: Disable ANSI output.
|
|
334
|
+
:param verbose: increase output verbosity.
|
|
335
|
+
:param target: List of errors to target.
|
|
336
|
+
:param disable: List of errors to disable.
|
|
337
|
+
:param exclude: Regular expression of files and dirs to exclude from
|
|
338
|
+
checks.
|
|
339
|
+
:return: Exit status for whether test failed or not.
|
|
340
|
+
"""
|
|
341
|
+
if list_checks:
|
|
342
|
+
return int(bool(_print_checks())) # type: ignore
|
|
343
|
+
|
|
344
|
+
excludes = [_DEFAULT_EXCLUDES]
|
|
345
|
+
if exclude is not None:
|
|
346
|
+
excludes.append(exclude)
|
|
347
|
+
|
|
348
|
+
if string is None:
|
|
349
|
+
retcode = 0
|
|
350
|
+
paths = _Paths(
|
|
351
|
+
*tuple(_Path(i) for i in path),
|
|
352
|
+
excludes=excludes,
|
|
353
|
+
include_ignored=include_ignored,
|
|
354
|
+
verbose=verbose,
|
|
355
|
+
)
|
|
356
|
+
for file in paths:
|
|
357
|
+
failures, parse_retcode = runner(
|
|
358
|
+
file,
|
|
359
|
+
disable,
|
|
360
|
+
check_class,
|
|
361
|
+
check_class_constructor,
|
|
362
|
+
check_dunders,
|
|
363
|
+
check_nested,
|
|
364
|
+
check_overridden,
|
|
365
|
+
check_protected,
|
|
366
|
+
check_property_returns,
|
|
367
|
+
ignore_no_params,
|
|
368
|
+
ignore_args,
|
|
369
|
+
ignore_kwargs,
|
|
370
|
+
ignore_typechecker,
|
|
371
|
+
check_protected_class_methods,
|
|
372
|
+
no_ansi,
|
|
373
|
+
verbose,
|
|
374
|
+
target,
|
|
375
|
+
)
|
|
376
|
+
retcode = retcode or parse_retcode
|
|
377
|
+
if failures:
|
|
378
|
+
_report(failures, str(file), no_ansi)
|
|
379
|
+
retcode = 1
|
|
380
|
+
|
|
381
|
+
return retcode
|
|
382
|
+
|
|
383
|
+
ast = _Ast.parse(string)
|
|
384
|
+
if ast.success:
|
|
385
|
+
_vprint(
|
|
386
|
+
_FILE_INFO.format(
|
|
387
|
+
path="stdin", msg="Parsing Python code successful"
|
|
388
|
+
),
|
|
389
|
+
verbose,
|
|
390
|
+
)
|
|
391
|
+
module = _Parent(
|
|
392
|
+
_ast.parse(string),
|
|
393
|
+
_Directives(string, messages=disable or _Messages()),
|
|
394
|
+
ignore_args=ignore_args,
|
|
395
|
+
ignore_kwargs=ignore_kwargs,
|
|
396
|
+
check_class_constructor=check_class_constructor,
|
|
397
|
+
)
|
|
398
|
+
failures = _get_failures(
|
|
399
|
+
module,
|
|
400
|
+
check_class,
|
|
401
|
+
check_class_constructor,
|
|
402
|
+
check_dunders,
|
|
403
|
+
check_nested,
|
|
404
|
+
check_overridden,
|
|
405
|
+
check_protected,
|
|
406
|
+
check_property_returns,
|
|
407
|
+
ignore_no_params,
|
|
408
|
+
ignore_typechecker,
|
|
409
|
+
check_protected_class_methods,
|
|
410
|
+
no_ansi,
|
|
411
|
+
target or _Messages(),
|
|
412
|
+
)
|
|
413
|
+
if failures:
|
|
414
|
+
_report(failures, no_ansi=no_ansi)
|
|
415
|
+
return 1
|
|
416
|
+
|
|
417
|
+
_vprint(_FILE_INFO.format(path="stdin", msg=str(ast.err)), verbose)
|
|
418
|
+
|
|
419
|
+
return 0
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
docsig._files
|
|
3
|
+
=============
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations as _
|
|
7
|
+
|
|
8
|
+
import os as _os
|
|
9
|
+
import re as _re
|
|
10
|
+
import typing as _t
|
|
11
|
+
from pathlib import Path as _Path
|
|
12
|
+
|
|
13
|
+
from pathspec import PathSpec as _PathSpec
|
|
14
|
+
from pathspec.patterns import GitWildMatchPattern as _GitWildMatchPattern
|
|
15
|
+
|
|
16
|
+
from ._utils import vprint as _vprint
|
|
17
|
+
|
|
18
|
+
FILE_INFO = "{path}: {msg}"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class _Gitignore(_PathSpec):
|
|
22
|
+
def _get_repo_relative_to(self, path: _Path) -> _Path | None:
|
|
23
|
+
if (path / ".git" / "HEAD").is_file():
|
|
24
|
+
return path
|
|
25
|
+
|
|
26
|
+
if str(path) == _os.path.abspath(_os.sep):
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
return self._get_repo_relative_to(path.parent)
|
|
30
|
+
|
|
31
|
+
def __init__(self) -> None:
|
|
32
|
+
patterns = []
|
|
33
|
+
repo = self._get_repo_relative_to(_Path.cwd())
|
|
34
|
+
# only consider gitignore patterns valid if inside a git repo
|
|
35
|
+
# there might be stray gitignore files lying about
|
|
36
|
+
if repo is not None:
|
|
37
|
+
# add patterns from all gitignore files
|
|
38
|
+
# adjust patterns to account for their relative paths
|
|
39
|
+
for file in repo.rglob(".gitignore"):
|
|
40
|
+
for pattern in file.read_text(encoding="utf-8").splitlines():
|
|
41
|
+
if pattern.startswith("#"):
|
|
42
|
+
continue
|
|
43
|
+
|
|
44
|
+
# if pattern starts with "/" then os.path.join will
|
|
45
|
+
# consider it in the filesystem root, and it will
|
|
46
|
+
# only ever return /pattern
|
|
47
|
+
if pattern.startswith("/"):
|
|
48
|
+
pattern = pattern[1:]
|
|
49
|
+
|
|
50
|
+
# use os.path.dirname, so it joins without a leading
|
|
51
|
+
# "./", like it does with pathlib parent
|
|
52
|
+
# use os.path.join so trailing slash is preserved
|
|
53
|
+
# replace sep with "/" as, even on windows,
|
|
54
|
+
# gitignore patterns only ever use "/"
|
|
55
|
+
patterns.append(
|
|
56
|
+
_os.path.join(
|
|
57
|
+
_os.path.dirname(file.relative_to(repo)),
|
|
58
|
+
pattern.strip(),
|
|
59
|
+
).replace(_os.sep, "/")
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
super().__init__(map(_GitWildMatchPattern, patterns))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class Paths(_t.List[_Path]): # pylint: disable=too-many-instance-attributes
|
|
66
|
+
"""Collect a list of valid paths.
|
|
67
|
+
|
|
68
|
+
:param paths: Path(s) to parse ``Module``(s) from.
|
|
69
|
+
:param excludes: List pf regular expression of files and dirs to
|
|
70
|
+
exclude from checks.
|
|
71
|
+
:param include_ignored: Check files even if they match a gitignore
|
|
72
|
+
pattern.
|
|
73
|
+
:param verbose: increase output verbosity.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __init__( # pylint: disable=too-many-arguments
|
|
77
|
+
self,
|
|
78
|
+
*paths: _Path,
|
|
79
|
+
excludes: list[str],
|
|
80
|
+
include_ignored: bool = False,
|
|
81
|
+
verbose: bool = False,
|
|
82
|
+
) -> None:
|
|
83
|
+
super().__init__()
|
|
84
|
+
self._excludes = excludes
|
|
85
|
+
self._include_ignored = include_ignored
|
|
86
|
+
self._verbose = verbose
|
|
87
|
+
self._gitignore = _Gitignore()
|
|
88
|
+
for path in paths:
|
|
89
|
+
self._populate(path)
|
|
90
|
+
|
|
91
|
+
self.sort()
|
|
92
|
+
|
|
93
|
+
def _populate(self, root: _Path) -> None:
|
|
94
|
+
if not root.exists():
|
|
95
|
+
raise FileNotFoundError(root)
|
|
96
|
+
|
|
97
|
+
if str(root) != "." and any(
|
|
98
|
+
_re.match(i, root.name) for i in self._excludes
|
|
99
|
+
):
|
|
100
|
+
_vprint(
|
|
101
|
+
FILE_INFO.format(path=root, msg="in exclude list, skipping"),
|
|
102
|
+
self._verbose,
|
|
103
|
+
)
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
if not self._include_ignored and self._gitignore.match_file(root):
|
|
107
|
+
_vprint(
|
|
108
|
+
FILE_INFO.format(path=root, msg="in gitignore, skipping"),
|
|
109
|
+
self._verbose,
|
|
110
|
+
)
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
if root.is_file():
|
|
114
|
+
self.append(root)
|
|
115
|
+
|
|
116
|
+
if root.is_dir():
|
|
117
|
+
for path in root.iterdir():
|
|
118
|
+
self._populate(path)
|