Skip to content

Commit fa84504

Browse files
De-duplicate code
1 parent 7f4eb00 commit fa84504

File tree

1 file changed

+21
-72
lines changed

1 file changed

+21
-72
lines changed

mypy/checker.py

Lines changed: 21 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6183,21 +6183,23 @@ def find_isinstance_check_helper(
61836183
attr = try_getting_str_literals(node.args[1], self.lookup_type(node.args[1]))
61846184
if literal(expr) == LITERAL_TYPE and attr and len(attr) == 1:
61856185
return self.hasattr_type_maps(expr, self.lookup_type(expr), attr[0])
6186-
elif isinstance(node.callee, RefExpr):
6187-
if node.callee.type_guard is not None or node.callee.type_is is not None:
6186+
elif isinstance(node.callee, (RefExpr, CallExpr)):
6187+
type_is, type_guard = None, None
6188+
# the first argument might be used as a kwarg
6189+
called_type = get_proper_type(self.lookup_type(node.callee))
6190+
6191+
# TODO: there are some more cases in check_call() to handle.
6192+
if isinstance(called_type, Instance):
6193+
call = find_member("__call__", called_type, called_type, is_operator=True)
6194+
if call is not None:
6195+
called_type = get_proper_type(call)
6196+
if isinstance(called_type, CallableType):
6197+
type_is, type_guard = called_type.type_is, called_type.type_guard
6198+
if isinstance(node.callee, RefExpr):
6199+
type_is, type_guard = node.callee.type_is, node.callee.type_guard
6200+
if type_guard is not None or type_is is not None:
61886201
# TODO: Follow *args, **kwargs
61896202
if node.arg_kinds[0] != nodes.ARG_POS:
6190-
# the first argument might be used as a kwarg
6191-
called_type = get_proper_type(self.lookup_type(node.callee))
6192-
6193-
# TODO: there are some more cases in check_call() to handle.
6194-
if isinstance(called_type, Instance):
6195-
call = find_member(
6196-
"__call__", called_type, called_type, is_operator=True
6197-
)
6198-
if call is not None:
6199-
called_type = get_proper_type(call)
6200-
62016203
# *assuming* the overloaded function is correct, there's a couple cases:
62026204
# 1) The first argument has different names, but is pos-only. We don't
62036205
# care about this case, the argument must be passed positionally.
@@ -6210,9 +6212,7 @@ def find_isinstance_check_helper(
62106212
# we want the idx-th variable to be narrowed
62116213
expr = collapse_walrus(node.args[idx])
62126214
else:
6213-
kind = (
6214-
"guard" if node.callee.type_guard is not None else "narrower"
6215-
)
6215+
kind = "guard" if type_guard is not None else "narrower"
62166216
self.fail(
62176217
message_registry.TYPE_GUARD_POS_ARG_REQUIRED.format(kind), node
62186218
)
@@ -6223,71 +6223,20 @@ def find_isinstance_check_helper(
62236223
# considered "always right" (i.e. even if the types are not overlapping).
62246224
# Also note that a care must be taken to unwrap this back at read places
62256225
# where we use this to narrow down declared type.
6226-
if node.callee.type_guard is not None:
6227-
return {expr: TypeGuardedType(node.callee.type_guard)}, {}
6226+
if type_guard is not None:
6227+
return {expr: TypeGuardedType(type_guard)}, {}
62286228
else:
6229-
assert node.callee.type_is is not None
6229+
assert type_is is not None
62306230
return conditional_types_to_typemaps(
62316231
expr,
62326232
*self.conditional_types_with_intersection(
62336233
self.lookup_type(expr),
6234-
[TypeRange(node.callee.type_is, is_upper_bound=False)],
6234+
[TypeRange(type_is, is_upper_bound=False)],
62356235
expr,
62366236
consider_runtime_isinstance=False,
62376237
),
62386238
)
6239-
elif isinstance(node.callee, CallExpr) and len(node.args) != 0:
6240-
# Handle case where callee is a call expression like E()(x)
6241-
# where E() returns an object with __call__ method that has TypeGuard
6242-
callee_type = get_proper_type(self.lookup_type(node.callee))
6243-
if isinstance(callee_type, Instance):
6244-
call_member = find_member(
6245-
"__call__", callee_type, callee_type, is_operator=True
6246-
)
6247-
if call_member is not None:
6248-
call_type = get_proper_type(call_member)
6249-
# Check if the __call__ method has type_guard or type_is
6250-
if isinstance(call_type, CallableType) and (
6251-
call_type.type_guard is not None or call_type.type_is is not None
6252-
):
6253-
# Handle keyword arguments similar to RefExpr case
6254-
expr = collapse_walrus(node.args[0]) # Default to first positional arg
6255-
if node.arg_kinds[0] != nodes.ARG_POS:
6256-
if call_type.arg_names:
6257-
name = call_type.arg_names[0]
6258-
if name in node.arg_names:
6259-
idx = node.arg_names.index(name)
6260-
# we want the idx-th variable to be narrowed
6261-
expr = collapse_walrus(node.args[idx])
6262-
else:
6263-
kind = (
6264-
"guard"
6265-
if call_type.type_guard is not None
6266-
else "narrower"
6267-
)
6268-
self.fail(
6269-
message_registry.TYPE_GUARD_POS_ARG_REQUIRED.format(
6270-
kind
6271-
),
6272-
node,
6273-
)
6274-
return {}, {}
6275-
6276-
if literal(expr) == LITERAL_TYPE:
6277-
# Apply the same TypeGuard narrowing logic
6278-
if call_type.type_guard is not None:
6279-
return {expr: TypeGuardedType(call_type.type_guard)}, {}
6280-
else:
6281-
assert call_type.type_is is not None
6282-
return conditional_types_to_typemaps(
6283-
expr,
6284-
*self.conditional_types_with_intersection(
6285-
self.lookup_type(expr),
6286-
[TypeRange(call_type.type_is, is_upper_bound=False)],
6287-
expr,
6288-
consider_runtime_isinstance=False,
6289-
),
6290-
)
6239+
62916240
elif isinstance(node, ComparisonExpr):
62926241
return self.comparison_type_narrowing_helper(node)
62936242
elif isinstance(node, AssignmentExpr):

0 commit comments

Comments
 (0)