Skip to content

Remove some Python 2 type checking logic #13261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 9 additions & 59 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,10 +469,6 @@ def check_first_pass(self) -> None:
seq_str = self.named_generic_type(
"typing.Sequence", [self.named_type("builtins.str")]
)
if self.options.python_version[0] < 3:
seq_str = self.named_generic_type(
"typing.Sequence", [self.named_type("builtins.unicode")]
)
if not is_subtype(all_.type, seq_str):
str_seq_s, all_s = format_type_distinctly(seq_str, all_.type)
self.fail(
Expand Down Expand Up @@ -1093,18 +1089,6 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str])
if not self.is_generator_return_type(typ.ret_type, defn.is_coroutine):
self.fail(message_registry.INVALID_RETURN_TYPE_FOR_GENERATOR, typ)

# Python 2 generators aren't allowed to return values.
orig_ret_type = get_proper_type(typ.ret_type)
if (
self.options.python_version[0] == 2
and isinstance(orig_ret_type, Instance)
and orig_ret_type.type.fullname == "typing.Generator"
):
if not isinstance(
get_proper_type(orig_ret_type.args[2]), (NoneType, AnyType)
):
self.fail(message_registry.INVALID_GENERATOR_RETURN_ITEM_TYPE, typ)

# Fix the type if decorated with `@types.coroutine` or `@asyncio.coroutine`.
if defn.is_awaitable_coroutine:
# Update the return type to AwaitableGenerator.
Expand Down Expand Up @@ -1145,7 +1129,6 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str])
ref_type = mypy.types.TypeType.make_normalized(ref_type)
erased = get_proper_type(erase_to_bound(arg_type))
if not is_subtype(ref_type, erased, ignore_type_params=True):
note = None
if (
isinstance(erased, Instance)
and erased.type.is_protocol
Expand All @@ -1158,23 +1141,13 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str])
# the consistency check will be performed at call sites.
msg = None
elif typ.arg_names[i] in {"self", "cls"}:
if (
self.options.python_version[0] < 3
and is_same_type(erased, arg_type)
and not isclass
):
msg = message_registry.INVALID_SELF_TYPE_OR_EXTRA_ARG
note = "(Hint: typically annotations omit the type for self)"
else:
msg = message_registry.ERASED_SELF_TYPE_NOT_SUPERTYPE.format(
erased, ref_type
)
msg = message_registry.ERASED_SELF_TYPE_NOT_SUPERTYPE.format(
erased, ref_type
)
else:
msg = message_registry.MISSING_OR_INVALID_SELF_TYPE
if msg:
self.fail(msg, defn)
if note:
self.note(note, defn)
elif isinstance(arg_type, TypeVarType):
# Refuse covariant parameter type variables
# TODO: check recursively for inner type variables
Expand Down Expand Up @@ -1287,16 +1260,10 @@ def check_default_args(self, item: FuncItem, body_is_trivial: bool) -> None:
)

def is_forward_op_method(self, method_name: str) -> bool:
if self.options.python_version[0] == 2 and method_name == "__div__":
return True
else:
return method_name in operators.reverse_op_methods
return method_name in operators.reverse_op_methods

def is_reverse_op_method(self, method_name: str) -> bool:
if self.options.python_version[0] == 2 and method_name == "__rdiv__":
return True
else:
return method_name in operators.reverse_op_method_set
return method_name in operators.reverse_op_method_set

def check_for_missing_annotations(self, fdef: FuncItem) -> None:
# Check for functions with unspecified/not fully specified types.
Expand Down Expand Up @@ -1459,10 +1426,7 @@ def check_reverse_op_method(
)
assert len(reverse_type.arg_types) >= 2

if self.options.python_version[0] == 2 and reverse_name == "__rdiv__":
forward_name = "__div__"
else:
forward_name = operators.normal_from_reverse_op[reverse_name]
forward_name = operators.normal_from_reverse_op[reverse_name]
forward_inst = get_proper_type(reverse_type.arg_types[1])
if isinstance(forward_inst, TypeVarType):
forward_inst = get_proper_type(forward_inst.upper_bound)
Expand Down Expand Up @@ -4198,20 +4162,10 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None:
self.accept(s.handlers[i])
var = s.vars[i]
if var:
# Exception variables are deleted in python 3 but not python 2.
# But, since it's bad form in python 2 and the type checking
# wouldn't work very well, we delete it anyway.

# Exception variables are deleted.
# Unfortunately, this doesn't let us detect usage before the
# try/except block.
if self.options.python_version[0] >= 3:
source = var.name
else:
source = (
'(exception variable "{}", which we do not '
"accept outside except: blocks even in "
"python 2)".format(var.name)
)
source = var.name
if isinstance(var.node, Var):
var.node.type = DeletedType(source=source)
self.binder.cleanse(var)
Expand Down Expand Up @@ -4302,11 +4256,7 @@ def analyze_iterable_item_type(self, expr: Expression) -> Tuple[Type, Type]:
return iterator, joined
else:
# Non-tuple iterable.
if self.options.python_version[0] >= 3:
nextmethod = "__next__"
else:
nextmethod = "next"
return iterator, echk.check_method_call_by_name(nextmethod, iterator, [], [], expr)[0]
return iterator, echk.check_method_call_by_name("__next__", iterator, [], [], expr)[0]

def analyze_container_item_type(self, typ: Type) -> Optional[Type]:
"""Check if a type is a nominal container of a union of such.
Expand Down
7 changes: 0 additions & 7 deletions mypy/message_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage":
'The return type of an async generator function should be "AsyncGenerator" or one of its '
"supertypes"
)
INVALID_GENERATOR_RETURN_ITEM_TYPE: Final = ErrorMessage(
"The return type of a generator function must be None in"
" its third type parameter in Python 2"
)
YIELD_VALUE_EXPECTED: Final = ErrorMessage("Yield value expected")
INCOMPATIBLE_TYPES: Final = "Incompatible types"
INCOMPATIBLE_TYPES_IN_ASSIGNMENT: Final = "Incompatible types in assignment"
Expand Down Expand Up @@ -203,9 +199,6 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage":
ERASED_SELF_TYPE_NOT_SUPERTYPE: Final = ErrorMessage(
'The erased type of self "{}" is not a supertype of its class "{}"'
)
INVALID_SELF_TYPE_OR_EXTRA_ARG: Final = ErrorMessage(
"Invalid type for self, or extra argument type in function annotation"
)

# Final
CANNOT_INHERIT_FROM_FINAL: Final = ErrorMessage('Cannot inherit from final class "{}"')
Expand Down