or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdconfig-logging.mdexceptions.mdformatting.mdindex.mdprogrammatic-api.md

exceptions.mddocs/

0

# Exception Handling

1

2

Comprehensive exception hierarchy for handling errors during flake8 execution, including plugin loading failures, execution errors, and early termination scenarios.

3

4

## Capabilities

5

6

### Base Exception Class

7

8

Base exception class for all flake8-specific errors.

9

10

```python { .api }

11

class Flake8Exception(Exception):

12

"""

13

Base exception class for all flake8-specific errors.

14

15

All flake8-related exceptions inherit from this class, allowing

16

for easy exception handling of flake8-specific issues.

17

18

Example:

19

try:

20

# flake8 operations

21

except Flake8Exception as e:

22

# Handle any flake8-specific error

23

"""

24

```

25

26

### Execution Control Exceptions

27

28

Exceptions related to execution flow and early termination.

29

30

```python { .api }

31

class EarlyQuit(Flake8Exception):

32

"""

33

Exception raised when flake8 encounters a KeyboardInterrupt.

34

35

This exception is raised when the user interrupts flake8 execution

36

(typically with Ctrl+C) to provide clean termination handling.

37

38

Example:

39

try:

40

style_guide.check_files(large_file_list)

41

except EarlyQuit:

42

print("Flake8 execution was interrupted by user")

43

"""

44

45

class ExecutionError(Flake8Exception):

46

"""

47

Exception raised during general execution of flake8.

48

49

This exception covers various execution errors that can occur

50

during flake8's operation that are not covered by more specific

51

exception types.

52

53

Example:

54

try:

55

app.run(invalid_args)

56

except ExecutionError as e:

57

print(f"Execution failed: {e}")

58

"""

59

```

60

61

### Plugin-Related Exceptions

62

63

Exceptions specifically related to plugin loading and execution failures.

64

65

```python { .api }

66

class FailedToLoadPlugin(Flake8Exception):

67

"""

68

Exception raised when a plugin fails to load.

69

70

This exception occurs when flake8 cannot load a configured plugin,

71

typically due to import errors, missing dependencies, or plugin

72

code issues.

73

"""

74

75

def __init__(self, plugin_name: str, exception: Exception) -> None:

76

"""

77

Initialize plugin loading failure exception.

78

79

Parameters:

80

plugin_name: Name of the plugin that failed to load

81

exception: The underlying exception that caused the failure

82

"""

83

84

@property

85

def plugin_name(self) -> str:

86

"""Name of the plugin that failed to load."""

87

88

@property

89

def original_exception(self) -> Exception:

90

"""The underlying exception that caused the plugin loading failure."""

91

92

class PluginRequestedUnknownParameters(Flake8Exception):

93

"""

94

Exception raised when a plugin requests unknown parameters.

95

96

This exception occurs when a plugin tries to access configuration

97

parameters or options that are not recognized by flake8.

98

"""

99

100

def __init__(self, plugin_name: str, exception: Exception) -> None:

101

"""

102

Initialize unknown parameters exception.

103

104

Parameters:

105

plugin_name: Name of the plugin requesting unknown parameters

106

exception: The underlying exception from the parameter request

107

"""

108

109

@property

110

def plugin_name(self) -> str:

111

"""Name of the plugin that requested unknown parameters."""

112

113

@property

114

def original_exception(self) -> Exception:

115

"""The underlying exception from the parameter request."""

116

117

class PluginExecutionFailed(Flake8Exception):

118

"""

119

Exception raised when a plugin fails during execution.

120

121

This exception occurs when a plugin encounters an error while

122

processing a file or performing its checking operations.

123

"""

124

125

def __init__(self, filename: str, plugin_name: str, exception: Exception) -> None:

126

"""

127

Initialize plugin execution failure exception.

128

129

Parameters:

130

filename: Path to the file being processed when the failure occurred

131

plugin_name: Name of the plugin that failed during execution

132

exception: The underlying exception that caused the execution failure

133

"""

134

135

@property

136

def filename(self) -> str:

137

"""Path to the file being processed when the plugin failed."""

138

139

@property

140

def plugin_name(self) -> str:

141

"""Name of the plugin that failed during execution."""

142

143

@property

144

def original_exception(self) -> Exception:

145

"""The underlying exception that caused the execution failure."""

146

```

