mostr-zulip-bot/tools/custom_check.py
Anders Kaseorg 774edb434e ruff: Fix C400 Unnecessary generator (rewrite as a list comprehension).
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-10-29 17:36:51 -07:00

152 lines
5.1 KiB
Python

from typing import List
from zulint.custom_rules import Rule, RuleList
whitespace_rules: List[Rule] = [
# This linter should be first since bash_rules depends on it.
{"pattern": r"[\t ]+$", "description": "Fix trailing whitespace"},
{"pattern": r"\t", "description": "Fix tab-based whitespace"},
]
markdown_whitespace_rules: List[Rule] = [
*(rule for rule in whitespace_rules if rule["pattern"] != r"[\t ]+$"),
# Two spaces trailing a line with other content is okay--it's a markdown line break.
# This rule finds one space trailing a non-space, three or more trailing spaces, and
# spaces on an empty line.
{
"pattern": r"((?<![\t ])[\t ]$)|([\t ][\t ][\t ]+$)|(^[\t ]+$)",
"description": "Fix trailing whitespace",
},
{
"pattern": r"^#+[A-Za-z0-9]",
"description": "Missing space after # in heading",
},
]
python_rules = RuleList(
langs=["py"],
rules=[
{
"pattern": r"assertEquals[(]",
"description": "Use assertEqual, not assertEquals (which is deprecated).",
},
{
"pattern": r"self: Any",
"description": "you can omit Any annotation for self",
"good_lines": ["def foo (self):"],
"bad_lines": ["def foo(self: Any):"],
},
# This next check could have false positives, but it seems pretty
# rare; if we find any, they can be added to the exclude list for
# this rule.
{
"pattern": r" % [a-zA-Z0-9_.]*\)?$",
"description": "Used % comprehension without a tuple",
},
{
"pattern": r".*%s.* % \([a-zA-Z0-9_.]*\)$",
"description": "Used % comprehension without a tuple",
},
{
"pattern": r"__future__",
"include_only": {"zulip_bots/zulip_bots/bots/"},
"description": "Bots no longer need __future__ imports.",
},
{
"pattern": r"#!/usr/bin/env python$",
"include_only": {"zulip_bots/"},
"description": "Python shebangs must be python3",
},
{
"pattern": r"(^|\s)open\s*\(",
"description": "open() should not be used in Zulip's bots. Use functions"
" provided by the bots framework to access the filesystem.",
"include_only": {"zulip_bots/zulip_bots/bots/"},
},
{
"pattern": r"pprint",
"description": "Used pprint, which is most likely a debugging leftover. For user output, use print().",
},
{
"pattern": r"\(BotTestCase\)",
"bad_lines": ["class TestSomeBot(BotTestCase):"],
"description": "Bot test cases should directly inherit from BotTestCase *and* DefaultTests.",
},
{
"pattern": r"\(DefaultTests, BotTestCase\)",
"bad_lines": ["class TestSomeBot(DefaultTests, BotTestCase):"],
"good_lines": ["class TestSomeBot(BotTestCase, DefaultTests):"],
"description": "Bot test cases should inherit from BotTestCase before DefaultTests.",
},
*whitespace_rules,
],
)
bash_rules = RuleList(
langs=["sh"],
rules=[
{
"pattern": r"#!.*sh [-xe]",
"description": "Fix shebang line with proper call to /usr/bin/env for Bash path, change -x|-e switches"
" to set -x|set -e",
},
*whitespace_rules[0:1],
],
)
json_rules = RuleList(
langs=["json"],
# Here, we don't check tab-based whitespace, because the tab-based
# whitespace rule flags a lot of third-party JSON fixtures
# under zerver/webhooks that we want preserved verbatim. So
# we just include the trailing whitespace rule and a modified
# version of the tab-based whitespace rule (we can't just use
# exclude in whitespace_rules, since we only want to ignore
# JSON files with tab-based whitespace, not webhook code).
rules=whitespace_rules[0:1],
)
prose_style_rules: List[Rule] = [
{
"pattern": r'[^\/\#\-"]([jJ]avascript)', # exclude usage in hrefs/divs
"description": "javascript should be spelled JavaScript",
},
{
"pattern": r"""[^\/\-\."'\_\=\>]([gG]ithub)[^\.\-\_"\<]""", # exclude usage in hrefs/divs
"description": "github should be spelled GitHub",
},
{
"pattern": r"[oO]rganisation", # exclude usage in hrefs/divs
"description": "Organization is spelled with a z",
},
{"pattern": r"!!! warning", "description": "!!! warning is invalid; it's spelled '!!! warn'"},
{
"pattern": r"[^-_]botserver(?!rc)|bot server",
"description": "Use Botserver instead of botserver or Botserver.",
},
]
markdown_rules = RuleList(
langs=["md"],
rules=[
*markdown_whitespace_rules,
*prose_style_rules,
{
"pattern": r"\[(?P<url>[^\]]+)\]\((?P=url)\)",
"description": "Linkified markdown URLs should use cleaner <http://example.com> syntax.",
},
],
)
txt_rules = RuleList(
langs=["txt"],
rules=whitespace_rules,
)
non_py_rules = [
json_rules,
markdown_rules,
bash_rules,
txt_rules,
]