Skip to content

Commit 6bcaf40

Browse files
authored
More tweaks to support mypyc (#5513)
1 parent dd70710 commit 6bcaf40

12 files changed

+124
-90
lines changed

mypy/bogus_type.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@
1010
For those cases some other technique should be used.
1111
"""
1212

13+
import sys
14+
1315
from mypy_extensions import FlexibleAlias
1416
from typing import TypeVar, Any
1517

1618
T = TypeVar('T')
1719

18-
SUPPRESS_BOGUS_TYPES = False
19-
if SUPPRESS_BOGUS_TYPES:
20+
# This won't ever be true at runtime, but we consider it true during
21+
# mypyc compilations.
22+
if sys.platform == 'mypyc':
2023
Bogus = FlexibleAlias[T, Any]
2124
else:
2225
Bogus = FlexibleAlias[T, T]

mypy/checkexpr.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,8 @@ def analyze_type_type_callee(self, item: Type, context: Context) -> Type:
720720
res = res.copy_modified(from_type_type=True)
721721
return expand_type_by_instance(res, item)
722722
if isinstance(item, UnionType):
723-
return UnionType([self.analyze_type_type_callee(item, context)
724-
for item in item.relevant_items()], item.line)
723+
return UnionType([self.analyze_type_type_callee(tp, context)
724+
for tp in item.relevant_items()], item.line)
725725
if isinstance(item, TypeVarType):
726726
# Pretend we're calling the typevar's upper bound,
727727
# i.e. its constructor (a poor approximation for reality,

mypy/fastparse2.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@
1717
from functools import wraps
1818
import sys
1919

20-
from typing import Tuple, Union, TypeVar, Callable, Sequence, Optional, Any, cast, List
20+
from typing import Tuple, Union, TypeVar, Callable, Sequence, Optional, Any, Dict, cast, List
21+
MYPY = False
22+
if MYPY:
23+
import typing # for typing.Type, which conflicts with types.Type
24+
from typing import ClassVar
25+
2126
from mypy.sharedparse import (
2227
special_function_elide_names, argument_elide_name,
2328
)
@@ -193,7 +198,7 @@ def translate_stmt_list(self, l: Sequence[ast27.AST]) -> List[Statement]:
193198
ast27.BitXor: '^',
194199
ast27.BitAnd: '&',
195200
ast27.FloorDiv: '//'
196-
}
201+
} # type: ClassVar[Dict[typing.Type[ast27.AST], str]]
197202

198203
def from_operator(self, op: ast27.operator) -> str:
199204
op_name = ASTConverter.op_map.get(type(op))
@@ -215,7 +220,7 @@ def from_operator(self, op: ast27.operator) -> str:
215220
ast27.IsNot: 'is not',
216221
ast27.In: 'in',
217222
ast27.NotIn: 'not in'
218-
}
223+
} # type: ClassVar[Dict[typing.Type[ast27.AST], str]]
219224

220225
def from_comp_operator(self, op: ast27.cmpop) -> str:
221226
op_name = ASTConverter.comp_op_map.get(type(op))
@@ -240,7 +245,7 @@ def as_required_block(self, stmts: List[ast27.stmt], lineno: int) -> Block:
240245
def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]:
241246
ret = [] # type: List[Statement]
242247
current_overload = [] # type: List[OverloadPart]
243-
current_overload_name = None
248+
current_overload_name = None # type: Optional[str]
244249
for stmt in stmts:
245250
if (current_overload_name is not None
246251
and isinstance(stmt, (Decorator, FuncDef))

mypy/options.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ def __init__(self) -> None:
191191
self.use_builtins_fixtures = False
192192

193193
# -- experimental options --
194-
self.shadow_file = None # type: Optional[List[Tuple[str, str]]]
194+
self.shadow_file = None # type: Optional[List[List[str]]]
195195
self.show_column_numbers = False # type: bool
196196
self.dump_graph = False
197197
self.dump_deps = False

mypy/stubgen.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import mypy.parse
5656
import mypy.errors
5757
import mypy.traverser
58+
import mypy.util
5859
from mypy import defaults
5960
from mypy.nodes import (
6061
Expression, IntExpr, UnaryExpr, StrExpr, BytesExpr, NameExpr, FloatExpr, MemberExpr, TupleExpr,
@@ -818,28 +819,33 @@ def is_recorded_name(self, name: str) -> bool:
818819
return self.is_top_level() and name in self._toplevel_names
819820

820821

822+
class SelfTraverser(mypy.traverser.TraverserVisitor):
823+
def __init__(self) -> None:
824+
self.results = [] # type: List[Tuple[str, Expression]]
825+
826+
def visit_assignment_stmt(self, o: AssignmentStmt) -> None:
827+
lvalue = o.lvalues[0]
828+
if (isinstance(lvalue, MemberExpr) and
829+
isinstance(lvalue.expr, NameExpr) and
830+
lvalue.expr.name == 'self'):
831+
self.results.append((lvalue.name, o.rvalue))
832+
833+
821834
def find_self_initializers(fdef: FuncBase) -> List[Tuple[str, Expression]]:
822-
results = [] # type: List[Tuple[str, Expression]]
835+
traverser = SelfTraverser()
836+
fdef.accept(traverser)
837+
return traverser.results
838+
823839

824-
class SelfTraverser(mypy.traverser.TraverserVisitor):
825-
def visit_assignment_stmt(self, o: AssignmentStmt) -> None:
826-
lvalue = o.lvalues[0]
827-
if (isinstance(lvalue, MemberExpr) and
828-
isinstance(lvalue.expr, NameExpr) and
829-
lvalue.expr.name == 'self'):
830-
results.append((lvalue.name, o.rvalue))
840+
class ReturnSeeker(mypy.traverser.TraverserVisitor):
841+
def __init__(self) -> None:
842+
self.found = False
831843

832-
fdef.accept(SelfTraverser())
833-
return results
844+
def visit_return_stmt(self, o: ReturnStmt) -> None:
845+
self.found = True
834846

835847

836848
def has_return_statement(fdef: FuncBase) -> bool:
837-
class ReturnSeeker(mypy.traverser.TraverserVisitor):
838-
def __init__(self) -> None:
839-
self.found = False
840-
841-
def visit_return_stmt(self, o: ReturnStmt) -> None:
842-
self.found = True
843849

844850
seeker = ReturnSeeker()
845851
fdef.accept(seeker)

mypy/stubgenc.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import importlib
77
import os.path
88
import re
9-
from typing import List, Dict, Tuple, Optional
9+
from typing import List, Dict, Tuple, Optional, Mapping, Any
1010
from types import ModuleType
1111

1212
from mypy.stubutil import is_c_module, write_header, infer_sig_from_docstring
@@ -137,7 +137,10 @@ def generate_c_type_stub(module: ModuleType,
137137
sigs: Dict[str, str] = {},
138138
class_sigs: Dict[str, str] = {},
139139
) -> None:
140-
items = sorted(obj.__dict__.items(), key=lambda x: method_name_sort_key(x[0]))
140+
# typeshed gives obj.__dict__ the not quite correct type Dict[str, Any]
141+
# (it could be a mappingproxy!), which makes mypyc mad, so obfuscate it.
142+
obj_dict = getattr(obj, '__dict__') # type: Mapping[str, Any]
143+
items = sorted(obj_dict.items(), key=lambda x: method_name_sort_key(x[0]))
141144
methods = []
142145
done = set()
143146
for attr, value in items:
@@ -151,7 +154,7 @@ def generate_c_type_stub(module: ModuleType,
151154
self_var = 'self'
152155
if attr == '__new__':
153156
# TODO: We should support __new__.
154-
if '__init__' in obj.__dict__:
157+
if '__init__' in obj_dict:
155158
# Avoid duplicate functions if both are present.
156159
# But is there any case where .__new__() has a
157160
# better signature than __init__() ?

mypy/test/testtransform.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
)
1010
from mypy.test.data import DataDrivenTestCase, DataSuite
1111
from mypy.test.config import test_temp_dir
12+
from mypy.test.visitors import TypeAssertTransformVisitor
1213
from mypy.errors import CompileError
13-
from mypy.treetransform import TransformVisitor
14-
from mypy.types import Type
1514
from mypy.options import Options
1615

1716

@@ -72,9 +71,3 @@ def test_transform(testcase: DataDrivenTestCase) -> None:
7271
testcase.output, a,
7372
'Invalid semantic analyzer output ({}, line {})'.format(testcase.file,
7473
testcase.line))
75-
76-
77-
class TypeAssertTransformVisitor(TransformVisitor):
78-
def type(self, type: Type) -> Type:
79-
assert type is not None
80-
return type

mypy/test/testtypegen.py

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@
22

33
import re
44

5-
from typing import Set
6-
75
from mypy import build
86
from mypy.build import BuildSource
97
from mypy.test.config import test_temp_dir
108
from mypy.test.data import DataDrivenTestCase, DataSuite
119
from mypy.test.helpers import assert_string_arrays_equal
10+
from mypy.test.visitors import SkippedNodeSearcher, ignore_node
1211
from mypy.util import short_type
1312
from mypy.nodes import (
1413
NameExpr, TypeVarExpr, CallExpr, Expression, MypyFile, AssignmentStmt, IntExpr
1514
)
16-
from mypy.traverser import TraverserVisitor
1715
from mypy.errors import CompileError
1816
from mypy.options import Options
1917

@@ -73,49 +71,3 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
7371
testcase.output, a,
7472
'Invalid type checker output ({}, line {})'.format(testcase.file,
7573
testcase.line))
76-
77-
78-
class SkippedNodeSearcher(TraverserVisitor):
79-
def __init__(self) -> None:
80-
self.nodes = set() # type: Set[Expression]
81-
self.is_typing = False
82-
83-
def visit_mypy_file(self, f: MypyFile) -> None:
84-
self.is_typing = f.fullname() == 'typing' or f.fullname() == 'builtins'
85-
super().visit_mypy_file(f)
86-
87-
def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
88-
if s.type or ignore_node(s.rvalue):
89-
for lvalue in s.lvalues:
90-
if isinstance(lvalue, NameExpr):
91-
self.nodes.add(lvalue)
92-
super().visit_assignment_stmt(s)
93-
94-
def visit_name_expr(self, n: NameExpr) -> None:
95-
self.skip_if_typing(n)
96-
97-
def visit_int_expr(self, n: IntExpr) -> None:
98-
self.skip_if_typing(n)
99-
100-
def skip_if_typing(self, n: Expression) -> None:
101-
if self.is_typing:
102-
self.nodes.add(n)
103-
104-
105-
def ignore_node(node: Expression) -> bool:
106-
"""Return True if node is to be omitted from test case output."""
107-
108-
# We want to get rid of object() expressions in the typing module stub
109-
# and also TypeVar(...) expressions. Since detecting whether a node comes
110-
# from the typing module is not easy, we just to strip them all away.
111-
if isinstance(node, TypeVarExpr):
112-
return True
113-
if isinstance(node, NameExpr) and node.fullname == 'builtins.object':
114-
return True
115-
if isinstance(node, NameExpr) and node.fullname == 'builtins.None':
116-
return True
117-
if isinstance(node, CallExpr) and (ignore_node(node.callee) or
118-
node.analyzed):
119-
return True
120-
121-
return False

mypy/test/visitors.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""Visitor classes pulled out from different tests
2+
3+
These are here because we don't currently support having interpreted
4+
classes subtype compiled ones but pytest grabs the python file
5+
even if the test was compiled.
6+
7+
"""
8+
9+
from typing import Set
10+
11+
from mypy.nodes import (
12+
NameExpr, TypeVarExpr, CallExpr, Expression, MypyFile, AssignmentStmt, IntExpr
13+
)
14+
from mypy.traverser import TraverserVisitor
15+
16+
from mypy.treetransform import TransformVisitor
17+
from mypy.types import Type
18+
19+
20+
# from testtypegen
21+
class SkippedNodeSearcher(TraverserVisitor):
22+
def __init__(self) -> None:
23+
self.nodes = set() # type: Set[Expression]
24+
self.is_typing = False
25+
26+
def visit_mypy_file(self, f: MypyFile) -> None:
27+
self.is_typing = f.fullname() == 'typing' or f.fullname() == 'builtins'
28+
super().visit_mypy_file(f)
29+
30+
def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
31+
if s.type or ignore_node(s.rvalue):
32+
for lvalue in s.lvalues:
33+
if isinstance(lvalue, NameExpr):
34+
self.nodes.add(lvalue)
35+
super().visit_assignment_stmt(s)
36+
37+
def visit_name_expr(self, n: NameExpr) -> None:
38+
self.skip_if_typing(n)
39+
40+
def visit_int_expr(self, n: IntExpr) -> None:
41+
self.skip_if_typing(n)
42+
43+
def skip_if_typing(self, n: Expression) -> None:
44+
if self.is_typing:
45+
self.nodes.add(n)
46+
47+
48+
def ignore_node(node: Expression) -> bool:
49+
"""Return True if node is to be omitted from test case output."""
50+
51+
# We want to get rid of object() expressions in the typing module stub
52+
# and also TypeVar(...) expressions. Since detecting whether a node comes
53+
# from the typing module is not easy, we just to strip them all away.
54+
if isinstance(node, TypeVarExpr):
55+
return True
56+
if isinstance(node, NameExpr) and node.fullname == 'builtins.object':
57+
return True
58+
if isinstance(node, NameExpr) and node.fullname == 'builtins.None':
59+
return True
60+
if isinstance(node, CallExpr) and (ignore_node(node.callee) or
61+
node.analyzed):
62+
return True
63+
64+
return False
65+
66+
67+
# from testtransform
68+
class TypeAssertTransformVisitor(TransformVisitor):
69+
def type(self, type: Type) -> Type:
70+
assert type is not None
71+
return type

mypy/treetransform.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def visit_func_def(self, node: FuncDef) -> FuncDef:
105105
new = FuncDef(node.name(),
106106
[self.copy_argument(arg) for arg in node.arguments],
107107
self.block(node.body),
108-
cast(FunctionLike, self.optional_type(node.type)))
108+
cast(Optional[FunctionLike], self.optional_type(node.type)))
109109

