0
# Main Functions
1
2
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.
3
4
## Capabilities
5
6
### Primary Entry Points
7
8
The main entry points for executing darker's formatting operations.
9
10
```python { .api }
11
def main(argv: List[str] = None) -> int:
12
"""
13
Parse the command line and reformat and optionally lint each source file.
14
15
This is the main entry point that orchestrates the entire darker process:
16
1. Parse command line arguments and configuration
17
2. Apply isort import sorting (optional)
18
3. Apply flynt f-string conversion (optional)
19
4. Apply main code formatter (Black, Ruff, etc.)
20
5. Compare with Git revisions to determine changed lines
21
6. Apply formatting selectively to only changed regions
22
7. Verify AST equivalence and write results
23
24
Parameters:
25
- argv: Command line arguments to the darker command (defaults to sys.argv[1:])
26
27
Returns:
28
Exit code: 1 if --check was provided and files would be reformatted, 0 otherwise
29
"""
30
31
def main_with_error_handling() -> int:
32
"""
33
Entry point for console script with comprehensive error handling.
34
35
Catches and handles various exception types (FileNotFoundError,
36
ArgumentError, DependencyError) and returns appropriate exit codes.
37
38
Returns:
39
Exit code based on success or specific error type
40
"""
41
```
42
43
### File Processing
44
45
Core function for processing and formatting edited parts of files.
46
47
```python { .api }
48
def format_edited_parts(
49
root: Path,
50
changed_files: Collection[Path],
51
exclude: Exclusions,
52
revrange: RevisionRange,
53
formatter: BaseFormatter,
54
report_unmodified: bool,
55
workers: int = 1,
56
) -> Generator[Tuple[Path, TextDocument, TextDocument], None, None]:
57
"""
58
Format modified chunks in specified files using configured formatter.
59
60
Parameters:
61
- root: The common root directory for relative path calculations
62
- changed_files: Collection of file paths to process
63
- exclude: File exclusion patterns for pre-processing steps
64
- revrange: Git revision range for comparison
65
- formatter: Formatter instance to use for reformatting
66
- report_unmodified: Whether to report files with no changes
67
- workers: Number of worker processes (1 for single-threaded)
68
69
Yields:
70
Tuples of (file_path, original_content, formatted_content)
71
"""
72
```
73
74
### File Operations
75
76
Utilities for modifying files and printing output.
77
78
```python { .api }
79
def modify_file(path: Path, new_content: TextDocument) -> None:
80
"""
81
Write new content to a file and log the action.
82
83
Parameters:
84
- path: Path to the file to modify
85
- new_content: New content to write to the file
86
"""
87
88
def print_diff(
89
path: Path,
90
old: TextDocument,
91
new: TextDocument,
92
common_root: Path,
93
use_color: bool,
94
) -> None:
95
"""
96
Print unified diff between old and new content.
97
98
Parameters:
99
- path: File path for diff header
100
- old: Original file content
101
- new: Modified file content
102
- common_root: Root path for relative path display
103
- use_color: Whether to use syntax highlighting
104
"""
105
106
def print_source(new: TextDocument, use_color: bool) -> None:
107
"""
108
Print reformatted Python source code with optional syntax highlighting.
109
110
Parameters:
111
- new: Source code content to print
112
- use_color: Whether to apply syntax highlighting
113
"""
114
```
115
116
## Usage Examples
117
118
### Basic Programmatic Usage
119
120
```python
121
from darker import main
122
import logging
123
124
# Run darker with basic options
125
exit_code = main(
126
src=["src/", "tests/"],
127
revision="HEAD~1",
128
check=True,
129
diff=True,
130
isort=True,
131
color=True,
132
log_level=logging.INFO
133
)
134
135
if exit_code == 0:
136
print("No formatting changes needed")
137
else:
138
print("Files would be reformatted")
139
```
140
141
### Advanced File Processing
142
143
```python
144
from darker import format_edited_parts
145
from darker.config import Exclusions
146
from darker.formatters import create_formatter
147
from darkgraylib.git import RevisionRange
148
from pathlib import Path
149
150
# Set up parameters
151
common_root = Path(".")
152
paths = {Path("mymodule.py"), Path("tests/test_module.py")}
153
exclusions = Exclusions(
154
formatter=set(),
155
isort={"**/*"} if not use_isort else set(),
156
flynt={"**/*"} if not use_flynt else set()
157
)
158
revrange = RevisionRange.parse_with_common_ancestor("HEAD", ":WORKTREE:")
159
formatter = create_formatter("black")
160
161
# Process files
162
for path, old_content, new_content in format_edited_parts(
163
common_root=common_root,
164
paths=paths,
165
exclusions=exclusions,
166
revrange=revrange,
167
formatter=formatter,
168
report_unmodified=False,
169
workers=1
170
):
171
if old_content != new_content:
172
print(f"Would reformat {path}")
173
# Print diff or save changes as needed
174
```
175
176
### Error Handling
177
178
```python
179
from darker import main_with_error_handling
180
from darker.exceptions import DependencyError, MissingPackageError
181
182
try:
183
# This would normally be called as console script entry point
184
exit_code = main_with_error_handling()
185
except Exception as e:
186
print(f"Unexpected error: {e}")
187
```