# retoor import ast import re import sys from pathlib import Path PKG_ROOT = Path(__file__).resolve().parent REPO_ROOT = PKG_ROOT.parent BREAKPOINTS = {360, 480, 768, 1024} HTTP_CLIENT_ALLOWLIST = {"molodetz/stealth.py", "molodetz/curl_transport.py"} CLIENT_RENDER_ALLOWLIST = {"molodetz/templates/admin/post_form.html"} LOADING_BUTTON_MODULE = "molodetz/static/js/utils/LoadingButton.js" _DASH_ENTITIES = ["&" + name + ";" for name in ("m" + "dash", "n" + "dash", "#8212", "#8211", "#x2014", "#x2013")] DASH_PATTERN = re.compile("|".join(["\u2014", "\u2013", *_DASH_ENTITIES]), re.IGNORECASE) DASH_SUFFIXES = {".py", ".html", ".md", ".js", ".css", ".toml", ".txt", ".sh", ".cfg", ".ini"} DASH_EXEMPT_DIRS = ("molodetz/static/vendor", "molodetz/static/js/generated") def _rel(path): return path.resolve().relative_to(REPO_ROOT).as_posix() def _files(base, pattern): return sorted((REPO_ROOT / base).rglob(pattern)) def gate_template_environment(): offenders = set() for path in _files("molodetz", "*.py"): text = path.read_text(encoding="utf-8") if re.search(r"\b(Jinja2Templates|Environment)\(", text) and _rel(path) != "molodetz/templating.py": offenders.add(_rel(path)) return offenders def gate_breakpoints(): found = set() for path in _files("molodetz/static/css", "*.css"): for match in re.finditer(r"@media[^{]*\((?:max|min)-width:\s*(\d+)px\)", path.read_text(encoding="utf-8")): found.add(int(match.group(1))) return found def gate_http_clients(): found = set() pattern = re.compile(r"\b(httpx\.(Async)?Client|AsyncSession|aiohttp\.ClientSession|urllib\.request\.urlopen)\(") for path in _files("molodetz", "*.py"): if pattern.search(path.read_text(encoding="utf-8")): found.add(_rel(path)) return found def gate_client_render_templates(): found = set() for path in _files("molodetz/templates", "*.html"): if "/templates/docs/" in path.as_posix(): continue if re.search(r"