Skip to content

Commit 81c7052

Browse files
Merge remote-tracking branch 'upstream/master' into jam
2 parents 513bb30 + 6267911 commit 81c7052

144 files changed

Lines changed: 5150 additions & 1093 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,18 @@ Please see [git log](https://github.com/python/typeshed/commits/main?after=f8f07
578578
- Allow dangerous identity comparisons to `Any` typed variables (Shantanu, PR [21142](https://github.com/python/mypy/pull/21142))
579579
- `--warn-unused-config` should not be a strict flag (Ivan Levkivskyi, PR [21139](https://github.com/python/mypy/pull/21139))
580580

581+
### Mypy 1.20.2
582+
583+
- Use WAL with SQLite cache and fix close (Shantanu, PR [21154](https://github.com/python/mypy/pull/21154))
584+
- Adjust SQLite journal mode (Ivan Levkivskyi, PR [21217](https://github.com/python/mypy/pull/21217))
585+
- Correctly aggregate narrowing information on parent expressions (Shantanu, PR [21206](https://github.com/python/mypy/pull/21206))
586+
- Fix regression related to generic callables (Shantanu, PR [21208](https://github.com/python/mypy/pull/21208))
587+
- Fix regression by avoiding widening types in some contexts (Shantanu, PR [21242](https://github.com/python/mypy/pull/21242))
588+
- Fix slicing in non-strict optional mode (Shantanu, PR [21282](https://github.com/python/mypy/pull/21282))
589+
- mypyc: Fix match statement semantics for "or" pattern (Shantanu, PR [21156](https://github.com/python/mypy/pull/21156))
590+
- mypyc: Fix issue with module dunder attributes (Piotr Sawicki, PR [21275](https://github.com/python/mypy/pull/21275))
591+
- Initial support for Python 3.15.0a8 (Marc Mueller, PR [21255](https://github.com/python/mypy/pull/21255))
592+
581593
### Acknowledgements
582594

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

docs/source/command_line.rst

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ of the above sections.
595595
This flag causes mypy to suppress errors caused by not being able to fully
596596
infer the types of global and class variables.
597597

598-
.. option:: --allow-redefinition-new
598+
.. option:: --allow-redefinition
599599

600600
By default, mypy won't allow a variable to be redefined with an
601601
unrelated type. This flag enables the redefinition of *unannotated*
@@ -613,7 +613,7 @@ of the above sections.
613613
# Type of "x" is "int | str" here.
614614
return x
615615
616-
Without the new flag, mypy only supports inferring optional types
616+
Without this flag, mypy only supports inferring optional types
617617
(``X | None``) from multiple assignments. With this option enabled,
618618
mypy can infer arbitrary union types.
619619

@@ -646,24 +646,21 @@ of the above sections.
646646
Note: We are planning to turn this flag on by default in a future mypy
647647
release.
648648

649-
.. option:: --allow-redefinition
649+
.. option:: --allow-redefinition-new
650650

651-
This is an alias to :option:`--allow-redefinition-old <mypy --allow-redefinition-old>`.
652-
In mypy v2.0 this will point to
653-
:option:`--allow-redefinition-new <mypy --allow-redefinition-new>`, and will
654-
eventually became the default.
651+
Deprecated alias for :option:`--allow-redefinition <mypy --allow-redefinition>`.
655652

656653
.. option:: --allow-redefinition-old
657654

658-
This is an older variant of
659-
:option:`--allow-redefinition-new <mypy --allow-redefinition-new>`.
655+
This is an older, more limited variant of
656+
:option:`--allow-redefinition <mypy --allow-redefinition>`.
660657
This flag enables redefinition of a variable with an
661658
arbitrary type *in some contexts*: only redefinitions within the
662659
same block and nesting depth as the original definition are allowed.
663660

664-
We have no plans to remove this flag, but we expect that
665-
:option:`--allow-redefinition-new <mypy --allow-redefinition-new>`
666-
will replace this flag for new use cases eventually.
661+
We have no plans to remove this flag, but
662+
:option:`--allow-redefinition <mypy --allow-redefinition>`
663+
is recommended for new use cases.
667664

668665
Example where this can be useful:
669666

docs/source/common_issues.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,7 @@ improved performance. You can ensure the presence of orjson using the ``faster-c
232232

233233
python3 -m pip install -U mypy[faster-cache]
234234

235-
Mypy may depend on orjson by default in the future. To use faster, native parser, use the
236-
``native-parse`` extra. Native parser will be default in near future.
235+
Mypy may depend on orjson by default in the future.
237236

238237
Types of empty collections
239238
--------------------------

docs/source/config_file.rst

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ section of the command line docs.
713713
Causes mypy to suppress errors caused by not being able to fully
714714
infer the types of global and class variables.
715715

716-
.. confval:: allow_redefinition_new
716+
.. confval:: allow_redefinition
717717

718718
:type: boolean
719719
:default: False
@@ -763,6 +763,13 @@ section of the command line docs.
763763
Note: We are planning to turn this flag on by default in a future mypy
764764
release.
765765

766+
.. confval:: allow_redefinition_new
767+
768+
:type: boolean
769+
:default: False
770+
771+
Deprecated alias for :confval:`allow_redefinition`.
772+
766773
.. confval:: allow_redefinition_old
767774

768775
:type: boolean
@@ -789,14 +796,6 @@ section of the command line docs.
789796
items = "100" # valid, items now has type str
790797
items = int(items) # valid, items now has type int
791798
792-
.. confval:: allow_redefinition
793-
794-
:type: boolean
795-
:default: False
796-
797-
An alias to :confval:`allow_redefinition_old`, in mypy v2.0 this will point to
798-
:confval:`allow_redefinition_new`, and will eventually became the default.
799-
800799
.. confval:: local_partial_types
801800

802801
:type: boolean

misc/apply-cache-diff.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,22 @@
1919
from librt.internal import ReadBuffer
2020

2121
from mypy.cache import CacheMeta
22+
from mypy.defaults import SQLITE_NUM_SHARDS
2223
from mypy.metastore import FilesystemMetadataStore, MetadataStore, SqliteMetadataStore
2324
from mypy.util import json_dumps, json_loads
2425

2526

26-
def make_cache(input_dir: str, sqlite: bool) -> MetadataStore:
27+
def make_cache(input_dir: str, sqlite: bool, num_shards: int = SQLITE_NUM_SHARDS) -> MetadataStore:
2728
if sqlite:
28-
return SqliteMetadataStore(input_dir)
29+
return SqliteMetadataStore(input_dir, num_shards=num_shards)
2930
else:
3031
return FilesystemMetadataStore(input_dir)
3132

3233

33-
def apply_diff(cache_dir: str, diff_file: str, sqlite: bool = False) -> None:
34-
cache = make_cache(cache_dir, sqlite)
34+
def apply_diff(
35+
cache_dir: str, diff_file: str, sqlite: bool = False, num_shards: int = SQLITE_NUM_SHARDS
36+
) -> None:
37+
cache = make_cache(cache_dir, sqlite, num_shards=num_shards)
3538
with open(diff_file, "rb") as f:
3639
diff = json_loads(f.read())
3740

@@ -63,11 +66,14 @@ def apply_diff(cache_dir: str, diff_file: str, sqlite: bool = False) -> None:
6366
def main() -> None:
6467
parser = argparse.ArgumentParser()
6568
parser.add_argument("--sqlite", action="store_true", default=False, help="Use a sqlite cache")
69+
parser.add_argument(
70+
"--num-shards", type=int, default=SQLITE_NUM_SHARDS, help=argparse.SUPPRESS
71+
)
6672
parser.add_argument("cache_dir", help="Directory for the cache")
6773
parser.add_argument("diff", help="Cache diff file")
6874
args = parser.parse_args()
6975

70-
apply_diff(args.cache_dir, args.diff, args.sqlite)
76+
apply_diff(args.cache_dir, args.diff, args.sqlite, num_shards=args.num_shards)
7177

7278

7379
if __name__ == "__main__":

misc/convert-cache.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import argparse
1717

18+
from mypy.defaults import SQLITE_NUM_SHARDS
1819
from mypy.metastore import FilesystemMetadataStore, MetadataStore, SqliteMetadataStore
1920

2021

@@ -26,6 +27,13 @@ def main() -> None:
2627
default=False,
2728
help="Convert to a sqlite cache (default: convert from)",
2829
)
30+
parser.add_argument(
31+
"--num-shards",
32+
type=int,
33+
default=SQLITE_NUM_SHARDS,
34+
dest="num_shards",
35+
help=argparse.SUPPRESS,
36+
)
2937
parser.add_argument(
3038
"--output_dir",
3139
action="store",
@@ -37,17 +45,23 @@ def main() -> None:
3745

3846
input_dir = args.input_dir
3947
output_dir = args.output_dir or input_dir
48+
num_shards = args.num_shards
4049
assert os.path.isdir(output_dir), f"{output_dir} is not a directory"
4150
if args.to_sqlite:
4251
input: MetadataStore = FilesystemMetadataStore(input_dir)
43-
output: MetadataStore = SqliteMetadataStore(output_dir)
52+
output: MetadataStore = SqliteMetadataStore(output_dir, num_shards=num_shards)
4453
else:
45-
fnam = os.path.join(input_dir, "cache.db")
46-
msg = f"{fnam} does not exist"
47-
if not re.match(r"[0-9]+\.[0-9]+$", os.path.basename(input_dir)):
48-
msg += f" (are you missing Python version at the end, e.g. {input_dir}/3.11)"
49-
assert os.path.isfile(fnam), msg
50-
input, output = SqliteMetadataStore(input_dir), FilesystemMetadataStore(output_dir)
54+
if num_shards <= 1:
55+
db_files = [os.path.join(input_dir, "cache.db")]
56+
else:
57+
db_files = [os.path.join(input_dir, f"cache.{i}.db") for i in range(num_shards)]
58+
for fnam in db_files:
59+
msg = f"{fnam} does not exist"
60+
if not re.match(r"[0-9]+\.[0-9]+$", os.path.basename(input_dir)):
61+
msg += f" (are you missing Python version at the end, e.g. {input_dir}/3.11)"
62+
assert os.path.isfile(fnam), msg
63+
input = SqliteMetadataStore(input_dir, num_shards=num_shards)
64+
output = FilesystemMetadataStore(output_dir)
5165

5266
for s in input.list_all():
5367
if s.endswith((".json", ".ff")):

misc/diff-cache.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
from librt.internal import ReadBuffer, WriteBuffer
2020

2121
from mypy.cache import CacheMeta, CacheMetaEx
22+
from mypy.defaults import SQLITE_NUM_SHARDS
2223
from mypy.metastore import FilesystemMetadataStore, MetadataStore, SqliteMetadataStore
2324
from mypy.util import json_dumps, json_loads
2425

2526

26-
def make_cache(input_dir: str, sqlite: bool) -> MetadataStore:
27+
def make_cache(input_dir: str, sqlite: bool, num_shards: int = SQLITE_NUM_SHARDS) -> MetadataStore:
2728
if sqlite:
28-
return SqliteMetadataStore(input_dir)
29+
return SqliteMetadataStore(input_dir, num_shards=num_shards)
2930
else:
3031
return FilesystemMetadataStore(input_dir)
3132

@@ -154,13 +155,16 @@ def main() -> None:
154155
parser = argparse.ArgumentParser()
155156
parser.add_argument("--verbose", action="store_true", default=False, help="Increase verbosity")
156157
parser.add_argument("--sqlite", action="store_true", default=False, help="Use a sqlite cache")
158+
parser.add_argument(
159+
"--num-shards", type=int, default=SQLITE_NUM_SHARDS, help=argparse.SUPPRESS
160+
)
157161
parser.add_argument("input_dir1", help="Input directory for the original cache")
158162
parser.add_argument("input_dir2", help="Input directory for the target cache")
159163
parser.add_argument("output", help="Output file with the diff from original cache")
160164
args = parser.parse_args()
161165

162-
cache1 = make_cache(args.input_dir1, args.sqlite)
163-
cache2 = make_cache(args.input_dir2, args.sqlite)
166+
cache1 = make_cache(args.input_dir1, args.sqlite, num_shards=args.num_shards)
167+
cache2 = make_cache(args.input_dir2, args.sqlite, num_shards=args.num_shards)
164168

165169
type_misses: dict[str, int] = defaultdict(int)
166170
type_hits: dict[str, int] = defaultdict(int)

mypy-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ mypy_extensions>=1.0.0
66
pathspec>=1.0.0
77
tomli>=1.1.0; python_version<'3.11'
88
librt>=0.9.0; platform_python_implementation != 'PyPy'
9+
ast-serialize>=0.2.2,<1.0.0

mypy/__main__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import sys
77
import traceback
88

9+
from mypy.fscache import FileSystemCache
910
from mypy.main import main, process_options
1011
from mypy.util import FancyFormatter
1112

@@ -22,7 +23,8 @@ def console_entry() -> None:
2223
os.dup2(devnull, sys.stdout.fileno())
2324
sys.exit(2)
2425
except KeyboardInterrupt:
25-
_, options = process_options(args=sys.argv[1:])
26+
# Setting fscache prevents bogus errors when --package-root is set.
27+
_, options = process_options(args=sys.argv[1:], fscache=FileSystemCache())
2628
if options.show_traceback:
2729
sys.stdout.write(traceback.format_exc())
2830
formatter = FancyFormatter(sys.stdout, sys.stderr, False)
@@ -36,7 +38,7 @@ def console_entry() -> None:
3638
try:
3739
import mypy.errors
3840

39-
_, options = process_options(args=sys.argv[1:])
41+
_, options = process_options(args=sys.argv[1:], fscache=FileSystemCache())
4042
mypy.errors.report_internal_error(e, None, 0, None, options)
4143
except Exception:
4244
pass

mypy/binder.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from collections import defaultdict
44
from collections.abc import Iterator
55
from contextlib import contextmanager
6-
from typing import Literal, NamedTuple, TypeAlias as _TypeAlias
6+
from typing import Final, Literal, TypeAlias as _TypeAlias
77

88
from mypy.erasetype import remove_instance_last_known_values
99
from mypy.literals import Key, extract_var_from_literal_hash, literal, literal_hash, subkeys
@@ -42,9 +42,10 @@
4242
BindableExpression: _TypeAlias = IndexExpr | MemberExpr | NameExpr
4343

4444

45-
class CurrentType(NamedTuple):
46-
type: Type
47-
from_assignment: bool
45+
class CurrentType:
46+
def __init__(self, type: Type, from_assignment: bool) -> None:
47+
self.type: Final = type
48+
self.from_assignment: Final = from_assignment
4849

4950

5051
class Frame:
@@ -199,8 +200,8 @@ def __init__(self, options: Options) -> None:
199200

200201
# If True, initial assignment to a simple variable (e.g. "x", but not "x.y")
201202
# is added to the binder. This allows more precise narrowing and more
202-
# flexible inference of variable types (--allow-redefinition-new).
203-
self.bind_all = options.allow_redefinition_new
203+
# flexible inference of variable types (--allow-redefinition).
204+
self.bind_all = options.allow_redefinition
204205

205206
# This tracks any externally visible changes in binder to invalidate
206207
# expression caches when needed.
@@ -339,7 +340,7 @@ def update_from_options(self, frames: list[Frame]) -> bool:
339340
continue
340341

341342
# Remove exact duplicates to save pointless work later, this is
342-
# a micro-optimization for --allow-redefinition-new.
343+
# a micro-optimization for --allow-redefinition.
343344
seen_types = set()
344345
resulting_types = []
345346
for rv in resulting_values:

0 commit comments

Comments
 (0)