docsig 0.45.0__tar.gz → 0.47.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.45.0 → docsig-0.47.0}/PKG-INFO +8 -6
- {docsig-0.45.0 → docsig-0.47.0}/README.rst +6 -4
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_config.py +13 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_core.py +57 -12
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_display.py +4 -4
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_main.py +2 -0
- docsig-0.47.0/docsig/_module.py +428 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_report.py +3 -3
- docsig-0.45.0/docsig/_function.py → docsig-0.47.0/docsig/_stub.py +21 -158
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_utils.py +10 -9
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_version.py +1 -1
- {docsig-0.45.0 → docsig-0.47.0}/pyproject.toml +2 -2
- docsig-0.45.0/docsig/_module.py +0 -229
- {docsig-0.45.0 → docsig-0.47.0}/LICENSE +0 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/__init__.py +0 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/__main__.py +0 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_decorators.py +0 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_directives.py +0 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_hooks.py +0 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/_message.py +0 -0
- {docsig-0.45.0 → docsig-0.47.0}/docsig/messages.py +0 -0
- {docsig-0.45.0 → docsig-0.47.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.47.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,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
20
|
Requires-Dist: Pygments (>=2.13.0,<3.0.0)
|
|
21
21
|
Requires-Dist: Sphinx (>=7.0.0,<8.0.0)
|
|
22
|
-
Requires-Dist: arcon (>=0.
|
|
22
|
+
Requires-Dist: arcon (>=0.4.0)
|
|
23
23
|
Requires-Dist: astroid (>=3.0.1,<4.0.0)
|
|
24
24
|
Requires-Dist: object-colors (>=2.1.0,<3.0.0)
|
|
25
25
|
Requires-Dist: typing-extensions (>=4.8.0,<5.0.0)
|
|
@@ -106,8 +106,8 @@ Commandline
|
|
|
106
106
|
|
|
107
107
|
.. code-block:: console
|
|
108
108
|
|
|
109
|
-
usage: docsig [-h] [-
|
|
110
|
-
[-n] [-S] [-s STR] [-d LIST] [-t LIST] [-e EXCLUDE]
|
|
109
|
+
usage: docsig [-h] [-V] [-l] [-c | -C] [-D] [-m] [-N] [-o] [-p] [-P] [-i] [-a]
|
|
110
|
+
[-k] [-n] [-S] [-v] [-s STR] [-d LIST] [-t LIST] [-e EXCLUDE]
|
|
111
111
|
[path [path ...]]
|
|
112
112
|
|
|
113
113
|
Check signature params for proper documentation
|
|
@@ -117,7 +117,7 @@ Commandline
|
|
|
117
117
|
|
|
118
118
|
optional arguments:
|
|
119
119
|
-h, --help show this help message and exit
|
|
120
|
-
-
|
|
120
|
+
-V, --version show program's version number and exit
|
|
121
121
|
-l, --list-checks display a list of all checks and their messages
|
|
122
122
|
-c, --check-class check class docstrings
|
|
123
123
|
-C, --check-class-constructor check __init__ methods. Note: mutually
|
|
@@ -125,6 +125,7 @@ Commandline
|
|
|
125
125
|
-D, --check-dunders check dunder methods
|
|
126
126
|
-m, --check-protected-class-methods check public methods belonging to protected
|
|
127
127
|
classes
|
|
128
|
+
-N, --check-nested check nested functions and classes
|
|
128
129
|
-o, --check-overridden check overridden methods
|
|
129
130
|
-p, --check-protected check protected functions and classes
|
|
130
131
|
-P, --check-property-returns check property return values
|
|
@@ -134,6 +135,7 @@ Commandline
|
|
|
134
135
|
-k, --ignore-kwargs ignore kwargs prefixed with two asterisks
|
|
135
136
|
-n, --no-ansi disable ansi output
|
|
136
137
|
-S, --summary print a summarised report
|
|
138
|
+
-v, --verbose increase output verbosity
|
|
137
139
|
-s STR, --string STR string to parse instead of files
|
|
138
140
|
-d LIST, --disable LIST comma separated list of rules to disable
|
|
139
141
|
-t LIST, --target LIST comma separated list of rules to target
|
|
@@ -231,7 +233,7 @@ It can be added to your .pre-commit-config.yaml as follows:
|
|
|
231
233
|
|
|
232
234
|
repos:
|
|
233
235
|
- repo: https://github.com/jshwi/docsig
|
|
234
|
-
rev: v0.
|
|
236
|
+
rev: v0.47.0
|
|
235
237
|
hooks:
|
|
236
238
|
- id: docsig
|
|
237
239
|
args:
|
|
@@ -77,8 +77,8 @@ Commandline
|
|
|
77
77
|
|
|
78
78
|
.. code-block:: console
|
|
79
79
|
|
|
80
|
-
usage: docsig [-h] [-
|
|
81
|
-
[-n] [-S] [-s STR] [-d LIST] [-t LIST] [-e EXCLUDE]
|
|
80
|
+
usage: docsig [-h] [-V] [-l] [-c | -C] [-D] [-m] [-N] [-o] [-p] [-P] [-i] [-a]
|
|
81
|
+
[-k] [-n] [-S] [-v] [-s STR] [-d LIST] [-t LIST] [-e EXCLUDE]
|
|
82
82
|
[path [path ...]]
|
|
83
83
|
|
|
84
84
|
Check signature params for proper documentation
|
|
@@ -88,7 +88,7 @@ Commandline
|
|
|
88
88
|
|
|
89
89
|
optional arguments:
|
|
90
90
|
-h, --help show this help message and exit
|
|
91
|
-
-
|
|
91
|
+
-V, --version show program's version number and exit
|
|
92
92
|
-l, --list-checks display a list of all checks and their messages
|
|
93
93
|
-c, --check-class check class docstrings
|
|
94
94
|
-C, --check-class-constructor check __init__ methods. Note: mutually
|
|
@@ -96,6 +96,7 @@ Commandline
|
|
|
96
96
|
-D, --check-dunders check dunder methods
|
|
97
97
|
-m, --check-protected-class-methods check public methods belonging to protected
|
|
98
98
|
classes
|
|
99
|
+
-N, --check-nested check nested functions and classes
|
|
99
100
|
-o, --check-overridden check overridden methods
|
|
100
101
|
-p, --check-protected check protected functions and classes
|
|
101
102
|
-P, --check-property-returns check property return values
|
|
@@ -105,6 +106,7 @@ Commandline
|
|
|
105
106
|
-k, --ignore-kwargs ignore kwargs prefixed with two asterisks
|
|
106
107
|
-n, --no-ansi disable ansi output
|
|
107
108
|
-S, --summary print a summarised report
|
|
109
|
+
-v, --verbose increase output verbosity
|
|
108
110
|
-s STR, --string STR string to parse instead of files
|
|
109
111
|
-d LIST, --disable LIST comma separated list of rules to disable
|
|
110
112
|
-t LIST, --target LIST comma separated list of rules to target
|
|
@@ -202,7 +204,7 @@ It can be added to your .pre-commit-config.yaml as follows:
|
|
|
202
204
|
|
|
203
205
|
repos:
|
|
204
206
|
- repo: https://github.com/jshwi/docsig
|
|
205
|
-
rev: v0.
|
|
207
|
+
rev: v0.47.0
|
|
206
208
|
hooks:
|
|
207
209
|
- id: docsig
|
|
208
210
|
args:
|
|
@@ -23,6 +23,7 @@ class Parser(_ArgumentParser):
|
|
|
23
23
|
prog, max_help_position=45
|
|
24
24
|
),
|
|
25
25
|
description="Check signature params for proper documentation",
|
|
26
|
+
version_short_form="-V",
|
|
26
27
|
)
|
|
27
28
|
self._add_arguments()
|
|
28
29
|
self.args = self.parse_args()
|
|
@@ -66,6 +67,12 @@ class Parser(_ArgumentParser):
|
|
|
66
67
|
action="store_true",
|
|
67
68
|
help="check public methods belonging to protected classes",
|
|
68
69
|
)
|
|
70
|
+
self.add_argument(
|
|
71
|
+
"-N",
|
|
72
|
+
"--check-nested",
|
|
73
|
+
action="store_true",
|
|
74
|
+
help="check nested functions and classes",
|
|
75
|
+
)
|
|
69
76
|
self.add_argument(
|
|
70
77
|
"-o",
|
|
71
78
|
"--check-overridden",
|
|
@@ -114,6 +121,12 @@ class Parser(_ArgumentParser):
|
|
|
114
121
|
action="store_true",
|
|
115
122
|
help="print a summarised report",
|
|
116
123
|
)
|
|
124
|
+
self.add_argument(
|
|
125
|
+
"-v",
|
|
126
|
+
"--verbose",
|
|
127
|
+
action="store_true",
|
|
128
|
+
help="increase output verbosity",
|
|
129
|
+
)
|
|
117
130
|
self.add_argument(
|
|
118
131
|
"-s",
|
|
119
132
|
"--string",
|
|
@@ -13,6 +13,7 @@ from ._display import Failure as _Failure
|
|
|
13
13
|
from ._display import Failures as _Failures
|
|
14
14
|
from ._display import FuncStr as _FuncStr
|
|
15
15
|
from ._message import Message as _Message
|
|
16
|
+
from ._module import Function as _Function
|
|
16
17
|
from ._module import Modules as _Modules
|
|
17
18
|
from ._module import Parent as _Parent
|
|
18
19
|
from ._report import generate_report as _generate_report
|
|
@@ -45,40 +46,75 @@ def _print_checks() -> None:
|
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
def _run_check( # pylint: disable=too-many-arguments
|
|
49
|
+
child: _Parent,
|
|
48
50
|
parent: _Parent,
|
|
49
51
|
check_class: bool,
|
|
50
52
|
check_class_constructor: bool,
|
|
51
53
|
check_dunders: bool,
|
|
54
|
+
check_nested: bool,
|
|
52
55
|
check_overridden: bool,
|
|
53
56
|
check_protected: bool,
|
|
54
57
|
check_property_returns: bool,
|
|
55
58
|
ignore_no_params: bool,
|
|
56
59
|
no_ansi: bool,
|
|
57
60
|
targets: list[_Message],
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if not (
|
|
62
|
-
not (
|
|
61
|
+
failures: _Failures,
|
|
62
|
+
) -> None:
|
|
63
|
+
if isinstance(child, _Function):
|
|
64
|
+
if not (child.isoverridden and not check_overridden) and (
|
|
65
|
+
not (child.isprotected and not check_protected)
|
|
63
66
|
and not (
|
|
64
|
-
|
|
67
|
+
child.isinit
|
|
65
68
|
and not (
|
|
66
69
|
(check_class or check_class_constructor)
|
|
67
70
|
and not (parent.isprotected and not check_protected)
|
|
68
71
|
)
|
|
69
72
|
)
|
|
70
|
-
and not (
|
|
71
|
-
and not (
|
|
73
|
+
and not (child.isdunder and not check_dunders)
|
|
74
|
+
and not (child.docstring.bare and ignore_no_params)
|
|
72
75
|
):
|
|
73
76
|
report = _generate_report(
|
|
74
|
-
|
|
77
|
+
child, targets, child.disabled, check_property_returns
|
|
75
78
|
)
|
|
76
79
|
if report:
|
|
77
80
|
failures.append(
|
|
78
|
-
_Failure(
|
|
81
|
+
_Failure(child, _FuncStr(child, no_ansi), report)
|
|
79
82
|
)
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
if check_nested:
|
|
85
|
+
for func in child:
|
|
86
|
+
_run_check(
|
|
87
|
+
func,
|
|
88
|
+
child,
|
|
89
|
+
check_class,
|
|
90
|
+
check_class_constructor,
|
|
91
|
+
check_dunders,
|
|
92
|
+
check_nested,
|
|
93
|
+
check_overridden,
|
|
94
|
+
check_protected,
|
|
95
|
+
check_property_returns,
|
|
96
|
+
ignore_no_params,
|
|
97
|
+
no_ansi,
|
|
98
|
+
targets,
|
|
99
|
+
failures,
|
|
100
|
+
)
|
|
101
|
+
else:
|
|
102
|
+
for func in child:
|
|
103
|
+
_run_check(
|
|
104
|
+
func,
|
|
105
|
+
child,
|
|
106
|
+
check_class,
|
|
107
|
+
check_class_constructor,
|
|
108
|
+
check_dunders,
|
|
109
|
+
check_nested,
|
|
110
|
+
check_overridden,
|
|
111
|
+
check_protected,
|
|
112
|
+
check_property_returns,
|
|
113
|
+
ignore_no_params,
|
|
114
|
+
no_ansi,
|
|
115
|
+
targets,
|
|
116
|
+
failures,
|
|
117
|
+
)
|
|
82
118
|
|
|
83
119
|
|
|
84
120
|
@_decorators.parse_msgs
|
|
@@ -91,6 +127,7 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
|
91
127
|
check_class_constructor: bool = False,
|
|
92
128
|
check_dunders: bool = False,
|
|
93
129
|
check_protected_class_methods: bool = False,
|
|
130
|
+
check_nested: bool = False,
|
|
94
131
|
check_overridden: bool = False,
|
|
95
132
|
check_protected: bool = False,
|
|
96
133
|
check_property_returns: bool = False,
|
|
@@ -99,6 +136,7 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
|
99
136
|
ignore_kwargs: bool = False,
|
|
100
137
|
no_ansi: bool = False,
|
|
101
138
|
summary: bool = False,
|
|
139
|
+
verbose: bool = False,
|
|
102
140
|
targets: list[_Message] | None = None,
|
|
103
141
|
disable: list[_Message] | None = None,
|
|
104
142
|
exclude: str | None = None,
|
|
@@ -121,6 +159,7 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
|
121
159
|
:param check_dunders: Check dunder methods
|
|
122
160
|
:param check_protected_class_methods: Check public methods belonging
|
|
123
161
|
to protected classes.
|
|
162
|
+
:param check_nested: Check nested functions and classes.
|
|
124
163
|
:param check_overridden: Check overridden methods
|
|
125
164
|
:param check_protected: Check protected functions and classes.
|
|
126
165
|
:param check_property_returns: Run return checks on properties.
|
|
@@ -130,6 +169,7 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
|
130
169
|
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
131
170
|
:param no_ansi: Disable ANSI output.
|
|
132
171
|
:param summary: Print a summarised report.
|
|
172
|
+
:param verbose: increase output verbosity.
|
|
133
173
|
:param targets: List of errors to target.
|
|
134
174
|
:param disable: List of errors to disable.
|
|
135
175
|
:param exclude: Regular expression of files and dirs to exclude from
|
|
@@ -151,6 +191,7 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
|
151
191
|
ignore_args=ignore_args,
|
|
152
192
|
ignore_kwargs=ignore_kwargs,
|
|
153
193
|
check_class_constructor=check_class_constructor,
|
|
194
|
+
verbose=verbose,
|
|
154
195
|
)
|
|
155
196
|
display = _Display(no_ansi)
|
|
156
197
|
for module in modules:
|
|
@@ -160,17 +201,21 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
|
|
|
160
201
|
or check_protected
|
|
161
202
|
or check_protected_class_methods
|
|
162
203
|
):
|
|
163
|
-
failures =
|
|
204
|
+
failures = _Failures()
|
|
205
|
+
_run_check(
|
|
164
206
|
top_level,
|
|
207
|
+
module,
|
|
165
208
|
check_class,
|
|
166
209
|
check_class_constructor,
|
|
167
210
|
check_dunders,
|
|
211
|
+
check_nested,
|
|
168
212
|
check_overridden,
|
|
169
213
|
check_protected,
|
|
170
214
|
check_property_returns,
|
|
171
215
|
ignore_no_params,
|
|
172
216
|
no_ansi,
|
|
173
217
|
targets or [],
|
|
218
|
+
failures,
|
|
174
219
|
)
|
|
175
220
|
if failures:
|
|
176
221
|
display[top_level.path].append(failures)
|
|
@@ -17,11 +17,11 @@ from pygments.formatters.terminal256 import (
|
|
|
17
17
|
# noinspection PyUnresolvedReferences
|
|
18
18
|
from pygments.lexers.python import PythonLexer as _PythonLexer
|
|
19
19
|
|
|
20
|
-
from .
|
|
21
|
-
from ._function import KEY as _KEY
|
|
22
|
-
from ._function import Function as _Function
|
|
23
|
-
from ._function import Param as _Param
|
|
20
|
+
from ._module import Function as _Function
|
|
24
21
|
from ._report import Report as _Report
|
|
22
|
+
from ._stub import ARG as _ARG
|
|
23
|
+
from ._stub import KEY as _KEY
|
|
24
|
+
from ._stub import Param as _Param
|
|
25
25
|
|
|
26
26
|
color = _Color()
|
|
27
27
|
|
|
@@ -31,6 +31,7 @@ def main() -> str | int:
|
|
|
31
31
|
check_protected_class_methods=(
|
|
32
32
|
parser.args.check_protected_class_methods
|
|
33
33
|
),
|
|
34
|
+
check_nested=parser.args.check_nested,
|
|
34
35
|
check_overridden=parser.args.check_overridden,
|
|
35
36
|
check_protected=parser.args.check_protected,
|
|
36
37
|
check_property_returns=parser.args.check_property_returns,
|
|
@@ -39,6 +40,7 @@ def main() -> str | int:
|
|
|
39
40
|
ignore_kwargs=parser.args.ignore_kwargs,
|
|
40
41
|
no_ansi=parser.args.no_ansi,
|
|
41
42
|
summary=parser.args.summary,
|
|
43
|
+
verbose=parser.args.verbose,
|
|
42
44
|
targets=parser.args.target,
|
|
43
45
|
disable=parser.args.disable,
|
|
44
46
|
exclude=parser.args.exclude,
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
"""
|
|
2
|
+
docsig._module
|
|
3
|
+
==============
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations as _
|
|
7
|
+
|
|
8
|
+
import re as _re
|
|
9
|
+
import typing as _t
|
|
10
|
+
from pathlib import Path as _Path
|
|
11
|
+
|
|
12
|
+
import astroid as _ast
|
|
13
|
+
from astroid import AstroidSyntaxError as _AstroidSyntaxError
|
|
14
|
+
|
|
15
|
+
from ._directives import Directive as _Directive
|
|
16
|
+
from ._directives import Directives as _Directives
|
|
17
|
+
from ._message import Message as _Message
|
|
18
|
+
from ._stub import Docstring as _Docstring
|
|
19
|
+
from ._stub import Signature as _Signature
|
|
20
|
+
from ._utils import vprint as _vprint
|
|
21
|
+
|
|
22
|
+
_FILE_INFO = "{path}: {msg}"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Parent(_t.List["Parent"]):
|
|
26
|
+
"""Represents an object that contains functions or methods.
|
|
27
|
+
|
|
28
|
+
:param node: Parent's abstract syntax tree.
|
|
29
|
+
:param directives: Data for directives and, subsequently, total of
|
|
30
|
+
errors which are excluded from function checks.
|
|
31
|
+
:param path: Path to base path representation on.
|
|
32
|
+
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
33
|
+
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
34
|
+
:param check_class_constructor: Check the class constructor's
|
|
35
|
+
docstring. Otherwise, expect the constructor's documentation to
|
|
36
|
+
be on the class level docstring.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__( # pylint: disable=too-many-arguments
|
|
40
|
+
self,
|
|
41
|
+
node: _ast.Module | _ast.ClassDef | _ast.FunctionDef,
|
|
42
|
+
directives: _Directives,
|
|
43
|
+
path: _Path | None = None,
|
|
44
|
+
ignore_args: bool = False,
|
|
45
|
+
ignore_kwargs: bool = False,
|
|
46
|
+
check_class_constructor: bool = False,
|
|
47
|
+
) -> None:
|
|
48
|
+
super().__init__()
|
|
49
|
+
self._name = node.name
|
|
50
|
+
self._path = f"{path}:" if path is not None else ""
|
|
51
|
+
overloads: list[str] = []
|
|
52
|
+
returns = None
|
|
53
|
+
self._parse_ast(
|
|
54
|
+
node,
|
|
55
|
+
directives,
|
|
56
|
+
path,
|
|
57
|
+
ignore_args,
|
|
58
|
+
ignore_kwargs,
|
|
59
|
+
check_class_constructor,
|
|
60
|
+
overloads,
|
|
61
|
+
returns,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def _parse_ast( # pylint: disable=protected-access,too-many-arguments
|
|
65
|
+
self,
|
|
66
|
+
node,
|
|
67
|
+
directives,
|
|
68
|
+
path,
|
|
69
|
+
ignore_args,
|
|
70
|
+
ignore_kwargs,
|
|
71
|
+
check_class_constructor,
|
|
72
|
+
overloads,
|
|
73
|
+
returns,
|
|
74
|
+
) -> None:
|
|
75
|
+
parent_comments, parent_disabled = directives.get(
|
|
76
|
+
node.lineno, ([], [])
|
|
77
|
+
)
|
|
78
|
+
if hasattr(node, "body"):
|
|
79
|
+
for subnode in node.body:
|
|
80
|
+
comments, disabled = directives.get(subnode.lineno, ([], []))
|
|
81
|
+
comments.extend(parent_comments)
|
|
82
|
+
disabled.extend(parent_disabled)
|
|
83
|
+
if isinstance(subnode, _ast.FunctionDef):
|
|
84
|
+
func = Function(
|
|
85
|
+
subnode,
|
|
86
|
+
comments,
|
|
87
|
+
directives,
|
|
88
|
+
disabled,
|
|
89
|
+
path,
|
|
90
|
+
ignore_args,
|
|
91
|
+
ignore_kwargs,
|
|
92
|
+
check_class_constructor,
|
|
93
|
+
)
|
|
94
|
+
if func.isoverloaded:
|
|
95
|
+
overloads.append(func.name)
|
|
96
|
+
returns = func.signature.rettype
|
|
97
|
+
else:
|
|
98
|
+
if func.name in overloads:
|
|
99
|
+
subnode.returns = returns
|
|
100
|
+
# noinspection PyProtectedMember
|
|
101
|
+
func._signature._rettype = (
|
|
102
|
+
returns
|
|
103
|
+
if isinstance(returns, str)
|
|
104
|
+
else func._signature._get_rettype(returns)
|
|
105
|
+
)
|
|
106
|
+
# noinspection PyProtectedMember
|
|
107
|
+
func._signature._returns = (
|
|
108
|
+
str(func._signature._rettype) != "None"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
self.append(func)
|
|
112
|
+
elif isinstance(subnode, _ast.ClassDef):
|
|
113
|
+
self.append(
|
|
114
|
+
Parent(
|
|
115
|
+
subnode,
|
|
116
|
+
directives,
|
|
117
|
+
path,
|
|
118
|
+
ignore_args,
|
|
119
|
+
ignore_kwargs,
|
|
120
|
+
check_class_constructor,
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
else:
|
|
124
|
+
self._parse_ast(
|
|
125
|
+
subnode,
|
|
126
|
+
directives,
|
|
127
|
+
path,
|
|
128
|
+
ignore_args,
|
|
129
|
+
ignore_kwargs,
|
|
130
|
+
check_class_constructor,
|
|
131
|
+
overloads,
|
|
132
|
+
returns,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def path(self) -> str:
|
|
137
|
+
"""Representation of path to parent."""
|
|
138
|
+
return self._path
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def isprotected(self) -> bool:
|
|
142
|
+
"""Boolean value for whether class is protected."""
|
|
143
|
+
return self._name.startswith("_")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class Function(Parent):
|
|
147
|
+
"""Represents a function with signature and docstring parameters.
|
|
148
|
+
|
|
149
|
+
:param node: Function's abstract syntax tree.
|
|
150
|
+
:param comments: Comments in list form containing directives.
|
|
151
|
+
:param directives: Directive, if any, belonging to this function.
|
|
152
|
+
:param disabled: List of disabled checks specific to this function.
|
|
153
|
+
:param path: Path to base path representation on.
|
|
154
|
+
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
155
|
+
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
156
|
+
:param check_class_constructor: If the function is the class
|
|
157
|
+
constructor, use its own docstring. Otherwise, use the class
|
|
158
|
+
level docstring for the constructor function.
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
def __init__( # pylint: disable=too-many-arguments
|
|
162
|
+
self,
|
|
163
|
+
node: _ast.FunctionDef,
|
|
164
|
+
comments: _t.List[_Directive],
|
|
165
|
+
directives: _Directives,
|
|
166
|
+
disabled: list[_Message],
|
|
167
|
+
path: _Path | None = None,
|
|
168
|
+
ignore_args: bool = False,
|
|
169
|
+
ignore_kwargs: bool = False,
|
|
170
|
+
check_class_constructor: bool = False,
|
|
171
|
+
) -> None:
|
|
172
|
+
super().__init__(
|
|
173
|
+
node,
|
|
174
|
+
directives,
|
|
175
|
+
path,
|
|
176
|
+
ignore_args,
|
|
177
|
+
ignore_kwargs,
|
|
178
|
+
check_class_constructor,
|
|
179
|
+
)
|
|
180
|
+
self._node = node
|
|
181
|
+
self._directives = comments
|
|
182
|
+
self._disabled = disabled
|
|
183
|
+
self._parent = node.parent.frame()
|
|
184
|
+
self._signature = _Signature(
|
|
185
|
+
node.args,
|
|
186
|
+
node.returns,
|
|
187
|
+
self.ismethod,
|
|
188
|
+
self.isstaticmethod,
|
|
189
|
+
ignore_args,
|
|
190
|
+
ignore_kwargs,
|
|
191
|
+
)
|
|
192
|
+
if self.isinit and not check_class_constructor:
|
|
193
|
+
# docstring for __init__ is expected on the class docstring
|
|
194
|
+
relevant_doc_node = self._parent.doc_node
|
|
195
|
+
else:
|
|
196
|
+
relevant_doc_node = node.doc_node
|
|
197
|
+
self._docstring = _Docstring(relevant_doc_node, ignore_kwargs)
|
|
198
|
+
|
|
199
|
+
def __len__(self) -> int:
|
|
200
|
+
"""Length of the longest sequence of args."""
|
|
201
|
+
return max([len(self.signature.args), len(self.docstring.args)])
|
|
202
|
+
|
|
203
|
+
def _decorated_with(self, name: str) -> bool:
|
|
204
|
+
if self._node.decorators is not None:
|
|
205
|
+
for dec in self._node.decorators.nodes:
|
|
206
|
+
return (isinstance(dec, _ast.Name) and dec.name == name) or (
|
|
207
|
+
isinstance(dec, _ast.Attribute) and dec.attrname == name
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return False
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def ismethod(self) -> bool:
|
|
214
|
+
"""Boolean value for whether function is a method."""
|
|
215
|
+
return isinstance(self._parent, _ast.ClassDef)
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def isproperty(self) -> bool:
|
|
219
|
+
"""Boolean value for whether function is a property."""
|
|
220
|
+
valid_properties = [
|
|
221
|
+
"property",
|
|
222
|
+
"cached_property",
|
|
223
|
+
]
|
|
224
|
+
return self.ismethod and any(
|
|
225
|
+
self._decorated_with(i) for i in valid_properties
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def isoverloaded(self) -> bool:
|
|
230
|
+
"""Boolean value for whether function is a property."""
|
|
231
|
+
return self._decorated_with("overload")
|
|
232
|
+
|
|
233
|
+
@property
|
|
234
|
+
def isinit(self) -> bool:
|
|
235
|
+
"""Boolean value for whether function is a class constructor."""
|
|
236
|
+
return self.ismethod and self.name == "__init__"
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def isoverridden(self) -> bool:
|
|
240
|
+
"""Boolean value for whether function is overridden."""
|
|
241
|
+
if self.ismethod and not self.isinit:
|
|
242
|
+
for ancestor in self._parent.ancestors():
|
|
243
|
+
if self.name in ancestor and isinstance(
|
|
244
|
+
ancestor[self.name], _ast.FunctionDef
|
|
245
|
+
):
|
|
246
|
+
return True
|
|
247
|
+
|
|
248
|
+
return False
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def isprotected(self) -> bool:
|
|
252
|
+
"""Boolean value for whether function is protected."""
|
|
253
|
+
return super().isprotected and not self.isinit and not self.isdunder
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def isstaticmethod(self) -> bool:
|
|
257
|
+
"""Boolean value for whether function is a static method."""
|
|
258
|
+
return self.ismethod and self._decorated_with("staticmethod")
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def isdunder(self) -> bool:
|
|
262
|
+
"""Boolean value for whether function is a dunder method."""
|
|
263
|
+
return (
|
|
264
|
+
self.ismethod
|
|
265
|
+
and not self.isinit
|
|
266
|
+
and bool(_re.match(r"__(.*)__", self.name))
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
@property
|
|
270
|
+
def name(self) -> str:
|
|
271
|
+
"""The name of the function."""
|
|
272
|
+
return self._node.name
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def parent(
|
|
276
|
+
self,
|
|
277
|
+
) -> _ast.FunctionDef | _ast.Module | _ast.ClassDef | _ast.Lambda:
|
|
278
|
+
"""Function's parent node."""
|
|
279
|
+
return self._parent
|
|
280
|
+
|
|
281
|
+
@property
|
|
282
|
+
def lineno(self) -> int:
|
|
283
|
+
"""Line number of function declaration."""
|
|
284
|
+
return self._node.lineno or 0
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def signature(self) -> _Signature:
|
|
288
|
+
"""The function's signature parameters."""
|
|
289
|
+
return self._signature
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def docstring(self) -> _Docstring:
|
|
293
|
+
"""The function's docstring."""
|
|
294
|
+
return self._docstring
|
|
295
|
+
|
|
296
|
+
@property
|
|
297
|
+
def disabled(self) -> list[_Message]:
|
|
298
|
+
"""List of disabled checks specific to this function."""
|
|
299
|
+
return self._disabled
|
|
300
|
+
|
|
301
|
+
@property
|
|
302
|
+
def directives(self) -> _t.List[_Directive]:
|
|
303
|
+
"""Directive, if any, belonging to this function."""
|
|
304
|
+
return self._directives
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
class Modules(_t.List[Parent]):
|
|
308
|
+
"""Sequence of ``Module`` objects parsed from Python modules or str.
|
|
309
|
+
|
|
310
|
+
Recursively collect Python files from within all dirs that exist
|
|
311
|
+
under paths provided.
|
|
312
|
+
|
|
313
|
+
If string is provided, ignore paths.
|
|
314
|
+
|
|
315
|
+
:param paths: Path(s) to parse ``Module``(s) from.
|
|
316
|
+
:param disable: List of checks to disable.
|
|
317
|
+
:param excludes: List pf regular expression of files and dirs to
|
|
318
|
+
exclude from checks.
|
|
319
|
+
:param string: String to parse if provided.
|
|
320
|
+
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
321
|
+
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
322
|
+
:param check_class_constructor: Check the class constructor's
|
|
323
|
+
docstring. Otherwise, expect the constructor's documentation to
|
|
324
|
+
be on the class level docstring.
|
|
325
|
+
:param verbose: increase output verbosity.
|
|
326
|
+
"""
|
|
327
|
+
|
|
328
|
+
# handle errors here before appending a module
|
|
329
|
+
def _add_module( # pylint: disable=too-many-arguments
|
|
330
|
+
self,
|
|
331
|
+
disable: list[_Message],
|
|
332
|
+
string: str | None = None,
|
|
333
|
+
root: _Path | None = None,
|
|
334
|
+
ignore_args: bool = False,
|
|
335
|
+
ignore_kwargs: bool = False,
|
|
336
|
+
check_class_constructor: bool = False,
|
|
337
|
+
) -> None:
|
|
338
|
+
try:
|
|
339
|
+
if root is not None:
|
|
340
|
+
string = root.read_text(encoding="utf-8")
|
|
341
|
+
|
|
342
|
+
# empty string won't happen but keeps the
|
|
343
|
+
# typechecker happy
|
|
344
|
+
string = string or ""
|
|
345
|
+
self.append(
|
|
346
|
+
Parent(
|
|
347
|
+
_ast.parse(string),
|
|
348
|
+
_Directives(string, disable),
|
|
349
|
+
root,
|
|
350
|
+
ignore_args,
|
|
351
|
+
ignore_kwargs,
|
|
352
|
+
check_class_constructor,
|
|
353
|
+
)
|
|
354
|
+
)
|
|
355
|
+
except (_AstroidSyntaxError, UnicodeDecodeError) as err:
|
|
356
|
+
if root is not None and root.name.endswith(".py"):
|
|
357
|
+
# keep raising errors for .py files as was done prior to
|
|
358
|
+
# this change
|
|
359
|
+
# pass by silently for files that do not end with .py,
|
|
360
|
+
# which were not checked at all prior (these may result
|
|
361
|
+
# in a 123 syntax error exit status in the future)
|
|
362
|
+
# with this there should be no breaking change, and
|
|
363
|
+
# files that are supposed to be python, files evident by
|
|
364
|
+
# their suffix, will continue to fail
|
|
365
|
+
raise err
|
|
366
|
+
|
|
367
|
+
_vprint(
|
|
368
|
+
_FILE_INFO.format(
|
|
369
|
+
path=root or "stdin", msg=str(err).replace("\n", " ")
|
|
370
|
+
),
|
|
371
|
+
self._verbose,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
def __init__( # pylint: disable=too-many-arguments
|
|
375
|
+
self,
|
|
376
|
+
*paths: _Path,
|
|
377
|
+
disable: list[_Message],
|
|
378
|
+
excludes: list[str],
|
|
379
|
+
string: str | None = None,
|
|
380
|
+
ignore_args: bool = False,
|
|
381
|
+
ignore_kwargs: bool = False,
|
|
382
|
+
check_class_constructor: bool = False,
|
|
383
|
+
verbose: bool = False,
|
|
384
|
+
) -> None:
|
|
385
|
+
super().__init__()
|
|
386
|
+
self._disable = disable
|
|
387
|
+
self._excludes = excludes
|
|
388
|
+
self._ignore_args = ignore_args
|
|
389
|
+
self._ignore_kwargs = ignore_kwargs
|
|
390
|
+
self.check_class_constructor = check_class_constructor
|
|
391
|
+
self._verbose = verbose
|
|
392
|
+
if string is not None:
|
|
393
|
+
self._add_module(
|
|
394
|
+
disable,
|
|
395
|
+
string=string,
|
|
396
|
+
ignore_args=ignore_args,
|
|
397
|
+
ignore_kwargs=ignore_kwargs,
|
|
398
|
+
check_class_constructor=check_class_constructor,
|
|
399
|
+
)
|
|
400
|
+
else:
|
|
401
|
+
for path in paths:
|
|
402
|
+
self._populate(path)
|
|
403
|
+
|
|
404
|
+
def _populate(self, root: _Path) -> None:
|
|
405
|
+
if not root.exists():
|
|
406
|
+
raise FileNotFoundError(root)
|
|
407
|
+
|
|
408
|
+
if str(root) != "." and any(
|
|
409
|
+
_re.match(i, root.name) for i in self._excludes
|
|
410
|
+
):
|
|
411
|
+
_vprint(
|
|
412
|
+
_FILE_INFO.format(path=root, msg="in exclude list, skipping"),
|
|
413
|
+
self._verbose,
|
|
414
|
+
)
|
|
415
|
+
return
|
|
416
|
+
|
|
417
|
+
if root.is_file():
|
|
418
|
+
self._add_module(
|
|
419
|
+
self._disable,
|
|
420
|
+
root=root,
|
|
421
|
+
ignore_args=self._ignore_args,
|
|
422
|
+
ignore_kwargs=self._ignore_kwargs,
|
|
423
|
+
check_class_constructor=self.check_class_constructor,
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
if root.is_dir():
|
|
427
|
+
for path in root.iterdir():
|
|
428
|
+
self._populate(path)
|
|
@@ -7,10 +7,10 @@ from __future__ import annotations as _
|
|
|
7
7
|
|
|
8
8
|
import typing as _t
|
|
9
9
|
|
|
10
|
-
from ._function import RETURN as _RETURN
|
|
11
|
-
from ._function import Function as _Function
|
|
12
|
-
from ._function import Param as _Param
|
|
13
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
14
|
from ._utils import almost_equal as _almost_equal
|
|
15
15
|
from .messages import TEMPLATE as _TEMPLATE
|
|
16
16
|
from .messages import E as _E
|
|
@@ -13,10 +13,6 @@ from collections import Counter as _Counter
|
|
|
13
13
|
import astroid as _ast
|
|
14
14
|
import sphinx.ext.napoleon as _s
|
|
15
15
|
|
|
16
|
-
from ._directives import Directive as _Directive
|
|
17
|
-
from ._message import Message as _Message
|
|
18
|
-
from ._utils import isprotected as _isprotected
|
|
19
|
-
|
|
20
16
|
PARAM = "param"
|
|
21
17
|
KEYWORD = "keyword"
|
|
22
18
|
KEY = "key"
|
|
@@ -151,7 +147,7 @@ class _Params(_t.List[Param]):
|
|
|
151
147
|
return any(k for k, v in _Counter(self).items() if v > 1)
|
|
152
148
|
|
|
153
149
|
|
|
154
|
-
class
|
|
150
|
+
class _Stub:
|
|
155
151
|
def __init__(
|
|
156
152
|
self, ignore_args: bool = False, ignore_kwargs: bool = False
|
|
157
153
|
) -> None:
|
|
@@ -169,7 +165,18 @@ class _DocSig:
|
|
|
169
165
|
return self._returns
|
|
170
166
|
|
|
171
167
|
|
|
172
|
-
class
|
|
168
|
+
class Signature(_Stub):
|
|
169
|
+
"""Represents a function signature.
|
|
170
|
+
|
|
171
|
+
:param arguments: Arguments provided to signature.
|
|
172
|
+
:param returns: Returns declared in signature.
|
|
173
|
+
:param ismethod: Whether this signature belongs to a method.
|
|
174
|
+
:param isstaticmethod: Whether this signature belongs to a static
|
|
175
|
+
method.
|
|
176
|
+
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
177
|
+
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
178
|
+
"""
|
|
179
|
+
|
|
173
180
|
def __init__( # pylint: disable=too-many-arguments
|
|
174
181
|
self,
|
|
175
182
|
arguments: _ast.Arguments,
|
|
@@ -239,7 +246,14 @@ class _Signature(_DocSig):
|
|
|
239
246
|
return self._rettype
|
|
240
247
|
|
|
241
248
|
|
|
242
|
-
class
|
|
249
|
+
class Docstring(_Stub):
|
|
250
|
+
"""Represents a function docstring.
|
|
251
|
+
|
|
252
|
+
:param node: Docstring ast node.
|
|
253
|
+
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
254
|
+
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
255
|
+
"""
|
|
256
|
+
|
|
243
257
|
def __init__(
|
|
244
258
|
self,
|
|
245
259
|
node: _ast.Const | None = None,
|
|
@@ -269,154 +283,3 @@ class _Docstring(_DocSig):
|
|
|
269
283
|
Docstring has to exist for docstring to be considered bare.
|
|
270
284
|
"""
|
|
271
285
|
return self._string is not None and not self._args and not self.returns
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
class Function: # pylint: disable=too-many-arguments
|
|
275
|
-
"""Represents a function with signature and docstring parameters.
|
|
276
|
-
|
|
277
|
-
:param node: Function's abstract syntax tree.
|
|
278
|
-
:param directives: Directive, if any, belonging to this function.
|
|
279
|
-
:param disabled: List of disabled checks specific to this function.
|
|
280
|
-
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
281
|
-
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
282
|
-
:param check_class_constructor: If the function is the class
|
|
283
|
-
constructor, use its own docstring. Otherwise, use the class
|
|
284
|
-
level docstring for the constructor function.
|
|
285
|
-
"""
|
|
286
|
-
|
|
287
|
-
def __init__( # pylint: disable=too-many-arguments
|
|
288
|
-
self,
|
|
289
|
-
node: _ast.FunctionDef,
|
|
290
|
-
directives: _t.List[_Directive],
|
|
291
|
-
disabled: list[_Message],
|
|
292
|
-
ignore_args: bool = False,
|
|
293
|
-
ignore_kwargs: bool = False,
|
|
294
|
-
check_class_constructor: bool = False,
|
|
295
|
-
) -> None:
|
|
296
|
-
self._node = node
|
|
297
|
-
self._directives = directives
|
|
298
|
-
self._disabled = disabled
|
|
299
|
-
self._parent = node.parent.frame()
|
|
300
|
-
self._signature = _Signature(
|
|
301
|
-
node.args,
|
|
302
|
-
node.returns,
|
|
303
|
-
self.ismethod,
|
|
304
|
-
self.isstaticmethod,
|
|
305
|
-
ignore_args,
|
|
306
|
-
ignore_kwargs,
|
|
307
|
-
)
|
|
308
|
-
if self.isinit and not check_class_constructor:
|
|
309
|
-
# docstring for __init__ is expected on the class docstring
|
|
310
|
-
relevant_doc_node = self._parent.doc_node
|
|
311
|
-
else:
|
|
312
|
-
relevant_doc_node = node.doc_node
|
|
313
|
-
self._docstring = _Docstring(relevant_doc_node, ignore_kwargs)
|
|
314
|
-
|
|
315
|
-
def __len__(self) -> int:
|
|
316
|
-
"""Length of the longest sequence of args."""
|
|
317
|
-
return max([len(self.signature.args), len(self.docstring.args)])
|
|
318
|
-
|
|
319
|
-
def _decorated_with(self, name: str) -> bool:
|
|
320
|
-
if self._node.decorators is not None:
|
|
321
|
-
for dec in self._node.decorators.nodes:
|
|
322
|
-
return (isinstance(dec, _ast.Name) and dec.name == name) or (
|
|
323
|
-
isinstance(dec, _ast.Attribute) and dec.attrname == name
|
|
324
|
-
)
|
|
325
|
-
|
|
326
|
-
return False
|
|
327
|
-
|
|
328
|
-
@property
|
|
329
|
-
def ismethod(self) -> bool:
|
|
330
|
-
"""Boolean value for whether function is a method."""
|
|
331
|
-
return isinstance(self._parent, _ast.ClassDef)
|
|
332
|
-
|
|
333
|
-
@property
|
|
334
|
-
def isproperty(self) -> bool:
|
|
335
|
-
"""Boolean value for whether function is a property."""
|
|
336
|
-
valid_properties = [
|
|
337
|
-
"property",
|
|
338
|
-
"cached_property",
|
|
339
|
-
]
|
|
340
|
-
return self.ismethod and any(
|
|
341
|
-
self._decorated_with(i) for i in valid_properties
|
|
342
|
-
)
|
|
343
|
-
|
|
344
|
-
@property
|
|
345
|
-
def isoverloaded(self) -> bool:
|
|
346
|
-
"""Boolean value for whether function is a property."""
|
|
347
|
-
return self._decorated_with("overload")
|
|
348
|
-
|
|
349
|
-
@property
|
|
350
|
-
def isinit(self) -> bool:
|
|
351
|
-
"""Boolean value for whether function is a class constructor."""
|
|
352
|
-
return self.ismethod and self.name == "__init__"
|
|
353
|
-
|
|
354
|
-
@property
|
|
355
|
-
def isoverridden(self) -> bool:
|
|
356
|
-
"""Boolean value for whether function is overridden."""
|
|
357
|
-
if self.ismethod and not self.isinit:
|
|
358
|
-
for ancestor in self._parent.ancestors():
|
|
359
|
-
if self.name in ancestor and isinstance(
|
|
360
|
-
ancestor[self.name], _ast.FunctionDef
|
|
361
|
-
):
|
|
362
|
-
return True
|
|
363
|
-
|
|
364
|
-
return False
|
|
365
|
-
|
|
366
|
-
@property
|
|
367
|
-
def isprotected(self) -> bool:
|
|
368
|
-
"""Boolean value for whether function is protected."""
|
|
369
|
-
return (
|
|
370
|
-
_isprotected(self.name) and not self.isinit and not self.isdunder
|
|
371
|
-
)
|
|
372
|
-
|
|
373
|
-
@property
|
|
374
|
-
def isstaticmethod(self) -> bool:
|
|
375
|
-
"""Boolean value for whether function is a static method."""
|
|
376
|
-
return self.ismethod and self._decorated_with("staticmethod")
|
|
377
|
-
|
|
378
|
-
@property
|
|
379
|
-
def isdunder(self) -> bool:
|
|
380
|
-
"""Boolean value for whether function is a dunder method."""
|
|
381
|
-
return (
|
|
382
|
-
self.ismethod
|
|
383
|
-
and not self.isinit
|
|
384
|
-
and bool(_re.match(r"__(.*)__", self.name))
|
|
385
|
-
)
|
|
386
|
-
|
|
387
|
-
@property
|
|
388
|
-
def name(self) -> str:
|
|
389
|
-
"""The name of the function."""
|
|
390
|
-
return self._node.name
|
|
391
|
-
|
|
392
|
-
@property
|
|
393
|
-
def parent(
|
|
394
|
-
self,
|
|
395
|
-
) -> _ast.FunctionDef | _ast.Module | _ast.ClassDef | _ast.Lambda:
|
|
396
|
-
"""Function's parent node."""
|
|
397
|
-
return self._parent
|
|
398
|
-
|
|
399
|
-
@property
|
|
400
|
-
def lineno(self) -> int:
|
|
401
|
-
"""Line number of function declaration."""
|
|
402
|
-
return self._node.lineno or 0
|
|
403
|
-
|
|
404
|
-
@property
|
|
405
|
-
def signature(self) -> _Signature:
|
|
406
|
-
"""The function's signature parameters."""
|
|
407
|
-
return self._signature
|
|
408
|
-
|
|
409
|
-
@property
|
|
410
|
-
def docstring(self) -> _Docstring:
|
|
411
|
-
"""The function's docstring."""
|
|
412
|
-
return self._docstring
|
|
413
|
-
|
|
414
|
-
@property
|
|
415
|
-
def disabled(self) -> list[_Message]:
|
|
416
|
-
"""List of disabled checks specific to this function."""
|
|
417
|
-
return self._disabled
|
|
418
|
-
|
|
419
|
-
@property
|
|
420
|
-
def directives(self) -> _t.List[_Directive]:
|
|
421
|
-
"""Directive, if any, belonging to this function."""
|
|
422
|
-
return self._directives
|
|
@@ -8,15 +8,6 @@ from __future__ import annotations as _
|
|
|
8
8
|
from difflib import SequenceMatcher as _SequenceMatcher
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def isprotected(name: str | None) -> bool:
|
|
12
|
-
"""Confirm whether attribute is protected or not.
|
|
13
|
-
|
|
14
|
-
:param name: Name to check.
|
|
15
|
-
:return: Boolean value for whether attribute is protected or not.
|
|
16
|
-
"""
|
|
17
|
-
return str(name).startswith("_")
|
|
18
|
-
|
|
19
|
-
|
|
20
11
|
def almost_equal(str1: str, str2: str, mini: float, maxi: float) -> bool:
|
|
21
12
|
"""Show result for more than the minimum but less than the maximum.
|
|
22
13
|
|
|
@@ -28,3 +19,13 @@ def almost_equal(str1: str, str2: str, mini: float, maxi: float) -> bool:
|
|
|
28
19
|
:return: Boolean result for whether both strings are almost equal.
|
|
29
20
|
"""
|
|
30
21
|
return mini < _SequenceMatcher(a=str1, b=str2).ratio() < maxi
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def vprint(msg: str, verbose: bool = False) -> None:
|
|
25
|
+
"""Print messages only if verbose is true.
|
|
26
|
+
|
|
27
|
+
:param msg: Message to print.
|
|
28
|
+
:param verbose: Whether verbose mode is enabled.
|
|
29
|
+
"""
|
|
30
|
+
if verbose:
|
|
31
|
+
print(msg)
|
|
@@ -72,12 +72,12 @@ maintainers = [
|
|
|
72
72
|
name = "docsig"
|
|
73
73
|
readme = "README.rst"
|
|
74
74
|
repository = "https://github.com/jshwi/docsig"
|
|
75
|
-
version = "0.
|
|
75
|
+
version = "0.47.0"
|
|
76
76
|
|
|
77
77
|
[tool.poetry.dependencies]
|
|
78
78
|
Pygments = "^2.13.0"
|
|
79
79
|
Sphinx = "^7.0.0"
|
|
80
|
-
arcon = ">=0.
|
|
80
|
+
arcon = ">=0.4.0"
|
|
81
81
|
astroid = "^3.0.1"
|
|
82
82
|
object-colors = "^2.1.0"
|
|
83
83
|
python = "^3.8"
|
docsig-0.45.0/docsig/_module.py
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
docsig._module
|
|
3
|
-
==============
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from __future__ import annotations as _
|
|
7
|
-
|
|
8
|
-
import re as _re
|
|
9
|
-
import typing as _t
|
|
10
|
-
from pathlib import Path as _Path
|
|
11
|
-
|
|
12
|
-
import astroid as _ast
|
|
13
|
-
from astroid import AstroidSyntaxError as _AstroidSyntaxError
|
|
14
|
-
|
|
15
|
-
from ._directives import Directives as _Directives
|
|
16
|
-
from ._function import Function as _Function
|
|
17
|
-
from ._message import Message as _Message
|
|
18
|
-
from ._utils import isprotected as _isprotected
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class Parent(_t.List[_Function]):
|
|
22
|
-
"""Represents an object that contains functions or methods.
|
|
23
|
-
|
|
24
|
-
:param node: Parent's abstract syntax tree.
|
|
25
|
-
:param directives: Data for directives and, subsequently, total of
|
|
26
|
-
errors which are excluded from function checks.
|
|
27
|
-
:param path: Path to base path representation on.
|
|
28
|
-
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
29
|
-
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
30
|
-
:param check_class_constructor: Check the class constructor's
|
|
31
|
-
docstring. Otherwise, expect the constructor's documentation to
|
|
32
|
-
be on the class level docstring.
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
def __init__( # pylint: disable=too-many-arguments
|
|
36
|
-
self,
|
|
37
|
-
node: _ast.Module | _ast.ClassDef,
|
|
38
|
-
directives: _Directives,
|
|
39
|
-
path: _Path | None = None,
|
|
40
|
-
ignore_args: bool = False,
|
|
41
|
-
ignore_kwargs: bool = False,
|
|
42
|
-
check_class_constructor: bool = False,
|
|
43
|
-
) -> None:
|
|
44
|
-
super().__init__()
|
|
45
|
-
self._name = node.name
|
|
46
|
-
self._path = f"{path}:" if path is not None else ""
|
|
47
|
-
overloads = []
|
|
48
|
-
returns = None
|
|
49
|
-
parent_comments, parent_disabled = directives.get(
|
|
50
|
-
node.lineno, ([], [])
|
|
51
|
-
)
|
|
52
|
-
for subnode in node.body:
|
|
53
|
-
comments, disabled = directives.get(subnode.lineno, ([], []))
|
|
54
|
-
comments.extend(parent_comments)
|
|
55
|
-
disabled.extend(parent_disabled)
|
|
56
|
-
if isinstance(subnode, _ast.FunctionDef):
|
|
57
|
-
func = _Function(
|
|
58
|
-
subnode,
|
|
59
|
-
comments,
|
|
60
|
-
disabled,
|
|
61
|
-
ignore_args,
|
|
62
|
-
ignore_kwargs,
|
|
63
|
-
check_class_constructor,
|
|
64
|
-
)
|
|
65
|
-
if func.isoverloaded:
|
|
66
|
-
overloads.append(func.name)
|
|
67
|
-
returns = func.signature.rettype
|
|
68
|
-
else:
|
|
69
|
-
if func.name in overloads:
|
|
70
|
-
subnode.returns = returns
|
|
71
|
-
# noinspection PyProtectedMember
|
|
72
|
-
func._signature._rettype = (
|
|
73
|
-
returns
|
|
74
|
-
if isinstance(returns, str)
|
|
75
|
-
else func._signature._get_rettype(returns)
|
|
76
|
-
)
|
|
77
|
-
# noinspection PyProtectedMember
|
|
78
|
-
func._signature._returns = (
|
|
79
|
-
str(func._signature._rettype) != "None"
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
self.append(func)
|
|
83
|
-
|
|
84
|
-
@property
|
|
85
|
-
def path(self) -> str:
|
|
86
|
-
"""Representation of path to parent."""
|
|
87
|
-
return self._path
|
|
88
|
-
|
|
89
|
-
@property
|
|
90
|
-
def isprotected(self) -> bool:
|
|
91
|
-
"""Boolean value for whether class is protected."""
|
|
92
|
-
return _isprotected(self._name)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
class _Module(_t.List[Parent]):
|
|
96
|
-
def __init__( # pylint: disable=too-many-arguments
|
|
97
|
-
self,
|
|
98
|
-
string: str,
|
|
99
|
-
disable: list[_Message],
|
|
100
|
-
path: _Path | None = None,
|
|
101
|
-
ignore_args: bool = False,
|
|
102
|
-
ignore_kwargs: bool = False,
|
|
103
|
-
check_class_constructor: bool = False,
|
|
104
|
-
) -> None:
|
|
105
|
-
super().__init__()
|
|
106
|
-
ast = _ast.parse(string)
|
|
107
|
-
directives = _Directives(string, disable)
|
|
108
|
-
self.append(Parent(ast, directives, path, ignore_args, ignore_kwargs))
|
|
109
|
-
for subnode in ast.body:
|
|
110
|
-
if isinstance(subnode, _ast.ClassDef):
|
|
111
|
-
self.append(
|
|
112
|
-
Parent(
|
|
113
|
-
subnode,
|
|
114
|
-
directives,
|
|
115
|
-
path,
|
|
116
|
-
ignore_args,
|
|
117
|
-
ignore_kwargs,
|
|
118
|
-
check_class_constructor,
|
|
119
|
-
)
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
class Modules(_t.List[_Module]):
|
|
124
|
-
"""Sequence of ``Module`` objects parsed from Python modules or str.
|
|
125
|
-
|
|
126
|
-
Recursively collect Python files from within all dirs that exist
|
|
127
|
-
under paths provided.
|
|
128
|
-
|
|
129
|
-
If string is provided, ignore paths.
|
|
130
|
-
|
|
131
|
-
:param paths: Path(s) to parse ``Module``(s) from.
|
|
132
|
-
:param disable: List of checks to disable.
|
|
133
|
-
:param excludes: List pf regular expression of files and dirs to
|
|
134
|
-
exclude from checks.
|
|
135
|
-
:param string: String to parse if provided.
|
|
136
|
-
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
137
|
-
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
138
|
-
:param check_class_constructor: Check the class constructor's
|
|
139
|
-
docstring. Otherwise, expect the constructor's documentation to
|
|
140
|
-
be on the class level docstring.
|
|
141
|
-
"""
|
|
142
|
-
|
|
143
|
-
# handle errors here before appending a module
|
|
144
|
-
def _add_module( # pylint: disable=too-many-arguments
|
|
145
|
-
self,
|
|
146
|
-
disable: list[_Message],
|
|
147
|
-
string: str | None = None,
|
|
148
|
-
root: _Path | None = None,
|
|
149
|
-
ignore_args: bool = False,
|
|
150
|
-
ignore_kwargs: bool = False,
|
|
151
|
-
check_class_constructor: bool = False,
|
|
152
|
-
) -> None:
|
|
153
|
-
try:
|
|
154
|
-
if root is not None:
|
|
155
|
-
string = root.read_text(encoding="utf-8")
|
|
156
|
-
|
|
157
|
-
self.append(
|
|
158
|
-
_Module(
|
|
159
|
-
# empty string won't happen but keeps the
|
|
160
|
-
# typechecker happy
|
|
161
|
-
string or "",
|
|
162
|
-
disable,
|
|
163
|
-
root,
|
|
164
|
-
ignore_args,
|
|
165
|
-
ignore_kwargs,
|
|
166
|
-
check_class_constructor,
|
|
167
|
-
)
|
|
168
|
-
)
|
|
169
|
-
except (_AstroidSyntaxError, UnicodeDecodeError) as err:
|
|
170
|
-
if root is not None and root.name.endswith(".py"):
|
|
171
|
-
# keep raising errors for .py files as was done prior to
|
|
172
|
-
# this change
|
|
173
|
-
# pass by silently for files that do not end with .py,
|
|
174
|
-
# which were not checked at all prior (these may result
|
|
175
|
-
# in a 123 syntax error exit status in the future)
|
|
176
|
-
# with this there should be no breaking change, and
|
|
177
|
-
# files that are supposed to be python, files evident by
|
|
178
|
-
# their suffix, will continue to fail
|
|
179
|
-
raise err
|
|
180
|
-
|
|
181
|
-
def __init__( # pylint: disable=too-many-arguments
|
|
182
|
-
self,
|
|
183
|
-
*paths: _Path,
|
|
184
|
-
disable: list[_Message],
|
|
185
|
-
excludes: list[str],
|
|
186
|
-
string: str | None = None,
|
|
187
|
-
ignore_args: bool = False,
|
|
188
|
-
ignore_kwargs: bool = False,
|
|
189
|
-
check_class_constructor: bool = False,
|
|
190
|
-
) -> None:
|
|
191
|
-
super().__init__()
|
|
192
|
-
self._disable = disable
|
|
193
|
-
self._excludes = excludes
|
|
194
|
-
self._ignore_args = ignore_args
|
|
195
|
-
self._ignore_kwargs = ignore_kwargs
|
|
196
|
-
self.check_class_constructor = check_class_constructor
|
|
197
|
-
if string is not None:
|
|
198
|
-
self._add_module(
|
|
199
|
-
disable,
|
|
200
|
-
string=string,
|
|
201
|
-
ignore_args=ignore_args,
|
|
202
|
-
ignore_kwargs=ignore_kwargs,
|
|
203
|
-
check_class_constructor=check_class_constructor,
|
|
204
|
-
)
|
|
205
|
-
else:
|
|
206
|
-
for path in paths:
|
|
207
|
-
self._populate(path)
|
|
208
|
-
|
|
209
|
-
def _populate(self, root: _Path) -> None:
|
|
210
|
-
if not root.exists():
|
|
211
|
-
raise FileNotFoundError(root)
|
|
212
|
-
|
|
213
|
-
if str(root) != "." and any(
|
|
214
|
-
_re.match(i, root.name) for i in self._excludes
|
|
215
|
-
):
|
|
216
|
-
return
|
|
217
|
-
|
|
218
|
-
if root.is_file():
|
|
219
|
-
self._add_module(
|
|
220
|
-
self._disable,
|
|
221
|
-
root=root,
|
|
222
|
-
ignore_args=self._ignore_args,
|
|
223
|
-
ignore_kwargs=self._ignore_kwargs,
|
|
224
|
-
check_class_constructor=self.check_class_constructor,
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
if root.is_dir():
|
|
228
|
-
for path in root.iterdir():
|
|
229
|
-
self._populate(path)
|
|
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
|