8000 Fix tests and typing · python/mypy@42b3aa6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 42b3aa6

Browse files
committed
Fix tests and typing
1 parent 41e00fc commit 42b3aa6

File tree

2 files changed

+29
-24
lines changed

2 files changed

+29
-24
lines changed

mypy/checker.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
Any, Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple, Iterator,
1010
Iterable, Sequence, Mapping, Generic, AbstractSet, Callable, overload
1111
)
12-
from typing_extensions import Final, TypeAlias as _TypeAlias
12+
from typing_extensions import Final, TypeAlias as _TypeAlias, TypeGuard
1313

1414
from mypy.backports import nullcontext
1515
from mypy.errors import Errors, report_internal_error
@@ -4703,7 +4703,7 @@ def is_narrowable_literal(expr: Expression) -> bool:
47034703
not is_literal_none(expr) and
47044704
not is_literal_enum(type_map, expr))
47054705

4706-
def is_len_of_narrowable_literal(expr: Expression) -> bool:
4706+
def is_len_of_narrowable_literal(expr: Expression) -> TypeGuard[CallExpr]:
47074707
return (
47084708
isinstance(expr, CallExpr) and
47094709
refers_to_fullname(expr.callee, 'builtins.len') and
@@ -5268,15 +5268,16 @@ def refine_len_comparison_expression(self,
52685268
too aggressive of a narrowing, depending on context.
52695269
"""
52705270

5271-
target = None # type: Optional[int]
5272-
target_index = None # type: Optional[int]
5271+
target: Optional[int] = None
5272+
target_index: Optional[int] = None
52735273
possible_target_indices = []
52745274
for i in chain_indices:
52755275
expr_type = operand_types[i]
52765276
expr_type = coerce_to_literal(expr_type)
5277-
if not isinstance(get_proper_type(expr_type), LiteralType):
5277+
proper_type = get_proper_type(expr_type)
5278+
if not isinstance(proper_type, LiteralType):
52785279
continue
5279-
if target and target != expr_type.value:
5280+
if target and target != proper_type.value:
52805281
if operator in {'==', '!='}:
52815282
# We have multiple different target values. So the 'if' branch
52825283
# must be unreachable.
@@ -5285,7 +5286,7 @@ def refine_len_comparison_expression(self,
52855286
# Other operators can go either way
52865287
return {}, {}
52875288

5288-
target = expr_type.value
5289+
target = proper_type.value #type: ignore[assignment]
52895290
target_index = i
52905291
possible_target_indices.append(i)
52915292

@@ -5300,7 +5301,8 @@ def refine_len_comparison_expression(self,
53005301
if i not in narrowable_operand_indices:
53015302
continue
53025303

5303-
expr = operands[i].args[0]
5304+
# we already checked that operand[i] is CallExpr since it is narrowable
5305+
expr = operands[i].args[0] #type: ignore[attr-defined]
53045306
expr_type = self.type_map[expr]
53055307

53065308
# We intentionally use 'conditional_type_map' directly here instead of
@@ -5314,8 +5316,9 @@ def refine_len_comparison_expression(self,
53145316
def narrow_type_by_length(self, operator: str, typ: Type, length: int) -> Type:
53155317
if operator not in {"==", "!="}:
53165318
return typ
5317-
if (isinstance(typ, Instance) and typ.type.fullname == "builtins.tuple" and length >= 0):
5318-
return TupleType(typ.args[0:1] * length, self.named_type('builtins.tuple'))
5319+
proper_type = get_proper_type(typ)
5320+
if (isinstance(proper_type, Instance) and proper_type.type.fullname == "builtins.tuple" and length >= 0):
5321+
return TupleType([proper_type.args[0]] * length, self.named_type('builtins.tuple'))
53195322
return typ
53205323

53215324
def conditional_len_map(self,
@@ -5324,7 +5327,7 @@ def conditional_len_map(self,
53245327
current_type: Optional[Type],
53255328
expr_index: int,
53265329
length: Optional[int],
5327-
target_index: int,
5330+
target_index: Optional[int],
53285331
) -> Tuple[TypeMap, TypeMap]:
53295332
"""Takes in an expression, the current type of the expression, and a
53305333
proposed length of that expression.
@@ -5333,8 +5336,9 @@ def conditional_len_map(self,
53335336
the proposed type, if the expression can be the proposed length. The
53345337
second element is a map from the expression to the type it would hold
53355338
if it was not the proposed length, if any. None means bot, {} means top"""
5336-
if length is not None and current_type is not None:
5337-
if isinstance(current_type, AnyType):
5339+
if length is not None and current_type is not None and target_index is not None:
5340+
proper_type = get_proper_type(current_type)
5341+
if isinstance(proper_type, AnyType):
53385342
# We don't really know much about the proposed type, so we shouldn't
53395343
# attempt to narrow anything. Instead, we broaden the expr to Any to
53405344
# avoid false positives
@@ -5373,10 +5377,10 @@ def conditional_len_map(self,
53735377
remaining_type = make_simplified_union([
53745378
typ for typ, l in zip(possible_types, len_of_types)
53755379
if l is None or not length_op(l, length)])
5376-
if_map = (
5380+
if_map: TypeMap = (
53775381
{} if is_same_type(proposed_type, current_type)
53785382
else {expr: proposed_type})
5379-
else_map = (
5383+
else_map: TypeMap = (
53805384
{} if is_same_type(remaining_type, current_type)
53815385
else {expr: remaining_type})
53825386
return if_map, else_map
@@ -5964,13 +5968,14 @@ def conditional_types_to_typemaps(expr: Expression,
59645968
return cast(Tuple[TypeMap, TypeMap], tuple(maps))
59655969

59665970

5967-
def len_of_type(typ: Type) -> int:
5971+
def len_of_type(typ: Type) -> Optional[int]:
59685972
"""Takes a type and returns an int that represents the length
59695973
of instances of that type or None if not applicable or variant length"""
5970-
if isinstance(typ, TupleType):
5971-
return len(typ.items)
5972-
if isinstance(typ, LiteralType) and isinstance(typ.value, str):
5973-
return len(typ.value)
5974+
proper_type = get_proper_type(typ)
5975+
if isinstance(proper_type, TupleType):
5976+
return len(proper_type.items)
5977+
if isinstance(proper_type, LiteralType) and isinstance(proper_type.value, str):
5978+
return len(proper_type.value)
59745979
return None
59755980

59765981

test-data/unit/check-narrowing.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,10 +1285,10 @@ x = make_tuple()
12851285
if len(x) == 3:
12861286
reveal_type(x) # N: Revealed type is "Tuple[builtins.int, builtins.int, builtins.int]"
12871287
else:
1288-
reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int]"
1288+
reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
12891289

12901290
if len(x) != 3:
1291-
reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int]"
1291+
reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
12921292
else:
12931293
reveal_type(x) # N: Revealed type is "Tuple[builtins.int, builtins.int, builtins.int]"
12941294
[builtins fixtures/len.pyi]
@@ -1402,7 +1402,7 @@ def make_tuple() -> VarTuple:
14021402

14031403
x = make_tuple()
14041404
if len(x) < 3:
1405-
reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int]"
1405+
reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
14061406
else:
1407-
reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int]"
1407+
reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
14081408
[builtins fixtures/len.pyi]

0 commit comments

Comments
 (0)
0