mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-10-31 03:55:09 +00:00 
			
		
		
		
	 ebad36da06
			
		
	
	
		ebad36da06
		
			
		
	
	
	
	
		
			
			Extends https://github.com/astral-sh/ruff/pull/8416 activating the `black-and-ruff` and `black-then-ruff` formatter comparison modes for ecosystem checks allowing us to compare changes to Black across the ecosystem.
		
			
				
	
	
		
			191 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			191 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import argparse
 | |
| import asyncio
 | |
| import logging
 | |
| import os
 | |
| import shutil
 | |
| import sys
 | |
| import sysconfig
 | |
| import tempfile
 | |
| from contextlib import nullcontext
 | |
| from pathlib import Path
 | |
| from signal import SIGINT, SIGTERM
 | |
| 
 | |
| from ruff_ecosystem import logger
 | |
| from ruff_ecosystem.defaults import DEFAULT_TARGETS
 | |
| from ruff_ecosystem.format import FormatComparison
 | |
| from ruff_ecosystem.main import OutputFormat, main
 | |
| from ruff_ecosystem.projects import RuffCommand
 | |
| 
 | |
| 
 | |
| def excepthook(type, value, tb):
 | |
|     if hasattr(sys, "ps1") or not sys.stderr.isatty():
 | |
|         # we are in interactive mode or we don't have a tty so call the default
 | |
|         sys.__excepthook__(type, value, tb)
 | |
|     else:
 | |
|         import pdb
 | |
|         import traceback
 | |
| 
 | |
|         traceback.print_exception(type, value, tb)
 | |
|         print()
 | |
|         pdb.post_mortem(tb)
 | |
| 
 | |
| 
 | |
| def entrypoint():
 | |
|     args = parse_args()
 | |
| 
 | |
|     if args.pdb:
 | |
|         sys.excepthook = excepthook
 | |
| 
 | |
|     if args.verbose:
 | |
|         logging.basicConfig(level=logging.DEBUG)
 | |
|     else:
 | |
|         logging.basicConfig(level=logging.INFO)
 | |
| 
 | |
|     # Use a temporary directory for caching if no cache is specified
 | |
|     cache_context = (
 | |
|         tempfile.TemporaryDirectory() if not args.cache else nullcontext(args.cache)
 | |
|     )
 | |
| 
 | |
|     baseline_executable = args.baseline_executable
 | |
|     if not args.baseline_executable.exists():
 | |
|         baseline_executable = get_executable_path(str(args.baseline_executable))
 | |
|         if not baseline_executable:
 | |
|             print(
 | |
|                 f"Could not find ruff baseline executable: {args.baseline_executable}",
 | |
|                 sys.stderr,
 | |
|             )
 | |
|             exit(1)
 | |
|         logger.info(
 | |
|             "Resolved baseline executable %s to %s",
 | |
|             args.baseline_executable,
 | |
|             baseline_executable,
 | |
|         )
 | |
| 
 | |
|     comparison_executable = args.comparison_executable
 | |
|     if not args.comparison_executable.exists():
 | |
|         comparison_executable = get_executable_path(str(args.comparison_executable))
 | |
|         if not comparison_executable:
 | |
|             print(
 | |
|                 f"Could not find ruff comparison executable: {args.comparison_executable}",
 | |
|                 sys.stderr,
 | |
|             )
 | |
|             exit(1)
 | |
|         logger.info(
 | |
|             "Resolved comparison executable %s to %s",
 | |
|             args.comparison_executable,
 | |
|             comparison_executable,
 | |
|         )
 | |
| 
 | |
|     targets = DEFAULT_TARGETS
 | |
|     if args.force_preview:
 | |
|         targets = [target.with_preview_enabled() for target in targets]
 | |
| 
 | |
|     format_comparison = (
 | |
|         FormatComparison(args.format_comparison)
 | |
|         if args.ruff_command == RuffCommand.format.value
 | |
|         else None
 | |
|     )
 | |
| 
 | |
|     with cache_context as cache:
 | |
|         loop = asyncio.get_event_loop()
 | |
|         main_task = asyncio.ensure_future(
 | |
|             main(
 | |
|                 command=RuffCommand(args.ruff_command),
 | |
|                 baseline_executable=baseline_executable,
 | |
|                 comparison_executable=comparison_executable,
 | |
|                 targets=targets,
 | |
|                 format=OutputFormat(args.output_format),
 | |
|                 project_dir=Path(cache),
 | |
|                 raise_on_failure=args.pdb,
 | |
|                 format_comparison=format_comparison,
 | |
|             )
 | |
|         )
 | |
|         # https://stackoverflow.com/a/58840987/3549270
 | |
|         for signal in [SIGINT, SIGTERM]:
 | |
|             loop.add_signal_handler(signal, main_task.cancel)
 | |
|         try:
 | |
|             loop.run_until_complete(main_task)
 | |
|         finally:
 | |
|             loop.close()
 | |
| 
 | |
| 
 | |
| def parse_args() -> argparse.Namespace:
 | |
|     parser = argparse.ArgumentParser(
 | |
|         description="Check two versions of ruff against a corpus of open-source code.",
 | |
|     )
 | |
| 
 | |
|     # TODO: Support non-default `--targets`
 | |
|     # parser.add_argument(
 | |
|     #     "--targets",
 | |
|     #     type=Path,
 | |
|     #     help=(
 | |
|     #         "Optional JSON files to use over the default repositories. "
 | |
|     #         "Supports both github_search_*.jsonl and known-github-tomls.jsonl."
 | |
|     #     ),
 | |
|     # )
 | |
|     parser.add_argument(
 | |
|         "--cache",
 | |
|         type=Path,
 | |
|         help="Location for caching cloned repositories",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "--output-format",
 | |
|         choices=[option.value for option in OutputFormat],
 | |
|         default="markdown",
 | |
|         help="Location for caching cloned repositories",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "-v",
 | |
|         "--verbose",
 | |
|         action="store_true",
 | |
|         help="Enable debug logging",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "--pdb",
 | |
|         action="store_true",
 | |
|         help="Enable debugging on failure",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "--force-preview",
 | |
|         action="store_true",
 | |
|         help="Force preview mode to be enabled for all projects",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "--format-comparison",
 | |
|         choices=[option.value for option in FormatComparison],
 | |
|         default=FormatComparison.ruff_and_ruff,
 | |
|         help="Type of comparison to make when checking formatting.",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "ruff_command",
 | |
|         choices=[option.value for option in RuffCommand],
 | |
|         help="The Ruff command to test",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "baseline_executable",
 | |
|         type=Path,
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "comparison_executable",
 | |
|         type=Path,
 | |
|     )
 | |
| 
 | |
|     return parser.parse_args()
 | |
| 
 | |
| 
 | |
| def get_executable_path(name: str) -> Path | None:
 | |
|     # Add suffix for Windows executables
 | |
|     name += ".exe" if sys.platform == "win32" and not name.endswith(".exe") else ""
 | |
| 
 | |
|     path = os.path.join(sysconfig.get_path("scripts"), name)
 | |
| 
 | |
|     # The executable in the current interpreter's scripts directory.
 | |
|     if os.path.exists(path):
 | |
|         return Path(path)
 | |
| 
 | |
|     # The executable in the global environment.
 | |
|     environment_path = shutil.which(name)
 | |
|     if environment_path:
 | |
|         return Path(environment_path)
 | |
| 
 | |
|     return None
 |