jaclang 0.4.6__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jaclang might be problematic. Click here for more details.

Files changed (152) hide show
  1. jaclang/__init__.py +5 -2
  2. jaclang/cli/cli.py +57 -10
  3. jaclang/cli/cmdreg.py +16 -9
  4. jaclang/compiler/__jac_gen__/jac_parser.py +11 -15
  5. jaclang/compiler/absyntree.py +53 -19
  6. jaclang/compiler/codeloc.py +3 -1
  7. jaclang/compiler/{transpiler.py → compile.py} +3 -2
  8. jaclang/compiler/constant.py +4 -0
  9. jaclang/compiler/parser.py +156 -108
  10. jaclang/compiler/passes/ir_pass.py +1 -0
  11. jaclang/compiler/passes/main/__init__.py +2 -1
  12. jaclang/compiler/passes/main/def_impl_match_pass.py +1 -0
  13. jaclang/compiler/passes/main/def_use_pass.py +1 -0
  14. jaclang/compiler/passes/main/import_pass.py +18 -18
  15. jaclang/compiler/passes/main/pyast_gen_pass.py +1228 -853
  16. jaclang/compiler/passes/main/pyast_load_pass.py +3 -1
  17. jaclang/compiler/passes/main/pybc_gen_pass.py +46 -0
  18. jaclang/compiler/passes/main/pyout_pass.py +6 -7
  19. jaclang/compiler/passes/main/schedules.py +5 -9
  20. jaclang/compiler/passes/main/sub_node_tab_pass.py +1 -0
  21. jaclang/compiler/passes/main/sym_tab_build_pass.py +21 -9
  22. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +2 -1
  23. jaclang/compiler/passes/main/tests/test_def_use_pass.py +2 -1
  24. jaclang/compiler/passes/main/tests/test_import_pass.py +2 -1
  25. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +1 -0
  26. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +15 -38
  27. jaclang/compiler/passes/main/tests/test_pybc_gen_pass.py +25 -0
  28. jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -1
  29. jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +2 -1
  30. jaclang/compiler/passes/main/tests/test_type_check_pass.py +17 -1
  31. jaclang/compiler/passes/main/type_check_pass.py +9 -6
  32. jaclang/compiler/passes/tool/__init__.py +1 -0
  33. jaclang/compiler/passes/tool/ast_printer_pass.py +1 -0
  34. jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -1
  35. jaclang/compiler/passes/tool/jac_formatter_pass.py +69 -32
  36. jaclang/compiler/passes/tool/schedules.py +1 -0
  37. jaclang/compiler/passes/tool/sym_tab_printer_pass.py +1 -0
  38. jaclang/compiler/passes/tool/tests/test_ast_print_pass.py +2 -1
  39. jaclang/compiler/passes/tool/tests/test_fuse_comments_pass.py +1 -0
  40. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -3
  41. jaclang/compiler/passes/tool/tests/test_symtab_print_pass.py +2 -1
  42. jaclang/compiler/passes/transform.py +1 -0
  43. jaclang/compiler/passes/utils/mypy_ast_build.py +203 -17
  44. jaclang/compiler/symtable.py +1 -0
  45. jaclang/compiler/tests/test_importer.py +3 -2
  46. jaclang/compiler/tests/test_parser.py +1 -0
  47. jaclang/compiler/tests/test_workspace.py +1 -0
  48. jaclang/compiler/workspace.py +18 -5
  49. jaclang/core/construct.py +9 -32
  50. jaclang/{compiler → core}/importer.py +95 -85
  51. jaclang/core/utils.py +17 -12
  52. jaclang/plugin/__init__.py +1 -0
  53. jaclang/plugin/default.py +145 -43
  54. jaclang/plugin/feature.py +65 -19
  55. jaclang/plugin/spec.py +56 -34
  56. jaclang/plugin/tests/test_features.py +9 -0
  57. jaclang/utils/helpers.py +1 -0
  58. jaclang/utils/lang_tools.py +13 -19
  59. jaclang/utils/tests/test_lang_tools.py +2 -1
  60. jaclang/utils/treeprinter.py +2 -1
  61. jaclang/vendor/lark/common.py +3 -1
  62. jaclang/vendor/lark/lexer.py +6 -12
  63. jaclang/vendor/lark/parsers/lalr_parser.py +1 -0
  64. jaclang/vendor/mypy/applytype.py +2 -1
  65. jaclang/vendor/mypy/binder.py +1 -1
  66. jaclang/vendor/mypy/build.py +7 -9
  67. jaclang/vendor/mypy/checker.py +57 -33
  68. jaclang/vendor/mypy/checkexpr.py +42 -29
  69. jaclang/vendor/mypy/checkmember.py +13 -1
  70. jaclang/vendor/mypy/checkpattern.py +1 -1
  71. jaclang/vendor/mypy/checkstrformat.py +2 -4
  72. jaclang/vendor/mypy/constraints.py +10 -5
  73. jaclang/vendor/mypy/dmypy_server.py +3 -3
  74. jaclang/vendor/mypy/dmypy_util.py +62 -3
  75. jaclang/vendor/mypy/errors.py +1 -1
  76. jaclang/vendor/mypy/evalexpr.py +1 -0
  77. jaclang/vendor/mypy/expandtype.py +29 -29
  78. jaclang/vendor/mypy/fastparse.py +51 -31
  79. jaclang/vendor/mypy/inspections.py +5 -3
  80. jaclang/vendor/mypy/join.py +4 -4
  81. jaclang/vendor/mypy/main.py +6 -6
  82. jaclang/vendor/mypy/message_registry.py +1 -2
  83. jaclang/vendor/mypy/messages.py +31 -23
  84. jaclang/vendor/mypy/metastore.py +1 -2
  85. jaclang/vendor/mypy/modulefinder.py +2 -22
  86. jaclang/vendor/mypy/nodes.py +22 -20
  87. jaclang/vendor/mypy/options.py +4 -0
  88. jaclang/vendor/mypy/parse.py +6 -2
  89. jaclang/vendor/mypy/patterns.py +6 -6
  90. jaclang/vendor/mypy/plugin.py +3 -1
  91. jaclang/vendor/mypy/plugins/attrs.py +52 -10
  92. jaclang/vendor/mypy/plugins/common.py +2 -1
  93. jaclang/vendor/mypy/plugins/enums.py +3 -2
  94. jaclang/vendor/mypy/plugins/functools.py +1 -0
  95. jaclang/vendor/mypy/renaming.py +1 -1
  96. jaclang/vendor/mypy/report.py +15 -15
  97. jaclang/vendor/mypy/semanal.py +22 -13
  98. jaclang/vendor/mypy/semanal_enum.py +1 -1
  99. jaclang/vendor/mypy/semanal_namedtuple.py +1 -2
  100. jaclang/vendor/mypy/semanal_shared.py +3 -6
  101. jaclang/vendor/mypy/semanal_typeddict.py +16 -5
  102. jaclang/vendor/mypy/server/astdiff.py +15 -9
  103. jaclang/vendor/mypy/server/astmerge.py +5 -5
  104. jaclang/vendor/mypy/stats.py +0 -5
  105. jaclang/vendor/mypy/stubdoc.py +1 -1
  106. jaclang/vendor/mypy/stubgen.py +12 -21
  107. jaclang/vendor/mypy/stubgenc.py +16 -8
  108. jaclang/vendor/mypy/stubtest.py +57 -48
  109. jaclang/vendor/mypy/stubutil.py +28 -15
  110. jaclang/vendor/mypy/subtypes.py +4 -4
  111. jaclang/vendor/mypy/test/helpers.py +2 -2
  112. jaclang/vendor/mypy/test/meta/test_parse_data.py +1 -0
  113. jaclang/vendor/mypy/test/meta/test_update_data.py +1 -0
  114. jaclang/vendor/mypy/test/testargs.py +1 -0
  115. jaclang/vendor/mypy/test/testcheck.py +4 -1
  116. jaclang/vendor/mypy/test/testconstraints.py +25 -7
  117. jaclang/vendor/mypy/test/testerrorstream.py +1 -0
  118. jaclang/vendor/mypy/test/testformatter.py +2 -2
  119. jaclang/vendor/mypy/test/testparse.py +6 -4
  120. jaclang/vendor/mypy/test/testpythoneval.py +1 -0
  121. jaclang/vendor/mypy/test/testreports.py +1 -0
  122. jaclang/vendor/mypy/test/teststubgen.py +1 -2
  123. jaclang/vendor/mypy/test/teststubtest.py +98 -4
  124. jaclang/vendor/mypy/test/testtypes.py +1 -1
  125. jaclang/vendor/mypy/test/testutil.py +22 -0
  126. jaclang/vendor/mypy/typeanal.py +302 -158
  127. jaclang/vendor/mypy/typeops.py +22 -13
  128. jaclang/vendor/mypy/types.py +33 -34
  129. jaclang/vendor/mypy/typestate.py +2 -2
  130. jaclang/vendor/mypy/util.py +7 -6
  131. jaclang/vendor/mypy/version.py +1 -1
  132. jaclang/vendor/mypyc/analysis/ircheck.py +1 -0
  133. jaclang/vendor/mypyc/codegen/emitfunc.py +5 -3
  134. jaclang/vendor/mypyc/codegen/emitmodule.py +12 -12
  135. jaclang/vendor/mypyc/codegen/emitwrapper.py +2 -2
  136. jaclang/vendor/mypyc/ir/class_ir.py +10 -6
  137. jaclang/vendor/mypyc/irbuild/builder.py +3 -4
  138. jaclang/vendor/mypyc/irbuild/function.py +5 -3
  139. jaclang/vendor/mypyc/irbuild/nonlocalcontrol.py +1 -2
  140. jaclang/vendor/mypyc/irbuild/prepare.py +6 -6
  141. jaclang/vendor/mypyc/primitives/registry.py +15 -5
  142. jaclang/vendor/mypyc/test/test_run.py +1 -2
  143. jaclang/vendor/mypyc/transform/uninit.py +3 -3
  144. jaclang/vendor/pluggy/_callers.py +1 -0
  145. jaclang/vendor/pluggy/_hooks.py +6 -10
  146. jaclang/vendor/pluggy/_result.py +1 -0
  147. jaclang/vendor/pluggy/_tracing.py +1 -0
  148. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/METADATA +1 -1
  149. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/RECORD +152 -150
  150. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/WHEEL +0 -0
  151. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/entry_points.txt +0 -0
  152. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/top_level.txt +0 -0
