-
-
Notifications
You must be signed in to change notification settings - Fork 468
/
Copy pathcheck_documentation.py
executable file
·85 lines (70 loc) · 2.92 KB
/
check_documentation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env python3
"""Checks for attributes and code examples in RedditBase subclasses."""
import os
import re
import sys
# This line imports from the local PRAW rather than the global installed PRAW.
sys.path.insert(0, os.path.abspath(os.path.join(__file__, "..", "..")))
from praw.models.reddit.base import RedditBase # noqa: E402
from praw.models.reddit.modmail import ModmailObject # noqa: E402
from praw.util.cache import cachedproperty # noqa: E402
class DocumentationChecker:
"""Checks for code block statements and attribute tables in subclasses.
Attribute exceptions holds all exceptions. All classes and subclasses in the
exceptions list will be ignored.
Attribute METHOD_EXCEPTIONS holds the names of methods that will be filtered out.
"""
BASE_SEARCH_CLASS = RedditBase
exceptions = {
ModmailObject, # is never publicly accessed
}
HAS_CODE_BLOCK = re.compile(r"\.\. code-block::")
HAS_ATTRIBUTE_TABLE = re.compile(r"Attribute[ ]+Description")
METHOD_EXCEPTIONS = {"from_data", "id_from_url", "parse", "sluggify", "gild"}
subclasses = set()
@staticmethod
def discover_subclasses(base_set):
working_items = list(base_set)
subclasses = set()
while working_items:
item = working_items.pop(0)
subclasses.add(item)
working_items.extend(item.__subclasses__())
return subclasses
@classmethod
def check(cls):
cls.subclasses |= cls.discover_subclasses(
cls.BASE_SEARCH_CLASS.__subclasses__()
)
cls.exceptions |= cls.discover_subclasses(cls.exceptions)
success = True
for subclass in cls.subclasses:
if subclass in cls.exceptions:
continue
if not cls.HAS_ATTRIBUTE_TABLE.search(subclass.__doc__):
print(
f"Subclass {subclass.__module__}.{subclass.__name__} is missing a"
" table of common attributes."
)
success = False
for method_name in dir(subclass):
if method_name in cls.METHOD_EXCEPTIONS:
continue
method = getattr(subclass, method_name)
if (
callable(method) or isinstance(method, cachedproperty)
) and not method_name.startswith("_"):
if isinstance(method, cachedproperty):
method = method.func
if not cls.HAS_CODE_BLOCK.search(method.__doc__):
print(
"Method"
f" {subclass.__module__}.{subclass.__name__}.{method.__name__}"
" is missing code examples."
)
success = False
return success
def main():
return int(not DocumentationChecker.check())
if __name__ == "__main__":
sys.exit(main())