docsig 0.36.0__tar.gz → 0.37.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.36.0 → docsig-0.37.0}/PKG-INFO +1 -1
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_core.py +14 -5
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_disable.py +10 -8
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_display.py +2 -3
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_function.py +2 -2
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_main.py +2 -0
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_module.py +26 -16
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_objects.py +1 -1
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_report.py +1 -1
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_utils.py +1 -1
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_version.py +1 -1
- {docsig-0.36.0 → docsig-0.37.0}/pyproject.toml +1 -1
- {docsig-0.36.0 → docsig-0.37.0}/LICENSE +0 -0
- {docsig-0.36.0 → docsig-0.37.0}/README.rst +0 -0
- {docsig-0.36.0 → docsig-0.37.0}/docsig/__init__.py +0 -0
- {docsig-0.36.0 → docsig-0.37.0}/docsig/__main__.py +0 -0
- {docsig-0.36.0 → docsig-0.37.0}/docsig/_config.py +0 -0
- {docsig-0.36.0 → docsig-0.37.0}/docsig/messages.py +0 -0
- {docsig-0.36.0 → docsig-0.37.0}/docsig/py.typed +0 -0
|
@@ -2,19 +2,30 @@
|
|
|
2
2
|
docsig._core
|
|
3
3
|
============
|
|
4
4
|
"""
|
|
5
|
-
from __future__ import annotations
|
|
5
|
+
from __future__ import annotations as _
|
|
6
6
|
|
|
7
|
+
import sys as _sys
|
|
8
|
+
from os import environ as _e
|
|
7
9
|
from pathlib import Path as _Path
|
|
8
10
|
|
|
9
11
|
from ._display import Display as _Display
|
|
10
12
|
from ._display import Failure as _Failure
|
|
11
13
|
from ._display import Failures as _Failures
|
|
12
14
|
from ._display import FuncStr as _FuncStr
|
|
15
|
+
from ._display import color as _color
|
|
13
16
|
from ._module import Modules as _Modules
|
|
14
17
|
from ._module import Parent as _Parent
|
|
15
18
|
from ._report import generate_report as _generate_report
|
|
16
19
|
|
|
17
20
|
|
|
21
|
+
def pretty_print_error() -> None:
|
|
22
|
+
"""Print user friendly commandline error if debug not enabled."""
|
|
23
|
+
if _e.get("DOCSIG_DEBUG", None) != "1":
|
|
24
|
+
_sys.excepthook = lambda x, y, _: print(
|
|
25
|
+
f"{_color.red.bold.get(x.__name__)}: {y}"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
18
29
|
def _run_check( # pylint: disable=too-many-arguments
|
|
19
30
|
parent: _Parent,
|
|
20
31
|
check_class: bool,
|
|
@@ -25,11 +36,9 @@ def _run_check( # pylint: disable=too-many-arguments
|
|
|
25
36
|
ignore_no_params: bool,
|
|
26
37
|
no_ansi: bool,
|
|
27
38
|
targets: list[str],
|
|
28
|
-
disable: list[str],
|
|
29
39
|
) -> _Failures:
|
|
30
40
|
failures = _Failures()
|
|
31
41
|
for func in parent:
|
|
32
|
-
disable_func = list({*disable, *func.disabled})
|
|
33
42
|
if not (func.isoverridden and not check_overridden) and (
|
|
34
43
|
not (func.isprotected and not check_protected)
|
|
35
44
|
and not (func.isinit and not check_class)
|
|
@@ -37,7 +46,7 @@ def _run_check( # pylint: disable=too-many-arguments
|
|
|
37
46
|
and not (func.docstring.bare and ignore_no_params)
|
|
38
47
|
):
|
|
39
48
|
report = _generate_report(
|
|
40
|
-
func, targets,
|
|
49
|
+
func, targets, func.disabled, check_property_returns
|
|
41
50
|
)
|
|
42
51
|
if report:
|
|
43
52
|
failures.append(
|
|
@@ -91,6 +100,7 @@ def docsig( # pylint: disable=too-many-locals
|
|
|
91
100
|
"""
|
|
92
101
|
modules = _Modules(
|
|
93
102
|
*path,
|
|
103
|
+
disable=disable or [],
|
|
94
104
|
string=string,
|
|
95
105
|
ignore_args=ignore_args,
|
|
96
106
|
ignore_kwargs=ignore_kwargs,
|
|
@@ -109,7 +119,6 @@ def docsig( # pylint: disable=too-many-locals
|
|
|
109
119
|
ignore_no_params,
|
|
110
120
|
no_ansi,
|
|
111
121
|
targets or [],
|
|
112
|
-
disable or [],
|
|
113
122
|
)
|
|
114
123
|
if failures:
|
|
115
124
|
display[top_level.path].append(failures)
|
|
@@ -2,31 +2,33 @@
|
|
|
2
2
|
docsig._disable
|
|
3
3
|
===============
|
|
4
4
|
"""
|
|
5
|
-
from __future__ import annotations
|
|
5
|
+
from __future__ import annotations as _
|
|
6
6
|
|
|
7
7
|
import tokenize as _tokenize
|
|
8
|
-
import typing as
|
|
8
|
+
import typing as _t
|
|
9
9
|
from io import StringIO as _StringIO
|
|
10
10
|
|
|
11
11
|
from ._report import ERRORS as _ERRORS
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class Disabled(
|
|
14
|
+
class Disabled(_t.Dict[int, _t.List[str]]):
|
|
15
15
|
"""Data for lines which are excluded from checks.
|
|
16
16
|
|
|
17
17
|
:param text: Python code.
|
|
18
|
+
:param disable: List of checks to disable.
|
|
18
19
|
"""
|
|
19
20
|
|
|
20
|
-
def __init__(self, text: str) -> None:
|
|
21
|
+
def __init__(self, text: str, disable: list[str]) -> None:
|
|
21
22
|
super().__init__()
|
|
22
23
|
fin = _StringIO(text)
|
|
23
24
|
module_is_disabled = False
|
|
24
25
|
for line in _tokenize.generate_tokens(fin.readline):
|
|
25
26
|
lineno = line.start[0]
|
|
26
27
|
col = line.start[1]
|
|
28
|
+
self[lineno] = list(disable)
|
|
27
29
|
if line.type == _tokenize.COMMENT:
|
|
28
|
-
if line.string.startswith(f"
|
|
29
|
-
string = line.string.split(":
|
|
30
|
+
if line.string[1:].strip().startswith(f"{__package__}:"):
|
|
31
|
+
string = line.string.split(":")[1].strip()
|
|
30
32
|
|
|
31
33
|
# module level comments
|
|
32
34
|
if col == 0:
|
|
@@ -37,11 +39,11 @@ class Disabled(t.Dict[int, t.List[str]]):
|
|
|
37
39
|
|
|
38
40
|
# otherwise, inline comments
|
|
39
41
|
elif string == "disable":
|
|
40
|
-
self[lineno]
|
|
42
|
+
self[lineno].extend(_ERRORS)
|
|
41
43
|
|
|
42
44
|
# keep appending disabled lines as long as this is true
|
|
43
45
|
if module_is_disabled:
|
|
44
|
-
self[lineno]
|
|
46
|
+
self[lineno].extend(_ERRORS)
|
|
45
47
|
|
|
46
48
|
def __setitem__(self, key: int, value: list[str]) -> None:
|
|
47
49
|
if key not in self:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
docsig._display
|
|
3
3
|
===============
|
|
4
4
|
"""
|
|
5
|
-
from __future__ import annotations
|
|
5
|
+
from __future__ import annotations as _
|
|
6
6
|
|
|
7
7
|
import typing as _t
|
|
8
8
|
from collections import UserString as _UserString
|
|
@@ -20,7 +20,6 @@ from ._function import ARG as _ARG
|
|
|
20
20
|
from ._function import KEY as _KEY
|
|
21
21
|
from ._function import Function as _Function
|
|
22
22
|
from ._function import Param as _Param
|
|
23
|
-
from ._objects import MutableSequence as _MutableSequence
|
|
24
23
|
from ._report import Report as _Report
|
|
25
24
|
|
|
26
25
|
color = _Color()
|
|
@@ -205,7 +204,7 @@ class Failure(_t.NamedTuple):
|
|
|
205
204
|
report: _Report
|
|
206
205
|
|
|
207
206
|
|
|
208
|
-
class Failures(
|
|
207
|
+
class Failures(_t.List[Failure]):
|
|
209
208
|
"""Sequence of failed functions."""
|
|
210
209
|
|
|
211
210
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
docsig._function
|
|
3
3
|
================
|
|
4
4
|
"""
|
|
5
|
-
from __future__ import annotations
|
|
5
|
+
from __future__ import annotations as _
|
|
6
6
|
|
|
7
7
|
import re as _re
|
|
8
8
|
import textwrap as _textwrap
|
|
@@ -75,7 +75,7 @@ class Param(_t.NamedTuple):
|
|
|
75
75
|
return str(self.name).startswith("_")
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
class _Matches(
|
|
78
|
+
class _Matches(_t.List[Param]):
|
|
79
79
|
_pattern = _re.compile(":(.*?):")
|
|
80
80
|
_normalize = {KEYWORD: KEY}
|
|
81
81
|
|
|
@@ -6,6 +6,7 @@ Contains package entry point.
|
|
|
6
6
|
"""
|
|
7
7
|
from ._config import Parser as _Parser
|
|
8
8
|
from ._core import docsig as _docsig
|
|
9
|
+
from ._core import pretty_print_error as _pretty_print_error
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
def main() -> int:
|
|
@@ -16,6 +17,7 @@ def main() -> int:
|
|
|
16
17
|
:return: Exit status for whether test failed or not.
|
|
17
18
|
"""
|
|
18
19
|
parser = _Parser()
|
|
20
|
+
_pretty_print_error()
|
|
19
21
|
return _docsig(
|
|
20
22
|
*parser.args.path,
|
|
21
23
|
string=parser.args.string,
|
|
@@ -2,21 +2,19 @@
|
|
|
2
2
|
docsig._module
|
|
3
3
|
==============
|
|
4
4
|
"""
|
|
5
|
-
from __future__ import annotations
|
|
5
|
+
from __future__ import annotations as _
|
|
6
6
|
|
|
7
|
+
import typing as _t
|
|
7
8
|
from pathlib import Path as _Path
|
|
8
9
|
|
|
9
10
|
import astroid as _ast
|
|
10
11
|
|
|
11
12
|
from ._disable import Disabled as _Disabled
|
|
12
13
|
from ._function import Function as _Function
|
|
13
|
-
from ._objects import MutableSequence as _MutableSequence
|
|
14
14
|
from ._utils import isprotected as _isprotected
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
class Parent(
|
|
18
|
-
_MutableSequence[_Function]
|
|
19
|
-
):
|
|
17
|
+
class Parent(_t.List[_Function]):
|
|
20
18
|
"""Represents an object that contains functions or methods.
|
|
21
19
|
|
|
22
20
|
:param node: Parent's abstract syntax tree.
|
|
@@ -26,7 +24,7 @@ class Parent( # pylint: disable=too-many-arguments
|
|
|
26
24
|
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
27
25
|
"""
|
|
28
26
|
|
|
29
|
-
def __init__(
|
|
27
|
+
def __init__( # pylint: disable=too-many-arguments
|
|
30
28
|
self,
|
|
31
29
|
node: _ast.Module | _ast.ClassDef,
|
|
32
30
|
disabled: _Disabled,
|
|
@@ -37,7 +35,6 @@ class Parent( # pylint: disable=too-many-arguments
|
|
|
37
35
|
super().__init__()
|
|
38
36
|
self._name = node.name
|
|
39
37
|
self._path = f"{path}:" if path is not None else ""
|
|
40
|
-
self._directives = disabled
|
|
41
38
|
overloads = []
|
|
42
39
|
returns = None
|
|
43
40
|
for subnode in node.body:
|
|
@@ -54,11 +51,15 @@ class Parent( # pylint: disable=too-many-arguments
|
|
|
54
51
|
else:
|
|
55
52
|
if func.name in overloads:
|
|
56
53
|
subnode.returns = returns
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
# noinspection PyProtectedMember
|
|
55
|
+
func._signature._rettype = (
|
|
56
|
+
returns
|
|
57
|
+
if isinstance(returns, str)
|
|
58
|
+
else func._signature._get_rettype(returns)
|
|
59
|
+
)
|
|
60
|
+
# noinspection PyProtectedMember
|
|
61
|
+
func._signature._returns = (
|
|
62
|
+
str(func._signature._rettype) != "None"
|
|
62
63
|
)
|
|
63
64
|
|
|
64
65
|
self.append(func)
|
|
@@ -74,17 +75,18 @@ class Parent( # pylint: disable=too-many-arguments
|
|
|
74
75
|
return _isprotected(self._name)
|
|
75
76
|
|
|
76
77
|
|
|
77
|
-
class _Module(
|
|
78
|
-
def __init__(
|
|
78
|
+
class _Module(_t.List[Parent]):
|
|
79
|
+
def __init__( # pylint: disable=too-many-arguments
|
|
79
80
|
self,
|
|
80
81
|
string: str,
|
|
82
|
+
disable: list[str],
|
|
81
83
|
path: _Path | None = None,
|
|
82
84
|
ignore_args: bool = False,
|
|
83
85
|
ignore_kwargs: bool = False,
|
|
84
86
|
) -> None:
|
|
85
87
|
super().__init__()
|
|
86
88
|
ast = _ast.parse(string)
|
|
87
|
-
disabled = _Disabled(string)
|
|
89
|
+
disabled = _Disabled(string, disable)
|
|
88
90
|
self.append(Parent(ast, disabled, path, ignore_args, ignore_kwargs))
|
|
89
91
|
for subnode in ast.body:
|
|
90
92
|
if isinstance(subnode, _ast.ClassDef):
|
|
@@ -93,7 +95,7 @@ class _Module(_MutableSequence[Parent]):
|
|
|
93
95
|
)
|
|
94
96
|
|
|
95
97
|
|
|
96
|
-
class Modules(
|
|
98
|
+
class Modules(_t.List[_Module]):
|
|
97
99
|
"""Sequence of ``Module`` objects parsed from Python modules or str.
|
|
98
100
|
|
|
99
101
|
Recursively collect Python files from within all dirs that exist
|
|
@@ -102,6 +104,7 @@ class Modules(_MutableSequence[_Module]):
|
|
|
102
104
|
If string is provided, ignore paths.
|
|
103
105
|
|
|
104
106
|
:param paths: Path(s) to parse ``Module``(s) from.
|
|
107
|
+
:param disable: List of checks to disable.
|
|
105
108
|
:param string: String to parse if provided.
|
|
106
109
|
:param ignore_args: Ignore args prefixed with an asterisk.
|
|
107
110
|
:param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
|
|
@@ -110,17 +113,20 @@ class Modules(_MutableSequence[_Module]):
|
|
|
110
113
|
def __init__(
|
|
111
114
|
self,
|
|
112
115
|
*paths: _Path,
|
|
116
|
+
disable: list[str],
|
|
113
117
|
string: str | None = None,
|
|
114
118
|
ignore_args: bool = False,
|
|
115
119
|
ignore_kwargs: bool = False,
|
|
116
120
|
) -> None:
|
|
117
121
|
super().__init__()
|
|
122
|
+
self._disable = disable
|
|
118
123
|
self._ignore_args = ignore_args
|
|
119
124
|
self._ignore_kwargs = ignore_kwargs
|
|
120
125
|
if string is not None:
|
|
121
126
|
self.append(
|
|
122
127
|
_Module(
|
|
123
128
|
string,
|
|
129
|
+
disable,
|
|
124
130
|
ignore_args=ignore_args,
|
|
125
131
|
ignore_kwargs=ignore_kwargs,
|
|
126
132
|
)
|
|
@@ -130,10 +136,14 @@ class Modules(_MutableSequence[_Module]):
|
|
|
130
136
|
self._populate(path)
|
|
131
137
|
|
|
132
138
|
def _populate(self, root: _Path) -> None:
|
|
139
|
+
if not root.exists():
|
|
140
|
+
raise FileNotFoundError(root)
|
|
141
|
+
|
|
133
142
|
if root.is_file() and root.name.endswith(".py"):
|
|
134
143
|
self.append(
|
|
135
144
|
_Module(
|
|
136
145
|
root.read_text(),
|
|
146
|
+
self._disable,
|
|
137
147
|
root,
|
|
138
148
|
self._ignore_args,
|
|
139
149
|
self._ignore_kwargs,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|