Skip to content

Commit bc27977

Browse files
Merge branch 'master' into builtins-folding
2 parents 148cc5f + 44bbb18 commit bc27977

40 files changed

+2664
-124
lines changed

.github/workflows/mypy_primer.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ jobs:
6767
--debug \
6868
--additional-flags="--debug-serialize" \
6969
--output concise \
70+
--mypy-install-librt \
7071
| tee diff_${{ matrix.shard-index }}.txt
7172
) || [ $? -eq 1 ]
7273
- if: ${{ matrix.shard-index == 0 }}

docs/source/command_line.rst

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ definitions or calls.
372372

373373
.. option:: --untyped-calls-exclude
374374

375-
This flag allows to selectively disable :option:`--disallow-untyped-calls`
375+
This flag allows one to selectively disable :option:`--disallow-untyped-calls`
376376
for functions and methods defined in specific packages, modules, or classes.
377377
Note that each exclude entry acts as a prefix. For example (assuming there
378378
are no type annotations for ``third_party_lib`` available):
@@ -562,7 +562,7 @@ potentially problematic or redundant in some way.
562562

563563
.. option:: --deprecated-calls-exclude
564564

565-
This flag allows to selectively disable :ref:`deprecated<code-deprecated>` warnings
565+
This flag allows one to selectively disable :ref:`deprecated<code-deprecated>` warnings
566566
for functions and methods defined in specific packages, modules, or classes.
567567
Note that each exclude entry acts as a prefix. For example (assuming ``foo.A.func`` is deprecated):
568568

@@ -1255,12 +1255,18 @@ Miscellaneous
12551255
stub packages were found, they are installed and then another run
12561256
is performed.
12571257

1258-
.. option:: --junit-xml JUNIT_XML
1258+
.. option:: --junit-xml JUNIT_XML_OUTPUT_FILE
12591259

12601260
Causes mypy to generate a JUnit XML test result document with
12611261
type checking results. This can make it easier to integrate mypy
12621262
with continuous integration (CI) tools.
12631263

1264+
.. option:: --junit-format {global,per_file}
1265+
1266+
If --junit-xml is set, specifies format.
1267+
global (default): single test with all errors;
1268+
per_file: one test entry per file with failures.
1269+
12641270
.. option:: --find-occurrences CLASS.MEMBER
12651271

12661272
This flag will make mypy print out all usages of a class member

docs/source/config_file.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,15 @@ These options may only be set in the global section (``[mypy]``).
11531153
type checking results. This can make it easier to integrate mypy
11541154
with continuous integration (CI) tools.
11551155

1156+
.. confval:: junit_format
1157+
1158+
:type: string
1159+
:default: ``global``
1160+
1161+
If junit_xml is set, specifies format.
1162+
global (default): single test with all errors;
1163+
per_file: one test entry per file with failures.
1164+
11561165
.. confval:: scripts_are_modules
11571166

11581167
:type: boolean

docs/source/error_code_list.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,8 +1032,8 @@ Warn about top level await expressions [top-level-await]
10321032
This error code is separate from the general ``[syntax]`` errors, because in
10331033
some environments (e.g. IPython) a top level ``await`` is allowed. In such
10341034
environments a user may want to use ``--disable-error-code=top-level-await``,
1035-
that allows to still have errors for other improper uses of ``await``, for
1036-
example:
1035+
which allows one to still have errors for other improper uses of ``await``,
1036+
for example:
10371037

10381038
.. code-block:: python
10391039

docs/source/mypy_daemon.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,16 @@ command.
252252
Statically inspect expressions
253253
******************************
254254

