def test_type_inference_with_timeout(self, gen_cache: MagicMock) -> None: timeout = 1 timeout_error = subprocess.TimeoutExpired(cmd="pyre query ...", timeout=timeout) gen_cache.side_effect = timeout_error paths = (str(self.DUMMY_PATH), ) type_caches = get_repo_caches( paths, FullRepoMetadataConfig({TypeInferenceProvider}, timeout)) reports = next( map_paths( operation=self.mock_operation, paths=paths, config={DummyTypeDependentRule}, workers=LintWorkers.USE_CURRENT_THREAD, metadata_caches=type_caches, )) # Expecting a placeholder cache to have been plugged in instead. self.mock_operation.assert_called_with( self.DUMMY_PATH, {DummyTypeDependentRule}, {TypeInferenceProvider: { "types": [] }}, ) self.assertEqual(len(reports), 1)
def call_map_paths_and_print_reports( file_paths: Iterable[str], opts: LintOpts, workers: LintWorkers, metadata_caches: Optional[Mapping[str, Mapping["ProviderT", object]]] = None, ) -> int: """ Calls map_paths with `apply_fix_operation`, and the passed in file_paths, opts, workers, metadata_cache. Returns the number of reports in the files. """ num_reports = 0 formatted_reports_iter = itertools.chain.from_iterable( map_paths( apply_fix_operation, file_paths, opts, workers=workers, metadata_caches=metadata_caches, )) for formatted_report in formatted_reports_iter: # Reports are yielded as soon as they're available. Stream the output to the # terminal. print(formatted_report) num_reports += 1 return num_reports
def _main(args: argparse.Namespace) -> int: width = shutil.get_terminal_size(fallback=(80, 24)).columns # Find files if directory was provided. file_paths = tuple(find_files((str(p) for p in args.paths))) if not args.compact: print(f"Scanning {len(file_paths)} files") print() start_time = time.time() if args.no_message: message = MessageKind.NO_MESSAGE elif args.message is not None: message = args.message else: message = MessageKind.USE_LINT_REPORT metadata_caches: Optional[Mapping[str, Mapping["ProviderT", object]]] = None if rules_require_metadata_cache({args.rule}): metadata_caches = get_metadata_caches(args.cache_timeout, file_paths) # opts is a more type-safe version of args that we pass around opts = InsertSuppressionsOpts( rule=args.rule, skip_autoformatter=args.skip_autoformatter, kind=SuppressionCommentKind[args.kind.upper()], message=message, max_lines=args.max_lines, formatter=SuppressedLintRuleReportFormatter(width, args.compact), ) formatted_reports_iter = itertools.chain.from_iterable( map_paths( get_formatted_reports_for_path, file_paths, opts, workers=args.workers, metadata_caches=metadata_caches, ) ) formatted_reports = [] for formatted_report in formatted_reports_iter: # Reports are yielded as soon as they're available. Stream the output to the # terminal. print(formatted_report) # save the report from the iterator for later use formatted_reports.append(formatted_report) if not args.compact: print() print( f"Found {len(formatted_reports)} reports in {len(file_paths)} files in " + f"{time.time() - start_time :.2f} seconds." ) return 0
def _main(args: argparse.Namespace) -> int: width = shutil.get_terminal_size(fallback=(80, 24)).columns # expand path if it's a directory file_paths = tuple(find_files(args.paths)) all_rules = args.rules if not args.compact: print(f"Scanning {len(file_paths)} files") print(f"Testing {len(all_rules)} rules") print() start_time = time.time() metadata_caches: Optional[Mapping[str, Mapping["ProviderT", object]]] = None if rules_require_metadata_cache(all_rules): metadata_caches = get_metadata_caches(args.cache_timeout, file_paths) # opts is a more type-safe version of args that we pass around opts = LintOpts( rules=all_rules, use_ignore_byte_markers=args.use_ignore_byte_markers, use_ignore_comments=args.use_ignore_comments, formatter=LintRuleReportFormatter(width, args.compact), ) formatted_reports_iter = itertools.chain.from_iterable( map_paths( get_formatted_reports_for_path, file_paths, opts, workers=args.workers, metadata_caches=metadata_caches, ) ) formatted_reports = [] for formatted_report in formatted_reports_iter: # Reports are yielded as soon as they're available. Stream the output to the # terminal. print(formatted_report) # save the report from the iterator for later use formatted_reports.append(formatted_report) if not args.compact: print() print( f"Found {len(formatted_reports)} reports in {len(file_paths)} files in " + f"{time.time() - start_time :.2f} seconds." ) # Return with an exit code of 1 if there are any violations found. return int(bool(formatted_reports))
def test_extra_opts(self) -> None: path = "path.py" results = next( map_paths( mock_operation, [path], self.opts, workers=LintWorkers.USE_CURRENT_THREAD, )) # Assert global list has been modified as expected. self.assertEqual(list(self.global_list), [path]) # Assert the rest of the reporting functionality is as expected self.assertEqual(len(results), 1) self.assertEqual(results[0].reports, ["fake picklable report"])
def test_basic_type_inference_multiple_paths(self, gen_cache: MagicMock) -> None: paths = (str(self.DUMMY_PATH), str(self.DUMMY_PATH_2)) gen_cache.return_value = {path: self.fake_pyre_data for path in paths} type_caches: Mapping[str, Dict[ProviderT, object]] = get_repo_caches( paths, FullRepoMetadataConfig({TypeInferenceProvider}, 1)) all_reports = map_paths( operation=self.mock_operation, paths=paths, config={DummyTypeDependentRule}, workers=LintWorkers.USE_CURRENT_THREAD, metadata_caches=type_caches, ) # Reports should be returned in order since we specified `LintWorkers.USE_CURRENT_THREAD`. for i, reports in enumerate(all_reports): self.assertEqual(len(reports), 1) self.assertEqual(reports[0].file_path, Path(paths[i]))
def test_extra_opts_multiple_paths(self) -> None: paths = ["path1.py", "path2.py"] results_iter = map_paths(mock_operation, paths, self.opts, workers=LintWorkers.USE_CURRENT_THREAD) results_count = 0 paths_reported = [] for results in results_iter: for result in results: results_count += 1 paths_reported.append(result.path) self.assertEqual(len(result.reports), 1) self.assertEqual(result.reports, ["fake picklable report"]) # Assert global list has been modified as expected. self.assertCountEqual(list(self.global_list), paths) # Assert all passed in paths have been visited as expected self.assertCountEqual(paths_reported, paths)
def test_basic_type_inference(self, gen_cache: MagicMock) -> None: # We want to intercept any calls that will require the pyre engine to be running. gen_cache.return_value = {str(self.DUMMY_PATH): self.fake_pyre_data} paths = (str(path) for path in [self.DUMMY_PATH]) type_caches: Mapping[str, Dict[ProviderT, object]] = get_repo_caches( paths, FullRepoMetadataConfig({TypeInferenceProvider}, 1)) paths = (path for path in type_caches.keys()) reports = next( map_paths( operation=self.mock_operation, paths=(path for path in type_caches.keys()), config={DummyTypeDependentRule}, workers=LintWorkers.USE_CURRENT_THREAD, metadata_caches=type_caches, )) self.mock_operation.assert_called_with( self.DUMMY_PATH, {DummyTypeDependentRule}, type_caches[str(self.DUMMY_PATH)]) self.assertEqual(len(reports), 1) self.assertEqual(reports[0].file_path, self.DUMMY_PATH)
def main(raw_args: Sequence[str]) -> int: parser = argparse.ArgumentParser( description= ("Inserts `# lint-fixme` comments into a file where lint violations are " + "found.\n" + "\n" + "You should only use this tool if it's not feasible to fix the existing " + "violations."), parents=[ get_rule_parser(), get_paths_parser(), get_skip_autoformatter_parser(), get_compact_parser(), get_metadata_cache_parser(), get_multiprocessing_parser(), ], ) parser.add_argument( "--kind", default="fixme", choices=[kind.name.lower() for kind in SuppressionCommentKind], help= "Should we use `# lint-fixme` or `# lint-ignore`? Defaults to 'fixme'.", ) message_group = parser.add_mutually_exclusive_group() message_group.add_argument( "--message", default=None, help="Overrides the lint message used in the fixme comment.", ) message_group.add_argument( "--no-message", action="store_true", help= ("Don't include a message with the suppression comment. Only include the " + "lint code."), ) parser.add_argument( "--max-lines", default=3, type=int, help= "The maximum number of lines a comment can span before getting truncated", ) args = parser.parse_args(raw_args) width = shutil.get_terminal_size(fallback=(80, 24)).columns # Find files if directory was provided. file_paths = tuple(find_files((str(p) for p in args.paths))) if not args.compact: print(f"Scanning {len(file_paths)} files") print() start_time = time.time() if args.no_message: message = MessageKind.NO_MESSAGE elif args.message is not None: message = args.message else: message = MessageKind.USE_LINT_REPORT metadata_caches: Optional[Mapping[str, Mapping["ProviderT", object]]] = None if rules_require_metadata_cache({args.rule}): metadata_caches = get_metadata_caches(args.cache_timeout, file_paths) # opts is a more type-safe version of args that we pass around opts = InsertSuppressionsOpts( rule=args.rule, skip_autoformatter=args.skip_autoformatter, kind=SuppressionCommentKind[args.kind.upper()], message=message, max_lines=args.max_lines, formatter=SuppressedLintRuleReportFormatter(width, args.compact), ) formatted_reports_iter = itertools.chain.from_iterable( map_paths( get_formatted_reports_for_path, file_paths, opts, workers=args.workers, metadata_caches=metadata_caches, )) formatted_reports = [] for formatted_report in formatted_reports_iter: # Reports are yielded as soon as they're available. Stream the output to the # terminal. print(formatted_report) # save the report from the iterator for later use formatted_reports.append(formatted_report) if not args.compact: print() print( f"Found {len(formatted_reports)} reports in {len(file_paths)} files in " + f"{time.time() - start_time :.2f} seconds.") return 0
def main(raw_args: Sequence[str]) -> int: parser = argparse.ArgumentParser( description=( "Validates your lint rules by running them against the specified, " + "directory or file(s). This is not a substitute for unit tests, " + "but it can provide additional confidence in your lint rules.\n" + "If no lint rules or packages are specified, runs all lint rules " + "found in the packages specified in `fixit.config.yaml`." ), parents=[ get_paths_parser(), get_rules_parser(), get_use_ignore_comments_parser(), get_skip_ignore_byte_marker_parser(), get_compact_parser(), get_multiprocessing_parser(), ], ) parser.add_argument( "--cache-timeout", type=int, help="Timeout (seconds) for metadata cache fetching. Default is 2 seconds.", default=2, ) args = parser.parse_args(raw_args) width = shutil.get_terminal_size(fallback=(80, 24)).columns # expand path if it's a directory file_paths = tuple(find_files(args.paths)) all_rules = args.rules if not args.compact: print(f"Scanning {len(file_paths)} files") print(f"Testing {len(all_rules)} rules") print() start_time = time.time() metadata_caches: Optional[Mapping[str, Mapping["ProviderT", object]]] = None if rules_require_metadata_cache(all_rules): metadata_caches = get_metadata_caches(args.cache_timeout, file_paths) # opts is a more type-safe version of args that we pass around opts = LintOpts( rules=all_rules, use_ignore_byte_markers=args.use_ignore_byte_markers, use_ignore_comments=args.use_ignore_comments, formatter=LintRuleReportFormatter(width, args.compact), ) formatted_reports_iter = itertools.chain.from_iterable( map_paths( get_formatted_reports_for_path, file_paths, opts, workers=args.workers, metadata_caches=metadata_caches, ) ) formatted_reports = [] for formatted_report in formatted_reports_iter: # Reports are yielded as soon as they're available. Stream the output to the # terminal. print(formatted_report) # save the report from the iterator for later use formatted_reports.append(formatted_report) if not args.compact: print() print( f"Found {len(formatted_reports)} reports in {len(file_paths)} files in " + f"{time.time() - start_time :.2f} seconds." ) # Return with an exit code of 1 if there are any violations found. return int(bool(formatted_reports))