Skip to content

Commit cc7667a

Browse files
authored
[mypyc] Refactor mypyc error handling (python#7627)
Pull Errors out into its own module and have it get managed externally from genops. This is in preparation for separate/incremental compilation.
1 parent 47dab6a commit cc7667a

File tree

6 files changed

+54
-37
lines changed

6 files changed

+54
-37
lines changed

mypyc/build.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from mypy.build import BuildSource
3636
from mypyc.namegen import exported_name
3737
from mypyc.options import CompilerOptions
38+
from mypyc.errors import Errors
3839

3940
from mypyc import emitmodule
4041

@@ -182,9 +183,15 @@ def generate_c(sources: List[BuildSource], options: Options,
182183
if compiler_options.verbose:
183184
print("Parsed and typechecked in {:.3f}s".format(t1 - t0))
184185

186+
errors = Errors()
187+
185188
ops = [] # type: List[str]
186189
ctext = emitmodule.compile_modules_to_c(result, module_names, shared_lib_name,
187-
compiler_options=compiler_options, ops=ops)
190+
compiler_options=compiler_options,
191+
errors=errors, ops=ops)
192+
if errors.num_errors:
193+
errors.flush_errors()
194+
sys.exit(1)
188195

189196
t2 = time.time()
190197
if compiler_options.verbose:

mypyc/emitmodule.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
"""Generate C code for a Python C extension module from Python source code."""
22

3-
import sys
4-
53
from collections import OrderedDict
64
from typing import List, Tuple, Dict, Iterable, Set, TypeVar, Optional
75

@@ -23,6 +21,7 @@
2321
from mypyc.refcount import insert_ref_count_opcodes
2422
from mypyc.exceptions import insert_exception_handling
2523
from mypyc.namegen import exported_name
24+
from mypyc.errors import Errors
2625

2726

2827
class MarkedDeclaration:
@@ -46,15 +45,16 @@ def parse_and_typecheck(sources: List[BuildSource], options: Options,
4645
def compile_modules_to_c(result: BuildResult, module_names: List[str],
4746
shared_lib_name: Optional[str],
4847
compiler_options: CompilerOptions,
48+
errors: Errors,
4949
ops: Optional[List[str]] = None) -> List[Tuple[str, str]]:
5050
"""Compile Python module(s) to C that can be used from Python C extension modules."""
5151

5252
# Generate basic IR, with missing exception and refcount handling.
5353
file_nodes = [result.files[name] for name in module_names]
54-
literals, modules, errors = genops.build_ir(file_nodes, result.graph, result.types,
55-
compiler_options)
56-
if errors > 0:
57-
sys.exit(1)
54+
literals, modules = genops.build_ir(file_nodes, result.graph, result.types,
55+
compiler_options, errors)
56+
if errors.num_errors > 0:
57+
return []
5858
# Insert uninit checks.
5959
for _, module in modules:
6060
for fn in module.functions:

mypyc/errors.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import mypy.errors
2+
3+
4+
class Errors:
5+
def __init__(self) -> None:
6+
self.num_errors = 0
7+
self.num_warnings = 0
8+
self._errors = mypy.errors.Errors()
9+
10+
def error(self, msg: str, path: str, line: int) -> None:
11+
self._errors.report(line, None, msg, severity='error', file=path)
12+
self.num_errors += 1
13+
14+
def warning(self, msg: str, path: str, line: int) -> None:
15+
self._errors.report(line, None, msg, severity='warning', file=path)
16+
self.num_warnings += 1
17+
18+
def flush_errors(self) -> None:
19+
for error in self._errors.new_messages():
20+
print(error)

mypyc/genops.py

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ def f(x: int) -> int:
3737
TypeVarExpr, TypedDictExpr, UnicodeExpr, WithStmt, YieldFromExpr, YieldExpr, GDEF, ARG_POS,
3838
ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR, ARG_STAR2, is_class_var, op_methods
3939
)
40-
import mypy.nodes
41-
import mypy.errors
4240
from mypy.types import (
4341
Type, Instance, CallableType, NoneTyp, TupleType, UnionType, AnyType, TypeVarType, PartialType,
4442
TypeType, Overloaded, TypeOfAny, UninhabitedType, UnboundType, TypedDictType,
@@ -99,6 +97,7 @@ def f(x: int) -> int:
9997
from mypyc.sametype import is_same_type, is_same_method_signature
10098
from mypyc.crash import catch_errors
10199
from mypyc.options import CompilerOptions
100+
from mypyc.errors import Errors
102101

103102
GenFunc = Callable[[], None]
104103
DictEntry = Tuple[Optional[Value], Value]
@@ -108,25 +107,6 @@ class UnsupportedException(Exception):
108107
pass
109108

110109

111-
class Errors:
112-
def __init__(self) -> None:
113-
self.num_errors = 0
114-
self.num_warnings = 0
115-
self._errors = mypy.errors.Errors()
116-
117-
def error(self, msg: str, path: str, line: int) -> None:
118-
self._errors.report(line, None, msg, severity='error', file=path)
119-
self.num_errors += 1
120-
121-
def warning(self, msg: str, path: str, line: int) -> None:
122-
self._errors.report(line, None, msg, severity='warning', file=path)
123-
self.num_warnings += 1
124-
125-
def flush_errors(self) -> None:
126-
for error in self._errors.new_messages():
127-
print(error)
128-
129-
130110
# The stubs for callable contextmanagers are busted so cast it to the
131111
# right type...
132112
F = TypeVar('F', bound=Callable[..., Any])
@@ -137,10 +117,10 @@ def flush_errors(self) -> None:
137117
def build_ir(modules: List[MypyFile],
138118
graph: Graph,
139119
types: Dict[Expression, Type],
140-
options: CompilerOptions) -> Tuple[LiteralsMap, List[Tuple[str, ModuleIR]], int]:
120+
options: CompilerOptions,
121+
errors: Errors) -> Tuple[LiteralsMap, List[Tuple[str, ModuleIR]]]:
141122
result = []
142123
mapper = Mapper()
143-
errors = Errors()
144124

145125
# Collect all classes defined in the compilation unit.
146126
classes = []
@@ -205,9 +185,7 @@ def build_ir(modules: List[MypyFile],
205185
if cir.is_ext_class:
206186
compute_vtable(cir)
207187

208-
errors.flush_errors()
209-
210-
return mapper.literals, result, errors.num_errors
188+
return mapper.literals, result
211189

212190

213191
def is_extension_class(cdef: ClassDef) -> bool:

mypyc/test/test_run.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from mypyc import emitmodule
1919
from mypyc.options import CompilerOptions
20+
from mypyc.errors import Errors
2021
from mypyc.build import shared_lib_name
2122
from mypyc.test.testutil import (
2223
ICODE_GEN_BUILTINS, TESTUTIL_PATH,
@@ -167,11 +168,18 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
167168
sources=sources,
168169
options=options,
169170
alt_lib_path='.')
171+
errors = Errors()
172+
compiler_options = CompilerOptions(multi_file=self.multi_file)
170173
cfiles = emitmodule.compile_modules_to_c(
171174
result,
172175
module_names=module_names,
173176
shared_lib_name=lib_name,
174-
compiler_options=CompilerOptions(multi_file=self.multi_file))
177+
compiler_options=compiler_options,
178+
errors=errors,
179+
)
180+
if errors.num_errors:
181+
errors.flush_errors()
182+
assert False, "Compile error"
175183
except CompileError as e:
176184
for line in e.messages:
177185
print(line)

mypyc/test/testutil.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from mypyc import genops
1818
from mypyc.options import CompilerOptions
1919
from mypyc.ops import FuncIR
20+
from mypyc.errors import Errors
2021
from mypyc.test.config import test_data_prefix
2122

2223
# The builtins stub used during icode generation test cases.
@@ -102,9 +103,12 @@ def build_ir_for_single_file(input_lines: List[str],
102103
alt_lib_path=test_temp_dir)
103104
if result.errors:
104105
raise CompileError(result.errors)
105-
_, modules, errors = genops.build_ir([result.files['__main__']], result.graph, result.types,
106-
compiler_options)
107-
assert errors == 0
106+
107+
errors = Errors()
108+
_, modules = genops.build_ir(
109+
[result.files['__main__']], result.graph, result.types,
110+
compiler_options, errors)
111+
assert errors.num_errors == 0
108112

109113
module = modules[0][1]
110114
return module.functions

0 commit comments

Comments
 (0)