Skip to content

Simplify boolean return logic #14012

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 16 commits into from
Nov 10, 2022
Merged
9 changes: 4 additions & 5 deletions misc/fix_annotate.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ def has_return_exprs(self, node):
results = {}
if self.return_expr.match(node, results):
return True
for child in node.children:
if child.type not in (syms.funcdef, syms.classdef):
if self.has_return_exprs(child):
return True
return False
return any(
child.type not in (syms.funcdef, syms.classdef) and self.has_return_exprs(child)
for child in node.children
)
20 changes: 9 additions & 11 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2728,11 +2728,8 @@ def in_partial_package(id: str, manager: BuildManager) -> bool:
else:
parent_mod = parent_st.tree
if parent_mod is not None:
if parent_mod.is_partial_stub_package:
return True
else:
# Bail out soon, complete subpackage found
return False
# Bail out soon, complete subpackage found
return parent_mod.is_partial_stub_package
id = parent
return False

Expand Down Expand Up @@ -3576,9 +3573,10 @@ def record_missing_stub_packages(cache_dir: str, missing_stub_packages: set[str]


def is_silent_import_module(manager: BuildManager, path: str) -> bool:
if not manager.options.no_silence_site_packages:
for dir in manager.search_paths.package_path + manager.search_paths.typeshed_path:
if is_sub_path(path, dir):
# Silence errors in site-package dirs and typeshed
return True
return False
if manager.options.no_silence_site_packages:
return False
# Silence errors in site-package dirs and typeshed
return any(
is_sub_path(path, dir)
for dir in manager.search_paths.package_path + manager.search_paths.typeshed_path
)
24 changes: 8 additions & 16 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2292,9 +2292,7 @@ def is_final_enum_value(self, sym: SymbolTableNode) -> bool:
):
return False

if self.is_stub or sym.node.has_explicit_value:
return True
return False
return self.is_stub or sym.node.has_explicit_value

def check_enum_bases(self, defn: ClassDef) -> None:
"""
Expand Down Expand Up @@ -5978,10 +5976,7 @@ def store_type(self, node: Expression, typ: Type) -> None:
self._type_maps[-1][node] = typ

def has_type(self, node: Expression) -> bool:
for m in reversed(self._type_maps):
if node in m:
return True
return False
return any(node in m for m in reversed(self._type_maps))

def lookup_type_or_none(self, node: Expression) -> Type | None:
for m in reversed(self._type_maps):
Expand Down Expand Up @@ -6152,13 +6147,11 @@ def handle_partial_var_type(
return fixup_partial_type(typ)

def is_defined_in_base_class(self, var: Var) -> bool:
if var.info:
for base in var.info.mro[1:]:
if base.get(var.name) is not None:
return True
if var.info.fallback_to_any:
return True
return False
if not var.info:
return False
return var.info.fallback_to_any or any(
base.get(var.name) is not None for base in var.info.mro[1:]
)

def find_partial_types(self, var: Var) -> dict[Var, Context] | None:
"""Look for an active partial type scope containing variable.
Expand Down Expand Up @@ -6354,8 +6347,7 @@ def is_writable_attribute(self, node: Node) -> bool:
elif isinstance(node, OverloadedFuncDef) and node.is_property:
first_item = cast(Decorator, node.items[0])
return first_item.var.is_settable_property
else:
return False
return False

def get_isinstance_type(self, expr: Expression) -> list[TypeRange] | None:
if isinstance(expr, OpExpr) and expr.op == "|":
Expand Down
23 changes: 10 additions & 13 deletions mypy/modulefinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,11 @@ def __init__(self, sources: list[BuildSource]) -> None:
self.source_modules[source.module] = source.path or ""

def is_source(self, file: MypyFile) -> bool:
if file.path and file.path in self.source_paths:
return True
elif file._fullname in self.source_modules:
return True
elif self.source_text_present:
return True
else:
return False
return (
(file.path and file.path in self.source_paths)
or file._fullname in self.source_modules
or self.source_text_present
)


