or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdconfiguration.mdformatting.mdindex.mdjupyter.mdserver.mdtypes.md

types.mddocs/

0

# Types and Exceptions

1

2

Exception classes for error handling, constants for default configuration, type definitions, and utility functions for encoding detection and reporting functionality.

3

4

## Capabilities

5

6

### Exception Classes

7

8

Exception hierarchy for handling various error conditions during code formatting.

9

10

```python { .api }

11

class NothingChanged(UserWarning):

12

"""

13

Raised when reformatted code is identical to source.

14

15

Used to indicate that formatting was successful but no changes

16

were needed. Commonly caught and handled gracefully in tooling.

17

"""

18

pass

19

20

class InvalidInput(ValueError):

21

"""

22

Raised when source code fails all parse attempts.

23

24

Indicates that the input code contains syntax errors or uses

25

unsupported Python syntax that cannot be parsed by Black.

26

"""

27

pass

28

29

class ASTSafetyError(Exception):

30

"""

31

Raised when Black's generated code is not equivalent to source AST.

32

33

This indicates a bug in Black's formatting logic where the

34

output is not semantically equivalent to the input.

35

"""

36

pass

37

```

38

39

### Report Classes

40

41

Classes for tracking and reporting formatting results and statistics.

42

43

```python { .api }

44

class Changed(Enum):

45

"""File change status enumeration."""

46

NO = 0 # File was not changed

47

CACHED = 1 # File was not changed (result from cache)

48

YES = 2 # File was changed

49

50

@dataclass

51

class Report:

52

"""

53

Tracks formatting results and statistics.

54

55

Used by CLI and batch processing to accumulate results

56

across multiple files and provide summary statistics.

57

"""

58

check: bool = False

59

diff: bool = False

60

quiet: bool = False

61

verbose: bool = False

62

change_count: int = 0

63

same_count: int = 0

64

failure_count: int = 0

65

66

def done(self, src: Path, changed: Changed) -> None:

67

"""

68

Record completion of file processing.

69

70

Parameters:

71

- src: Path of processed file

72

- changed: Whether file was modified

73

"""

74

75

def failed(self, src: Path, message: str) -> None:

76

"""

77

Record processing failure.

78

79

Parameters:

80

- src: Path of failed file

81

- message: Error message

82

"""

83

84

def path_ignored(self, path: Path, message: str) -> None:

85

"""

86

Record ignored path with reason.

87

88

Parameters:

89

- path: Ignored path

90

- message: Reason for ignoring

91

"""

92

93

@property

94

def return_code(self) -> int:

95

"""

96

Calculate exit code for CLI usage.

97

98

Returns:

99

- 0: Success (no changes needed or changes made successfully)

100

- 1: Changes needed (when check=True) or formatting errors

101

"""

102

```

103

104

### Cache Management

105

106

Classes for managing formatting result caching to improve performance.

107

108

```python { .api }

109

@dataclass

110

class Cache:

111

"""

112

File formatting cache management.

113

114

Caches formatting results based on file content hash and

115

configuration to avoid re-formatting unchanged files.

116

"""

117

mode: Mode

118

cache_file: Path

119

file_data: dict[str, FileData] = field(default_factory=dict)

120

121

@classmethod

122

def read(cls, mode: Mode) -> 'Cache':

123

"""

124

Read existing cache from disk.

125

126

Parameters:

127

- mode: Mode configuration for cache key generation

128

129

Returns:

130

Cache instance loaded from disk or new empty cache

131

"""

132

133

@staticmethod

134

def hash_digest(path: Path) -> str:

135

"""

136

Generate hash digest for file content.

137

138

Parameters:

139

- path: Path to file

140

141

Returns:

142

SHA-256 hash of file content and metadata

143

"""

144

145

@staticmethod

146

def get_file_data(path: Path) -> 'FileData':

147

"""

148

Get file metadata for caching.

149

150

Parameters:

151

- path: Path to file

152

153

Returns:

154

FileData with hash and modification time

155

"""

156

157

@dataclass

158

class FileData:

159

"""File metadata for cache entries."""

160

hash: str

161

mtime: float

162

```

163

164

### Output Functions

165

166

Functions for formatted output with styling support.

167

168