110110
self.copy_function_attributes(new, node)
111111

@@ -131,8 +131,8 @@ def visit_func_def(self, node: FuncDef) -> FuncDef:
131131

132132
def visit_lambda_expr(self, node: LambdaExpr) -> LambdaExpr:
133133
new = LambdaExpr([self.copy_argument(arg) for arg in node.arguments],
134-
self.block(node.body),
135-
cast(FunctionLike, self.optional_type(node.type)))
134+
self.block(node.body),
135+
cast(Optional[FunctionLike], self.optional_type(node.type)))
136136
self.copy_function_attributes(new, node)
137137
return new
138138

mypy_bootstrap.ini

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ disallow_any_generics = True
88
disallow_any_unimported = True
99
warn_redundant_casts = True
1010
warn_unused_configs = True
11-
always_true = SUPPRESS_BOGUS_TYPES
11+
show_traceback = True
12+
# Set the platform to something nonsense to signal to make Bogus = Any.
13+
platform = mypyc
1214

1315
# needs py2 compatibility
1416
[mypy-mypy.test.testextensions]

mypy_self_check.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ disallow_any_generics = True
88
disallow_any_unimported = True
99
warn_redundant_casts = True
1010
warn_unused_configs = True
11-
always_false = SUPPRESS_BOGUS_TYPES
1211
show_traceback = True
1312

1413
# needs py2 compatibility

0 commit comments

Comments
 (0)