options.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. from __future__ import annotations
  2. import pprint
  3. import re
  4. import sys
  5. import sysconfig
  6. from typing import Any, Callable, Dict, Mapping, Pattern
  7. from typing_extensions import Final
  8. from mypy import defaults
  9. from mypy.errorcodes import ErrorCode, error_codes
  10. from mypy.util import get_class_descriptors, replace_object_state
  11. class BuildType:
  12. STANDARD: Final = 0
  13. MODULE: Final = 1
  14. PROGRAM_TEXT: Final = 2
  15. PER_MODULE_OPTIONS: Final = {
  16. # Please keep this list sorted
  17. "allow_redefinition",
  18. "allow_untyped_globals",
  19. "always_false",
  20. "always_true",
  21. "check_untyped_defs",
  22. "debug_cache",
  23. "disable_error_code",
  24. "disabled_error_codes",
  25. "disallow_any_decorated",
  26. "disallow_any_explicit",
  27. "disallow_any_expr",
  28. "disallow_any_generics",
  29. "disallow_any_unimported",
  30. "disallow_incomplete_defs",
  31. "disallow_subclassing_any",
  32. "disallow_untyped_calls",
  33. "disallow_untyped_decorators",
  34. "disallow_untyped_defs",
  35. "enable_error_code",
  36. "enabled_error_codes",
  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. # Make arguments prepended via Concatenate be truly positional-only.
  167. self.strict_concatenate = False
  168. # Report an error for any branches inferred to be unreachable as a result of
  169. # type analysis.
  170. self.warn_unreachable = False
  171. # Variable names considered True
  172. self.always_true: list[str] = []
  173. # Variable names considered False
  174. self.always_false: list[str] = []
  175. # Error codes to disable
  176. self.disable_error_code: list[str] = []
  177. self.disabled_error_codes: set[ErrorCode] = set()
  178. # Error codes to enable
  179. self.enable_error_code: list[str] = []
  180. self.enabled_error_codes: set[ErrorCode] = set()
  181. # Use script name instead of __main__
  182. self.scripts_are_modules = False
  183. # Config file name
  184. self.config_file: str | None = None
  185. # A filename containing a JSON mapping from filenames to
  186. # mtime/size/hash arrays, used to avoid having to recalculate
  187. # source hashes as often.
  188. self.quickstart_file: str | None = None
  189. # A comma-separated list of files/directories for mypy to type check;
  190. # supports globbing
  191. self.files: list[str] | None = None
  192. # A list of packages for mypy to type check
  193. self.packages: list[str] | None = None
  194. # A list of modules for mypy to type check
  195. self.modules: list[str] | None = None
  196. # Write junit.xml to given file
  197. self.junit_xml: str | None = None
  198. # Caching and incremental checking options
  199. self.incremental = True
  200. self.cache_dir = defaults.CACHE_DIR
  201. self.sqlite_cache = False
  202. self.debug_cache = False
  203. self.skip_version_check = False
  204. self.skip_cache_mtime_checks = False
  205. self.fine_grained_incremental = False
  206. # Include fine-grained dependencies in written cache files
  207. self.cache_fine_grained = False
  208. # Read cache files in fine-grained incremental mode (cache must include dependencies)
  209. self.use_fine_grained_cache = False
  210. # Run tree.serialize() even if cache generation is disabled
  211. self.debug_serialize = False
  212. # Tune certain behaviors when being used as a front-end to mypyc. Set per-module
  213. # in modules being compiled. Not in the config file or command line.
  214. self.mypyc = False
  215. # An internal flag to modify some type-checking logic while
  216. # running inspections (e.g. don't expand function definitions).
  217. # Not in the config file or command line.
  218. self.inspections = False
  219. # Disable the memory optimization of freeing ASTs when
  220. # possible. This isn't exposed as a command line option
  221. # because it is intended for software integrating with
  222. # mypy. (Like mypyc.)
  223. self.preserve_asts = False
  224. # Paths of user plugins
  225. self.plugins: list[str] = []
  226. # Per-module options (raw)
  227. self.per_module_options: dict[str, dict[str, object]] = {}
  228. self._glob_options: list[tuple[str, Pattern[str]]] = []
  229. self.unused_configs: set[str] = set()
  230. # -- development options --
  231. self.verbosity = 0 # More verbose messages (for troubleshooting)
  232. self.pdb = False
  233. self.show_traceback = False
  234. self.raise_exceptions = False
  235. self.dump_type_stats = False
  236. self.dump_inference_stats = False
  237. self.dump_build_stats = False
  238. self.enable_incomplete_features = False # deprecated
  239. self.enable_incomplete_feature: list[str] = []
  240. self.timing_stats: str | None = None
  241. self.line_checking_stats: str | None = None
  242. # -- test options --
  243. # Stop after the semantic analysis phase
  244. self.semantic_analysis_only = False
  245. # Use stub builtins fixtures to speed up tests
  246. self.use_builtins_fixtures = False
  247. # -- experimental options --
  248. self.shadow_file: list[list[str]] | None = None
  249. self.show_column_numbers: bool = False
  250. self.show_error_end: bool = False
  251. self.hide_error_codes = False
  252. # Use soft word wrap and show trimmed source snippets with error location markers.
  253. self.pretty = False
  254. self.dump_graph = False
  255. self.dump_deps = False
  256. self.logical_deps = False
  257. # If True, partial types can't span a module top level and a function
  258. self.local_partial_types = False
  259. # Some behaviors are changed when using Bazel (https://bazel.build).
  260. self.bazel = False
  261. # If True, export inferred types for all expressions as BuildResult.types
  262. self.export_types = False
  263. # List of package roots -- directories under these are packages even
  264. # if they don't have __init__.py.
  265. self.package_root: list[str] = []
  266. self.cache_map: dict[str, tuple[str, str]] = {}
  267. # Don't properly free objects on exit, just kill the current process.
  268. self.fast_exit = True
  269. # fast path for finding modules from source set
  270. self.fast_module_lookup = False
  271. # Allow empty function bodies even if it is not safe, used for testing only.
  272. self.allow_empty_bodies = False
  273. # Used to transform source code before parsing if not None
  274. # TODO: Make the type precise (AnyStr -> AnyStr)
  275. self.transform_source: Callable[[Any], Any] | None = None
  276. # Print full path to each file in the report.
  277. self.show_absolute_path: bool = False
  278. # Install missing stub packages if True
  279. self.install_types = False
  280. # Install missing stub packages in non-interactive mode (don't prompt for
  281. # confirmation, and don't show any errors)
  282. self.non_interactive = False
  283. # When we encounter errors that may cause many additional errors,
  284. # skip most errors after this many messages have been reported.
  285. # -1 means unlimited.
  286. self.many_errors_threshold = defaults.MANY_ERRORS_THRESHOLD
  287. # Disable recursive type aliases (currently experimental)
  288. self.disable_recursive_aliases = False
  289. # Deprecated reverse version of the above, do not use.
  290. self.enable_recursive_aliases = False
  291. # Export line-level, limited, fine-grained dependency information in cache data
  292. # (undocumented feature).
  293. self.export_ref_info = False
  294. self.disable_bytearray_promotion = False
  295. self.disable_memoryview_promotion = False
  296. self.force_uppercase_builtins = False
  297. self.force_union_syntax = False
  298. def use_lowercase_names(self) -> bool:
  299. if self.python_version >= (3, 9):
  300. return not self.force_uppercase_builtins
  301. return False
  302. def use_or_syntax(self) -> bool:
  303. if self.python_version >= (3, 10):
  304. return not self.force_union_syntax
  305. return False
  306. # To avoid breaking plugin compatibility, keep providing new_semantic_analyzer
  307. @property
  308. def new_semantic_analyzer(self) -> bool:
  309. return True
  310. def snapshot(self) -> object:
  311. """Produce a comparable snapshot of this Option"""
  312. # Under mypyc, we don't have a __dict__, so we need to do worse things.
  313. d = dict(getattr(self, "__dict__", ()))
  314. for k in get_class_descriptors(Options):
  315. if hasattr(self, k) and k != "new_semantic_analyzer":
  316. d[k] = getattr(self, k)
  317. # Remove private attributes from snapshot
  318. d = {k: v for k, v in d.items() if not k.startswith("_")}
  319. return d
  320. def __repr__(self) -> str:
  321. return f"Options({pprint.pformat(self.snapshot())})"
  322. def apply_changes(self, changes: dict[str, object]) -> Options:
  323. new_options = Options()
  324. # Under mypyc, we don't have a __dict__, so we need to do worse things.
  325. replace_object_state(new_options, self, copy_dict=True)
  326. for key, value in changes.items():
  327. setattr(new_options, key, value)
  328. if changes.get("ignore_missing_imports"):
  329. # This is the only option for which a per-module and a global
  330. # option sometimes beheave differently.
  331. new_options.ignore_missing_imports_per_module = True
  332. # These two act as overrides, so apply them when cloning.
  333. # Similar to global codes enabling overrides disabling, so we start from latter.
  334. new_options.disabled_error_codes = self.disabled_error_codes.copy()
  335. new_options.enabled_error_codes = self.enabled_error_codes.copy()
  336. for code_str in new_options.disable_error_code:
  337. code = error_codes[code_str]
  338. new_options.disabled_error_codes.add(code)
  339. new_options.enabled_error_codes.discard(code)
  340. for code_str in new_options.enable_error_code:
  341. code = error_codes[code_str]
  342. new_options.enabled_error_codes.add(code)
  343. new_options.disabled_error_codes.discard(code)
  344. return new_options
  345. def build_per_module_cache(self) -> None:
  346. self._per_module_cache = {}
  347. # Config precedence is as follows:
  348. # 1. Concrete section names: foo.bar.baz
  349. # 2. "Unstructured" glob patterns: foo.*.baz, in the order
  350. # they appear in the file (last wins)
  351. # 3. "Well-structured" wildcard patterns: foo.bar.*, in specificity order.
  352. # Since structured configs inherit from structured configs above them in the hierarchy,
  353. # we need to process per-module configs in a careful order.
  354. # We have to process foo.* before foo.bar.* before foo.bar,
  355. # and we need to apply *.bar to foo.bar but not to foo.bar.*.
  356. # To do this, process all well-structured glob configs before non-glob configs and
  357. # exploit the fact that foo.* sorts earlier ASCIIbetically (unicodebetically?)
  358. # than foo.bar.*.
  359. # (A section being "processed last" results in its config "winning".)
  360. # Unstructured glob configs are stored and are all checked for each module.
  361. unstructured_glob_keys = [k for k in self.per_module_options.keys() if "*" in k[:-1]]
  362. structured_keys = [k for k in self.per_module_options.keys() if "*" not in k[:-1]]
  363. wildcards = sorted(k for k in structured_keys if k.endswith(".*"))
  364. concrete = [k for k in structured_keys if not k.endswith(".*")]
  365. for glob in unstructured_glob_keys:
  366. self._glob_options.append((glob, self.compile_glob(glob)))
  367. # We (for ease of implementation) treat unstructured glob
  368. # sections as used if any real modules use them or if any
  369. # concrete config sections use them. This means we need to
  370. # track which get used while constructing.
  371. self.unused_configs = set(unstructured_glob_keys)
  372. for key in wildcards + concrete:
  373. # Find what the options for this key would be, just based
  374. # on inheriting from parent configs.
  375. options = self.clone_for_module(key)
  376. # And then update it with its per-module options.
  377. self._per_module_cache[key] = options.apply_changes(self.per_module_options[key])
  378. # Add the more structured sections into unused configs, since
  379. # they only count as used if actually used by a real module.
  380. self.unused_configs.update(structured_keys)
  381. def clone_for_module(self, module: str) -> Options:
  382. """Create an Options object that incorporates per-module options.
  383. NOTE: Once this method is called all Options objects should be
  384. considered read-only, else the caching might be incorrect.
  385. """
  386. if self._per_module_cache is None:
  387. self.build_per_module_cache()
  388. assert self._per_module_cache is not None
  389. # If the module just directly has a config entry, use it.
  390. if module in self._per_module_cache:
  391. self.unused_configs.discard(module)
  392. return self._per_module_cache[module]
  393. # If not, search for glob paths at all the parents. So if we are looking for
  394. # options for foo.bar.baz, we search foo.bar.baz.*, foo.bar.*, foo.*,
  395. # in that order, looking for an entry.
  396. # This is technically quadratic in the length of the path, but module paths
  397. # don't actually get all that long.
  398. options = self
  399. path = module.split(".")
  400. for i in range(len(path), 0, -1):
  401. key = ".".join(path[:i] + ["*"])
  402. if key in self._per_module_cache:
  403. self.unused_configs.discard(key)
  404. options = self._per_module_cache[key]
  405. break
  406. # OK and *now* we need to look for unstructured glob matches.
  407. # We only do this for concrete modules, not structured wildcards.
  408. if not module.endswith(".*"):
  409. for key, pattern in self._glob_options:
  410. if pattern.match(module):
  411. self.unused_configs.discard(key)
  412. options = options.apply_changes(self.per_module_options[key])
  413. # We could update the cache to directly point to modules once
  414. # they have been looked up, but in testing this made things
  415. # slower and not faster, so we don't bother.
  416. return options
  417. def compile_glob(self, s: str) -> Pattern[str]:
  418. # Compile one of the glob patterns to a regex so that '.*' can
  419. # match *zero or more* module sections. This means we compile
  420. # '.*' into '(\..*)?'.
  421. parts = s.split(".")
  422. expr = re.escape(parts[0]) if parts[0] != "*" else ".*"
  423. for part in parts[1:]:
  424. expr += re.escape("." + part) if part != "*" else r"(\..*)?"
  425. return re.compile(expr + "\\Z")
  426. def select_options_affecting_cache(self) -> Mapping[str, object]:
  427. result: Dict[str, object] = {}
  428. for opt in OPTIONS_AFFECTING_CACHE:
  429. val = getattr(self, opt)
  430. if opt in ("disabled_error_codes", "enabled_error_codes"):
  431. val = sorted([code.code for code in val])
  432. result[opt] = val
  433. return result