Skip to content

Commit 764492d

Browse files
Merge branch 'master' into cli
2 parents 6c8d1c8 + feeb3f0 commit 764492d

23 files changed

+184
-129
lines changed

CHANGELOG.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
## Next Release
44

5-
## Mypy 1.18
5+
## Mypy 1.18.1
66

7-
We’ve just uploaded mypy 1.18 to the Python Package Index ([PyPI](https://pypi.org/project/mypy/)).
7+
We’ve just uploaded mypy 1.18.1 to the Python Package Index ([PyPI](https://pypi.org/project/mypy/)).
88
Mypy is a static type checker for Python. This release includes new features, performance
99
improvements and bug fixes. You can install it as follows:
1010

@@ -14,7 +14,7 @@ You can read the full documentation for this release on [Read the Docs](http://m
1414

1515
### Mypy Performance Improvements
1616

17-
Mypy 1.18 includes numerous performance improvements, resulting in about 40% speedup
17+
Mypy 1.18.1 includes numerous performance improvements, resulting in about 40% speedup
1818
compared to 1.17 when type checking mypy itself. In extreme cases, the improvement
1919
can be 10x or higher. The list below is an overview of the various mypy optimizations.
2020
Many mypyc improvements (discussed in a separate section below) also improve performance.
@@ -283,6 +283,12 @@ Related PRs:
283283

284284
Please see [git log](https://github.com/python/typeshed/commits/main?after=2480d7e7c74493a024eaf254c5d2c6f452c80ee2+0&branch=main&path=stdlib) for full list of standard library typeshed stub changes.
285285

286+
### Mypy 1.18.2
287+
288+
- Fix crash on recursive alias (Ivan Levkivskyi, PR [19845](https://github.com/python/mypy/pull/19845))
289+
- Add additional guidance for stubtest errors when runtime is `object.__init__` (Stephen Morton, PR [19733](https://github.com/python/mypy/pull/19733))
290+
- Fix handling of None values in f-string expressions in mypyc (BobTheBuidler, PR [19846](https://github.com/python/mypy/pull/19846))
291+
286292
### Acknowledgements
287293

288294
Thanks to all mypy contributors who contributed to this release:

docs/source/command_line.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,12 +1263,23 @@ Miscellaneous
12631263
stub packages were found, they are installed and then another run
12641264
is performed.
12651265

1266-
.. option:: --junit-xml JUNIT_XML
1266+
.. option:: --junit-xml JUNIT_XML_OUTPUT_FILE
12671267

12681268
Causes mypy to generate a JUnit XML test result document with
12691269
type checking results. This can make it easier to integrate mypy
12701270
with continuous integration (CI) tools.
12711271

1272+
.. option:: --junit-format {global,per_file}
1273+
1274+
If --junit-xml is set, specifies format.
1275+
global (default): single test with all errors;
1276+
per_file: one test entry per file with failures.
1277+
1278+
.. option:: --find-occurrences CLASS.MEMBER
1279+
1280+
This flag will make mypy print out all usages of a class member
1281+
based on static type information. This feature is experimental.
1282+
12721283
.. option:: --scripts-are-modules
12731284

12741285
This flag will give command line arguments that appear to be

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

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/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 & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,14 +1270,16 @@ def add_invertible_flag(
12701270

12711271
misc_group = parser.add_argument_group(title="Miscellaneous")
12721272
misc_group.add_argument("--quickstart-file", help=argparse.SUPPRESS)
1273-
misc_group.add_argument("--junit-xml", help="Write junit.xml to the given file")
1274-
imports_group.add_argument(
1273+
misc_group.add_argument(
1274+
"--junit-xml",
1275+
metavar="JUNIT_XML_OUTPUT_FILE",
1276+
help="Write a JUnit XML test result document with type checking results to the given file",
1277+
)
1278+
misc_group.add_argument(
12751279
"--junit-format",
12761280
choices=["global", "per_file"],
12771281
default="global",
1278-
help="If --junit-xml is set, specifies format."
1279-
+ " global: single test with all errors;"
1280-
+ " per_file: one test entry per file with failures",
1282+
help="If --junit-xml is set, specifies format. global (default): single test with all errors; per_file: one test entry per file with failures",
12811283
)
12821284
misc_group.add_argument(
12831285
"--scripts-are-modules",

mypy/message_registry.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
from typing import Final, NamedTuple
1212

1313
from mypy import errorcodes as codes
14+
from mypy.errorcodes import ErrorCode
1415

1516

1617
class ErrorMessage(NamedTuple):
1718
value: str
18-
code: codes.ErrorCode | None = None
19+
code: ErrorCode | None = None
1920

2021
def format(self, *args: object, **kwargs: object) -> ErrorMessage:
2122
return ErrorMessage(self.value.format(*args, **kwargs), code=self.code)

mypy/typeshed/stdlib/asyncio/events.pyi

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -602,18 +602,25 @@ class AbstractEventLoop:
602602
@abstractmethod
603603
async def shutdown_default_executor(self) -> None: ...
604604

605-
# This class does not exist at runtime, but stubtest complains if it's marked as
606-
# @type_check_only because it has an alias that does exist at runtime. See mypy#19568.
607-
# @type_check_only
608-
class _AbstractEventLoopPolicy:
609-
@abstractmethod
610-
def get_event_loop(self) -> AbstractEventLoop: ...
611-
@abstractmethod
612-
def set_event_loop(self, loop: AbstractEventLoop | None) -> None: ...
613-
@abstractmethod
614-
def new_event_loop(self) -> AbstractEventLoop: ...
615-
# Child processes handling (Unix only).
616-
if sys.version_info < (3, 14):
605+
if sys.version_info >= (3, 14):
606+
class _AbstractEventLoopPolicy:
607+
@abstractmethod
608+
def get_event_loop(self) -> AbstractEventLoop: ...
609+
@abstractmethod
610+
def set_event_loop(self, loop: AbstractEventLoop | None) -> None: ...
611+
@abstractmethod
612+
def new_event_loop(self) -> AbstractEventLoop: ...
613+
614+
else:
615+
@type_check_only
616+
class _AbstractEventLoopPolicy:
617+
@abstractmethod
618+
def get_event_loop(self) -> AbstractEventLoop: ...
619+
@abstractmethod
620+
def set_event_loop(self, loop: AbstractEventLoop | None) -> None: ...
621+
@abstractmethod
622+
def new_event_loop(self) -> AbstractEventLoop: ...
623+
# Child processes handling (Unix only).
617624
if sys.version_info >= (3, 12):
618625
@abstractmethod
619626
@deprecated("Deprecated since Python 3.12; removed in Python 3.14.")
@@ -627,7 +634,6 @@ class _AbstractEventLoopPolicy:
627634
@abstractmethod
628635
def set_child_watcher(self, watcher: AbstractChildWatcher) -> None: ...
629636

630-
if sys.version_info < (3, 14):
631637
AbstractEventLoopPolicy = _AbstractEventLoopPolicy
632638

633639
if sys.version_info >= (3, 14):

0 commit comments

Comments
 (0)