options.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. from __future__ import annotations
  2. import pprint
  3. import re
  4. import sys
  5. import sysconfig
  6. from typing import Any, Callable, Final, Mapping, Pattern
  7. from mypy import defaults
  8. from mypy.errorcodes import ErrorCode, error_codes
  9. from mypy.util import get_class_descriptors, replace_object_state
  10. class BuildType:
  11. STANDARD: Final = 0
  12. MODULE: Final = 1
  13. PROGRAM_TEXT: Final = 2
  14. PER_MODULE_OPTIONS: Final = {
  15. # Please keep this list sorted
  16. "allow_redefinition",
  17. "allow_untyped_globals",
  18. "always_false",
  19. "always_true",
  20. "check_untyped_defs",
  21. "debug_cache",
  22. "disable_error_code",
  23. "disabled_error_codes",
  24. "disallow_any_decorated",
  25. "disallow_any_explicit",
  26. "disallow_any_expr",
  27. "disallow_any_generics",
  28. "disallow_any_unimported",
  29. "disallow_incomplete_defs",
  30. "disallow_subclassing_any",
  31. "disallow_untyped_calls",
  32. "disallow_untyped_decorators",
  33. "disallow_untyped_defs",
  34. "enable_error_code",
  35. "enabled_error_codes",
  36. "extra_checks",
  37. "follow_imports_for_stubs",
  38. "follow_imports",
  39. "ignore_errors",
  40. "ignore_missing_imports",
  41. "implicit_optional",
  42. "implicit_reexport",
  43. "local_partial_types",
  44. "mypyc",
  45. "strict_concatenate",
  46. "strict_equality",
  47. "strict_optional",
  48. "warn_no_return",
  49. "warn_return_any",
  50. "warn_unreachable",
  51. "warn_unused_ignores",
  52. }
  53. OPTIONS_AFFECTING_CACHE: Final = (
  54. PER_MODULE_OPTIONS
  55. | {
  56. "platform",
  57. "bazel",
  58. "plugins",
  59. "disable_bytearray_promotion",
  60. "disable_memoryview_promotion",
  61. }
  62. ) - {"debug_cache"}
  63. # Features that are currently incomplete/experimental
  64. TYPE_VAR_TUPLE: Final = "TypeVarTuple"
  65. UNPACK: Final = "Unpack"
  66. INCOMPLETE_FEATURES: Final = frozenset((TYPE_VAR_TUPLE, UNPACK))
  67. class Options:
  68. """Options collected from flags."""
  69. def __init__(self) -> None:
  70. # Cache for clone_for_module()
  71. self._per_module_cache: dict[str, Options] | None = None
  72. # -- build options --
  73. self.build_type = BuildType.STANDARD
  74. self.python_version: tuple[int, int] = sys.version_info[:2]
  75. # The executable used to search for PEP 561 packages. If this is None,
  76. # then mypy does not search for PEP 561 packages.
  77. self.python_executable: str | None = sys.executable
  78. # When cross compiling to emscripten, we need to rely on MACHDEP because
  79. # sys.platform is the host build platform, not emscripten.
  80. MACHDEP = sysconfig.get_config_var("MACHDEP")
  81. if MACHDEP == "emscripten":
  82. self.platform = MACHDEP
  83. else:
  84. self.platform = sys.platform
  85. self.custom_typing_module: str | None = None
  86. self.custom_typeshed_dir: str | None = None
  87. # The abspath() version of the above, we compute it once as an optimization.
  88. self.abs_custom_typeshed_dir: str | None = None
  89. self.mypy_path: list[str] = []
  90. self.report_dirs: dict[str, str] = {}
  91. # Show errors in PEP 561 packages/site-packages modules
  92. self.no_silence_site_packages = False
  93. self.no_site_packages = False
  94. self.ignore_missing_imports = False
  95. # Is ignore_missing_imports set in a per-module section
  96. self.ignore_missing_imports_per_module = False
  97. self.follow_imports = "normal" # normal|silent|skip|error
  98. # Whether to respect the follow_imports setting even for stub files.
  99. # Intended to be used for disabling specific stubs.
  100. self.follow_imports_for_stubs = False
  101. # PEP 420 namespace packages
  102. # This allows definitions of packages without __init__.py and allows packages to span
  103. # multiple directories. This flag affects both import discovery and the association of
  104. # input files/modules/packages to the relevant file and fully qualified module name.
  105. self.namespace_packages = True
  106. # Use current directory and MYPYPATH to determine fully qualified module names of files
  107. # passed by automatically considering their subdirectories as packages. This is only
  108. # relevant if namespace packages are enabled, since otherwise examining __init__.py's is
  109. # sufficient to determine module names for files. As a possible alternative, add a single
  110. # top-level __init__.py to your packages.
  111. self.explicit_package_bases = False
  112. # File names, directory names or subpaths to avoid checking
  113. self.exclude: list[str] = []
  114. # disallow_any options
  115. self.disallow_any_generics = False
  116. self.disallow_any_unimported = False
  117. self.disallow_any_expr = False
  118. self.disallow_any_decorated = False
  119. self.disallow_any_explicit = False
  120. # Disallow calling untyped functions from typed ones
  121. self.disallow_untyped_calls = False
  122. # Disallow defining untyped (or incompletely typed) functions
  123. self.disallow_untyped_defs = False
  124. # Disallow defining incompletely typed functions
  125. self.disallow_incomplete_defs = False
  126. # Type check unannotated functions
  127. self.check_untyped_defs = False
  128. # Disallow decorating typed functions with untyped decorators
  129. self.disallow_untyped_decorators = False
  130. # Disallow subclassing values of type 'Any'
  131. self.disallow_subclassing_any = False
  132. # Also check typeshed for missing annotations
  133. self.warn_incomplete_stub = False
  134. # Warn about casting an expression to its inferred type
  135. self.warn_redundant_casts = False
  136. # Warn about falling off the end of a function returning non-None
  137. self.warn_no_return = True
  138. # Warn about returning objects of type Any when the function is
  139. # declared with a precise type
  140. self.warn_return_any = False
  141. # Warn about unused '# type: ignore' comments
  142. self.warn_unused_ignores = False
  143. # Warn about unused '[mypy-<pattern>]' or '[[tool.mypy.overrides]]' config sections
  144. self.warn_unused_configs = False
  145. # Files in which to ignore all non-fatal errors
  146. self.ignore_errors = False
  147. # Apply strict None checking
  148. self.strict_optional = True
  149. # Show "note: In function "foo":" messages.
  150. self.show_error_context = False
  151. # Use nicer output (when possible).
  152. self.color_output = True
  153. self.error_summary = True
  154. # Assume arguments with default values of None are Optional
  155. self.implicit_optional = False
  156. # Don't re-export names unless they are imported with `from ... as ...`
  157. self.implicit_reexport = True
  158. # Suppress toplevel errors caused by missing annotations
  159. self.allow_untyped_globals = False
  160. # Allow variable to be redefined with an arbitrary type in the same block
  161. # and the same nesting level as the initialization
  162. self.allow_redefinition = False
  163. # Prohibit equality, identity, and container checks for non-overlapping types.
  164. # This makes 1 == '1', 1 in ['1'], and 1 is '1' errors.
  165. self.strict_equality = False
  166. # Deprecated, use extra_checks instead.
  167. self.strict_concatenate = False
  168. # Enable additional checks that are technically correct but impractical.
  169. self.extra_checks = False
  170. # Report an error for any branches inferred to be unreachable as a result of
  171. # type analysis.
  172. self.warn_unreachable = False
  173. # Variable names considered True
  174. self.always_true: list[str] = []
  175. # Variable names considered False
  176. self.always_false: list[str] = []
  177. # Error codes to disable
  178. self.disable_error_code: list[str] = []
  179. self.disabled_error_codes: set[ErrorCode] = set()
  180. # Error codes to enable
  181. self.enable_error_code: list[str] = []
  182. self.enabled_error_codes: set[ErrorCode] = set()
  183. # Use script name instead of __main__
  184. self.scripts_are_modules = False
  185. # Config file name
  186. self.config_file: str | None = None
  187. # A filename containing a JSON mapping from filenames to
  188. # mtime/size/hash arrays, used to avoid having to recalculate
  189. # source hashes as often.
  190. self.quickstart_file: str | None = None
  191. # A comma-separated list of files/directories for mypy to type check;
  192. # supports globbing
  193. self.files: list[str] | None = None
  194. # A list of packages for mypy to type check
  195. self.packages: list[str] | None = None
  196. # A list of modules for mypy to type check
  197. self.modules: list[str] | None = None
  198. # Write junit.xml to given file
  199. self.junit_xml: str | None = None
  200. # Caching and incremental checking options
  201. self.incremental = True
  202. self.cache_dir = defaults.CACHE_DIR
  203. self.sqlite_cache = False
  204. self.debug_cache = False
  205. self.skip_version_check = False
  206. self.skip_cache_mtime_checks = False
  207. self.fine_grained_incremental = False
  208. # Include fine-grained dependencies in written cache files
  209. self.cache_fine_grained = False
  210. # Read cache files in fine-grained incremental mode (cache must include dependencies)
  211. self.use_fine_grained_cache = False
  212. # Run tree.serialize() even if cache generation is disabled
  213. self.debug_serialize = False
  214. # Tune certain behaviors when being used as a front-end to mypyc. Set per-module
  215. # in modules being compiled. Not in the config file or command line.
  216. self.mypyc = False
  217. # An internal flag to modify some type-checking logic while
  218. # running inspections (e.g. don't expand function definitions).
  219. # Not in the config file or command line.
  220. self.inspections = False
  221. # Disable the memory optimization of freeing ASTs when
  222. # possible. This isn't exposed as a command line option
  223. # because it is intended for software integrating with
  224. # mypy. (Like mypyc.)
  225. self.preserve_asts = False
  226. # Paths of user plugins
  227. self.plugins: list[str] = []
  228. # Per-module options (raw)
  229. self.per_module_options: dict[str, dict[str, object]] = {}
  230. self._glob_options: list[tuple[str, Pattern[str]]] = []
  231. self.unused_configs: set[str] = set()
  232. # -- development options --
  233. self.verbosity = 0 # More verbose messages (for troubleshooting)
  234. self.pdb = False
  235. self.show_traceback = False
  236. self.raise_exceptions = False
  237. self.dump_type_stats = False
  238. self.dump_inference_stats = False
  239. self.dump_build_stats = False
  240. self.enable_incomplete_features = False # deprecated
  241. self.enable_incomplete_feature: list[str] = []
  242. self.timing_stats: str | None = None
  243. self.line_checking_stats: str | None = None
  244. # -- test options --
  245. # Stop after the semantic analysis phase
  246. self.semantic_analysis_only = False
  247. # Use stub builtins fixtures to speed up tests
  248. self.use_builtins_fixtures = False
  249. # -- experimental options --
  250. self.shadow_file: list[list[str]] | None = None
  251. self.show_column_numbers: bool = False
  252. self.show_error_end: bool = False
  253. self.hide_error_codes = False
  254. self.show_error_code_links = False
  255. # Use soft word wrap and show trimmed source snippets with error location markers.
  256. self.pretty = False
  257. self.dump_graph = False
  258. self.dump_deps = False
  259. self.logical_deps = False
  260. # If True, partial types can't span a module top level and a function
  261. self.local_partial_types = False
  262. # Some behaviors are changed when using Bazel (https://bazel.build).
  263. self.bazel = False
  264. # If True, export inferred types for all expressions as BuildResult.types
  265. self.export_types = False
  266. # List of package roots -- directories under these are packages even
  267. # if they don't have __init__.py.
  268. self.package_root: list[str] = []
  269. self.cache_map: dict[str, tuple[str, str]] = {}
  270. # Don't properly free objects on exit, just kill the current process.
  271. self.fast_exit = True
  272. # fast path for finding modules from source set
  273. self.fast_module_lookup = False
  274. # Allow empty function bodies even if it is not safe, used for testing only.
  275. self.allow_empty_bodies = False
  276. # Used to transform source code before parsing if not None
  277. # TODO: Make the type precise (AnyStr -> AnyStr)
  278. self.transform_source: Callable[[Any], Any] | None = None
  279. # Print full path to each file in the report.
  280. self.show_absolute_path: bool = False
  281. # Install missing stub packages if True
  282. self.install_types = False
  283. # Install missing stub packages in non-interactive mode (don't prompt for
  284. # confirmation, and don't show any errors)
  285. self.non_interactive = False
  286. # When we encounter errors that may cause many additional errors,
  287. # skip most errors after this many messages have been reported.
  288. # -1 means unlimited.
  289. self.many_errors_threshold = defaults.MANY_ERRORS_THRESHOLD
  290. # Enable new experimental type inference algorithm.
  291. self.new_type_inference = False
  292. # Disable recursive type aliases (currently experimental)
  293. self.disable_recursive_aliases = False
  294. # Deprecated reverse version of the above, do not use.
  295. self.enable_recursive_aliases = False
  296. # Export line-level, limited, fine-grained dependency information in cache data
  297. # (undocumented feature).
  298. self.export_ref_info = False
  299. self.disable_bytearray_promotion = False
  300. self.disable_memoryview_promotion = False
  301. self.force_uppercase_builtins = False
  302. self.force_union_syntax = False
  303. def use_lowercase_names(self) -> bool:
  304. if self.python_version >= (3, 9):
  305. return not self.force_uppercase_builtins
  306. return False
  307. def use_or_syntax(self) -> bool:
  308. if self.python_version >= (3, 10):
  309. return not self.force_union_syntax
  310. return False
  311. # To avoid breaking plugin compatibility, keep providing new_semantic_analyzer
  312. @property
  313. def new_semantic_analyzer(self) -> bool:
  314. return True
  315. def snapshot(self) -> dict[str, object]:
  316. """Produce a comparable snapshot of this Option"""
  317. # Under mypyc, we don't have a __dict__, so we need to do worse things.
  318. d = dict(getattr(self, "__dict__", ()))
  319. for k in get_class_descriptors(Options):
  320. if hasattr(self, k) and k != "new_semantic_analyzer":
  321. d[k] = getattr(self, k)
  322. # Remove private attributes from snapshot
  323. d = {k: v for k, v in d.items() if not k.startswith("_")}
  324. return d
  325. def __repr__(self) -> str:
  326. return f"Options({pprint.pformat(self.snapshot())})"
  327. def apply_changes(self, changes: dict[str, object]) -> Options:
  328. # Note: effects of this method *must* be idempotent.
  329. new_options = Options()
  330. # Under mypyc, we don't have a __dict__, so we need to do worse things.
  331. replace_object_state(new_options, self, copy_dict=True)
  332. for key, value in changes.items():
  333. setattr(new_options, key, value)
  334. if changes.get("ignore_missing_imports"):
  335. # This is the only option for which a per-module and a global
  336. # option sometimes beheave differently.
  337. new_options.ignore_missing_imports_per_module = True
  338. # These two act as overrides, so apply them when cloning.
  339. # Similar to global codes enabling overrides disabling, so we start from latter.
  340. new_options.disabled_error_codes = self.disabled_error_codes.copy()
  341. new_options.enabled_error_codes = self.enabled_error_codes.copy()
  342. for code_str in new_options.disable_error_code:
  343. code = error_codes[code_str]
  344. new_options.disabled_error_codes.add(code)
  345. new_options.enabled_error_codes.discard(code)
  346. for code_str in new_options.enable_error_code:
  347. code = error_codes[code_str]
  348. new_options.enabled_error_codes.add(code)
  349. new_options.disabled_error_codes.discard(code)
  350. return new_options
  351. def compare_stable(self, other_snapshot: dict[str, object]) -> bool:
  352. """Compare options in a way that is stable for snapshot() -> apply_changes() roundtrip.
  353. This is needed because apply_changes() has non-trivial effects for some flags, so
  354. Options().apply_changes(options.snapshot()) may result in a (slightly) different object.
  355. """
  356. return (
  357. Options().apply_changes(self.snapshot()).snapshot()
  358. == Options().apply_changes(other_snapshot).snapshot()
  359. )
  360. def build_per_module_cache(self) -> None:
  361. self._per_module_cache = {}
  362. # Config precedence is as follows:
  363. # 1. Concrete section names: foo.bar.baz
  364. # 2. "Unstructured" glob patterns: foo.*.baz, in the order
  365. # they appear in the file (last wins)
  366. # 3. "Well-structured" wildcard patterns: foo.bar.*, in specificity order.
  367. # Since structured configs inherit from structured configs above them in the hierarchy,
  368. # we need to process per-module configs in a careful order.
  369. # We have to process foo.* before foo.bar.* before foo.bar,
  370. # and we need to apply *.bar to foo.bar but not to foo.bar.*.
  371. # To do this, process all well-structured glob configs before non-glob configs and
  372. # exploit the fact that foo.* sorts earlier ASCIIbetically (unicodebetically?)
  373. # than foo.bar.*.
  374. # (A section being "processed last" results in its config "winning".)
  375. # Unstructured glob configs are stored and are all checked for each module.
  376. unstructured_glob_keys = [k for k in self.per_module_options.keys() if "*" in k[:-1]]
  377. structured_keys = [k for k in self.per_module_options.keys() if "*" not in k[:-1]]
  378. wildcards = sorted(k for k in structured_keys if k.endswith(".*"))
  379. concrete = [k for k in structured_keys if not k.endswith(".*")]
  380. for glob in unstructured_glob_keys:
  381. self._glob_options.append((glob, self.compile_glob(glob)))
  382. # We (for ease of implementation) treat unstructured glob
  383. # sections as used if any real modules use them or if any
  384. # concrete config sections use them. This means we need to
  385. # track which get used while constructing.
  386. self.unused_configs = set(unstructured_glob_keys)
  387. for key in wildcards + concrete:
  388. # Find what the options for this key would be, just based
  389. # on inheriting from parent configs.
  390. options = self.clone_for_module(key)
  391. # And then update it with its per-module options.
  392. self._per_module_cache[key] = options.apply_changes(self.per_module_options[key])
  393. # Add the more structured sections into unused configs, since
  394. # they only count as used if actually used by a real module.
  395. self.unused_configs.update(structured_keys)
  396. def clone_for_module(self, module: str) -> Options:
  397. """Create an Options object that incorporates per-module options.
  398. NOTE: Once this method is called all Options objects should be
  399. considered read-only, else the caching might be incorrect.
  400. """
  401. if self._per_module_cache is None:
  402. self.build_per_module_cache()
  403. assert self._per_module_cache is not None
  404. # If the module just directly has a config entry, use it.
  405. if module in self._per_module_cache:
  406. self.unused_configs.discard(module)
  407. return self._per_module_cache[module]
  408. # If not, search for glob paths at all the parents. So if we are looking for
  409. # options for foo.bar.baz, we search foo.bar.baz.*, foo.bar.*, foo.*,
  410. # in that order, looking for an entry.
  411. # This is technically quadratic in the length of the path, but module paths
  412. # don't actually get all that long.
  413. options = self
  414. path = module.split(".")
  415. for i in range(len(path), 0, -1):
  416. key = ".".join(path[:i] + ["*"])
  417. if key in self._per_module_cache:
  418. self.unused_configs.discard(key)
  419. options = self._per_module_cache[key]
  420. break
  421. # OK and *now* we need to look for unstructured glob matches.
  422. # We only do this for concrete modules, not structured wildcards.
  423. if not module.endswith(".*"):
  424. for key, pattern in self._glob_options:
  425. if pattern.match(module):
  426. self.unused_configs.discard(key)
  427. options = options.apply_changes(self.per_module_options[key])
  428. # We could update the cache to directly point to modules once
  429. # they have been looked up, but in testing this made things
  430. # slower and not faster, so we don't bother.
  431. return options
  432. def compile_glob(self, s: str) -> Pattern[str]:
  433. # Compile one of the glob patterns to a regex so that '.*' can
  434. # match *zero or more* module sections. This means we compile
  435. # '.*' into '(\..*)?'.
  436. parts = s.split(".")
  437. expr = re.escape(parts[0]) if parts[0] != "*" else ".*"
  438. for part in parts[1:]:
  439. expr += re.escape("." + part) if part != "*" else r"(\..*)?"
  440. return re.compile(expr + "\\Z")
  441. def select_options_affecting_cache(self) -> Mapping[str, object]:
  442. result: dict[str, object] = {}
  443. for opt in OPTIONS_AFFECTING_CACHE:
  444. val = getattr(self, opt)
  445. if opt in ("disabled_error_codes", "enabled_error_codes"):
  446. val = sorted([code.code for code in val])
  447. result[opt] = val
  448. return result