class FindModuleCache:
Expand Down Expand Up @@ -569,11 +566,11 @@ def _is_compatible_stub_package(self, stub_dir: str) -> bool:
whether the stubs are compatible with Python 2 and 3.
"""
metadata_fnam = os.path.join(stub_dir, "METADATA.toml")
if os.path.isfile(metadata_fnam):
with open(metadata_fnam, "rb") as f:
metadata = tomllib.load(f)
return bool(metadata.get("python3", True))
return True
if not os.path.isfile(metadata_fnam):
return True
with open(metadata_fnam, "rb") as f:
metadata = tomllib.load(f)
return bool(metadata.get("python3", True))

def find_modules_recursive(self, module: str) -> list[BuildSource]:
module_path = self.find_module(module)
Expand Down
5 changes: 1 addition & 4 deletions mypy/stubgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1309,10 +1309,7 @@ def is_private_name(self, name: str, fullname: str | None = None) -> bool:

def is_private_member(self, fullname: str) -> bool:
parts = fullname.split(".")
for part in parts:
if self.is_private_name(part):
return True
return False
return any(self.is_private_name(part) for part in parts)

def get_str_type_of_node(
self, rvalue: Expression, can_infer_optional: bool = False, can_be_any: bool = True
Expand Down
34 changes: 11 additions & 23 deletions mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,22 +429,18 @@ def visit_erased_type(self, left: ErasedType) -> bool:
# This may be encountered during type inference. The result probably doesn't
# matter much.
# TODO: it actually does matter, figure out more principled logic about this.
if self.subtype_context.keep_erased_types:
return False
return True
return not self.subtype_context.keep_erased_types

def visit_deleted_type(self, left: DeletedType) -> bool:
return True

def visit_instance(self, left: Instance) -> bool:
if left.type.fallback_to_any and not self.proper_subtype:
if isinstance(self.right, NoneType):
# NOTE: `None` is a *non-subclassable* singleton, therefore no class
# can by a subtype of it, even with an `Any` fallback.
# This special case is needed to treat descriptors in classes with
# dynamic base classes correctly, see #5456.
return False
return True
# NOTE: `None` is a *non-subclassable* singleton, therefore no class
# can by a subtype of it, even with an `Any` fallback.
# This special case is needed to treat descriptors in classes with
# dynamic base classes correctly, see #5456.
return not isinstance(self.right, NoneType)
right = self.right
if isinstance(right, TupleType) and mypy.typeops.tuple_fallback(right).type.is_enum:
return self._is_subtype(left, mypy.typeops.tuple_fallback(right))
Expand Down Expand Up @@ -513,11 +509,7 @@ def check_mixed(
isinstance(unpacked_type, Instance)
and unpacked_type.type.fullname == "builtins.tuple"
):
if not all(
is_equivalent(l, unpacked_type.args[0]) for l in compare_to
):
return False
return True
return all(is_equivalent(l, unpacked_type.args[0]) for l in compare_to)
if isinstance(unpacked_type, TypeVarTupleType):
return False
if isinstance(unpacked_type, AnyType):
Expand Down Expand Up @@ -741,9 +733,8 @@ def visit_tuple_type(self, left: TupleType) -> bool:
elif isinstance(right, TupleType):
if len(left.items) != len(right.items):
return False
for l, r in zip(left.items, right.items):
if not self._is_subtype(l, r):
return False
if any(not self._is_subtype(l, r) for l, r in zip(left.items, right.items)):
return False
rfallback = mypy.typeops.tuple_fallback(right)
if is_named_instance(rfallback, "builtins.tuple"):
# No need to verify fallback. This is useful since the calculated fallback
Expand All @@ -752,9 +743,7 @@ def visit_tuple_type(self, left: TupleType) -> bool:
# join(Union[int, C], Union[str, C]) == Union[int, str, C].
return True
lfallback = mypy.typeops.tuple_fallback(left)
if not self._is_subtype(lfallback, rfallback):
return False
return True
return self._is_subtype(lfallback, rfallback)
else:
return False

Expand Down Expand Up @@ -1368,8 +1357,7 @@ def g(x: int) -> int: ...
unified = unify_generic_callable(left, right, ignore_return=ignore_return)
if unified is None:
return False
else:
left = unified
left = unified

# If we allow partial overlaps, we don't need to leave R generic:
# if we can find even just a single typevar assignment which
Expand Down
4 changes: 1 addition & 3 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1729,9 +1729,7 @@ def __init__(
def _seems_like_callable(self, type: UnboundType) -> bool:
if not type.args:
return False
if isinstance(type.args[0], (EllipsisType, TypeList, ParamSpecType)):
return True
return False
return isinstance(type.args[0], (EllipsisType, TypeList, ParamSpecType))

def visit_unbound_type(self, t: UnboundType) -> TypeVarLikeList:
name = t.name
Expand Down
47 changes: 23 additions & 24 deletions mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,12 @@ def __repr__(self) -> str:
return self.raw_id.__repr__()

def __eq__(self, other: object) -> bool:
if isinstance(other, TypeVarId):
return (
self.raw_id == other.raw_id
and self.meta_level == other.meta_level
and self.namespace == other.namespace
)
else:
return False
return (
isinstance(other, TypeVarId)
and self.raw_id == other.raw_id
and self.meta_level == other.meta_level
and self.namespace == other.namespace
)

def __ne__(self, other: object) -> bool:
return not (self == other)
Expand Down Expand Up @@ -910,9 +908,7 @@ def __hash__(self) -> int:
return hash(tuple(self.items))

def __eq__(self, other: object) -> bool:
if not isinstance(other, TypeList):
return False
return self.items == other.items
return isinstance(other, TypeList) and self.items == other.items


class UnpackType(ProperType):
Expand Down Expand Up @@ -2263,16 +2259,19 @@ def __hash__(self) -> int:
return hash((frozenset(self.items.items()), self.fallback, frozenset(self.required_keys)))

def __eq__(self, other: object) -> bool:
if isinstance(other, TypedDictType):
if frozenset(self.items.keys()) != frozenset(other.items.keys()):
return False
for (_, left_item_type, right_item_type) in self.zip(other):
if not left_item_type == right_item_type:
return False
return self.fallback == other.fallback and self.required_keys == other.required_keys
else:
if not isinstance(other, TypedDictType):
return NotImplemented

return (
frozenset(self.items.keys()) == frozenset(other.items.keys())
and all(
left_item_type == right_item_type
for (_, left_item_type, right_item_type) in self.zip(other)
)
and self.fallback == other.fallback
and self.required_keys == other.required_keys
)

def serialize(self) -> JsonDict:
return {
".class": "TypedDictType",
Expand Down Expand Up @@ -3346,11 +3345,11 @@ def is_literal_type(typ: ProperType, fallback_fullname: str, value: LiteralValue
"""Check if this type is a LiteralType with the given fallback type and value."""
if isinstance(typ, Instance) and typ.last_known_value:
typ = typ.last_known_value
if not isinstance(typ, LiteralType):
return False
if typ.fallback.type.fullname != fallback_fullname:
return False
return typ.value == value
return (
isinstance(typ, LiteralType)
and typ.fallback.type.fullname == fallback_fullname
and typ.value == value
)


def is_self_type_like(typ: Type, *, is_classmethod: bool) -> bool:
Expand Down
5 changes: 1 addition & 4 deletions mypyc/ir/class_ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,7 @@ def has_attr(self, name: str) -> bool:
return True

def is_deletable(self, name: str) -> bool:
for ir in self.mro:
if name in ir.deletable:
return True
return False
return any(name in ir.deletable for ir in self.mro)

def is_always_defined(self, name: str) -> bool:
if self.is_deletable(name):
Expand Down
10 changes: 4 additions & 6 deletions mypyc/irbuild/prebuildvisitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,10 @@ def visit_symbol_node(self, symbol: SymbolNode) -> None:
def is_parent(self, fitem: FuncItem, child: FuncItem) -> bool:
# Check if child is nested within fdef (possibly indirectly
# within multiple nested functions).
if child in self.nested_funcs:
parent = self.nested_funcs[child]
if parent == fitem:
return True
return self.is_parent(fitem, parent)
return False
if child not in self.nested_funcs:
return False
parent = self.nested_funcs[child]
return parent == fitem or self.is_parent(fitem, parent)

def add_free_variable(self, symbol: SymbolNode) -> None:
# Find the function where the symbol was (likely) first declared,
Expand Down
23 changes: 14 additions & 9 deletions mypyc/irbuild/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,20 @@ def prepare_method_def(

def is_valid_multipart_property_def(prop: OverloadedFuncDef) -> bool:
# Checks to ensure supported property decorator semantics
if len(prop.items) == 2:
getter = prop.items[0]
setter = prop.items[1]
if isinstance(getter, Decorator) and isinstance(setter, Decorator):
if getter.func.is_property and len(setter.decorators) == 1:
if isinstance(setter.decorators[0], MemberExpr):
if setter.decorators[0].name == "setter":
return True
return False
if len(prop.items) != 2:
return False

getter = prop.items[0]
setter = prop.items[1]

return (
isinstance(getter, Decorator)
and isinstance(setter, Decorator)
and getter.func.is_property
and len(setter.decorators) == 1
and isinstance(setter.decorators[0], MemberExpr)
and setter.decorators[0].name == "setter"
)


def can_subclass_builtin(builtin_base: str) -> bool:
Expand Down