@@ -50,18 +50,15 @@ import mypy.type_visitor # ruff: isort: skip
50
50
 
51
51
 
52
52
  @overload
53
- def expand_type(typ: CallableType, env: Mapping[TypeVarId, Type]) -> CallableType:
54
- ...
53
+ def expand_type(typ: CallableType, env: Mapping[TypeVarId, Type]) -> CallableType: ...
55
54
 
56
55
 
57
56
  @overload
58
- def expand_type(typ: ProperType, env: Mapping[TypeVarId, Type]) -> ProperType:
59
- ...
57
+ def expand_type(typ: ProperType, env: Mapping[TypeVarId, Type]) -> ProperType: ...
60
58
 
61
59
 
62
60
  @overload
63
- def expand_type(typ: Type, env: Mapping[TypeVarId, Type]) -> Type:
64
- ...
61
+ def expand_type(typ: Type, env: Mapping[TypeVarId, Type]) -> Type: ...
65
62
 
66
63
 
67
64
  def expand_type(typ: Type, env: Mapping[TypeVarId, Type]) -> Type:
@@ -72,18 +69,15 @@ def expand_type(typ: Type, env: Mapping[TypeVarId, Type]) -> Type:
72
69
 
73
70
 
74
71
  @overload
75
- def expand_type_by_instance(typ: CallableType, instance: Instance) -> CallableType:
76
- ...
72
+ def expand_type_by_instance(typ: CallableType, instance: Instance) -> CallableType: ...
77
73
 
