mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-20 19:52:23 +02:00
82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
"""Check infrastructure: shared filter/match utilities."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import fnmatch
|
|
import os
|
|
from pathlib import Path
|
|
|
|
LINTIGNORE_PREFIX = ".lintignore"
|
|
|
|
|
|
class CheckError(Exception):
|
|
"""Raised when a check could not complete (missing tool, timeout, crash).
|
|
|
|
Distinct from "ran and found zero problems": the orchestrator surfaces this
|
|
loudly so a partial run is never silently reported as a clean one (returning
|
|
[] on failure made a timed-out/crashed tool look identical to a passing one).
|
|
"""
|
|
|
|
def __init__(self, reason: str) -> None:
|
|
super().__init__(reason)
|
|
self.reason = reason
|
|
|
|
|
|
def _matches_any(text: str, patterns: list[str]) -> bool:
|
|
return any(fnmatch.fnmatch(text, p) for p in patterns)
|
|
|
|
|
|
def is_excluded(path: Path, root: Path, excludes: list[str]) -> bool:
|
|
rel = path.relative_to(root)
|
|
for part in rel.parts:
|
|
if _matches_any(part, excludes):
|
|
return True
|
|
return _matches_any(str(rel), excludes)
|
|
|
|
|
|
def is_excepted(rel_path: str, rule: str, exceptions: dict[str, list[str]]) -> bool:
|
|
return _matches_any(rel_path, exceptions.get(rule, []))
|
|
|
|
|
|
def collect_lintignores(root: Path, excludes: list[str]) -> dict[Path, set[str]]:
|
|
"""Scan *root* for ``.lintignore*`` sentinel files.
|
|
|
|
Returns ``{directory: set_of_ignored_rules}``.
|
|
The special token ``"__all__"`` means every rule is ignored.
|
|
"""
|
|
ignores: dict[Path, set[str]] = {}
|
|
for dirpath_str, dirnames, filenames in os.walk(root):
|
|
dp = Path(dirpath_str)
|
|
if is_excluded(dp, root, excludes):
|
|
dirnames.clear()
|
|
continue
|
|
for fname in filenames:
|
|
if fname == LINTIGNORE_PREFIX:
|
|
ignores.setdefault(dp, set()).add("__all__")
|
|
elif fname.startswith(f"{LINTIGNORE_PREFIX}-"):
|
|
rule = fname[len(LINTIGNORE_PREFIX) + 1 :]
|
|
ignores.setdefault(dp, set()).add(rule)
|
|
return ignores
|
|
|
|
|
|
def is_lintignored(
|
|
path: Path,
|
|
root: Path,
|
|
rule: str,
|
|
ignores: dict[Path, set[str]],
|
|
) -> bool:
|
|
"""Return True if *path* is covered by a ``.lintignore`` file for *rule*.
|
|
|
|
Walks from *path* up to *root* checking each ancestor directory.
|
|
"""
|
|
current = path if path.is_dir() else path.parent
|
|
root = root.resolve()
|
|
while True:
|
|
rules = ignores.get(current)
|
|
if rules and ("__all__" in rules or rule in rules):
|
|
return True
|
|
if current == root:
|
|
break
|
|
current = current.parent
|
|
return False
|