check_stronglist.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import argparse
  2. import glob
  3. import os.path
  4. import re
  5. from collections.abc import Sequence
  6. import tomllib
  7. def _glob_to_re(s: str) -> str:
  8. if s.endswith(".*"):
  9. pat = rf'{re.escape(s.removesuffix(".*"))}(?:|\..*+)'
  10. else:
  11. pat = re.escape(s)
  12. return f"^{pat}$"
  13. def main(argv: Sequence[str] | None = None) -> int:
  14. parser = argparse.ArgumentParser()
  15. parser.add_argument("filenames", nargs="*")
  16. args = parser.parse_args(argv)
  17. retv = 0
  18. for filename in args.filenames:
  19. reldir = os.path.dirname(os.path.abspath(filename))
  20. with open(filename, "rb") as f:
  21. overrides = tomllib.load(f)["tool"]["mypy"]["overrides"]
  22. (allowlist,) = (cfg for cfg in overrides if "disable_error_code" in cfg)
  23. (stronglist,) = (cfg for cfg in overrides if "disallow_untyped_defs" in cfg)
  24. stronglist_re = re.compile("|".join(_glob_to_re(g) for g in stronglist["module"]))
  25. for mod in allowlist["module"]:
  26. if stronglist_re.fullmatch(mod):
  27. print(f"{filename}: {mod} is in the typing errors allowlist *and* stronglist")
  28. retv = 1
  29. for pat in stronglist["module"]:
  30. orig_pat = pat
  31. firstmod = pat.split(".")[0]
  32. if os.path.exists(os.path.join(reldir, "src", firstmod)):
  33. pat = f"src.{pat}"
  34. pat = pat.replace(".", "/")
  35. if pat.endswith("*"):
  36. if glob.glob(os.path.join(reldir, pat)):
  37. continue
  38. elif os.path.exists(os.path.join(reldir, f"{pat}.py")):
  39. continue
  40. elif os.path.exists(os.path.join(reldir, pat, "__init__.py")):
  41. continue
  42. print(f"{filename}: {orig_pat} in stronglist does not match any files!")
  43. retv = 1
  44. return retv
  45. if __name__ == "__main__":
  46. raise SystemExit(main())