147

148

## Exception Handling Examples

149

150

### Basic Exception Handling

151

152

```python

153

from flake8.api import legacy

154

from flake8 import exceptions

155

156

def safe_flake8_check(files):

157

"""Run flake8 with comprehensive exception handling."""

158

159

try:

160

style_guide = legacy.get_style_guide()

161

report = style_guide.check_files(files)

162

return report.total_errors

163

164

except exceptions.EarlyQuit:

165

print("⚠️ Flake8 execution was interrupted by user")

166

return -1

167

168

except exceptions.ExecutionError as e:

169

print(f"❌ Flake8 execution failed: {e}")

170

return -1

171

172

except exceptions.FailedToLoadPlugin as e:

173

print(f"❌ Plugin loading failed: {e.plugin_name}")

174

print(f" Reason: {e.original_exception}")

175

return -1

176

177

except exceptions.PluginExecutionFailed as e:

178

print(f"❌ Plugin execution failed: {e.plugin_name}")

179

print(f" File: {e.filename}")

180

print(f" Error: {e.original_exception}")

181

return -1

182

183

except exceptions.PluginRequestedUnknownParameters as e:

184

print(f"❌ Plugin configuration error: {e.plugin_name}")

185

print(f" Reason: {e.original_exception}")

186

return -1

187

188

except exceptions.Flake8Exception as e:

189

print(f"❌ General flake8 error: {e}")

190

return -1

191

192

except Exception as e:

193

print(f"💥 Unexpected error: {e}")

194

return -1

195

196

# Usage

197

result = safe_flake8_check(['myproject/'])

198

if result >= 0:

199

print(f"Found {result} violations")

200

else:

201

print("Check failed due to errors")

202

```

203

204

### Plugin Error Recovery

205

206

```python

207

from flake8.api import legacy

208

from flake8 import exceptions

209

import logging

210

211

class RobustFlake8Runner:

212

"""Flake8 runner with plugin error recovery."""

213

214

def __init__(self):

215

self.failed_plugins = set()

216

self.logger = logging.getLogger(__name__)

217

218

def run_with_fallback(self, files, plugins=None):

219

"""Run flake8 with automatic plugin fallback."""

220

221

plugins = plugins or []

222

working_plugins = [p for p in plugins if p not in self.failed_plugins]

223

224

try:

225

# Try with current working plugins

226

style_guide = legacy.get_style_guide(

227

enable_extensions=working_plugins

228

)

229

report = style_guide.check_files(files)

230

return report.total_errors

231

232

except exceptions.FailedToLoadPlugin as e:

233

self.logger.warning(f"Plugin {e.plugin_name} failed to load: {e.original_exception}")

234

self.failed_plugins.add(e.plugin_name)

235

236

# Retry without the failed plugin

237

if e.plugin_name in working_plugins:

238

working_plugins.remove(e.plugin_name)

239

return self.run_with_fallback(files, working_plugins)

240

241

# If no plugins left, try with defaults

242

return self._run_default(files)

243

244

except exceptions.PluginExecutionFailed as e:

245

self.logger.error(f"Plugin {e.plugin_name} failed on {e.filename}: {e.original_exception}")

246

self.failed_plugins.add(e.plugin_name)

247

248

# Retry without the failed plugin

249

if e.plugin_name in working_plugins:

250

working_plugins.remove(e.plugin_name)

251

return self.run_with_fallback(files, working_plugins)

252

253

return self._run_default(files)

254

255

except exceptions.PluginRequestedUnknownParameters as e:

256

self.logger.warning(f"Plugin {e.plugin_name} has configuration issues: {e.original_exception}")

257

self.failed_plugins.add(e.plugin_name)

258

259

# Retry without the problematic plugin

260

if e.plugin_name in working_plugins:

261

working_plugins.remove(e.plugin_name)

262

return self.run_with_fallback(files, working_plugins)

263

264

return self._run_default(files)

265

266

def _run_default(self, files):

267

"""Run flake8 with only default built-in checkers."""

268

269

try:

270

self.logger.info("Running with default checkers only")

271

style_guide = legacy.get_style_guide()

272

report = style_guide.check_files(files)

273

return report.total_errors

274

275

except exceptions.Flake8Exception as e:

276

self.logger.error(f"Even default flake8 failed: {e}")

277

raise

278

279

# Usage

280

runner = RobustFlake8Runner()

281

try:

282

violations = runner.run_with_fallback(

283

['myproject/'],

284

plugins=['flake8-bugbear', 'flake8-import-order', 'flake8-docstrings']

285

)

286

print(f"Found {violations} violations")

287

except Exception as e:

288

print(f"Complete failure: {e}")

289

```

