Apply Black formatting only in regions changed since last commit
—
Core entry points for running darker formatting operations, including the main function that orchestrates the entire process and utility functions for file modification and output.
The main entry points for executing darker's formatting operations.
def main(argv: List[str] = None) -> int:
"""
Parse the command line and reformat and optionally lint each source file.
This is the main entry point that orchestrates the entire darker process:
1. Parse command line arguments and configuration
2. Apply isort import sorting (optional)
3. Apply flynt f-string conversion (optional)
4. Apply main code formatter (Black, Ruff, etc.)
5. Compare with Git revisions to determine changed lines
6. Apply formatting selectively to only changed regions
7. Verify AST equivalence and write results
Parameters:
- argv: Command line arguments to the darker command (defaults to sys.argv[1:])
Returns:
Exit code: 1 if --check was provided and files would be reformatted, 0 otherwise
"""
def main_with_error_handling() -> int:
"""
Entry point for console script with comprehensive error handling.
Catches and handles various exception types (FileNotFoundError,
ArgumentError, DependencyError) and returns appropriate exit codes.
Returns:
Exit code based on success or specific error type
"""Core function for processing and formatting edited parts of files.
def format_edited_parts(
root: Path,
changed_files: Collection[Path],
exclude: Exclusions,
revrange: RevisionRange,
formatter: BaseFormatter,
report_unmodified: bool,
workers: int = 1,
) -> Generator[Tuple[Path, TextDocument, TextDocument], None, None]:
"""
Format modified chunks in specified files using configured formatter.
Parameters:
- root: The common root directory for relative path calculations
- changed_files: Collection of file paths to process
- exclude: File exclusion patterns for pre-processing steps
- revrange: Git revision range for comparison
- formatter: Formatter instance to use for reformatting
- report_unmodified: Whether to report files with no changes
- workers: Number of worker processes (1 for single-threaded)
Yields:
Tuples of (file_path, original_content, formatted_content)
"""Utilities for modifying files and printing output.
def modify_file(path: Path, new_content: TextDocument) -> None:
"""
Write new content to a file and log the action.
Parameters:
- path: Path to the file to modify
- new_content: New content to write to the file
"""
def print_diff(
path: Path,
old: TextDocument,
new: TextDocument,
common_root: Path,
use_color: bool,
) -> None:
"""
Print unified diff between old and new content.
Parameters:
- path: File path for diff header
- old: Original file content
- new: Modified file content
- common_root: Root path for relative path display
- use_color: Whether to use syntax highlighting
"""
def print_source(new: TextDocument, use_color: bool) -> None:
"""
Print reformatted Python source code with optional syntax highlighting.
Parameters:
- new: Source code content to print
- use_color: Whether to apply syntax highlighting
"""from darker import main
import logging
# Run darker with basic options
exit_code = main(
src=["src/", "tests/"],
revision="HEAD~1",
check=True,
diff=True,
isort=True,
color=True,
log_level=logging.INFO
)
if exit_code == 0:
print("No formatting changes needed")
else:
print("Files would be reformatted")from darker import format_edited_parts
from darker.config import Exclusions
from darker.formatters import create_formatter
from darkgraylib.git import RevisionRange
from pathlib import Path
# Set up parameters
common_root = Path(".")
paths = {Path("mymodule.py"), Path("tests/test_module.py")}
exclusions = Exclusions(
formatter=set(),
isort={"**/*"} if not use_isort else set(),
flynt={"**/*"} if not use_flynt else set()
)
revrange = RevisionRange.parse_with_common_ancestor("HEAD", ":WORKTREE:")
formatter = create_formatter("black")
# Process files
for path, old_content, new_content in format_edited_parts(
common_root=common_root,
paths=paths,
exclusions=exclusions,
revrange=revrange,
formatter=formatter,
report_unmodified=False,
workers=1
):
if old_content != new_content:
print(f"Would reformat {path}")
# Print diff or save changes as neededfrom darker import main_with_error_handling
from darker.exceptions import DependencyError, MissingPackageError
try:
# This would normally be called as console script entry point
exit_code = main_with_error_handling()
except Exception as e:
print(f"Unexpected error: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-darker@3.0.1