78
74
 
79
75
  @overload
80
- def expand_type_by_instance(typ: ProperType, instance: Instance) -> ProperType:
81
- ...
76
+ def expand_type_by_instance(typ: ProperType, instance: Instance) -> ProperType: ...
82
77
 
83
78
 
84
79
  @overload
85
- def expand_type_by_instance(typ: Type, instance: Instance) -> Type:
86
- ...
80
+ def expand_type_by_instance(typ: Type, instance: Instance) -> Type: ...
87
81
 
88
82
 
89
83
  def expand_type_by_instance(typ: Type, instance: Instance) -> Type:
@@ -286,6 +280,8 @@ class ExpandTypeVisitor(TrivialSyntheticTypeTranslator):
286
280
  def expand_unpack(self, t: UnpackType) -> list[Type]:
287
281
  assert isinstance(t.type, TypeVarTupleType)
288
282
  repl = get_proper_type(self.variables.get(t.type.id, t.type))
283
+ if isinstance(repl, UnpackType):
284
+ repl = get_proper_type(repl.type)
289
285
  if isinstance(repl, TupleType):
290
286
  return repl.items
291
287
  elif (
@@ -312,20 +308,24 @@ class ExpandTypeVisitor(TrivialSyntheticTypeTranslator):
312
308
  suffix = self.expand_types(t.arg_types[star_index + 1 :])
313
309
 
314
310
  var_arg_type = get_proper_type(var_arg.type)
315
- # We have something like Unpack[Tuple[Unpack[Ts], X1, X2]]
316
- if isinstance(var_arg_type, TupleType):
317
- expanded_tuple = var_arg_type.accept(self)
318
- assert isinstance(expanded_tuple, ProperType) and isinstance(
319
- expanded_tuple, TupleType
320
- )
321
- expanded_items = expanded_tuple.items
322
- fallback = var_arg_type.partial_fallback
311
+ if isinstance(var_arg_type, Instance):
312
+ # we have something like Unpack[Tuple[Any, ...]]
313
+ new_unpack = var_arg
323
314
  else:
324
- # We have plain Unpack[Ts]
325
- assert isinstance(var_arg_type, TypeVarTupleType)
326
- fallback = var_arg_type.tuple_fallback
327
- expanded_items = self.expand_unpack(var_arg)
328
- new_unpack = UnpackType(TupleType(expanded_items, fallback))
315
+ if isinstance(var_arg_type, TupleType):
316
+ # We have something like Unpack[Tuple[Unpack[Ts], X1, X2]]
317
+ expanded_tuple = var_arg_type.accept(self)
318
+ assert isinstance(expanded_tuple, ProperType) and isinstance(
319
+ expanded_tuple, TupleType
320
+ )
321
+ expanded_items = expanded_tuple.items
322
+ fallback = var_arg_type.partial_fallback
323
+ else:
324
+ # We have plain Unpack[Ts]
325
+ assert isinstance(var_arg_type, TypeVarTupleType), type(var_arg_type)
326
+ fallback = var_arg_type.tuple_fallback
327
+ expanded_items = self.expand_unpack(var_arg)
328
+ new_unpack = UnpackType(TupleType(expanded_items, fallback))
329
329
  return prefix + [new_unpack] + suffix
330
330
 
331
331
  def visit_callable_type(self, t: CallableType) -> CallableType:
@@ -481,13 +481,13 @@ class ExpandTypeVisitor(TrivialSyntheticTypeTranslator):
481
481
 
482
482
 
483
483
  @overload
484
- def expand_self_type(var: Var, typ: ProperType, replacement: ProperType) -> ProperType:
485
- ...
484
+ def expand_self_type(
485
+ var: Var, typ: ProperType, replacement: ProperType
486
+ ) -> ProperType: ...
486
487
 
487
488
 
488
489
  @overload
489
- def expand_self_type(var: Var, typ: Type, replacement: Type) -> Type:
490
- ...
490
+ def expand_self_type(var: Var, typ: Type, replacement: Type) -> Type: ...
491
491
 
492
492
 
493
493
  def expand_self_type(var: Var, typ: Type, replacement: Type) -> Type:
@@ -126,7 +126,18 @@ PY_MINOR_VERSION: Final = sys.version_info[1]
126
126
  import ast as ast3
127
127
 
128
128
  # TODO: Index, ExtSlice are deprecated in 3.9.
129
- from ast import AST, Attribute, Call, FunctionType, Index, Name, Starred, UnaryOp, USub
129
+ from ast import (
130
+ AST,
131
+ Attribute,
132
+ Call,
133
+ FunctionType,
134
+ Index,
135
+ Name,
136
+ Starred,
137
+ UAdd,
138
+ UnaryOp,
139
+ USub,
140
+ )
130
141
 
131
142
 
132
143
  def ast3_parse(
@@ -193,7 +204,7 @@ def parse(
193
204
  source: str | bytes,
194
205
  fnam: str,
195
206
  module: str | None,
196
- errors: Errors | None = None,
207
+ errors: Errors,
197
208
  options: Options | None = None,
198
209
  ) -> MypyFile:
199
210
  """Parse a source file, without doing any semantic analysis.
@@ -202,18 +213,15 @@ def parse(
202
213
  on failure. Otherwise, use the errors object to report parse errors.
203
214
  """
204
215
  ignore_errors = (options is not None and options.ignore_errors) or (
205
- errors is not None and fnam in errors.ignored_files
216
+ fnam in errors.ignored_files
206
217
  )
207
218
  # If errors are ignored, we can drop many function bodies to speed up type checking.
208
219
  strip_function_bodies = ignore_errors and (
209
220
  options is None or not options.preserve_asts
210
221
  )
211
- raise_on_error = False
222
+
212
223
  if options is None:
213
224
  options = Options()
214
- if errors is None:
215
- errors = Errors(options)
216
- raise_on_error = True
217
225
  errors.set_file(fnam, module, options=options)
218
226
  is_stub_file = fnam.endswith(".pyi")
219
227
  if is_stub_file:
@@ -236,11 +244,9 @@ def parse(
236
244
  options=options,
237
245
  is_stub=is_stub_file,
238
246
  errors=errors,
239
- ignore_errors=ignore_errors,
240
247
  strip_function_bodies=strip_function_bodies,
248
+ path=fnam,
241
249
  ).visit(ast)
242
- tree.path = fnam
243
- tree.is_stub = is_stub_file
244
250
  except SyntaxError as e:
245
251
  # alias to please mypyc
246
252
  is_py38_or_earlier = sys.version_info < (3, 9)
@@ -266,9 +272,6 @@ def parse(
266
272
  )
267
273
  tree = MypyFile([], [], False, {})
268
274
 
269
- if raise_on_error and errors.is_errors():
270
- errors.raise_error()
271
-
272
275
  assert isinstance(tree, MypyFile)
273
276
  return tree
274
277
 
@@ -344,7 +347,7 @@ def parse_type_string(
344
347
  """
345
348
  try:
346
349
  _, node = parse_type_comment(
347
- expr_string.strip(), line=line, column=column, errors=None
350
+ f"({expr_string})", line=line, column=column, errors=None
348
351
  )
349
352
  if isinstance(node, UnboundType) and node.original_str_expr is None:
350
353
  node.original_str_expr = expr_string
@@ -376,8 +379,8 @@ class ASTConverter:
376
379
  is_stub: bool,
377
380
  errors: Errors,
378
381
  *,
379
- ignore_errors: bool,
380
382
  strip_function_bodies: bool,
383
+ path: str,
381
384
  ) -> None:
382
385
  # 'C' for class, 'D' for function signature, 'F' for function, 'L' for lambda
383
386
  self.class_and_function_stack: list[Literal["C", "D", "F", "L"]] = []
@@ -386,8 +389,8 @@ class ASTConverter:
386
389
  self.options = options
387
390
  self.is_stub = is_stub
388
391
  self.errors = errors
389
- self.ignore_errors = ignore_errors
390
392
  self.strip_function_bodies = strip_function_bodies
393
+ self.path = path
391
394
 
392
395
  self.type_ignores: dict[int, list[str]] = {}
393
396
 
@@ -401,6 +404,10 @@ class ASTConverter:
401
404
  self, msg: ErrorMessage, line: int, column: int, blocker: bool = True
402
405
  ) -> None:
403
406
  if blocker or not self.options.ignore_errors:
407
+ # Make sure self.errors reflects any type ignores that we have parsed
408
+ self.errors.set_file_ignored_lines(
409
+ self.path, self.type_ignores, self.options.ignore_errors
410
+ )
404
411
  self.errors.report(line, column, msg.value, blocker=blocker, code=msg.code)
405
412
 
406
413
  def fail_merge_overload(self, node: IfStmt) -> None:
@@ -908,10 +915,15 @@ class ASTConverter:
908
915
  self.fail(
909
916
  message_registry.INVALID_TYPE_IGNORE, ti.lineno, -1, blocker=False
910
917
  )
918
+
911
919
  body = self.fix_function_overloads(
912
920
  self.translate_stmt_list(mod.body, ismodule=True)
913
921
  )
914
- return MypyFile(body, self.imports, False, self.type_ignores)
922
+
923
+ ret = MypyFile(body, self.imports, False, ignored_lines=self.type_ignores)
924
+ ret.is_stub = self.is_stub
925
+ ret.path = self.path
926
+ return ret
915
927
 
916
928
  # --- stmt ---
917
929
  # FunctionDef(identifier name, arguments args,
@@ -967,9 +979,11 @@ class ASTConverter:
967
979
  n.col_offset,
968
980
  )
969
981
  arg_types = [
970
- a.type_annotation
971
- if a.type_annotation is not None
972
- else AnyType(TypeOfAny.unannotated)
982
+ (
983
+ a.type_annotation
984
+ if a.type_annotation is not None
985
+ else AnyType(TypeOfAny.unannotated)
986
+ )
973
987
  for a in args
974
988
  ]
975
989
  else:
@@ -1056,9 +1070,11 @@ class ASTConverter:
1056
1070
  ],
1057
1071
  arg_kinds,
1058
1072
  arg_names,
1059
- return_type
1060
- if return_type is not None
1061
- else AnyType(TypeOfAny.unannotated),
1073
+ (
1074
+ return_type
1075
+ if return_type is not None
1076
+ else AnyType(TypeOfAny.unannotated)
1077
+ ),
1062
1078
  _dummy_fallback,
1063
1079
  )
1064
1080
 
@@ -1905,12 +1921,10 @@ class TypeConverter:
1905
1921
  )
1906
1922
 
1907
1923
  @overload
1908
- def visit(self, node: ast3.expr) -> ProperType:
1909
- ...
1924
+ def visit(self, node: ast3.expr) -> ProperType: ...
1910
1925
 
1911
1926
  @overload
1912
- def visit(self, node: AST | None) -> ProperType | None:
1913
- ...
1927
+ def visit(self, node: AST | None) -> ProperType | None: ...
1914
1928
 
1915
1929
  def visit(self, node: AST | None) -> ProperType | None:
1916
1930
  """Modified visit -- keep track of the stack of nodes"""
@@ -2071,13 +2085,19 @@ class TypeConverter:
2071
2085
 
2072
2086
  # UnaryOp(op, operand)
2073
2087
  def visit_UnaryOp(self, n: UnaryOp) -> Type:
2074
- # We support specifically Literal[-4] and nothing else.
2075
- # For example, Literal[+4] or Literal[~6] is not supported.
2088
+ # We support specifically Literal[-4], Literal[+4], and nothing else.
2089
+ # For example, Literal[~6] or Literal[not False] is not supported.
2076
2090
  typ = self.visit(n.operand)
2077
- if isinstance(typ, RawExpressionType) and isinstance(n.op, USub):
2078
- if isinstance(typ.literal_value, int):
2091
+ if (
2092
+ isinstance(typ, RawExpressionType)
2093
+ # Use type() because we do not want to allow bools.
2094
+ and type(typ.literal_value) is int # noqa: E721
2095
+ ):
2096
+ if isinstance(n.op, USub):
2079
2097
  typ.literal_value *= -1
2080
2098
  return typ
2099
+ if isinstance(n.op, UAdd):
2100
+ return typ
2081
2101
  return self.invalid_type(n)
2082
2102
 
2083
2103
  def numeric_type(self, value: object, n: AST) -> Type:
@@ -563,9 +563,11 @@ class InspectionEngine:
563
563
  self.module = state
564
564
  return (
565
565
  state,
566
- {"out": f"Unknown module: {file}", "err": "", "status": 1}
567
- if state is None
568
- else {},
566
+ (
567
+ {"out": f"Unknown module: {file}", "err": "", "status": 1}
568
+ if state is None
569
+ else {}
570
+ ),
569
571
  )
570
572
 
571
573
  def run_inspection(
@@ -244,13 +244,13 @@ def trivial_join(s: Type, t: Type) -> Type:
244
244
  @overload
245
245
  def join_types(
246
246
  s: ProperType, t: ProperType, instance_joiner: InstanceJoiner | None = None
247
- ) -> ProperType:
248
- ...
247
+ ) -> ProperType: ...
249
248
 
250
249
 
251
250
  @overload
252
- def join_types(s: Type, t: Type, instance_joiner: InstanceJoiner | None = None) -> Type:
253
- ...
251
+ def join_types(
252
+ s: Type, t: Type, instance_joiner: InstanceJoiner | None = None
253
+ ) -> Type: ...
254
254
 
255
255
 
256
256
  def join_types(s: Type, t: Type, instance_joiner: InstanceJoiner | None = None) -> Type:
@@ -173,7 +173,7 @@ def main(
173
173
  sys.exit(code)
174
174
 
175
175
  # HACK: keep res alive so that mypyc won't free it before the hard_exit
176
- list([res])
176
+ list([res]) # noqa: C410
177
177
 
178
178
 
179
179
  def run_build(
@@ -377,14 +377,13 @@ FOOTER: Final = """Environment variables:
377
377
 
378
378
 
379
379
  class CapturableArgumentParser(argparse.ArgumentParser):
380
-
381
380
  """Override ArgumentParser methods that use sys.stdout/sys.stderr directly.
382
381
 
383
382
  This is needed because hijacking sys.std* is not thread-safe,
384
383
  yet output must be captured to properly support mypy.api.run.
385
384
  """
386
385
 
387
- def __init__(self, *args: Any, **kwargs: Any):
386
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
388
387
  self.stdout = kwargs.pop("stdout", sys.stdout)
389
388
  self.stderr = kwargs.pop("stderr", sys.stderr)
390
389
  super().__init__(*args, **kwargs)
@@ -431,7 +430,6 @@ class CapturableArgumentParser(argparse.ArgumentParser):
431
430
 
432
431
 
433
432
  class CapturableVersionAction(argparse.Action):
434
-
435
433
  """Supplement CapturableArgumentParser to handle --version.
436
434
 
437
435
  This is nearly identical to argparse._VersionAction except,
@@ -450,7 +448,7 @@ class CapturableVersionAction(argparse.Action):
450
448
  default: str = argparse.SUPPRESS,
451
449
  help: str = "show program's version number and exit",
452
450
  stdout: IO[str] | None = None,
453
- ):
451
+ ) -> None:
454
452
  super().__init__(
455
453
  option_strings=option_strings,
456
454
  dest=dest,
@@ -1067,7 +1065,7 @@ def process_options(
1067
1065
  parser.add_argument(
1068
1066
  "--enable-incomplete-feature",
1069
1067
  action="append",
1070
- metavar="FEATURE",
1068
+ metavar="{" + ",".join(sorted(INCOMPLETE_FEATURES)) + "}",
1071
1069
  help="Enable support of incomplete/experimental features for early preview",
1072
1070
  )
1073
1071
  internals_group.add_argument(
@@ -1207,6 +1205,8 @@ def process_options(
1207
1205
  parser.add_argument(
1208
1206
  "--semantic-analysis-only", action="store_true", help=argparse.SUPPRESS
1209
1207
  )
1208
+ # Some tests use this to tell mypy that we are running a test.
1209
+ parser.add_argument("--test-env", action="store_true", help=argparse.SUPPRESS)
1210
1210
  # --local-partial-types disallows partial types spanning module top level and a function
1211
1211
  # (implicitly defined in fine-grained incremental mode)
1212
1212
  parser.add_argument(
@@ -58,8 +58,7 @@ RETURN_IN_ASYNC_GENERATOR: Final = ErrorMessage(
58
58
  '"return" with value in async generator is not allowed'
59
59
  )
60
60
  INVALID_RETURN_TYPE_FOR_GENERATOR: Final = ErrorMessage(
61
- 'The return type of a generator function should be "Generator"'
62
- " or one of its supertypes"
61
+ 'The return type of a generator function should be "Generator" or one of its supertypes'
63
62
  )
64
63
  INVALID_RETURN_TYPE_FOR_ASYNC_GENERATOR: Final = ErrorMessage(
65
64
  'The return type of an async generator function should be "AsyncGenerator" or one of its '
@@ -1458,22 +1458,27 @@ class MessageBuilder:
1458
1458
  return target
1459
1459
 
1460
1460
  def incompatible_type_application(
1461
- self, expected_arg_count: int, actual_arg_count: int, context: Context
1461
+ self,
1462
+ min_arg_count: int,
1463
+ max_arg_count: int,
1464
+ actual_arg_count: int,
1465
+ context: Context,
1462
1466
  ) -> None:
1463
- if expected_arg_count == 0:
1467
+ if max_arg_count == 0:
1464
1468
  self.fail(
1465
1469
  "Type application targets a non-generic function or class", context
1466
1470
  )
1467
- elif actual_arg_count > expected_arg_count:
1468
- self.fail(
1469
- f"Type application has too many types ({expected_arg_count} expected)",
1470
- context,
1471
- )
1471
+ return
1472
+
1473
+ if min_arg_count == max_arg_count:
1474
+ s = f"{max_arg_count} expected"
1472
1475
  else:
1473
- self.fail(
1474
- f"Type application has too few types ({expected_arg_count} expected)",
1475
- context,
1476
- )
1476
+ s = f"expected between {min_arg_count} and {max_arg_count}"
1477
+
1478
+ if actual_arg_count > max_arg_count:
1479
+ self.fail(f"Type application has too many types ({s})", context)
1480
+ else:
1481
+ self.fail(f"Type application has too few types ({s})", context)
1477
1482
 
1478
1483
  def could_not_infer_type_arguments(
1479
1484
  self, callee_type: CallableType, n: int, context: Context
@@ -2267,7 +2272,7 @@ class MessageBuilder:
2267
2272
  def impossible_intersection(
2268
2273
  self, formatted_base_class_list: str, reason: str, context: Context
2269
2274
  ) -> None:
2270
- template = "Subclass of {} cannot exist: would have {}"
2275
+ template = "Subclass of {} cannot exist: {}"
2271
2276
  self.fail(
2272
2277
  template.format(formatted_base_class_list, reason),
2273
2278
  context,
@@ -2786,10 +2791,10 @@ def format_type_inner(
2786
2791
  else:
2787
2792
  base_str = itype.type.name
2788
2793
  if not itype.args:
2789
- if not itype.type.has_type_var_tuple_type:
2790
- # No type arguments, just return the type name
2791
- return base_str
2792
- return base_str + "[()]"
2794
+ if itype.type.has_type_var_tuple_type and len(itype.type.type_vars) == 1:
2795
+ return base_str + "[()]"
2796
+ # No type arguments, just return the type name
2797
+ return base_str
2793
2798
  elif itype.type.fullname == "builtins.tuple":
2794
2799
  item_type_str = format(itype.args[0])
2795
2800
  return f"{'tuple' if options.use_lowercase_names() else 'Tuple'}[{item_type_str}, ...]"
@@ -3326,12 +3331,15 @@ def for_function(callee: CallableType) -> str:
3326
3331
  return ""
3327
3332
 
3328
3333
 
3329
- def wrong_type_arg_count(n: int, act: str, name: str) -> str:
3330
- s = f"{n} type arguments"
3331
- if n == 0:
3332
- s = "no type arguments"
3333
- elif n == 1:
3334
- s = "1 type argument"
3334
+ def wrong_type_arg_count(low: int, high: int, act: str, name: str) -> str:
3335
+ if low == high:
3336
+ s = f"{low} type arguments"
3337
+ if low == 0:
3338
+ s = "no type arguments"
3339
+ elif low == 1:
3340
+ s = "1 type argument"
3341
+ else:
3342
+ s = f"between {low} and {high} type arguments"
3335
3343
  if act == "0":
3336
3344
  act = "none"
3337
3345
  return f'"{name}" expects {s}, but {act} given'
@@ -3413,7 +3421,7 @@ def append_invariance_notes(
3413
3421
  ):
3414
3422
  invariant_type = "Dict"
3415
3423
  covariant_suggestion = (
3416
- 'Consider using "Mapping" instead, ' "which is covariant in the value type"
3424
+ 'Consider using "Mapping" instead, which is covariant in the value type'
3417
3425
  )
3418
3426
  if invariant_type and covariant_suggestion:
3419
3427
  notes.append(
@@ -63,8 +63,7 @@ class MetadataStore:
63
63
  """
64
64
 
65
65
  @abstractmethod
66
- def list_all(self) -> Iterable[str]:
67
- ...
66
+ def list_all(self) -> Iterable[str]: ...
68
67
 
69
68
 
70
69
  def random_string() -> str:
@@ -13,18 +13,11 @@ import re
13
13
  import subprocess
14
14
  import sys
15
15
  from enum import Enum, unique
16
-
17
- from mypy.errors import CompileError
18
-
19
- if sys.version_info >= (3, 11):
20
- import tomllib
21
- else:
22
- import tomli as tomllib
23
-
24
16
  from typing import Dict, Final, List, NamedTuple, Optional, Tuple, Union
25
17
  from typing_extensions import TypeAlias as _TypeAlias
26
18
 
27
19
  from mypy import pyinfo
20
+ from mypy.errors import CompileError
28
21
  from mypy.fscache import FileSystemCache
29
22
  from mypy.nodes import MypyFile
30
23
  from mypy.options import Options
@@ -444,7 +437,7 @@ class FindModuleCache:
444
437
  for pkg_dir in self.search_paths.package_path:
445
438
  stub_name = components[0] + "-stubs"
446
439
  stub_dir = os.path.join(pkg_dir, stub_name)
447
- if fscache.isdir(stub_dir) and self._is_compatible_stub_package(stub_dir):
440
+ if fscache.isdir(stub_dir):
448
441
  stub_typed_file = os.path.join(stub_dir, "py.typed")
449
442
  stub_components = [stub_name] + components[1:]
450
443
  path = os.path.join(pkg_dir, *stub_components[:-1])
@@ -586,19 +579,6 @@ class FindModuleCache:
586
579
  else:
587
580
  return ModuleNotFoundReason.NOT_FOUND
588
581
 
589
- def _is_compatible_stub_package(self, stub_dir: str) -> bool:
590
- """Does a stub package support the target Python version?
591
-
592
- Stub packages may contain a metadata file which specifies
593
- whether the stubs are compatible with Python 2 and 3.
594
- """
595
- metadata_fnam = os.path.join(stub_dir, "METADATA.toml")
596
- if not os.path.isfile(metadata_fnam):
597
- return True
598
- with open(metadata_fnam, "rb") as f:
599
- metadata = tomllib.load(f)
600
- return bool(metadata.get("python3", True))
601
-
602
582
  def find_modules_recursive(self, module: str) -> list[BuildSource]:
603
583
  module_path = self.find_module(module)
604
584
  if isinstance(module_path, ModuleNotFoundReason):
@@ -419,7 +419,9 @@ class ImportBase(Statement):
419
419
 
420
420
  __slots__ = ("is_unreachable", "is_top_level", "is_mypy_only", "assignments")
421
421
 
422
- is_unreachable: bool # Set by semanal.SemanticAnalyzerPass1 if inside `if False` etc.
422
+ is_unreachable: (
423
+ bool # Set by semanal.SemanticAnalyzerPass1 if inside `if False` etc.
424
+ )
423
425
  is_top_level: bool # Ditto if outside any class or def
424
426
  is_mypy_only: bool # Ditto if inside `if TYPE_CHECKING` or `if MYPY`
425
427
 
@@ -1178,7 +1180,7 @@ class ClassDef(Statement):
1178
1180
  }
1179
1181
 
1180
1182
  @classmethod
1181
- def deserialize(self, data: JsonDict) -> ClassDef:
1183
+ def deserialize(cls, data: JsonDict) -> ClassDef:
1182
1184
  assert data[".class"] == "ClassDef"
1183
1185
  res = ClassDef(
1184
1186
  data["name"],
@@ -3201,7 +3203,7 @@ class TypeInfo(SymbolNode):
3201
3203
  if name in EXCLUDED_PROTOCOL_ATTRIBUTES:
3202
3204
  continue
3203
3205
  members.add(name)
3204
- return sorted(list(members))
3206
+ return sorted(members)
3205
3207
 
3206
3208
  def __getitem__(self, name: str) -> SymbolTableNode:
3207
3209
  n = self.get(name)
@@ -3348,30 +3350,30 @@ class TypeInfo(SymbolNode):
3348
3350
  "bases": [b.serialize() for b in self.bases],
3349
3351
  "mro": [c.fullname for c in self.mro],
3350
3352
  "_promote": [p.serialize() for p in self._promote],
3351
- "alt_promote": None
3352
- if self.alt_promote is None
3353
- else self.alt_promote.serialize(),
3353
+ "alt_promote": (
3354
+ None if self.alt_promote is None else self.alt_promote.serialize()
3355
+ ),
3354
3356
  "declared_metaclass": (
3355
3357
  None
3356
3358
  if self.declared_metaclass is None
3357
3359
  else self.declared_metaclass.serialize()
3358
3360
  ),
3359
- "metaclass_type": None
3360
- if self.metaclass_type is None
3361
- else self.metaclass_type.serialize(),
3362
- "tuple_type": None
3363
- if self.tuple_type is None
3364
- else self.tuple_type.serialize(),
3365
- "typeddict_type": None
3366
- if self.typeddict_type is None
3367
- else self.typeddict_type.serialize(),
3361
+ "metaclass_type": (
3362
+ None if self.metaclass_type is None else self.metaclass_type.serialize()
3363
+ ),
3364
+ "tuple_type": (
3365
+ None if self.tuple_type is None else self.tuple_type.serialize()
3366
+ ),
3367
+ "typeddict_type": (
3368
+ None if self.typeddict_type is None else self.typeddict_type.serialize()
3369
+ ),
3368
3370
  "flags": get_flags(self, TypeInfo.FLAGS),
3369
3371
  "metadata": self.metadata,
3370
- "slots": list(sorted(self.slots)) if self.slots is not None else None,
3372
+ "slots": sorted(self.slots) if self.slots is not None else None,
3371
3373
  "deletable_attributes": self.deletable_attributes,
3372
- "self_type": self.self_type.serialize()
3373
- if self.self_type is not None
3374
- else None,
3374
+ "self_type": (
3375
+ self.self_type.serialize() if self.self_type is not None else None
3376
+ ),
3375
3377
  "dataclass_transform_spec": (
3376
3378
  self.dataclass_transform_spec.serialize()
3377
3379
  if self.dataclass_transform_spec is not None
@@ -4046,7 +4048,7 @@ class DataclassTransformSpec:
4046
4048
  # frozen_default was added to CPythonin https://github.com/python/cpython/pull/99958 citing
4047
4049
  # positive discussion in typing-sig
4048
4050
  frozen_default: bool | None = None,
4049
- ):
4051
+ ) -> None:
4050
4052
  self.eq_default = eq_default if eq_default is not None else True
4051
4053
  self.order_default = order_default if order_default is not None else False
4052
4054
  self.kw_only_default = kw_only_default if kw_only_default is not None else False
@@ -321,6 +321,10 @@ class Options:
321
321
  # Use stub builtins fixtures to speed up tests
322
322
  self.use_builtins_fixtures = False
323
323
 
324
+ # This should only be set when running certain mypy tests.
325
+ # Use this sparingly to avoid tests diverging from non-test behavior.
326
+ self.test_env = False
327
+
324
328
  # -- experimental options --
325
329
  self.shadow_file: list[list[str]] | None = None
326
330
  self.show_column_numbers: bool = False