Skip to content

Commit 92cdcd7

Browse files
authored
Merge branch 'master' into master
2 parents de4d7d4 + fa01a07 commit 92cdcd7

Some content is hidden

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

42 files changed

+392
-160
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
exclude: '^(mypyc/external/)|(mypy/typeshed/)|misc/typeshed_patches' # Exclude all vendored code from lints
22
repos:
33
- repo: https://github.com/pre-commit/pre-commit-hooks
4-
rev: v4.5.0 # must match test-requirements.txt
4+
rev: v4.5.0
55
hooks:
66
- id: trailing-whitespace
77
- id: end-of-file-fixer
88
- repo: https://github.com/psf/black-pre-commit-mirror
9-
rev: 24.8.0 # must match test-requirements.txt
9+
rev: 24.8.0
1010
hooks:
1111
- id: black
1212
exclude: '^(test-data/)'
1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.6.9 # must match test-requirements.txt
14+
rev: v0.6.9
1515
hooks:
1616
- id: ruff
1717
args: [--exit-non-zero-on-fix]

mypy/checker.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,10 +2367,11 @@ def erase_override(t: Type) -> Type:
23672367
else:
23682368
continue
23692369
if not is_subtype(original_arg_type, erase_override(override_arg_type)):
2370+
context: Context = node
23702371
if isinstance(node, FuncDef) and not node.is_property:
2371-
context: Context = node.arguments[i + len(override.bound_args)]
2372-
else:
2373-
context = node
2372+
arg_node = node.arguments[i + len(override.bound_args)]
2373+
if arg_node.line != -1:
2374+
context = arg_node
23742375
self.msg.argument_incompatible_with_supertype(
23752376
i + 1,
23762377
name,

mypy/checkpattern.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ def visit_or_pattern(self, o: OrPattern) -> PatternType:
158158
for pattern in o.patterns:
159159
pattern_type = self.accept(pattern, current_type)
160160
pattern_types.append(pattern_type)
161-
current_type = pattern_type.rest_type
161+
if not is_uninhabited(pattern_type.type):
162+
current_type = pattern_type.rest_type
162163

163164
#
164165
# Collect the final type
@@ -693,7 +694,9 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType:
693694

694695
def should_self_match(self, typ: Type) -> bool:
695696
typ = get_proper_type(typ)
696-
if isinstance(typ, Instance) and typ.type.is_named_tuple:
697+
if isinstance(typ, Instance) and typ.type.get("__match_args__") is not None:
698+
# Named tuples and other subtypes of builtins that define __match_args__
699+
# should not self match.
697700
return False
698701
for other in self.self_match_types:
699702
if is_subtype(typ, other):

mypy/nodes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1727,7 +1727,7 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
17271727
return visitor.visit_str_expr(self)
17281728

17291729

1730-
def is_StrExpr_list(seq: list[Expression]) -> TypeGuard[list[StrExpr]]:
1730+
def is_StrExpr_list(seq: list[Expression]) -> TypeGuard[list[StrExpr]]: # noqa: N802
17311731
return all(isinstance(item, StrExpr) for item in seq)
17321732

17331733

mypy/stubutil.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,8 @@ def is_not_in_all(self, name: str) -> bool:
832832
return False
833833

834834
def is_private_name(self, name: str, fullname: str | None = None) -> bool:
835+
if "__mypy-" in name:
836+
return True # Never include mypy generated symbols
835837
if self._include_private:
836838
return False
837839
if fullname in self.EXTRA_EXPORTED:

mypy/test/data.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ def __init__(
304304
self.data = data
305305
self.line = line
306306
self.old_cwd: str | None = None
307-
self.tmpdir: tempfile.TemporaryDirectory[str] | None = None
307+
self.tmpdir: str | None = None
308308

309309
def runtest(self) -> None:
310310
if self.skip:
@@ -323,19 +323,19 @@ def runtest(self) -> None:
323323
save_dir: str | None = self.config.getoption("--save-failures-to", None)
324324
if save_dir:
325325
assert self.tmpdir is not None
326-
target_dir = os.path.join(save_dir, os.path.basename(self.tmpdir.name))
326+
target_dir = os.path.join(save_dir, os.path.basename(self.tmpdir))
327327
print(f"Copying data from test {self.name} to {target_dir}")
328328
if not os.path.isabs(target_dir):
329329
assert self.old_cwd
330330
target_dir = os.path.join(self.old_cwd, target_dir)
331-
shutil.copytree(self.tmpdir.name, target_dir)
331+
shutil.copytree(self.tmpdir, target_dir)
332332
raise
333333

334334
def setup(self) -> None:
335335
parse_test_case(case=self)
336336
self.old_cwd = os.getcwd()
337-
self.tmpdir = tempfile.TemporaryDirectory(prefix="mypy-test-")
338-
os.chdir(self.tmpdir.name)
337+
self.tmpdir = tempfile.mkdtemp(prefix="mypy-test-")
338+
os.chdir(self.tmpdir)
339339
os.mkdir(test_temp_dir)
340340

341341
# Precalculate steps for find_steps()
@@ -371,10 +371,7 @@ def teardown(self) -> None:
371371
if self.old_cwd is not None:
372372
os.chdir(self.old_cwd)
373373
if self.tmpdir is not None:
374-
try:
375-
self.tmpdir.cleanup()
376-
except OSError:
377-
pass
374+
shutil.rmtree(self.tmpdir, ignore_errors=True)
378375
self.old_cwd = None
379376
self.tmpdir = None
380377

mypy/test/testfinegrained.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
101101
if messages:
102102
a.extend(normalize_messages(messages))
103103

104-
assert testcase.tmpdir
105-
a.extend(self.maybe_suggest(step, server, main_src, testcase.tmpdir.name))
104+
assert testcase.tmpdir is not None
105+
a.extend(self.maybe_suggest(step, server, main_src, testcase.tmpdir))
106106
a.extend(self.maybe_inspect(step, server, main_src))
107107

108108
if server.fine_grained_manager:
@@ -248,8 +248,8 @@ def perform_step(
248248
new_messages = normalize_messages(new_messages)
249249

250250
a = new_messages
251-
assert testcase.tmpdir
252-
a.extend(self.maybe_suggest(step, server, main_src, testcase.tmpdir.name))
251+
assert testcase.tmpdir is not None
252+
a.extend(self.maybe_suggest(step, server, main_src, testcase.tmpdir))
253253
a.extend(self.maybe_inspect(step, server, main_src))
254254

255255
return a, triggered

mypy/test/teststubgen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ def test(cls, arg0: str) -> None:
987987
def test_generate_c_type_classmethod_with_overloads(self) -> None:
988988
class TestClass:
989989
@classmethod
990-
def test(self, arg0: str) -> None:
990+
def test(cls, arg0: str) -> None:
991991
"""
992992
test(cls, arg0: str)
993993
test(cls, arg0: int)

mypy/typeops.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,8 +650,16 @@ def _remove_redundant_union_items(items: list[Type], keep_erased: bool) -> list[
650650
def _get_type_method_ret_type(t: Type, *, name: str) -> Type | None:
651651
t = get_proper_type(t)
652652

653+
# For Enum literals the ret_type can change based on the Enum
654+
# we need to check the type of the enum rather than the literal
655+
if isinstance(t, LiteralType) and t.is_enum_literal():
656+
t = t.fallback
657+
653658
if isinstance(t, Instance):
654659
sym = t.type.get(name)
660+
# Fallback to the metaclass for the lookup when necessary
661+
if not sym and (m := t.type.metaclass_type):
662+
sym = m.type.get(name)
655663
if sym:
656664
sym_type = get_proper_type(sym.type)
657665
if isinstance(sym_type, CallableType):

mypy/types.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,10 +2818,28 @@ def __init__(
28182818
self.fallback = fallback
28192819
self._hash = -1 # Cached hash value
28202820

2821+
# NOTE: Enum types are always truthy by default, but this can be changed
2822+
# in subclasses, so we need to get the truthyness from the Enum
2823+
# type rather than base it on the value (which is a non-empty
2824+
# string for enums, so always truthy)
2825+
# TODO: We should consider moving this branch to the `can_be_true`
2826+
# `can_be_false` properties instead, so the truthyness only
2827+
# needs to be determined once per set of Enum literals.
2828+
# However, the same can be said for `TypeAliasType` in some
2829+
# cases and we only set the default based on the type it is
2830+
# aliasing. So if we decide to change this, we may want to
2831+
# change that as well. perf_compare output was inconclusive
2832+
# but slightly favored this version, probably because we have
2833+
# almost no test cases where we would redundantly compute
2834+
# `can_be_false`/`can_be_true`.
28212835
def can_be_false_default(self) -> bool:
2836+
if self.fallback.type.is_enum:
2837+
return self.fallback.can_be_false
28222838
return not self.value
28232839

28242840
def can_be_true_default(self) -> bool:
2841+
if self.fallback.type.is_enum:
2842+
return self.fallback.can_be_true
28252843
return bool(self.value)
28262844

28272845
def accept(self, visitor: TypeVisitor[T]) -> T:

0 commit comments

Comments
 (0)