zulip/tools/check-templates

179 lines
5.9 KiB
Plaintext
Raw Normal View History

#!/usr/bin/env python3
import argparse
import logging
import os
import sys
2016-08-02 00:14:01 +02:00
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
# check for the venv
from tools.lib import sanity_check
sanity_check.check_venv(__file__)
linter_lib: Fix mypy errors. tools/linter_lib/pyflakes.py:35: error: Argument 3 to "run_pyflakes" has incompatible type "List[Tuple[bytes, bytes]]"; expected "List[Tuple[str, str]]" tools/linter_lib/custom_check.py:110: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:214: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:214: error: Argument "shebang_rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:502: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:502: error: Argument "shebang_rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:519: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:706: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:728: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:738: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:779: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:779: error: Argument "length_exclude" to "RuleList" has incompatible type "Set[str]"; expected "List[str]" tools/linter_lib/custom_check.py:803: error: Argument "length_exclude" to "RuleList" has incompatible type "Set[str]"; expected "List[str]" tools/linter_lib/custom_check.py:805: error: Unsupported operand types for + ("List[Rule]" and "List[Dict[str, Any]]") tools/linter_lib/custom_check.py:819: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" These were missed the `zulint` package was missing PEP 561 type annotation markers, and if it’d had them, mypy daemon mode would’ve required us to set `follow_imports = skip` for it. Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-08-07 03:29:33 +02:00
from typing import Dict, Iterable, List
from zulint import lister
from tools.lib.html_branches import build_id_dict
from tools.lib.pretty_print import validate_indent_html
from tools.lib.template_parser import validate
EXCLUDED_FILES = [
## Test data Files for testing modules in tests
"tools/tests/test_template_data",
# Our parser doesn't handle the way its conditionals are layered
"templates/zerver/emails/missed_message.source.html",
# Previously unchecked and our parser doesn't like its indentation
"static/assets/icons/template.hbs",
# The parser does not like the indentation of custom ReadTheDocs templates
"docs/_templates/layout.html",
]
def check_our_files(modified_only: bool, all_dups: bool, fix: bool, targets: List[str]) -> None:
linter_lib: Fix mypy errors. tools/linter_lib/pyflakes.py:35: error: Argument 3 to "run_pyflakes" has incompatible type "List[Tuple[bytes, bytes]]"; expected "List[Tuple[str, str]]" tools/linter_lib/custom_check.py:110: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:214: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:214: error: Argument "shebang_rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:502: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:502: error: Argument "shebang_rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:519: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:706: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:728: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:738: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:779: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:779: error: Argument "length_exclude" to "RuleList" has incompatible type "Set[str]"; expected "List[str]" tools/linter_lib/custom_check.py:803: error: Argument "length_exclude" to "RuleList" has incompatible type "Set[str]"; expected "List[str]" tools/linter_lib/custom_check.py:805: error: Unsupported operand types for + ("List[Rule]" and "List[Dict[str, Any]]") tools/linter_lib/custom_check.py:819: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" These were missed the `zulint` package was missing PEP 561 type annotation markers, and if it’d had them, mypy daemon mode would’ve required us to set `follow_imports = skip` for it. Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-08-07 03:29:33 +02:00
by_lang = lister.list_files(
targets=targets,
modified_only=args.modified,
ftypes=["hbs", "html"],
group_by_ftype=True,
exclude=EXCLUDED_FILES,
linter_lib: Fix mypy errors. tools/linter_lib/pyflakes.py:35: error: Argument 3 to "run_pyflakes" has incompatible type "List[Tuple[bytes, bytes]]"; expected "List[Tuple[str, str]]" tools/linter_lib/custom_check.py:110: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:214: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:214: error: Argument "shebang_rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:502: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:502: error: Argument "shebang_rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:519: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:706: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:728: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:738: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:779: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" tools/linter_lib/custom_check.py:779: error: Argument "length_exclude" to "RuleList" has incompatible type "Set[str]"; expected "List[str]" tools/linter_lib/custom_check.py:803: error: Argument "length_exclude" to "RuleList" has incompatible type "Set[str]"; expected "List[str]" tools/linter_lib/custom_check.py:805: error: Unsupported operand types for + ("List[Rule]" and "List[Dict[str, Any]]") tools/linter_lib/custom_check.py:819: error: Argument "rules" to "RuleList" has incompatible type "List[Dict[str, Any]]"; expected "List[Rule]" These were missed the `zulint` package was missing PEP 561 type annotation markers, and if it’d had them, mypy daemon mode would’ve required us to set `follow_imports = skip` for it. Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-08-07 03:29:33 +02:00
)
check_handlebar_templates(by_lang["hbs"], fix)
check_html_templates(by_lang["html"], all_dups, fix)
def check_html_templates(templates: Iterable[str], all_dups: bool, fix: bool) -> None:
# Our files with .html extensions are usually for Django, but we also
# have a few static .html files.
logging.basicConfig(format="%(levelname)s:%(message)s")
templates = sorted(fn for fn in templates)
# Use of lodash templates <%= %>.
if "templates/zerver/team.html" in templates:
templates.remove("templates/zerver/team.html")
def check_for_duplicate_ids(templates: List[str]) -> Dict[str, List[str]]:
template_id_dict = build_id_dict(templates)
# TODO: Clean up these cases of duplicate ids in the code
IGNORE_IDS = [
"api-example-tabs",
"errors",
"error-message-box",
"email",
"messages",
"registration",
"pw_strength",
"id_password",
"top_navbar",
"id_email",
"id_terms",
"logout_form",
"send_confirm",
"register",
"footer",
"charged_amount",
"change-plan-status",
# Temporary while we have searchbox forked
"search_exit",
"search_query",
"message_view_header",
"search_arrows",
"searchbox_form",
"searchbox",
]
bad_ids_dict = {
ids: fns
for ids, fns in template_id_dict.items()
if (ids not in IGNORE_IDS) and len(fns) > 1
}
if all_dups:
ignorable_ids_dict = {
ids: fns
for ids, fns in template_id_dict.items()
if ids in IGNORE_IDS and len(fns) > 1
}
for ids, fns in ignorable_ids_dict.items():
logging.warning(
"Duplicate ID(s) detected :Id '" + ids + "' present at following files:"
)
for fn in fns:
print(fn)
for ids, fns in bad_ids_dict.items():
logging.error("Duplicate ID(s) detected :Id '" + ids + "' present at following files:")
for fn in fns:
print(fn)
return bad_ids_dict
bad_ids_list = list(check_for_duplicate_ids(templates).keys())
if bad_ids_list:
print("Exiting--please clean up all duplicates before running this again.")
sys.exit(1)
for fn in templates:
# Many of our Django templates have strange indentation. The
# indentation errors are often harmless, even stylistically
# harmless, but they tend to be in files that might be old
# and might eventually require more scrutiny for things like
# localization. See GitHub #1236.
bad_files = [
# These use various whitespace-dependent formatting that
# prevent cleaning them.
"templates/corporate/zephyr-mirror.html",
]
validate(fn=fn, check_indent=(fn not in bad_files))
# Ignore these files since these have not been cleaned yet :/
IGNORE_FILES = [
# zephyr-mirror.html has some whitespace-dependent formatting
# for code blocks that prevent cleaning it. Might make sense
# to convert it to a /help/ Markdown article.
"templates/corporate/zephyr-mirror.html",
]
# TODO: Clean these files
for fn in templates:
if fn not in IGNORE_FILES:
if not validate_indent_html(fn, fix):
sys.exit(1)
def check_handlebar_templates(templates: Iterable[str], fix: bool) -> None:
2016-08-02 00:14:01 +02:00
# Check all our handlebars templates.
templates = [fn for fn in templates if fn.endswith(".hbs")]
IGNORE_FILES = [
# TODO: Add some exclude mechanism for the line-wrapping issue here.
"static/templates/recipient_row.hbs",
]
2016-08-02 00:14:01 +02:00
for fn in templates:
if fn in IGNORE_FILES:
continue
validate(fn=fn, check_indent=True)
2016-08-02 00:14:01 +02:00
for fn in templates:
if fn in IGNORE_FILES:
continue
if not validate_indent_html(fn, fix):
sys.exit(1)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-m", "--modified", action="store_true", help="only check modified files")
parser.add_argument(
"--all-dups",
action="store_true",
help="Run lint tool to detect duplicate ids on ignored files as well",
)
parser.add_argument(
"--fix", action="store_true", help="Automatically fix indentation problems."
)
parser.add_argument("targets", nargs=argparse.REMAINDER)
args = parser.parse_args()
check_our_files(args.modified, args.all_dups, args.fix, args.targets)