-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Infer types from issubclass() calls #3005
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
Changes from 1 commit
158c889
c5525bd
1776e90
3334b8e
3587549
81e1923
e4ffdc5
9440a52
c831401
a4a7214
f94ca45
a260b79
fbd0b91
e48d983
b0ce683
aca05c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ | |
import sys | ||
|
||
from typing import ( | ||
Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple, Iterator | ||
Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple, Iterator, MutableMapping | ||
) | ||
|
||
from mypy.errors import Errors, report_internal_error | ||
|
@@ -2616,6 +2616,20 @@ def or_conditional_maps(m1: TypeMap, m2: TypeMap) -> TypeMap: | |
return result | ||
|
||
|
||
def convert_to_types(m: MutableMapping[Expression, Type]) -> None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't you just reuse the |
||
for k in m: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use longer names for variables:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done for this and other CR changes |
||
x = m[k] | ||
if isinstance(x, UnionType): | ||
m[k] = UnionType([TypeType(t) for t in x.items]) | ||
elif isinstance(x, Instance): | ||
m[k] = TypeType(m[k]) | ||
else: | ||
# TODO: verify this is ok | ||
# unknown object, don't know how to convert | ||
m.clear() | ||
return | ||
|
||
|
||
def find_isinstance_check(node: Expression, | ||
type_map: Dict[Expression, Type], | ||
) -> Tuple[TypeMap, TypeMap]: | ||
|
@@ -2639,8 +2653,24 @@ def find_isinstance_check(node: Expression, | |
expr = node.args[0] | ||
if expr.literal == LITERAL_TYPE: | ||
vartype = type_map[expr] | ||
types = get_isinstance_type(node.args[1], type_map) | ||
return conditional_type_map(expr, vartype, types) | ||
type = get_isinstance_type(node.args[1], type_map) | ||
return conditional_type_map(expr, vartype, type) | ||
elif refers_to_fullname(node.callee, 'builtins.issubclass'): | ||
expr = node.args[0] | ||
if expr.literal == LITERAL_TYPE: | ||
vartype = type_map[expr] | ||
type = get_issubclass_type(node.args[1], type_map) | ||
if isinstance(vartype, UnionType): | ||
vartype = UnionType([t.item for t in vartype.items]) # type: ignore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed using isinstance |
||
elif isinstance(vartype, TypeType): | ||
vartype = vartype.item | ||
else: | ||
# TODO: verify this is ok | ||
return {}, {} # unknown type | ||
yes_map, no_map = conditional_type_map(expr, vartype, type) | ||
convert_to_types(yes_map) | ||
convert_to_types(no_map) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need to make in-place changes in |
||
return yes_map, no_map | ||
elif refers_to_fullname(node.callee, 'builtins.callable'): | ||
expr = node.args[0] | ||
if expr.literal == LITERAL_TYPE: | ||
|
@@ -2747,6 +2777,30 @@ def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> L | |
return types | ||
|
||
|
||
def get_issubclass_type(expr: Expression, type_map: Dict[Expression, Type]) -> Type: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function exactly duplicates the function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I thought it might be similar, but then I actually managed to make it work without changing anything at all - and didn't notice. I removed it. |
||
all_types = [type_map[e] for e in flatten(expr)] | ||
|
||
types = [] # type: List[Type] | ||
|
||
for type in all_types: | ||
if isinstance(type, FunctionLike): | ||
if type.is_type_obj(): | ||
# Type variables may be present -- erase them, which is the best | ||
# we can do (outside disallowing them here). | ||
type = erase_typevars(type.items()[0].ret_type) | ||
types.append(type) | ||
elif isinstance(type, TypeType): | ||
types.append(type.item) | ||
else: # we didn't see an actual type, but rather a variable whose value is unknown to us | ||
return None | ||
|
||
assert len(types) != 0 | ||
if len(types) == 1: | ||
return types[0] | ||
else: | ||
return UnionType(types) | ||
|
||
|
||
def expand_func(defn: FuncItem, map: Dict[TypeVarId, Type]) -> FuncItem: | ||
visitor = TypeTransformVisitor(map) | ||
ret = defn.accept(visitor) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the name of this function does not reflect its behaviour. Something like "convert_to_typetype" 8000 would be better.