290

291

### Detailed Error Reporting

292

293

```python

294

from flake8.api import legacy

295

from flake8 import exceptions

296

import traceback

297

import sys

298

299

def detailed_flake8_check(files, report_file=None):

300

"""Run flake8 with detailed error reporting."""

301

302

error_report = {

303

'success': False,

304

'violations': 0,

305

'errors': [],

306

'warnings': []

307

}

308

309

try:

310

style_guide = legacy.get_style_guide(show_source=True)

311

report = style_guide.check_files(files)

312

313

error_report['success'] = True

314

error_report['violations'] = report.total_errors

315

316

return error_report

317

318

except exceptions.EarlyQuit:

319

error_report['errors'].append({

320

'type': 'EarlyQuit',

321

'message': 'User interrupted execution',

322

'fatal': False

323

})

324

325

except exceptions.FailedToLoadPlugin as e:

326

error_report['errors'].append({

327

'type': 'PluginLoadError',

328

'plugin': e.plugin_name,

329

'message': str(e.original_exception),

330

'fatal': True,

331

'traceback': traceback.format_exc()

332

})

333

334

except exceptions.PluginExecutionFailed as e:

335

error_report['errors'].append({

336

'type': 'PluginExecutionError',

337

'plugin': e.plugin_name,

338

'file': e.filename,

339

'message': str(e.original_exception),

340

'fatal': False,

341

'traceback': traceback.format_exc()

342

})

343

344

except exceptions.PluginRequestedUnknownParameters as e:

345

error_report['warnings'].append({

346

'type': 'PluginConfigurationWarning',

347

'plugin': e.plugin_name,

348

'message': str(e.original_exception),

349

'suggestion': 'Check plugin documentation and configuration'

350

})

351

352

except exceptions.ExecutionError as e:

353

error_report['errors'].append({

354

'type': 'ExecutionError',

355

'message': str(e),

356

'fatal': True,

357

'traceback': traceback.format_exc()

358

})

359

360

except exceptions.Flake8Exception as e:

361

error_report['errors'].append({

362

'type': 'GeneralFlake8Error',

363

'message': str(e),

364

'fatal': True,

365

'traceback': traceback.format_exc()

366

})

367

368

except Exception as e:

369

error_report['errors'].append({

370

'type': 'UnexpectedError',

371

'message': str(e),

372

'fatal': True,

373

'traceback': traceback.format_exc()

374

})

375

376

# Save detailed report if requested

377

if report_file:

378

import json

379

with open(report_file, 'w') as f:

380

json.dump(error_report, f, indent=2)

381

382

return error_report

383

384

def print_error_report(error_report):

385

"""Print formatted error report."""

386

387

if error_report['success']:

388

print(f"✅ Success! Found {error_report['violations']} violations")

389

return

390

391

print("❌ Flake8 execution encountered errors:")

392

393

for error in error_report['errors']:

394

print(f"\n🔥 {error['type']}: {error['message']}")

395

if 'plugin' in error:

396

print(f" Plugin: {error['plugin']}")

397

if 'file' in error:

398

print(f" File: {error['file']}")

399

if error.get('fatal'):

400

print(" ⚠️ This is a fatal error")

401

402

for warning in error_report['warnings']:

403

print(f"\n⚠️ {warning['type']}: {warning['message']}")

404

if 'plugin' in warning:

405

print(f" Plugin: {warning['plugin']}")

406

if 'suggestion' in warning:

407

print(f" 💡 {warning['suggestion']}")

408

409

# Usage

410

if __name__ == "__main__":

411

files_to_check = sys.argv[1:] or ['.']

412

413

report = detailed_flake8_check(files_to_check, 'flake8-error-report.json')

414

print_error_report(report)

415

416

# Exit with appropriate code

417

if report['success']:

418

sys.exit(0 if report['violations'] == 0 else 1)

419

else:

420

sys.exit(2) # Error during execution

421

```