|
8 | 8 |
|
9 | 9 | whitespace_rules = [
|
10 | 10 | # This linter should be first since bash_rules depends on it.
|
11 |
| - {'pattern': r'\s+$', |
12 |
| - 'strip': '\n', |
13 |
| - 'description': 'Fix trailing whitespace'}, |
14 |
| - {'pattern': '\t', |
15 |
| - 'strip': '\n', |
16 |
| - 'description': 'Fix tab-based whitespace'}, |
| 11 | + {"pattern": r"\s+$", "strip": "\n", "description": "Fix trailing whitespace"}, |
| 12 | + {"pattern": "\t", "strip": "\n", "description": "Fix tab-based whitespace"}, |
17 | 13 | ] # type: List[Rule]
|
18 | 14 |
|
19 |
| -markdown_whitespace_rules = list([rule for rule in whitespace_rules if rule['pattern'] != r'\s+$']) + [ |
| 15 | +markdown_whitespace_rules = list( |
| 16 | + [rule for rule in whitespace_rules if rule["pattern"] != r"\s+$"] |
| 17 | +) + [ |
20 | 18 | # Two spaces trailing a line with other content is okay--it's a markdown line break.
|
21 | 19 | # This rule finds one space trailing a non-space, three or more trailing spaces, and
|
22 | 20 | # spaces on an empty line.
|
23 |
| - {'pattern': r'((?<!\s)\s$)|(\s\s\s+$)|(^\s+$)', |
24 |
| - 'strip': '\n', |
25 |
| - 'description': 'Fix trailing whitespace'}, |
26 |
| - {'pattern': r'^#+[A-Za-z0-9]', |
27 |
| - 'strip': '\n', |
28 |
| - 'description': 'Missing space after # in heading'}, |
| 21 | + { |
| 22 | + "pattern": r"((?<!\s)\s$)|(\s\s\s+$)|(^\s+$)", |
| 23 | + "strip": "\n", |
| 24 | + "description": "Fix trailing whitespace", |
| 25 | + }, |
| 26 | + { |
| 27 | + "pattern": r"^#+[A-Za-z0-9]", |
| 28 | + "strip": "\n", |
| 29 | + "description": "Missing space after # in heading", |
| 30 | + }, |
29 | 31 | ]
|
30 | 32 |
|
31 | 33 | python_rules = RuleList(
|
32 |
| - langs=['py'], |
| 34 | + langs=["py"], |
33 | 35 | rules=[
|
34 |
| - {'pattern': r'".*"%\([a-z_].*\)?$', |
35 |
| - 'description': 'Missing space around "%"'}, |
36 |
| - {'pattern': r"'.*'%\([a-z_].*\)?$", |
37 |
| - 'description': 'Missing space around "%"'}, |
| 36 | + {"pattern": r'".*"%\([a-z_].*\)?$', "description": 'Missing space around "%"'}, |
| 37 | + {"pattern": r"'.*'%\([a-z_].*\)?$", "description": 'Missing space around "%"'}, |
38 | 38 | # This rule is constructed with + to avoid triggering on itself
|
39 |
| - {'pattern': r" =" + r'[^ =>~"]', |
40 |
| - 'description': 'Missing whitespace after "="'}, |
41 |
| - {'pattern': r'":\w[^"]*$', |
42 |
| - 'description': 'Missing whitespace after ":"'}, |
43 |
| - {'pattern': r"':\w[^']*$", |
44 |
| - 'description': 'Missing whitespace after ":"'}, |
45 |
| - {'pattern': r"^\s+[#]\w", |
46 |
| - 'strip': '\n', |
47 |
| - 'description': 'Missing whitespace after "#"'}, |
48 |
| - {'pattern': r"assertEquals[(]", |
49 |
| - 'description': 'Use assertEqual, not assertEquals (which is deprecated).'}, |
50 |
| - {'pattern': r'self: Any', |
51 |
| - 'description': 'you can omit Any annotation for self', |
52 |
| - 'good_lines': ['def foo (self):'], |
53 |
| - 'bad_lines': ['def foo(self: Any):']}, |
54 |
| - {'pattern': r"== None", |
55 |
| - 'description': 'Use `is None` to check whether something is None'}, |
56 |
| - {'pattern': r"type:[(]", |
57 |
| - 'description': 'Missing whitespace after ":" in type annotation'}, |
58 |
| - {'pattern': r"# type [(]", |
59 |
| - 'description': 'Missing : after type in type annotation'}, |
60 |
| - {'pattern': r"#type", |
61 |
| - 'description': 'Missing whitespace after "#" in type annotation'}, |
62 |
| - {'pattern': r'if[(]', |
63 |
| - 'description': 'Missing space between if and ('}, |
64 |
| - {'pattern': r", [)]", |
65 |
| - 'description': 'Unnecessary whitespace between "," and ")"'}, |
66 |
| - {'pattern': r"% [(]", |
67 |
| - 'description': 'Unnecessary whitespace between "%" and "("'}, |
| 39 | + {"pattern": r" =" + r'[^ =>~"]', "description": 'Missing whitespace after "="'}, |
| 40 | + {"pattern": r'":\w[^"]*$', "description": 'Missing whitespace after ":"'}, |
| 41 | + {"pattern": r"':\w[^']*$", "description": 'Missing whitespace after ":"'}, |
| 42 | + {"pattern": r"^\s+[#]\w", "strip": "\n", "description": 'Missing whitespace after "#"'}, |
| 43 | + { |
| 44 | + "pattern": r"assertEquals[(]", |
| 45 | + "description": "Use assertEqual, not assertEquals (which is deprecated).", |
| 46 | + }, |
| 47 | + { |
| 48 | + "pattern": r"self: Any", |
| 49 | + "description": "you can omit Any annotation for self", |
| 50 | + "good_lines": ["def foo (self):"], |
| 51 | + "bad_lines": ["def foo(self: Any):"], |
| 52 | + }, |
| 53 | + {"pattern": r"== None", "description": "Use `is None` to check whether something is None"}, |
| 54 | + {"pattern": r"type:[(]", "description": 'Missing whitespace after ":" in type annotation'}, |
| 55 | + {"pattern": r"# type [(]", "description": "Missing : after type in type annotation"}, |
| 56 | + {"pattern": r"#type", "description": 'Missing whitespace after "#" in type annotation'}, |
| 57 | + {"pattern": r"if[(]", "description": "Missing space between if and ("}, |
| 58 | + {"pattern": r", [)]", "description": 'Unnecessary whitespace between "," and ")"'}, |
| 59 | + {"pattern": r"% [(]", "description": 'Unnecessary whitespace between "%" and "("'}, |
68 | 60 | # This next check could have false positives, but it seems pretty
|
69 | 61 | # rare; if we find any, they can be added to the exclude list for
|
70 | 62 | # this rule.
|
71 |
| - {'pattern': r' % [a-zA-Z0-9_.]*\)?$', |
72 |
| - 'description': 'Used % comprehension without a tuple'}, |
73 |
| - {'pattern': r'.*%s.* % \([a-zA-Z0-9_.]*\)$', |
74 |
| - 'description': 'Used % comprehension without a tuple'}, |
75 |
| - {'pattern': r'__future__', |
76 |
| - 'include_only': {'zulip_bots/zulip_bots/bots/'}, |
77 |
| - 'description': 'Bots no longer need __future__ imports.'}, |
78 |
| - {'pattern': r'#!/usr/bin/env python$', |
79 |
| - 'include_only': {'zulip_bots/'}, |
80 |
| - 'description': 'Python shebangs must be python3'}, |
81 |
| - {'pattern': r'(^|\s)open\s*\(', |
82 |
| - 'description': 'open() should not be used in Zulip\'s bots. Use functions' |
83 |
| - ' provided by the bots framework to access the filesystem.', |
84 |
| - 'include_only': {'zulip_bots/zulip_bots/bots/'}}, |
85 |
| - {'pattern': r'pprint', |
86 |
| - 'description': 'Used pprint, which is most likely a debugging leftover. For user output, use print().'}, |
87 |
| - {'pattern': r'\(BotTestCase\)', |
88 |
| - 'bad_lines': ['class TestSomeBot(BotTestCase):'], |
89 |
| - 'description': 'Bot test cases should directly inherit from BotTestCase *and* DefaultTests.'}, |
90 |
| - {'pattern': r'\(DefaultTests, BotTestCase\)', |
91 |
| - 'bad_lines': ['class TestSomeBot(DefaultTests, BotTestCase):'], |
92 |
| - 'good_lines': ['class TestSomeBot(BotTestCase, DefaultTests):'], |
93 |
| - 'description': 'Bot test cases should inherit from BotTestCase before DefaultTests.'}, |
| 63 | + { |
| 64 | + "pattern": r" % [a-zA-Z0-9_.]*\)?$", |
| 65 | + "description": "Used % comprehension without a tuple", |
| 66 | + }, |
| 67 | + { |
| 68 | + "pattern": r".*%s.* % \([a-zA-Z0-9_.]*\)$", |
| 69 | + "description": "Used % comprehension without a tuple", |
| 70 | + }, |
| 71 | + { |
| 72 | + "pattern": r"__future__", |
| 73 | + "include_only": {"zulip_bots/zulip_bots/bots/"}, |
| 74 | + "description": "Bots no longer need __future__ imports.", |
| 75 | + }, |
| 76 | + { |
| 77 | + "pattern": r"#!/usr/bin/env python$", |
| 78 | + "include_only": {"zulip_bots/"}, |
| 79 | + "description": "Python shebangs must be python3", |
| 80 | + }, |
| 81 | + { |
| 82 | + "pattern": r"(^|\s)open\s*\(", |
| 83 | + "description": "open() should not be used in Zulip's bots. Use functions" |
| 84 | + " provided by the bots framework to access the filesystem.", |
| 85 | + "include_only": {"zulip_bots/zulip_bots/bots/"}, |
| 86 | + }, |
| 87 | + { |
| 88 | + "pattern": r"pprint", |
| 89 | + "description": "Used pprint, which is most likely a debugging leftover. For user output, use print().", |
| 90 | + }, |
| 91 | + { |
| 92 | + "pattern": r"\(BotTestCase\)", |
| 93 | + "bad_lines": ["class TestSomeBot(BotTestCase):"], |
| 94 | + "description": "Bot test cases should directly inherit from BotTestCase *and* DefaultTests.", |
| 95 | + }, |
| 96 | + { |
| 97 | + "pattern": r"\(DefaultTests, BotTestCase\)", |
| 98 | + "bad_lines": ["class TestSomeBot(DefaultTests, BotTestCase):"], |
| 99 | + "good_lines": ["class TestSomeBot(BotTestCase, DefaultTests):"], |
| 100 | + "description": "Bot test cases should inherit from BotTestCase before DefaultTests.", |
| 101 | + }, |
94 | 102 | *whitespace_rules,
|
95 | 103 | ],
|
96 | 104 | max_length=140,
|
97 | 105 | )
|
98 | 106 |
|
99 | 107 | bash_rules = RuleList(
|
100 |
| - langs=['sh'], |
| 108 | + langs=["sh"], |
101 | 109 | rules=[
|
102 |
| - {'pattern': r'#!.*sh [-xe]', |
103 |
| - 'description': 'Fix shebang line with proper call to /usr/bin/env for Bash path, change -x|-e switches' |
104 |
| - ' to set -x|set -e'}, |
| 110 | + { |
| 111 | + "pattern": r"#!.*sh [-xe]", |
| 112 | + "description": "Fix shebang line with proper call to /usr/bin/env for Bash path, change -x|-e switches" |
| 113 | + " to set -x|set -e", |
| 114 | + }, |
105 | 115 | *whitespace_rules[0:1],
|
106 | 116 | ],
|
107 | 117 | )
|
108 | 118 |
|
109 | 119 |
|
110 | 120 | json_rules = RuleList(
|
111 |
| - langs=['json'], |
| 121 | + langs=["json"], |
112 | 122 | # Here, we don't check tab-based whitespace, because the tab-based
|
113 | 123 | # whitespace rule flags a lot of third-party JSON fixtures
|
114 | 124 | # under zerver/webhooks that we want preserved verbatim. So
|
115 | 125 | # we just include the trailing whitespace rule and a modified
|
116 | 126 | # version of the tab-based whitespace rule (we can't just use
|
117 | 127 | # exclude in whitespace_rules, since we only want to ignore
|
118 | 128 | # JSON files with tab-based whitespace, not webhook code).
|
119 |
| - rules= whitespace_rules[0:1], |
| 129 | + rules=whitespace_rules[0:1], |
120 | 130 | )
|
121 | 131 |
|
122 | 132 | prose_style_rules = [
|
123 |
| - {'pattern': r'[^\/\#\-"]([jJ]avascript)', # exclude usage in hrefs/divs |
124 |
| - 'description': "javascript should be spelled JavaScript"}, |
125 |
| - {'pattern': r'''[^\/\-\."'\_\=\>]([gG]ithub)[^\.\-\_"\<]''', # exclude usage in hrefs/divs |
126 |
| - 'description': "github should be spelled GitHub"}, |
127 |
| - {'pattern': r'[oO]rganisation', # exclude usage in hrefs/divs |
128 |
| - 'description': "Organization is spelled with a z"}, |
129 |
| - {'pattern': r'!!! warning', |
130 |
| - 'description': "!!! warning is invalid; it's spelled '!!! warn'"}, |
131 |
| - {'pattern': r'[^-_]botserver(?!rc)|bot server', |
132 |
| - 'description': "Use Botserver instead of botserver or Botserver."}, |
| 133 | + { |
| 134 | + "pattern": r'[^\/\#\-"]([jJ]avascript)', # exclude usage in hrefs/divs |
| 135 | + "description": "javascript should be spelled JavaScript", |
| 136 | + }, |
| 137 | + { |
| 138 | + "pattern": r"""[^\/\-\."'\_\=\>]([gG]ithub)[^\.\-\_"\<]""", # exclude usage in hrefs/divs |
| 139 | + "description": "github should be spelled GitHub", |
| 140 | + }, |
| 141 | + { |
| 142 | + "pattern": r"[oO]rganisation", # exclude usage in hrefs/divs |
| 143 | + "description": "Organization is spelled with a z", |
| 144 | + }, |
| 145 | + {"pattern": r"!!! warning", "description": "!!! warning is invalid; it's spelled '!!! warn'"}, |
| 146 | + { |
| 147 | + "pattern": r"[^-_]botserver(?!rc)|bot server", |
| 148 | + "description": "Use Botserver instead of botserver or Botserver.", |
| 149 | + }, |
133 | 150 | ] # type: List[Rule]
|
134 | 151 |
|
135 | 152 | markdown_docs_length_exclude = {
|
136 | 153 | "zulip_bots/zulip_bots/bots/converter/doc.md",
|
137 | 154 | }
|
138 | 155 |
|
139 | 156 | markdown_rules = RuleList(
|
140 |
| - langs=['md'], |
| 157 | + langs=["md"], |
141 | 158 | rules=[
|
142 | 159 | *markdown_whitespace_rules,
|
143 | 160 | *prose_style_rules,
|
144 |
| - {'pattern': r'\[(?P<url>[^\]]+)\]\((?P=url)\)', |
145 |
| - 'description': 'Linkified markdown URLs should use cleaner <http://example.com> syntax.'} |
| 161 | + { |
| 162 | + "pattern": r"\[(?P<url>[^\]]+)\]\((?P=url)\)", |
| 163 | + "description": "Linkified markdown URLs should use cleaner <http://example.com> syntax.", |
| 164 | + }, |
146 | 165 | ],
|
147 | 166 | max_length=120,
|
148 | 167 | length_exclude=markdown_docs_length_exclude,
|
149 | 168 | )
|
150 | 169 |
|
151 | 170 | txt_rules = RuleList(
|
152 |
| - langs=['txt'], |
| 171 | + langs=["txt"], |
153 | 172 | rules=whitespace_rules,
|
154 | 173 | )
|
155 | 174 |
|
|
0 commit comments