255-
The daemon allows to get declared or inferred type of an expression (or other
255+
The daemon allows one to get the declared or inferred type of an expression (or other
256256
information about an expression, such as known attributes or definition location)
257-
using ``dmypy inspect LOCATION`` command. The location of the expression should be
257+
using the ``dmypy inspect LOCATION`` command. The location of the expression should be
258258
specified in the format ``path/to/file.py:line:column[:end_line:end_column]``.
259259
Both line and column are 1-based. Both start and end position are inclusive.
260260
These rules match how mypy prints the error location in error messages.
261261

262262
If a span is given (i.e. all 4 numbers), then only an exactly matching expression
263263
is inspected. If only a position is given (i.e. 2 numbers, line and column), mypy
264-
will inspect all *expressions*, that include this position, starting from the
264+
will inspect all expressions that include this position, starting from the
265265
innermost one.
266266

267267
Consider this Python code snippet:

misc/analyze_cache.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def extract(chunks: Iterable[JsonDict]) -> Iterable[JsonDict]:
4141
if isinstance(chunk, dict):
4242
yield chunk
4343
yield from extract(chunk.values())
44-
elif isinstance(chunk, list):
44+
elif isinstance(chunk, list): # type: ignore[unreachable] #TODO: is this actually unreachable, or are our types wrong?
4545
yield from extract(chunk)
4646

4747
yield from extract([chunk.data for chunk in chunks])
@@ -93,7 +93,7 @@ def compress(chunk: JsonDict) -> JsonDict:
9393
def helper(chunk: JsonDict) -> JsonDict:
9494
nonlocal counter
9595
if not isinstance(chunk, dict):
96-
return chunk
96+
return chunk # type: ignore[unreachable] #TODO: is this actually unreachable, or are our types wrong?
9797

9898
if len(chunk) <= 2:
9999
return chunk
@@ -124,7 +124,7 @@ def decompress(chunk: JsonDict) -> JsonDict:
124124

125125
def helper(chunk: JsonDict) -> JsonDict:
126126
if not isinstance(chunk, dict):
127-
return chunk
127+
return chunk # type: ignore[unreachable] #TODO: is this actually unreachable, or are our types wrong?
128128
if ".id" in chunk:
129129
return cache[chunk[".id"]]
130130

misc/profile_check.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,22 @@ def check_requirements() -> None:
7878
if sys.platform != "linux":
7979
# TODO: How to make this work on other platforms?
8080
sys.exit("error: Only Linux is supported")
81-
82-
try:
83-
subprocess.run(["perf", "-h"], capture_output=True)
84-
except (subprocess.CalledProcessError, FileNotFoundError):
85-
print("error: The 'perf' profiler is not installed")
86-
sys.exit(1)
87-
88-
try:
89-
subprocess.run(["clang", "--version"], capture_output=True)
90-
except (subprocess.CalledProcessError, FileNotFoundError):
91-
print("error: The clang compiler is not installed")
92-
sys.exit(1)
93-
94-
if not os.path.isfile("mypy_self_check.ini"):
95-
print("error: Run this in the mypy repository root")
96-
sys.exit(1)
81+
else: # fun fact/todo: we have to use else here, because of https://github.com/python/mypy/issues/10773
82+
try:
83+
subprocess.run(["perf", "-h"], capture_output=True)
84+
except (subprocess.CalledProcessError, FileNotFoundError):
85+
print("error: The 'perf' profiler is not installed")
86+
sys.exit(1)
87+
88+
try:
89+
subprocess.run(["clang", "--version"], capture_output=True)
90+
except (subprocess.CalledProcessError, FileNotFoundError):
91+
print("error: The clang compiler is not installed")
92+
sys.exit(1)
93+
94+
if not os.path.isfile("mypy_self_check.ini"):
95+
print("error: Run this in the mypy repository root")
96+
sys.exit(1)
9797

9898

9999
def main() -> None:

mypy/build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3488,7 +3488,7 @@ def process_stale_scc(graph: Graph, scc: list[str], manager: BuildManager) -> No
34883488

34893489

34903490
def sorted_components(
3491-
graph: Graph, vertices: AbstractSet[str] | None = None, pri_max: int = PRI_ALL
3491+
graph: Graph, vertices: AbstractSet[str] | None = None, pri_max: int = PRI_INDIRECT
34923492
) -> list[AbstractSet[str]]:
34933493
"""Return the graph's SCCs, topologically sorted by dependencies.
34943494

mypy/errorcodes.py

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -52,32 +52,28 @@ def __hash__(self) -> int:
5252

5353
ATTR_DEFINED: Final = ErrorCode("attr-defined", "Check that attribute exists", "General")
5454
NAME_DEFINED: Final = ErrorCode("name-defined", "Check that name is defined", "General")
55-
CALL_ARG: Final[ErrorCode] = ErrorCode(
55+
CALL_ARG: Final = ErrorCode(
5656
"call-arg", "Check number, names and kinds of arguments in calls", "General"
5757
)
5858
ARG_TYPE: Final = ErrorCode("arg-type", "Check argument types in calls", "General")
5959
CALL_OVERLOAD: Final = ErrorCode(
6060
"call-overload", "Check that an overload variant matches arguments", "General"
6161
)
62-
VALID_TYPE: Final[ErrorCode] = ErrorCode(
63-
"valid-type", "Check that type (annotation) is valid", "General"
64-
)
62+
VALID_TYPE: Final = ErrorCode("valid-type", "Check that type (annotation) is valid", "General")
6563
VAR_ANNOTATED: Final = ErrorCode(
6664
"var-annotated", "Require variable annotation if type can't be inferred", "General"
6765
)
6866
OVERRIDE: Final = ErrorCode(
6967
"override", "Check that method override is compatible with base class", "General"
7068
)
71-
RETURN: Final[ErrorCode] = ErrorCode(
72-
"return", "Check that function always returns a value", "General"
73-
)
74-
RETURN_VALUE: Final[ErrorCode] = ErrorCode(
69+
RETURN: Final = ErrorCode("return", "Check that function always returns a value", "General")
70+
RETURN_VALUE: Final = ErrorCode(
7571
"return-value", "Check that return value is compatible with signature", "General"
7672
)
77-
ASSIGNMENT: Final[ErrorCode] = ErrorCode(
73+
ASSIGNMENT: Final = ErrorCode(
7874
"assignment", "Check that assigned value is compatible with target", "General"
7975
)
80-
METHOD_ASSIGN: Final[ErrorCode] = ErrorCode(
76+
METHOD_ASSIGN: Final = ErrorCode(
8177
"method-assign",
8278
"Check that assignment target is not a method",
8379
"General",
@@ -143,9 +139,7 @@ def __hash__(self) -> int:
143139
UNUSED_COROUTINE: Final = ErrorCode(
144140
"unused-coroutine", "Ensure that all coroutines are used", "General"
145141
)
146-
# TODO: why do we need the explicit type here? Without it mypyc CI builds fail with
147-
# mypy/message_registry.py:37: error: Cannot determine type of "EMPTY_BODY" [has-type]
148-
EMPTY_BODY: Final[ErrorCode] = ErrorCode(
142+
EMPTY_BODY: Final = ErrorCode(
149143
"empty-body",
150144
"A dedicated error code to opt out return errors for empty/trivial bodies",
151145
"General",
@@ -160,7 +154,7 @@ def __hash__(self) -> int:
160154
"await-not-async", 'Warn about "await" outside coroutine ("async def")', "General"
161155
)
162156
# These error codes aren't enabled by default.
163-
NO_UNTYPED_DEF: Final[ErrorCode] = ErrorCode(
157+
NO_UNTYPED_DEF: Final = ErrorCode(
164158
"no-untyped-def", "Check that every function has an annotation", "General"
165159
)
166160
NO_UNTYPED_CALL: Final = ErrorCode(
@@ -186,13 +180,13 @@ def __hash__(self) -> int:
186180
UNREACHABLE: Final = ErrorCode(
187181
"unreachable", "Warn about unreachable statements or expressions", "General"
188182
)
189-
ANNOTATION_UNCHECKED = ErrorCode(
183+
ANNOTATION_UNCHECKED: Final = ErrorCode(
190184
"annotation-unchecked", "Notify about type annotations in unchecked functions", "General"
191185
)
192-
TYPEDDICT_READONLY_MUTATED = ErrorCode(
186+
TYPEDDICT_READONLY_MUTATED: Final = ErrorCode(
193187
"typeddict-readonly-mutated", "TypedDict's ReadOnly key is mutated", "General"
194188
)
195-
POSSIBLY_UNDEFINED: Final[ErrorCode] = ErrorCode(
189+
POSSIBLY_UNDEFINED: Final = ErrorCode(
196190
"possibly-undefined",
197191
"Warn about variables that are defined only in some execution paths",
198192
"General",
@@ -201,18 +195,18 @@ def __hash__(self) -> int:
201195
REDUNDANT_EXPR: Final = ErrorCode(
202196
"redundant-expr", "Warn about redundant expressions", "General", default_enabled=False
203197
)
204-
TRUTHY_BOOL: Final[ErrorCode] = ErrorCode(
198+
TRUTHY_BOOL: Final = ErrorCode(
205199
"truthy-bool",
206200
"Warn about expressions that could always evaluate to true in boolean contexts",
207201
"General",
208202
default_enabled=False,
209203
)
210-
TRUTHY_FUNCTION: Final[ErrorCode] = ErrorCode(
204+
TRUTHY_FUNCTION: Final = ErrorCode(
211205
"truthy-function",
212206
"Warn about function that always evaluate to true in boolean contexts",
213207
"General",
214208
)
215-
TRUTHY_ITERABLE: Final[ErrorCode] = ErrorCode(
209+
TRUTHY_ITERABLE: Final = ErrorCode(
216210
"truthy-iterable",
217211
"Warn about Iterable expressions that could always evaluate to true in boolean contexts",
218212
"General",
@@ -238,13 +232,13 @@ def __hash__(self) -> int:
238232
"General",
239233
default_enabled=False,
240234
)
241-
REDUNDANT_SELF_TYPE = ErrorCode(
235+
REDUNDANT_SELF_TYPE: Final = ErrorCode(
242236
"redundant-self",
243237
"Warn about redundant Self type annotations on method first argument",
244238
"General",
245239
default_enabled=False,
246240
)
247-
USED_BEFORE_DEF: Final[ErrorCode] = ErrorCode(
241+
USED_BEFORE_DEF: Final = ErrorCode(
248242
"used-before-def", "Warn about variables that are used before they are defined", "General"
249243
)
250244
UNUSED_IGNORE: Final = ErrorCode(
@@ -262,7 +256,7 @@ def __hash__(self) -> int:
262256
"General",
263257
default_enabled=False,
264258
)
265-
MUTABLE_OVERRIDE: Final[ErrorCode] = ErrorCode(
259+
MUTABLE_OVERRIDE: Final = ErrorCode(
266260
"mutable-override",
267261
"Reject covariant overrides for mutable attributes",
268262
"General",
@@ -274,42 +268,41 @@ def __hash__(self) -> int:
274268
"General",
275269
default_enabled=False,
276270
)
277-
METACLASS: Final[ErrorCode] = ErrorCode("metaclass", "Ensure that metaclass is valid", "General")
271+
METACLASS: Final = ErrorCode("metaclass", "Ensure that metaclass is valid", "General")
278272

279273
# Syntax errors are often blocking.
280-
SYNTAX: Final[ErrorCode] = ErrorCode("syntax", "Report syntax errors", "General")
274+
SYNTAX: Final = ErrorCode("syntax", "Report syntax errors", "General")
281275

282276
# This is an internal marker code for a whole-file ignore. It is not intended to
283277
# be user-visible.
284278
FILE: Final = ErrorCode("file", "Internal marker for a whole file being ignored", "General")
285279
del error_codes[FILE.code]
286280

287281
# This is a catch-all for remaining uncategorized errors.
288-
MISC: Final[ErrorCode] = ErrorCode("misc", "Miscellaneous other checks", "General")
282+
MISC: Final = ErrorCode("misc", "Miscellaneous other checks", "General")
289283

290-
OVERLOAD_CANNOT_MATCH: Final[ErrorCode] = ErrorCode(
284+
OVERLOAD_CANNOT_MATCH: Final = ErrorCode(
291285
"overload-cannot-match",
292286
"Warn if an @overload signature can never be matched",
293287
"General",
294288
sub_code_of=MISC,
295289
)
296290

297-
298-
OVERLOAD_OVERLAP: Final[ErrorCode] = ErrorCode(
291+
OVERLOAD_OVERLAP: Final = ErrorCode(
299292
"overload-overlap",
300293
"Warn if multiple @overload variants overlap in unsafe ways",
301294
"General",
302295
sub_code_of=MISC,
303296
)
304297

305-
PROPERTY_DECORATOR = ErrorCode(
298+
PROPERTY_DECORATOR: Final = ErrorCode(
306299
"prop-decorator",
307300
"Decorators on top of @property are not supported",
308301
"General",
309302
sub_code_of=MISC,
310303
)
311304

312-
NARROWED_TYPE_NOT_SUBTYPE: Final[ErrorCode] = ErrorCode(
305+
NARROWED_TYPE_NOT_SUBTYPE: Final = ErrorCode(
313306
"narrowed-type-not-subtype",
314307
"Warn if a TypeIs function's narrowed type is not a subtype of the original type",
315308
"General",

mypy/main.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,12 +1165,16 @@ def add_invertible_flag(
11651165

11661166
misc_group = parser.add_argument_group(title="Miscellaneous")
11671167
misc_group.add_argument("--quickstart-file", help=argparse.SUPPRESS)
1168-
misc_group.add_argument("--junit-xml", help="Write junit.xml to the given file")
1169-
imports_group.add_argument(
1168+
misc_group.add_argument(
1169+
"--junit-xml",
1170+
metavar="JUNIT_XML_OUTPUT_FILE",
1171+
help="Write a JUnit XML test result document with type checking results to the given file",
1172+
)
1173+
misc_group.add_argument(
11701174
"--junit-format",
11711175
choices=["global", "per_file"],
11721176
default="global",
1173-
help="If --junit-xml is set, specifies format. global: single test with all errors; per_file: one test entry per file with failures",
1177+
help="If --junit-xml is set, specifies format. global (default): single test with all errors; per_file: one test entry per file with failures",
11741178
)
11751179
misc_group.add_argument(
11761180
"--find-occurrences",

0 commit comments

Comments
 (0)