make_module_ignores.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. from __future__ import annotations
  2. import os
  3. import re
  4. import shutil
  5. import subprocess
  6. import sys
  7. ERROR_RE = re.compile(r".*error:.*\[([^]]+)\]$")
  8. def main() -> int:
  9. shutil.rmtree(".mypy_cache", ignore_errors=True)
  10. codes = set()
  11. filenames = set()
  12. out = subprocess.run(
  13. (sys.executable, "-m", "tools.mypy_helpers.mypy_without_ignores", *sys.argv[1:]),
  14. capture_output=True,
  15. )
  16. for line in out.stdout.decode().splitlines():
  17. filename, _, _ = line.partition(":")
  18. if filename.endswith(".py"):
  19. filenames.add(filename)
  20. match = ERROR_RE.match(line)
  21. if match is not None:
  22. codes.add(match[1])
  23. os.makedirs(".artifacts", exist_ok=True)
  24. with open(".artifacts/mypy-all", "wb") as f:
  25. f.write(out.stdout)
  26. mods = []
  27. for filename in sorted(filenames):
  28. # TODO: removeprefix / removesuffix python 3.9+
  29. if filename.endswith(".py"):
  30. filename = filename[: -len(".py")]
  31. if filename.startswith("src/"):
  32. filename = filename[len("src/") :]
  33. if filename.endswith("/__init__"):
  34. filename = filename[: -len("/__init__")]
  35. mods.append(filename.replace("/", "."))
  36. mods_s = "".join(f' "{mod}",\n' for mod in mods)
  37. codes_s = "".join(f' "{code}",\n' for code in sorted(codes))
  38. generated = (
  39. f"# - remove the module from the list and fix the issues!\n"
  40. f"# - python3 -m tools.mypy_helpers.find_easiest_modules\n"
  41. f"[[tool.mypy.overrides]]\n"
  42. f"module = [\n{mods_s}]\n"
  43. f"disable_error_code = [\n{codes_s}]\n"
  44. )
  45. with open("pyproject.toml") as f:
  46. src = f.read()
  47. msg = "sentry modules with typing issues"
  48. before, begin, rest = src.partition(f"# begin: {msg}\n")
  49. _, end, rest = rest.partition(f"# end: {msg}\n")
  50. with open("pyproject.toml", "w") as f:
  51. f.write(before + begin + generated + end + rest)
  52. # # begin possibly_undefined fixer
  53. shutil.rmtree(".mypy_cache", ignore_errors=True)
  54. codes = set()
  55. filenames = set()
  56. out = subprocess.run(
  57. (
  58. sys.executable,
  59. "-m",
  60. "tools.mypy_helpers.mypy_without_ignore_possibly_undefined",
  61. *sys.argv[1:],
  62. ),
  63. capture_output=True,
  64. )
  65. for line in out.stdout.decode().splitlines():
  66. filename, _, _ = line.partition(":")
  67. if filename.endswith(".py"):
  68. filenames.add(filename)
  69. if match is not None:
  70. codes.add(match[1])
  71. os.makedirs(".artifacts", exist_ok=True)
  72. with open(".artifacts/mypy-all", "wb") as f:
  73. f.write(out.stdout)
  74. mods = []
  75. for filename in sorted(filenames):
  76. # TODO: removeprefix / removesuffix python 3.9+
  77. if filename.endswith(".py"):
  78. filename = filename[: -len(".py")]
  79. if filename.startswith("src/"):
  80. filename = filename[len("src/") :]
  81. if filename.endswith("/__init__"):
  82. filename = filename[: -len("/__init__")]
  83. mods.append(filename.replace("/", "."))
  84. mods_s = "".join(f' "{mod}",\n' for mod in mods)
  85. generated = f"[[tool.mypy.overrides]]\n" f"module = [\n{mods_s}]\n"
  86. with open("pyproject.toml") as f:
  87. src = f.read()
  88. msg = "sentry modules with possibly undefined variables"
  89. before, begin, rest = src.partition(f"# begin: {msg}\n")
  90. _, end, rest = rest.partition(f"# end: {msg}\n")
  91. with open("pyproject.toml", "w") as f:
  92. f.write(before + begin + generated + end + rest)
  93. return 0
  94. if __name__ == "__main__":
  95. raise SystemExit(main())