Skip to content

Commit 4fbb8fd

Browse files
committed
split stubgen to data (pytest) and myunit; fix name-filtering regression
1 parent c1e96f5 commit 4fbb8fd

File tree

3 files changed

+118
-108
lines changed

3 files changed

+118
-108
lines changed

mypy/test/teststubgen.py

Lines changed: 1 addition & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,8 @@
1-
import glob
2-
import importlib
3-
import os.path
4-
import random
5-
import shutil
6-
import sys
7-
import tempfile
8-
import time
9-
import re
101
from types import ModuleType
112

123
from typing import List, Tuple
134

14-
from mypy.myunit import Suite, AssertionFailure, assert_equal
15-
from mypy.test.helpers import assert_string_arrays_equal
16-
from mypy.test.data import parse_test_cases, DataDrivenTestCase
17-
from mypy.test import config
18-
from mypy.parse import parse
19-
from mypy.errors import CompileError
20-
from mypy.stubgen import generate_stub, generate_stub_for_module, parse_options, Options
5+
from mypy.myunit import Suite, assert_equal
216
from mypy.stubgenc import generate_c_type_stub, infer_method_sig
227
from mypy.stubutil import (
238
parse_signature, parse_all_signatures, build_signature, find_unique_signatures,
@@ -95,89 +80,6 @@ def test_infer_sig_from_docstring(self) -> None:
9580
assert_equal(infer_sig_from_docstring('\nfunc x', 'func'), None)
9681

9782

98-
class StubgenPythonSuite(Suite):
99-
test_data_files = ['stubgen.test']
100-
101-
def cases(self) -> List[DataDrivenTestCase]:
102-
c = [] # type: List[DataDrivenTestCase]
103-
for path in self.test_data_files:
104-
c += parse_test_cases(os.path.join(config.test_data_prefix, path), test_stubgen)
105-
return c
106-
107-
108-
def parse_flags(program_text: str) -> Options:
109-
flags = re.search('# flags: (.*)$', program_text, flags=re.MULTILINE)
110-
if flags:
111-
flag_list = flags.group(1).split()
112-
else:
113-
flag_list = []
114-
return parse_options(flag_list + ['dummy.py'])
115-
116-
117-
def test_stubgen(testcase: DataDrivenTestCase) -> None:
118-
if 'stubgen-test-path' not in sys.path:
119-
sys.path.insert(0, 'stubgen-test-path')
120-
os.mkdir('stubgen-test-path')
121-
source = '\n'.join(testcase.input)
122-
options = parse_flags(source)
123-
handle = tempfile.NamedTemporaryFile(prefix='prog_', suffix='.py', dir='stubgen-test-path',
124-
delete=False)
125-
assert os.path.isabs(handle.name)
126-
path = os.path.basename(handle.name)
127-
name = path[:-3]
128-
path = os.path.join('stubgen-test-path', path)
129-
out_dir = '_out'
130-
os.mkdir(out_dir)
131-
try:
132-
handle.write(bytes(source, 'ascii'))
133-
handle.close()
134-
# Without this we may sometimes be unable to import the module below, as importlib
135-
# caches os.listdir() results in Python 3.3+ (Guido explained this to me).
136-
reset_importlib_caches()
137-
try:
138-
if testcase.name.endswith('_import'):
139-
generate_stub_for_module(name, out_dir, quiet=True,
140-
no_import=options.no_import,
141-
include_private=options.include_private)
142-
else:
143-
generate_stub(path, out_dir, include_private=options.include_private)
144-
a = load_output(out_dir)
145-
except CompileError as e:
146-
a = e.messages
147-
assert_string_arrays_equal(testcase.output, a,
148-
'Invalid output ({}, line {})'.format(
149-
testcase.file, testcase.line))
150-
finally:
151-
handle.close()
152-
os.unlink(handle.name)
153-
shutil.rmtree(out_dir)
154-
155-
156-
def reset_importlib_caches() -> None:
157-
try:
158-
importlib.invalidate_caches()
159-
except (ImportError, AttributeError):
160-
pass
161-
162-
163-
def load_output(dirname: str) -> List[str]:
164-
result = [] # type: List[str]
165-
entries = glob.glob('%s/*' % dirname)
166-
assert entries, 'No files generated'
167-
if len(entries) == 1:
168-
add_file(entries[0], result)
169-
else:
170-
for entry in entries:
171-
result.append('## %s ##' % entry)
172-
add_file(entry, result)
173-
return result
174-
175-
176-
def add_file(path: str, result: List[str]) -> None:
177-
with open(path) as file:
178-
result.extend(file.read().splitlines())
179-
180-
18183
class StubgencSuite(Suite):
18284
def test_infer_hash_sig(self) -> None:
18385
assert_equal(infer_method_sig('__hash__'), '()')

mypy/test/teststubgendata.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import glob
2+
import importlib
3+
import os.path
4+
import shutil
5+
import sys
6+
import tempfile
7+
import re
8+
9+
from typing import List
10+
11+
from mypy.test.helpers import assert_string_arrays_equal
12+
from mypy.test.data import DataSuite, parse_test_cases, DataDrivenTestCase
13+
from mypy.test import config
14+
from mypy.errors import CompileError
15+
from mypy.stubgen import generate_stub, generate_stub_for_module, parse_options, Options
16+
17+
18+
# This file handles the data-driven part of the stubgen tests
19+
# The other part is in teststubgen.py
20+
# This splitting is necessary since data driven tests are executed by pytest,
21+
# whereas the rest of the tests are executed by myunit.
22+
23+
24+
class StubgenPythonSuite(DataSuite):
25+
test_data_files = ['stubgen.test']
26+
27+
@classmethod
28+
def cases(cls) -> List[DataDrivenTestCase]:
29+
c = [] # type: List[DataDrivenTestCase]
30+
for path in cls.test_data_files:
31+
c += parse_test_cases(os.path.join(config.test_data_prefix, path), test_stubgen)
32+
return c
33+
34+
def run_case(self, testcase: DataDrivenTestCase) -> None:
35+
test_stubgen(testcase)
36+
37+
38+
def parse_flags(program_text: str) -> Options:
39+
flags = re.search('# flags: (.*)$', program_text, flags=re.MULTILINE)
40+
if flags:
41+
flag_list = flags.group(1).split()
42+
else:
43+
flag_list = []
44+
return parse_options(flag_list + ['dummy.py'])
45+
46+
47+
def test_stubgen(testcase: DataDrivenTestCase) -> None:
48+
if 'stubgen-test-path' not in sys.path:
49+
sys.path.insert(0, 'stubgen-test-path')
50+
os.mkdir('stubgen-test-path')
51+
source = '\n'.join(testcase.input)
52+
options = parse_flags(source)
53+
handle = tempfile.NamedTemporaryFile(prefix='prog_', suffix='.py', dir='stubgen-test-path',
54+
delete=False)
55+
assert os.path.isabs(handle.name)
56+
path = os.path.basename(handle.name)
57+
name = path[:-3]
58+
path = os.path.join('stubgen-test-path', path)
59+
out_dir = '_out'
60+
os.mkdir(out_dir)
61+
try:
62+
handle.write(bytes(source, 'ascii'))
63+
handle.close()
64+
# Without this we may sometimes be unable to import the module below, as importlib
65+
# caches os.listdir() results in Python 3.3+ (Guido explained this to me).
66+
reset_importlib_caches()
67+
try:
68+
if testcase.name.endswith('_import'):
69+
generate_stub_for_module(name, out_dir, quiet=True,
70+
no_import=options.no_import,
71+
include_private=options.include_private)
72+
else:
73+
generate_stub(path, out_dir, include_private=options.include_private)
74+
a = load_output(out_dir)
75+
except CompileError as e:
76+
a = e.messages
77+
assert_string_arrays_equal(testcase.output, a,
78+
'Invalid output ({}, line {})'.format(
79+
testcase.file, testcase.line))
80+
finally:
81+
handle.close()
82+
os.unlink(handle.name)
83+
shutil.rmtree(out_dir)
84+
85+
86+
def reset_importlib_caches() -> None:
87+
try:
88+
importlib.invalidate_caches()
89+
except (ImportError, AttributeError):
90+
pass
91+
92+
93+
def load_output(dirname: str) -> List[str]:
94+
result = [] # type: List[str]
95+
entries = glob.glob('%s/*' % dirname)
96+
assert entries, 'No files generated'
97+
if len(entries) == 1:
98+
add_file(entries[0], result)
99+
else:
100+
for entry in entries:
101+
result.append('## %s ##' % entry)
102+
add_file(entry, result)
103+
return result
104+
105+
106+
def add_file(path: str, result: List[str]) -> None:
107+
with open(path) as file:
108+
result.extend(file.read().splitlines())

runtests.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,17 @@ def add_mypy_package(self, name: str, packagename: str, *flags: str) -> None:
8989
def add_mypy_string(self, name: str, *args: str, cwd: Optional[str] = None) -> None:
9090
self.add_mypy_cmd(name, ['-c'] + list(args), cwd=cwd)
9191

92-
def add_pytest(self, name: str, pytest_files: List[str], coverage: bool = True) -> None:
93-
pytest_args = pytest_files + self.arglist + self.pyt_arglist
94-
full_name = 'pytest %s' % name
95-
if not self.allow(full_name):
92+
def add_pytest(self, pytest_files: List[str], coverage: bool = True) -> None:
93+
pytest_files = [name for name in pytest_files if self.allow(name[4:])]
94+
if not pytest_files:
9695
return
96+
pytest_args = pytest_files + self.arglist + self.pyt_arglist
9797
if coverage and self.coverage:
9898
args = [sys.executable, '-m', 'pytest', '--cov=mypy'] + pytest_args
9999
else:
100100
args = [sys.executable, '-m', 'pytest'] + pytest_args
101101

102-
self.waiter.add(LazySubprocess(full_name, args, env=self.env, passthrough=self.verbosity),
102+
self.waiter.add(LazySubprocess('pytest', args, env=self.env, passthrough=self.verbosity),
103103
sequential=True)
104104

105105
def add_python(self, name: str, *args: str, cwd: Optional[str] = None) -> None:
@@ -212,12 +212,12 @@ def test_path(*names: str):
212212
'testparse',
213213
'testsemanal',
214214
'testpythoneval',
215-
'testcmdline'
215+
'testcmdline',
216+
'teststubgendata'
216217
)
217218

218219
MYUNIT_FILES = test_path(
219-
'teststubgen', # contains data-driven suite
220-
220+
'teststubgen',
221221
'testargs',
222222
'testgraph',
223223
'testinfer',
@@ -233,7 +233,7 @@ def test_path(*names: str):
233233

234234

235235
def add_pytest(driver: Driver) -> None:
236-
driver.add_pytest('pytest', PYTEST_FILES)
236+
driver.add_pytest(PYTEST_FILES)
237237

238238

239239
def add_myunit(driver: Driver) -> None:

0 commit comments

Comments
 (0)