```python { .api }

169

def out(message: Optional[str] = None, nl: bool = True, **styles: Any) -> None:

170

"""

171

Standard output with optional styling.

172

173

Parameters:

174

- message: Message to output (None for newline only)

175

- nl: Add newline after message

176

- **styles: Click styling options (fg, bg, bold, etc.)

177

"""

178

179

def err(message: Optional[str] = None, nl: bool = True, **styles: Any) -> None:

180

"""

181

Error output with optional styling.

182

183

Parameters:

184

- message: Error message to output

185

- nl: Add newline after message

186

- **styles: Click styling options

187

"""

188

189

def diff(a: str, b: str, a_name: str, b_name: str) -> str:

190

"""

191

Generate unified diff between strings.

192

193

Parameters:

194

- a: Original content

195

- b: Modified content

196

- a_name: Name/label for original

197

- b_name: Name/label for modified

198

199

Returns:

200

Unified diff string

201

"""

202

203

def color_diff(contents: str) -> str:

204

"""

205

Add ANSI color codes to diff output.

206

207

Parameters:

208

- contents: Plain diff text

209

210

Returns:

211

Colorized diff with ANSI escape sequences

212

"""

213

214

def ipynb_diff(a: str, b: str, a_name: str, b_name: str) -> str:

215

"""

216

Generate diff for Jupyter notebook cells.

217

218

Parameters:

219

- a: Original notebook cell content

220

- b: Modified notebook cell content

221

- a_name: Label for original

222

- b_name: Label for modified

223

224

Returns:

225

Diff formatted for notebook context

226

"""

227

228

def dump_to_file(*output: str, ensure_final_newline: bool = True) -> str:

229

"""

230

Write output to temporary file and return path.

231

232

Parameters:

233

- *output: Content strings to write

234

- ensure_final_newline: Add final newline if missing

235

236

Returns:

237

Path to created temporary file

238

"""

239

```

240

241

### Parsing Utilities

242

243

Core parsing functions and AST processing utilities.

244

245

```python { .api }

246

def lib2to3_parse(src_txt: str, target_versions: Collection[TargetVersion] = ()) -> Node:

247

"""

248

Parse Python source using lib2to3 with version targeting.

249

250

Parameters:

251

- src_txt: Python source code to parse

252

- target_versions: Python versions to attempt parsing with

253

254

Returns:

255

lib2to3 Node representing parsed AST

256

257

Raises:

258

- InvalidInput: If parsing fails for all target versions

259

"""

260

261

def parse_ast(src: str) -> ast.AST:

262

"""

263

Parse source to standard Python AST.

264

265

Parameters:

266

- src: Python source code

267

268

Returns:

269

Python ast.AST object

270

271

Raises:

272

- SyntaxError: If source contains syntax errors

273

"""

274

275

def stringify_ast(node: ast.AST) -> Iterator[str]:

276

"""

277

Convert AST to comparable string representation.

278

279

Parameters:

280

- node: AST node to stringify

281

282

Yields:

283

String tokens representing AST structure

284

"""

285

```

286

287

## Constants

288

289

### Default Configuration Values

290

291

```python { .api }

292

# Line length default

293

DEFAULT_LINE_LENGTH: int = 88

294

295

# File pattern constants

296

DEFAULT_EXCLUDES: str = r"/(\.direnv|\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|venv|\.svn|\.ipynb_checkpoints|_build|buck-out|build|dist)/"

297

298

DEFAULT_INCLUDES: str = r"(\.pyi?|\.ipynb)$"

299

300

# Stdin placeholder for file processing

301

STDIN_PLACEHOLDER: str = "__BLACK_STDIN_FILENAME__"

302

```

303

304

### Type Aliases

305

306

```python { .api }

307

# Content types

308

FileContent = str

309

Encoding = str

310

NewLine = str

311

312

# Legacy compatibility

313

FileMode = Mode

314

315

# AST types (from blib2to3)

316

Node = blib2to3.pytree.Node

317

Leaf = blib2to3.pytree.Leaf

318

LN = Union[Leaf, Node] # Leaf or Node

319

NL = blib2to3.pytree.Base # Node or Leaf base

320

321

# Path types

322

PathLike = Union[str, Path, os.PathLike[str]]

323

324

# Collection types

325

Collection = typing.Collection

326

Sequence = typing.Sequence

327

Iterator = typing.Iterator

328

```

329

330

## Usage Examples

331

332

### Exception Handling

333

334

```python

335

import black

336

from pathlib import Path

337

338

def safe_format_file(file_path: Path) -> tuple[bool, str]:

339

"""Safely format file with comprehensive error handling."""

340

try:

341

changed = black.format_file_in_place(

342

file_path,

343

fast=False,

344

mode=black.Mode(),

345

write_back=black.WriteBack.YES

346

)

347

return changed, "Success"

348

349

except black.NothingChanged:

350

return False, "No changes needed"

351

352

except black.InvalidInput as e:

353

return False, f"Syntax error: {e}"

354

355

except black.ASTSafetyError as e:

356

return False, f"AST safety check failed: {e}"

357

358

except PermissionError:

359

return False, "Permission denied"

360

361

except Exception as e:

362

return False, f"Unexpected error: {e}"

363

364

# Usage

365

changed, message = safe_format_file(Path("example.py"))

366

print(f"Result: {message}")

367

```

