Skip to content

selfcheck: Enable the redundant-expr error code #13547

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 6 commits into from
Aug 31, 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
2 changes: 1 addition & 1 deletion build-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-r mypy-requirements.txt
types-psutil
types-setuptools
types-typed-ast>=1.5.0,<1.6.0
types-typed-ast>=1.5.8,<1.6.0
10 changes: 7 additions & 3 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1292,11 +1292,15 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> CacheMeta | No
)

# Don't check for path match, that is dealt with in validate_meta().
#
# TODO: these `type: ignore`s wouldn't be necessary
# if the type annotations for CacheMeta were more accurate
# (all of these attributes can be `None`)
if (
m.id != id
or m.mtime is None
or m.size is None
or m.dependencies is None
or m.mtime is None # type: ignore[redundant-expr]
or m.size is None # type: ignore[redundant-expr]
or m.dependencies is None # type: ignore[redundant-expr]
or m.data_mtime is None
):
manager.log(f"Metadata abandoned for {id}: attributes are missing")
Expand Down
12 changes: 4 additions & 8 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1311,7 +1311,7 @@ def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None:
bound_type = bind_self(typ, self_type, is_classmethod=True)
# Check that __new__ (after binding cls) returns an instance
# type (or any).
if isinstance(fdef.info, TypeInfo) and fdef.info.is_metaclass():
if fdef.info.is_metaclass():
# This is a metaclass, so it must return a new unrelated type.
self.check_subtype(
bound_type.ret_type,
Expand Down Expand Up @@ -1899,7 +1899,7 @@ def check_override(
):
fail = True
op_method_wider_note = True
if isinstance(original, FunctionLike) and isinstance(override, FunctionLike):
if isinstance(override, FunctionLike):
if original_class_or_static and not override_class_or_static:
fail = True
elif isinstance(original, CallableType) and isinstance(override, CallableType):
Expand Down Expand Up @@ -2802,12 +2802,8 @@ def check_compatibility_all_supers(
# The type of "__slots__" and some other attributes usually doesn't need to
# be compatible with a base class. We'll still check the type of "__slots__"
# against "object" as an exception.
if (
isinstance(lvalue_node, Var)
and lvalue_node.allow_incompatible_override
and not (
lvalue_node.name == "__slots__" and base.fullname == "builtins.object"
)
if lvalue_node.allow_incompatible_override and not (
lvalue_node.name == "__slots__" and base.fullname == "builtins.object"
):
continue

Expand Down
2 changes: 1 addition & 1 deletion mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ def analyze_instance_member_access(
# the first argument.
pass
else:
if isinstance(signature, FunctionLike) and name != "__call__":
if name != "__call__":
# TODO: use proper treatment of special methods on unions instead
# of this hack here and below (i.e. mx.self_type).
dispatched_type = meet.meet_types(mx.original_type, typ)
Expand Down
10 changes: 4 additions & 6 deletions mypy/fastparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ def _check_ifstmt_for_overloads(
if stmt.else_body is None:
return overload_name

if isinstance(stmt.else_body, Block) and len(stmt.else_body.body) == 1:
if len(stmt.else_body.body) == 1:
# For elif: else_body contains an IfStmt itself -> do a recursive check.
if (
isinstance(stmt.else_body.body[0], (Decorator, FuncDef, OverloadedFuncDef))
Expand Down Expand Up @@ -901,13 +901,11 @@ def do_func_def(
# PEP 484 disallows both type annotations and type comments
if n.returns or any(a.type_annotation is not None for a in args):
self.fail(message_registry.DUPLICATE_TYPE_SIGNATURES, lineno, n.col_offset)
translated_args = TypeConverter(
translated_args: list[Type] = TypeConverter(
self.errors, line=lineno, override_column=n.col_offset
).translate_expr_list(func_type_ast.argtypes)
arg_types = [
a if a is not None else AnyType(TypeOfAny.unannotated)
for a in translated_args
]
# Use a cast to work around `list` invariance
arg_types = cast(List[Optional[Type]], translated_args)
return_type = TypeConverter(self.errors, line=lineno).visit(func_type_ast.returns)

# add implicit self type
Expand Down
8 changes: 2 additions & 6 deletions mypy/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -2475,11 +2475,7 @@ def [T <: int] f(self, x: int, y: T) -> None
slash = True

# If we got a "special arg" (i.e: self, cls, etc...), prepend it to the arg list
if (
isinstance(tp.definition, FuncDef)
and tp.definition.name is not None
and hasattr(tp.definition, "arguments")
):
if isinstance(tp.definition, FuncDef) and hasattr(tp.definition, "arguments"):
definition_arg_names = [arg.variable.name for arg in tp.definition.arguments]
if (
len(definition_arg_names) > len(tp.arg_names)
Expand Down Expand Up @@ -2671,7 +2667,7 @@ def find_defining_module(modules: dict[str, MypyFile], typ: CallableType) -> Myp
if not typ.definition:
return None
fullname = typ.definition.fullname
if fullname is not None and "." in fullname:
if "." in fullname:
for i in range(fullname.count(".")):
module_name = fullname.rsplit(".", i + 1)[0]
try:
Expand Down
5 changes: 4 additions & 1 deletion mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3580,7 +3580,10 @@ def serialize(self, prefix: str, name: str) -> JsonDict:
if prefix is not None:
fullname = self.node.fullname
if (
fullname is not None
# See the comment above SymbolNode.fullname -- fullname can often be None,
# but for complex reasons it's annotated as being `Bogus[str]` instead of `str | None`,
# meaning mypy erroneously thinks the `fullname is not None` check here is redundant
fullname is not None # type: ignore[redundant-expr]
and "." in fullname
and fullname != prefix + "." + name
and not (isinstance(self.node, Var) and self.node.from_module_getattr)
Expand Down
2 changes: 1 addition & 1 deletion mypy/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ def visit_func_def(self, defn: FuncDef) -> None:
if cur_indent is None:
# Consume the line, but don't mark it as belonging to the function yet.
cur_line += 1
elif start_indent is not None and cur_indent > start_indent:
elif cur_indent > start_indent:
# A non-blank line that belongs to the function.
cur_line += 1
end_line = cur_line
Expand Down
2 changes: 1 addition & 1 deletion mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -5889,7 +5889,7 @@ def in_checked_function(self) -> bool:
current_index = len(self.function_stack) - 1
while current_index >= 0:
current_func = self.function_stack[current_index]
if isinstance(current_func, FuncItem) and not isinstance(current_func, LambdaExpr):
if not isinstance(current_func, LambdaExpr):
return not current_func.is_dynamic()

# Special case, `lambda` inherits the "checked" state from its parent.
Expand Down
6 changes: 2 additions & 4 deletions mypy/stubgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ def visit_overloaded_func_def(self, o: OverloadedFuncDef) -> None:
self.visit_func_def(item.func, is_abstract=is_abstract, is_overload=is_overload)
if is_overload:
overload_chain = True
elif overload_chain and is_overload:
elif is_overload:
self.visit_func_def(item.func, is_abstract=is_abstract, is_overload=is_overload)
else:
# skip the overload implementation and clear the decorator we just processed
Expand Down Expand Up @@ -725,9 +725,7 @@ def visit_func_def(
retname = None # implicit Any
else:
retname = self.print_annotation(o.unanalyzed_type.ret_type)
elif isinstance(o, FuncDef) and (
o.abstract_status == IS_ABSTRACT or o.name in METHODS_WITH_RETURN_VALUE
):
elif o.abstract_status == IS_ABSTRACT or o.name in METHODS_WITH_RETURN_VALUE:
# Always assume abstract methods return Any unless explicitly annotated. Also
# some dunder methods should not have a None return type.
retname = None # implicit Any
Expand Down
2 changes: 1 addition & 1 deletion mypy/test/testsemanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ class TypeInfoMap(Dict[str, TypeInfo]):
def __str__(self) -> str:
a: list[str] = ["TypeInfoMap("]
for x, y in sorted(self.items()):
if isinstance(x, str) and (
if (
not x.startswith("builtins.")
and not x.startswith("typing.")
and not x.startswith("abc.")
Expand Down
2 changes: 1 addition & 1 deletion mypy/test/testtypegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
# Filter nodes that should be included in the output.
keys = []
for node in nodes:
if node.line is not None and node.line != -1 and map[node]:
if node.line != -1 and map[node]:
if ignore_node(node) or node in ignored:
continue
if re.match(mask, short_type(node)) or (
Expand Down
2 changes: 1 addition & 1 deletion mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1939,7 +1939,7 @@ def with_unpacked_kwargs(self) -> NormalizedCallableType:
if not self.unpack_kwargs:
return NormalizedCallableType(self.copy_modified())
last_type = get_proper_type(self.arg_types[-1])
assert isinstance(last_type, ProperType) and isinstance(last_type, TypedDictType)
assert isinstance(last_type, TypedDictType)
extra_kinds = [
ArgKind.ARG_NAMED if name in last_type.required_keys else ArgKind.ARG_NAMED_OPT
for name in last_type.items
Expand Down
2 changes: 1 addition & 1 deletion mypy_self_check.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ always_false = MYPYC
plugins = misc/proper_plugin.py
python_version = 3.7
exclude = mypy/typeshed/|mypyc/test-data/|mypyc/lib-rt/
enable_error_code = ignore-without-code
enable_error_code = ignore-without-code,redundant-expr