def get_semanal_options(program_text: str, testcase: DataDrivenTestCase) -> Options: options = parse_options(program_text, testcase, 1) options.use_builtins_fixtures = True options.semantic_analysis_only = True options.show_traceback = True options.python_version = PYTHON3_VERSION return options
def build(self, source: str, testcase: DataDrivenTestCase, sources_override: Optional[List[Tuple[str, str]]], build_cache: bool, enable_cache: bool) -> Tuple[List[str], BuildManager, Graph]: # This handles things like '# flags: --foo'. options = parse_options(source, testcase, incremental_step=1) options.incremental = True options.use_builtins_fixtures = True options.show_traceback = True options.fine_grained_incremental = not build_cache options.use_fine_grained_cache = enable_cache and not build_cache options.cache_fine_grained = enable_cache main_path = os.path.join(test_temp_dir, 'main') with open(main_path, 'w') as f: f.write(source) if sources_override is not None: sources = [ BuildSource(path, module, None) for module, path in sources_override ] else: sources = [BuildSource(main_path, None, None)] try: result = build.build(sources=sources, options=options, alt_lib_path=test_temp_dir) except CompileError as e: # TODO: We need a manager and a graph in this case as well assert False, str('\n'.join(e.messages)) return e.messages, None, None return result.errors, result.manager, result.graph
def get_options( self, source: str, testcase: DataDrivenTestCase, build_cache: bool, ) -> Options: # This handles things like '# flags: --foo'. options = parse_options(source, testcase, incremental_step=1) options.incremental = True options.use_builtins_fixtures = True options.show_traceback = True options.error_summary = False options.fine_grained_incremental = not build_cache options.use_fine_grained_cache = self.use_cache and not build_cache options.cache_fine_grained = self.use_cache options.local_partial_types = True if re.search('flags:.*--follow-imports', source) is None: # Override the default for follow_imports options.follow_imports = 'error' for name, _ in testcase.files: if 'mypy.ini' in name or 'pyproject.toml' in name: parse_config_file(options, lambda: None, name) break return options
def get_semanal_options(program_text: str, testcase: DataDrivenTestCase) -> Options: options = parse_options(program_text, testcase, 1) options.use_builtins_fixtures = True options.semantic_analysis_only = True options.show_traceback = True options.python_version = PYTHON3_VERSION return options
def run_case(self, testcase: DataDrivenTestCase) -> None: first_src = '\n'.join(testcase.input) files_dict = dict(testcase.files) second_src = files_dict['tmp/next.py'] options = parse_options(first_src, testcase, 1) messages1, files1 = self.build(first_src, options) messages2, files2 = self.build(second_src, options) a = [] if messages1: a.extend(messages1) if messages2: a.append('== next ==') a.extend(messages2) assert files1 is not None and files2 is not None, ( 'cases where CompileError' ' occurred should not be run') prefix = '__main__' snapshot1 = snapshot_symbol_table(prefix, files1['__main__'].names) snapshot2 = snapshot_symbol_table(prefix, files2['__main__'].names) diff = compare_symbol_table_snapshots(prefix, snapshot1, snapshot2) for trigger in sorted(diff): a.append(trigger) assert_string_arrays_equal( testcase.output, a, 'Invalid output ({}, line {})'.format(testcase.file, testcase.line))
def run_case(self, testcase: DataDrivenTestCase) -> None: first_src = '\n'.join(testcase.input) files_dict = dict(testcase.files) second_src = files_dict['tmp/next.py'] options = parse_options(first_src, testcase, 1) messages1, files1 = self.build(first_src, options) messages2, files2 = self.build(second_src, options) a = [] if messages1: a.extend(messages1) if messages2: a.append('== next ==') a.extend(messages2) assert files1 is not None and files2 is not None, ('cases where CompileError' ' occurred should not be run') prefix = '__main__' snapshot1 = snapshot_symbol_table(prefix, files1['__main__'].names) snapshot2 = snapshot_symbol_table(prefix, files2['__main__'].names) diff = compare_symbol_table_snapshots(prefix, snapshot1, snapshot2) for trigger in sorted(diff): a.append(trigger) assert_string_arrays_equal( testcase.output, a, 'Invalid output ({}, line {})'.format(testcase.file, testcase.line))
def get_options(self, source: str, testcase: DataDrivenTestCase, build_cache: bool) -> Options: # This handles things like '# flags: --foo'. options = parse_options(source, testcase, incremental_step=1) options.incremental = True options.use_builtins_fixtures = True options.show_traceback = True options.fine_grained_incremental = not build_cache options.use_fine_grained_cache = self.use_cache and not build_cache options.cache_fine_grained = self.use_cache options.local_partial_types = True if options.follow_imports == 'normal': options.follow_imports = 'error' return options
def run_case(self, testcase: DataDrivenTestCase) -> None: src = '\n'.join(testcase.input) dump_all = '# __dump_all__' in src if testcase.name.endswith('python2'): python_version = defaults.PYTHON2_VERSION else: python_version = defaults.PYTHON3_VERSION options = parse_options(src, testcase, incremental_step=1) options.use_builtins_fixtures = True options.show_traceback = True options.cache_dir = os.devnull options.python_version = python_version options.export_types = True options.preserve_asts = True messages, files, type_map = self.build(src, options) a = messages if files is None or type_map is None: if not a: a = [ 'Unknown compile error (likely syntax error in test case or fixture)' ] else: deps = defaultdict(set) # type: DefaultDict[str, Set[str]] for module in files: if module in dumped_modules or dump_all and module not in ( 'abc', 'typing', 'mypy_extensions', 'typing_extensions', 'enum'): new_deps = get_dependencies(files[module], type_map, python_version, options) for source in new_deps: deps[source].update(new_deps[source]) TypeState.add_all_protocol_deps(deps) for source, targets in sorted(deps.items()): if source.startswith(('<enum', '<typing', '<mypy')): # Remove noise. continue line = '%s -> %s' % (source, ', '.join(sorted(targets))) # Clean up output a bit line = line.replace('__main__', 'm') a.append(line) assert_string_arrays_equal( testcase.output, a, 'Invalid output ({}, line {})'.format(testcase.file, testcase.line))
def get_options(self, source: str, testcase: DataDrivenTestCase, build_cache: bool) -> Options: # This handles things like '# flags: --foo'. options = parse_options(source, testcase, incremental_step=1) options.incremental = True options.use_builtins_fixtures = True options.show_traceback = True options.fine_grained_incremental = not build_cache options.use_fine_grained_cache = self.use_cache and not build_cache options.cache_fine_grained = self.use_cache options.local_partial_types = True if options.follow_imports == 'normal': options.follow_imports = 'error' return options
def run_case(self, testcase: DataDrivenTestCase) -> None: src = '\n'.join(testcase.input) dump_all = '# __dump_all__' in src if testcase.name.endswith('python2'): python_version = defaults.PYTHON2_VERSION else: python_version = defaults.PYTHON3_VERSION options = parse_options(src, testcase, incremental_step=1) options.use_builtins_fixtures = True options.show_traceback = True options.cache_dir = os.devnull options.python_version = python_version options.export_types = True messages, files, type_map = self.build(src, options) a = messages if files is None or type_map is None: if not a: a = ['Unknown compile error (likely syntax error in test case or fixture)'] else: deps = defaultdict(set) # type: DefaultDict[str, Set[str]] for module in files: if module in dumped_modules or dump_all and module not in ('abc', 'typing', 'mypy_extensions', 'typing_extensions', 'enum'): new_deps = get_dependencies(files[module], type_map, python_version, options) for source in new_deps: deps[source].update(new_deps[source]) TypeState.add_all_protocol_deps(deps) for source, targets in sorted(deps.items()): if source.startswith('<enum.'): # Remove noise. continue line = '%s -> %s' % (source, ', '.join(sorted(targets))) # Clean up output a bit line = line.replace('__main__', 'm') a.append(line) assert_string_arrays_equal( testcase.output, a, 'Invalid output ({}, line {})'.format(testcase.file, testcase.line))
def test_parse_error(testcase: DataDrivenTestCase) -> None: try: options = parse_options('\n'.join(testcase.input), testcase, 0) if options.python_version != sys.version_info[:2]: skip() # Compile temporary file. The test file contains non-ASCII characters. parse(bytes('\n'.join(testcase.input), 'utf-8'), INPUT_FILE_NAME, '__main__', None, options) raise AssertionError('No errors reported') except CompileError as e: if e.module_with_blocker is not None: assert e.module_with_blocker == '__main__' # Verify that there was a compile error and that the error messages # are equivalent. assert_string_arrays_equal( testcase.output, e.messages, 'Invalid compiler output ({}, line {})'.format( testcase.file, testcase.line))
def build(self, source: str, testcase: DataDrivenTestCase) -> Optional[BuildResult]: options = parse_options(source, testcase, incremental_step=1) options.incremental = True options.fine_grained_incremental = True options.use_builtins_fixtures = True options.show_traceback = True options.python_version = PYTHON3_VERSION main_path = os.path.join(test_temp_dir, 'main') with open(main_path, 'w', encoding='utf8') as f: f.write(source) try: result = build.build(sources=[BuildSource(main_path, None, None)], options=options, alt_lib_path=test_temp_dir) except CompileError: # TODO: Is it okay to return None? return None return result
def test_transform(testcase: DataDrivenTestCase) -> None: """Perform an identity transform test case.""" try: src = '\n'.join(testcase.input) options = parse_options(src, testcase, 1) options.use_builtins_fixtures = True options.semantic_analysis_only = True options.enable_incomplete_features = True options.show_traceback = True result = build.build(sources=[BuildSource('main', None, src)], options=options, alt_lib_path=test_temp_dir) a = result.errors if a: raise CompileError(a) # Include string representations of the source files in the actual # output. for fnam in sorted(result.files.keys()): f = result.files[fnam] # Omit the builtins module and files with a special marker in the # path. # TODO the test is not reliable if (not f.path.endswith((os.sep + 'builtins.pyi', 'typing_extensions.pyi', 'typing.pyi', 'abc.pyi', 'sys.pyi')) and not os.path.basename(f.path).startswith('_') and not os.path.splitext( os.path.basename(f.path))[0].endswith('_')): t = TypeAssertTransformVisitor() t.test_only = True f = t.mypyfile(f) a += str(f).split('\n') except CompileError as e: a = e.messages if testcase.normalize_output: a = normalize_error_messages(a) assert_string_arrays_equal( testcase.output, a, f'Invalid semantic analyzer output ({testcase.file}, line {testcase.line})')
def get_options(self, source: str, testcase: DataDrivenTestCase, build_cache: bool) -> Options: # This handles things like '# flags: --foo'. options = parse_options(source, testcase, incremental_step=1) options.incremental = True options.use_builtins_fixtures = True options.show_traceback = True options.error_summary = False options.fine_grained_incremental = not build_cache options.use_fine_grained_cache = self.use_cache and not build_cache options.cache_fine_grained = self.use_cache options.local_partial_types = True if options.follow_imports == 'normal': options.follow_imports = 'error' for name, _ in testcase.files: if 'mypy.ini' in name: parse_config_file(options, name) break return options
def test_transform(testcase: DataDrivenTestCase) -> None: """Perform an identity transform test case.""" try: src = '\n'.join(testcase.input) options = parse_options(src, testcase, 1) options.use_builtins_fixtures = True options.semantic_analysis_only = True options.show_traceback = True result = build.build(sources=[BuildSource('main', None, src)], options=options, alt_lib_path=test_temp_dir) a = result.errors if a: raise CompileError(a) # Include string representations of the source files in the actual # output. for fnam in sorted(result.files.keys()): f = result.files[fnam] # Omit the builtins module and files with a special marker in the # path. # TODO the test is not reliable if (not f.path.endswith((os.sep + 'builtins.pyi', 'typing.pyi', 'abc.pyi')) and not os.path.basename(f.path).startswith('_') and not os.path.splitext( os.path.basename(f.path))[0].endswith('_')): t = TypeAssertTransformVisitor() f = t.mypyfile(f) a += str(f).split('\n') except CompileError as e: a = e.messages if testcase.normalize_output: a = normalize_error_messages(a) assert_string_arrays_equal( testcase.output, a, 'Invalid semantic analyzer output ({}, line {})'.format(testcase.file, testcase.line))
def run_case_once(self, testcase: DataDrivenTestCase, incremental_step: int = 0) -> None: find_module_clear_caches() original_program_text = '\n'.join(testcase.input) module_data = self.parse_module(original_program_text, incremental_step) if incremental_step: if incremental_step == 1: # In run 1, copy program text to program file. for module_name, program_path, program_text in module_data: if module_name == '__main__': with open(program_path, 'w') as f: f.write(program_text) break elif incremental_step > 1: # In runs 2+, copy *.[num] files to * files. for dn, dirs, files in os.walk(os.curdir): for file in files: if file.endswith('.' + str(incremental_step)): full = os.path.join(dn, file) target = full[:-2] # Use retries to work around potential flakiness on Windows (AppVeyor). retry_on_error(lambda: shutil.copy(full, target)) # In some systems, mtime has a resolution of 1 second which can cause # annoying-to-debug issues when a file has the same size after a # change. We manually set the mtime to circumvent this. new_time = os.stat(target).st_mtime + 1 os.utime(target, times=(new_time, new_time)) # Delete files scheduled to be deleted in [delete <path>.num] sections. for path in testcase.deleted_paths.get(incremental_step, set()): # Use retries to work around potential flakiness on Windows (AppVeyor). retry_on_error(lambda: os.remove(path)) # Parse options after moving files (in case mypy.ini is being moved). options = parse_options(original_program_text, testcase, incremental_step) options.use_builtins_fixtures = True options.show_traceback = True if 'optional' in testcase.file: options.strict_optional = True if incremental_step: options.incremental = True else: options.cache_dir = os.devnull # Don't waste time writing cache sources = [] for module_name, program_path, program_text in module_data: # Always set to none so we're forced to reread the module in incremental mode sources.append(BuildSource(program_path, module_name, None if incremental_step else program_text)) res = None try: res = build.build(sources=sources, options=options, alt_lib_path=test_temp_dir) a = res.errors except CompileError as e: a = e.messages a = normalize_error_messages(a) # Make sure error messages match if incremental_step == 0: # Not incremental msg = 'Unexpected type checker output ({}, line {})' output = testcase.output elif incremental_step == 1: msg = 'Unexpected type checker output in incremental, run 1 ({}, line {})' output = testcase.output elif incremental_step > 1: msg = ('Unexpected type checker output in incremental, run {}'.format( incremental_step) + ' ({}, line {})') output = testcase.output2.get(incremental_step, []) else: raise AssertionError() if output != a and self.update_data: update_testcase_output(testcase, a) assert_string_arrays_equal(output, a, msg.format(testcase.file, testcase.line)) if incremental_step and res: if options.follow_imports == 'normal' and testcase.output is None: self.verify_cache(module_data, a, res.manager) if incremental_step > 1: suffix = '' if incremental_step == 2 else str(incremental_step - 1) self.check_module_equivalence( 'rechecked' + suffix, testcase.expected_rechecked_modules.get(incremental_step - 1), res.manager.rechecked_modules) self.check_module_equivalence( 'stale' + suffix, testcase.expected_stale_modules.get(incremental_step - 1), res.manager.stale_modules)
def run_case_once(self, testcase: DataDrivenTestCase, operations: List[FileOperation] = [], incremental_step: int = 0) -> None: original_program_text = '\n'.join(testcase.input) module_data = self.parse_module(original_program_text, incremental_step) # Unload already loaded plugins, they may be updated. for file, _ in testcase.files: module = module_from_path(file) if module.endswith('_plugin') and module in sys.modules: del sys.modules[module] if incremental_step == 0 or incremental_step == 1: # In run 1, copy program text to program file. for module_name, program_path, program_text in module_data: if module_name == '__main__': with open(program_path, 'w', encoding='utf8') as f: f.write(program_text) break elif incremental_step > 1: # In runs 2+, copy *.[num] files to * files. for op in operations: if isinstance(op, UpdateFile): # Modify/create file copy_and_fudge_mtime(op.source_path, op.target_path) else: # Delete file # Use retries to work around potential flakiness on Windows (AppVeyor). path = op.path retry_on_error(lambda: os.remove(path)) # Parse options after moving files (in case mypy.ini is being moved). options = parse_options(original_program_text, testcase, incremental_step) options.use_builtins_fixtures = True options.show_traceback = True # Enable some options automatically based on test file name. if 'optional' in testcase.file: options.strict_optional = True if 'columns' in testcase.file: options.show_column_numbers = True if 'errorcodes' in testcase.file: options.show_error_codes = True if incremental_step and options.incremental: # Don't overwrite # flags: --no-incremental in incremental test cases options.incremental = True else: options.incremental = False # Don't waste time writing cache unless we are specifically looking for it if not testcase.writescache: options.cache_dir = os.devnull sources = [] for module_name, program_path, program_text in module_data: # Always set to none so we're forced to reread the module in incremental mode sources.append( BuildSource(program_path, module_name, None if incremental_step else program_text)) plugin_dir = os.path.join(test_data_prefix, 'plugins') sys.path.insert(0, plugin_dir) res = None try: res = build.build(sources=sources, options=options, alt_lib_path=test_temp_dir) a = res.errors except CompileError as e: a = e.messages finally: assert sys.path[0] == plugin_dir del sys.path[0] if testcase.normalize_output: a = normalize_error_messages(a) # Make sure error messages match if incremental_step == 0: # Not incremental msg = 'Unexpected type checker output ({}, line {})' output = testcase.output elif incremental_step == 1: msg = 'Unexpected type checker output in incremental, run 1 ({}, line {})' output = testcase.output elif incremental_step > 1: msg = ('Unexpected type checker output in incremental, run {}'. format(incremental_step) + ' ({}, line {})') output = testcase.output2.get(incremental_step, []) else: raise AssertionError() if output != a and testcase.config.getoption('--update-data', False): update_testcase_output(testcase, a) assert_string_arrays_equal(output, a, msg.format(testcase.file, testcase.line)) if res: if options.cache_dir != os.devnull: self.verify_cache(module_data, res.errors, res.manager, res.graph) name = 'targets' if incremental_step: name += str(incremental_step + 1) expected = testcase.expected_fine_grained_targets.get( incremental_step + 1) actual = res.manager.processed_targets # Skip the initial builtin cycle. actual = [ t for t in actual if not any( t.startswith(mod) for mod in core_modules + ['mypy_extensions']) ] if expected is not None: assert_target_equivalence(name, expected, actual) if incremental_step > 1: suffix = '' if incremental_step == 2 else str( incremental_step - 1) expected_rechecked = testcase.expected_rechecked_modules.get( incremental_step - 1) if expected_rechecked is not None: assert_module_equivalence('rechecked' + suffix, expected_rechecked, res.manager.rechecked_modules) expected_stale = testcase.expected_stale_modules.get( incremental_step - 1) if expected_stale is not None: assert_module_equivalence('stale' + suffix, expected_stale, res.manager.stale_modules) if testcase.output_files: check_test_output_files(testcase, incremental_step, strip_prefix='tmp/')
def run_case_once(self, testcase: DataDrivenTestCase, incremental_step: int = 0) -> None: original_program_text = '\n'.join(testcase.input) module_data = self.parse_module(original_program_text, incremental_step) if incremental_step == 0 or incremental_step == 1: # In run 1, copy program text to program file. for module_name, program_path, program_text in module_data: if module_name == '__main__': with open(program_path, 'w') as f: f.write(program_text) break elif incremental_step > 1: # In runs 2+, copy *.[num] files to * files. for dn, dirs, files in os.walk(os.curdir): for file in files: if file.endswith('.' + str(incremental_step)): full = os.path.join(dn, file) target = full[:-2] copy_and_fudge_mtime(full, target) # Delete files scheduled to be deleted in [delete <path>.num] sections. for path in testcase.deleted_paths.get(incremental_step, set()): # Use retries to work around potential flakiness on Windows (AppVeyor). retry_on_error(lambda: os.remove(path)) # Parse options after moving files (in case mypy.ini is being moved). options = parse_options(original_program_text, testcase, incremental_step) options.use_builtins_fixtures = True options.show_traceback = True if 'optional' in testcase.file: options.strict_optional = True if incremental_step: options.incremental = True sources = [] for module_name, program_path, program_text in module_data: # Always set to none so we're forced to reread the module in incremental mode sources.append(BuildSource(program_path, module_name, None if incremental_step else program_text)) res = None try: res = build.build(sources=sources, options=options, alt_lib_path=test_temp_dir) a = res.errors except CompileError as e: a = e.messages a = normalize_error_messages(a) # Make sure error messages match if incremental_step == 0: # Not incremental msg = 'Unexpected type checker output ({}, line {})' output = testcase.output elif incremental_step == 1: msg = 'Unexpected type checker output in incremental, run 1 ({}, line {})' output = testcase.output elif incremental_step > 1: msg = ('Unexpected type checker output in incremental, run {}'.format( incremental_step) + ' ({}, line {})') output = testcase.output2.get(incremental_step, []) else: raise AssertionError() if output != a and self.update_data: update_testcase_output(testcase, a) assert_string_arrays_equal(output, a, msg.format(testcase.file, testcase.line)) if res: self.verify_cache(module_data, res.errors, res.manager, res.graph) if incremental_step > 1: suffix = '' if incremental_step == 2 else str(incremental_step - 1) assert_module_equivalence( 'rechecked' + suffix, testcase.expected_rechecked_modules.get(incremental_step - 1), res.manager.rechecked_modules) assert_module_equivalence( 'stale' + suffix, testcase.expected_stale_modules.get(incremental_step - 1), res.manager.stale_modules)
def run_case_once(self, testcase: DataDrivenTestCase, operations: List[FileOperation] = [], incremental_step: int = 0) -> None: original_program_text = '\n'.join(testcase.input) module_data = self.parse_module(original_program_text, incremental_step) if incremental_step == 0 or incremental_step == 1: # In run 1, copy program text to program file. for module_name, program_path, program_text in module_data: if module_name == '__main__': with open(program_path, 'w') as f: f.write(program_text) break elif incremental_step > 1: # In runs 2+, copy *.[num] files to * files. for op in operations: if isinstance(op, UpdateFile): # Modify/create file copy_and_fudge_mtime(op.source_path, op.target_path) else: # Delete file # Use retries to work around potential flakiness on Windows (AppVeyor). path = op.path retry_on_error(lambda: os.remove(path)) # Parse options after moving files (in case mypy.ini is being moved). options = parse_options(original_program_text, testcase, incremental_step) options.use_builtins_fixtures = True options.show_traceback = True if 'optional' in testcase.file: options.strict_optional = True if incremental_step and options.incremental: # Don't overwrite # flags: --no-incremental in incremental test cases options.incremental = True else: options.incremental = False # Don't waste time writing cache unless we are specifically looking for it if 'writescache' not in testcase.name.lower(): options.cache_dir = os.devnull sources = [] for module_name, program_path, program_text in module_data: # Always set to none so we're forced to reread the module in incremental mode sources.append( BuildSource(program_path, module_name, None if incremental_step else program_text)) res = None try: res = build.build(sources=sources, options=options, alt_lib_path=test_temp_dir) a = res.errors except CompileError as e: a = e.messages a = normalize_error_messages(a) # Make sure error messages match if incremental_step == 0: # Not incremental msg = 'Unexpected type checker output ({}, line {})' output = testcase.output elif incremental_step == 1: msg = 'Unexpected type checker output in incremental, run 1 ({}, line {})' output = testcase.output elif incremental_step > 1: msg = ('Unexpected type checker output in incremental, run {}'. format(incremental_step) + ' ({}, line {})') output = testcase.output2.get(incremental_step, []) else: raise AssertionError() if output != a and testcase.config.getoption('--update-data', False): update_testcase_output(testcase, a) assert_string_arrays_equal(output, a, msg.format(testcase.file, testcase.line)) if res: if options.cache_dir != os.devnull: self.verify_cache(module_data, res.errors, res.manager, res.graph) if incremental_step > 1: suffix = '' if incremental_step == 2 else str( incremental_step - 1) assert_module_equivalence( 'rechecked' + suffix, testcase.expected_rechecked_modules.get(incremental_step - 1), res.manager.rechecked_modules) assert_module_equivalence( 'stale' + suffix, testcase.expected_stale_modules.get(incremental_step - 1), res.manager.stale_modules)
def run_case_once(self, testcase: DataDrivenTestCase, operations: List[FileOperation] = [], incremental_step: int = 0) -> None: original_program_text = '\n'.join(testcase.input) module_data = self.parse_module(original_program_text, incremental_step) # Unload already loaded plugins, they may be updated. for file, _ in testcase.files: module = module_from_path(file) if module.endswith('_plugin') and module in sys.modules: del sys.modules[module] if incremental_step == 0 or incremental_step == 1: # In run 1, copy program text to program file. for module_name, program_path, program_text in module_data: if module_name == '__main__': with open(program_path, 'w', encoding='utf8') as f: f.write(program_text) break elif incremental_step > 1: # In runs 2+, copy *.[num] files to * files. for op in operations: if isinstance(op, UpdateFile): # Modify/create file copy_and_fudge_mtime(op.source_path, op.target_path) else: # Delete file # Use retries to work around potential flakiness on Windows (AppVeyor). path = op.path retry_on_error(lambda: os.remove(path)) # Parse options after moving files (in case mypy.ini is being moved). options = parse_options(original_program_text, testcase, incremental_step) options.use_builtins_fixtures = True options.show_traceback = True if 'optional' in testcase.file: options.strict_optional = True if 'newsemanal' in testcase.file: options.new_semantic_analyzer = True if incremental_step and options.incremental: # Don't overwrite # flags: --no-incremental in incremental test cases options.incremental = True else: options.incremental = False # Don't waste time writing cache unless we are specifically looking for it if not testcase.writescache: options.cache_dir = os.devnull sources = [] for module_name, program_path, program_text in module_data: # Always set to none so we're forced to reread the module in incremental mode sources.append(BuildSource(program_path, module_name, None if incremental_step else program_text)) plugin_dir = os.path.join(test_data_prefix, 'plugins') sys.path.insert(0, plugin_dir) res = None try: res = build.build(sources=sources, options=options, alt_lib_path=test_temp_dir) a = res.errors except CompileError as e: a = e.messages finally: assert sys.path[0] == plugin_dir del sys.path[0] if testcase.normalize_output: a = normalize_error_messages(a) # Make sure error messages match if incremental_step == 0: # Not incremental msg = 'Unexpected type checker output ({}, line {})' output = testcase.output elif incremental_step == 1: msg = 'Unexpected type checker output in incremental, run 1 ({}, line {})' output = testcase.output elif incremental_step > 1: msg = ('Unexpected type checker output in incremental, run {}'.format( incremental_step) + ' ({}, line {})') output = testcase.output2.get(incremental_step, []) else: raise AssertionError() if output != a and testcase.config.getoption('--update-data', False): update_testcase_output(testcase, a) assert_string_arrays_equal(output, a, msg.format(testcase.file, testcase.line)) if res: if options.cache_dir != os.devnull: self.verify_cache(module_data, res.errors, res.manager, res.graph) if incremental_step > 1: suffix = '' if incremental_step == 2 else str(incremental_step - 1) assert_module_equivalence( 'rechecked' + suffix, testcase.expected_rechecked_modules.get(incremental_step - 1), res.manager.rechecked_modules) assert_module_equivalence( 'stale' + suffix, testcase.expected_stale_modules.get(incremental_step - 1), res.manager.stale_modules)