368

369

### Report Usage

370

371

```python

372

from pathlib import Path

373

374

# Create report for batch processing

375

report = black.Report(check=False, diff=True, verbose=True)

376

377

files = [Path("file1.py"), Path("file2.py"), Path("file3.py")]

378

379

for file_path in files:

380

try:

381

changed = black.format_file_in_place(

382

file_path,

383

fast=False,

384

mode=black.Mode(),

385

write_back=black.WriteBack.YES

386

)

387

388

# Record result

389

status = black.Changed.YES if changed else black.Changed.NO

390

report.done(file_path, status)

391

392

except Exception as e:

393

report.failed(file_path, str(e))

394

395

# Print summary

396

print(f"Files changed: {report.change_count}")

397

print(f"Files unchanged: {report.same_count}")

398

print(f"Files failed: {report.failure_count}")

399

print(f"Exit code: {report.return_code}")

400

```

401

402

### Cache Usage

403

404

```python

405

# Read existing cache

406

mode = black.Mode(line_length=88)

407

cache = black.Cache.read(mode)

408

409

# Check if file needs formatting

410

file_path = Path("example.py")

411

file_data = black.Cache.get_file_data(file_path)

412

file_hash = black.Cache.hash_digest(file_path)

413

414

if file_hash in cache.file_data:

415

print("File already processed (cached)")

416

else:

417

print("File needs processing")

418

# ... format file ...

419

# Update cache with new file data

420

cache.file_data[file_hash] = file_data

421

```

422

423

### Output Functions Usage

424

425

```python

426

import black

427

428

# Styled output

429

black.out("Formatting completed successfully", fg="green", bold=True)

430

black.err("Formatting failed", fg="red", bold=True)

431

432

# Generate and display diff

433

original = "def hello(name):print(f'Hello {name}!')"

434

formatted = black.format_str(original, mode=black.Mode())

435

436

diff_text = black.diff(original, formatted, "original", "formatted")

437

colored_diff = black.color_diff(diff_text)

438

439

print("Plain diff:")

440

print(diff_text)

441

print("\nColored diff:")

442

print(colored_diff)

443

444

# Write to temporary file

445

temp_path = black.dump_to_file(formatted, ensure_final_newline=True)

446

print(f"Wrote formatted code to: {temp_path}")

447

```

448

449

### Parsing and AST Usage

450

451

```python

452

import ast

453

import black

454

455

code = """

456

def example_function(x: int, y: str = "default") -> str:

457

return f"{x}: {y}"

458

"""

459

460

# Parse with lib2to3 (Black's parser)

461

lib2to3_tree = black.lib2to3_parse(code)

462

print(f"lib2to3 tree type: {type(lib2to3_tree)}")

463

464

# Parse with standard AST

465

ast_tree = black.parse_ast(code)

466

print(f"AST tree type: {type(ast_tree)}")

467

468

# Convert AST to comparable format

469

ast_strings = list(black.stringify_ast(ast_tree))

470

print(f"AST representation: {ast_strings[:5]}...") # First 5 tokens

471

472

# Use in equivalence checking

473

formatted = black.format_str(code, mode=black.Mode())

474

try:

475

black.assert_equivalent(code, formatted)

476

print("Formatted code is AST-equivalent to original")

477

except AssertionError as e:

478

print(f"AST equivalence check failed: {e}")

479

```

480

481

### Type Checking Integration

482

483

```python

484

from typing import Union, Optional

485

import black

486

487

def format_code_safe(

488

code: str,

489

*,

490

mode: Optional[black.Mode] = None,

491

lines: Optional[black.Collection[tuple[int, int]]] = None

492

) -> Union[str, None]:

493

"""

494

Type-safe code formatting function.

495

496

Returns None if formatting fails, formatted string if successful.

497

"""

498

if mode is None:

499

mode = black.Mode()

500

501

if lines is None:

502

lines = ()

503

504

try:

505

return black.format_str(code, mode=mode, lines=lines)

506

except (black.InvalidInput, black.NothingChanged):

507

return None

508

except Exception:

509

return None

510

511

# Usage with type checking

512

result = format_code_safe("def hello(): pass")

513

if result is not None:

514

print("Formatted successfully")

515

print(result)

516

else:

517

print("Formatting failed")

518

```