0
# Exception Handling
1
2
Complete exception hierarchy for coverage-related errors including data file issues, source code problems, plugin errors, and configuration problems.
3
4
## Capabilities
5
6
### Base Exception Classes
7
8
Core exception hierarchy for all coverage.py errors.
9
10
```python { .api }
11
class CoverageException(Exception):
12
"""
13
Base class for all exceptions raised by coverage.py.
14
15
This is the parent class for all coverage-specific exceptions.
16
Catch this to handle any coverage.py error.
17
"""
18
19
class _BaseCoverageException(Exception):
20
"""
21
Base-base class for all coverage exceptions.
22
23
Internal base class - use CoverageException instead.
24
"""
25
```
26
27
Usage example:
28
29
```python
30
import coverage
31
32
try:
33
cov = coverage.Coverage()
34
cov.start()
35
# ... your code ...
36
cov.stop()
37
cov.report()
38
except coverage.CoverageException as e:
39
print(f"Coverage error: {e}")
40
# Handle any coverage-related error
41
```
42
43
### Data-Related Exceptions
44
45
Exceptions related to coverage data file operations and data integrity.
46
47
```python { .api }
48
class DataError(CoverageException):
49
"""
50
An error occurred while using a coverage data file.
51
52
Raised when there are problems reading, writing, or processing
53
coverage data files.
54
"""
55
56
class NoDataError(CoverageException):
57
"""
58
No coverage data was available.
59
60
Raised when attempting to generate reports or perform analysis
61
without any collected coverage data.
62
"""
63
```
64
65
Usage example:
66
67
```python
68
import coverage
69
70
cov = coverage.Coverage()
71
72
try:
73
# Try to load data file
74
cov.load()
75
except coverage.NoDataError:
76
print("No coverage data found. Run 'coverage run' first.")
77
except coverage.DataError as e:
78
print(f"Data file error: {e}")
79
80
try:
81
# Try to generate report without data
82
cov.report()
83
except coverage.NoDataError:
84
print("No data to report on")
85
```
86
87
### Source Code Exceptions
88
89
Exceptions related to finding and processing source code files.
90
91
```python { .api }
92
class NoSource(CoverageException):
93
"""
94
Couldn't find the source code for a module.
95
96
Raised when coverage.py cannot locate the source file
97
for a module that was imported or executed.
98
"""
99
100
class NoCode(NoSource):
101
"""
102
Couldn't find any executable code.
103
104
Raised when a file exists but contains no executable
105
Python code (e.g., empty file, comments only).
106
"""
107
108
class NotPython(CoverageException):
109
"""
110
A source file turned out not to be parsable Python.
111
112
Raised when coverage.py attempts to parse a file as Python
113
but it contains invalid Python syntax.
114
"""
115
```
116
117
Usage example:
118
119
```python
120
import coverage
121
122
cov = coverage.Coverage()
123
cov.start()
124
125
try:
126
# Import a module that might not have source
127
import compiled_module
128
except coverage.NoSource as e:
129
print(f"Source not found: {e}")
130
except coverage.NotPython as e:
131
print(f"Not valid Python: {e}")
132
133
cov.stop()
134
135
try:
136
# Analyze a problematic file
137
analysis = cov.analysis2('problematic_file.py')
138
except coverage.NoSource:
139
print("Cannot find source for analysis")
140
except coverage.NoCode:
141
print("File contains no executable code")
142
```
143
144
### Plugin-Related Exceptions
145
146
Exceptions related to plugin operations and misbehavior.
147
148
```python { .api }
149
class PluginError(CoverageException):
150
"""
151
A plugin misbehaved in some way.
152
153
Raised when a coverage plugin encounters an error or
154
violates the plugin contract.
155
"""
156
```
157
158
Usage example:
159
160
```python
161
import coverage
162
163
try:
164
cov = coverage.Coverage(plugins=['my_plugin'])
165
cov.start()
166
# ... code execution ...
167
cov.stop()
168
except coverage.PluginError as e:
169
print(f"Plugin error: {e}")
170
# Plugin failed to initialize or caused an error
171
```
172
173
### Configuration Exceptions
174
175
Exceptions related to configuration file problems and invalid settings.
176
177
```python { .api }
178
class ConfigError(_BaseCoverageException):
179
"""
180
A problem with a configuration file or configuration value.
181
182
Raised when there are syntax errors in configuration files,
183
invalid configuration options, or conflicting settings.
184
185
Note: Inherits from _BaseCoverageException, not CoverageException.
186
"""
187
```
188
189
Usage example:
190
191
```python
192
import coverage
193
194
try:
195
cov = coverage.Coverage(config_file='invalid_config.ini')
196
except coverage.ConfigError as e:
197
print(f"Configuration error: {e}")
198
199
# Also can occur with programmatic configuration
200
try:
201
cov = coverage.Coverage()
202
cov.set_option('invalid_section:invalid_option', 'value')
203
except coverage.ConfigError as e:
204
print(f"Invalid configuration option: {e}")
205
```
206
207
### Internal Exceptions
208
209
Internal exceptions used by coverage.py for error handling during execution.
210
211
```python { .api }
212
class _ExceptionDuringRun(CoverageException):
213
"""
214
An exception happened while running customer code.
215
216
This exception is used internally to wrap exceptions that
217
occur during code execution under coverage measurement.
218
Constructed with three arguments from sys.exc_info().
219
"""
220
```
221
222
### Warning Class
223
224
Warning class for non-fatal coverage issues.
225
226
```python { .api }
227
class CoverageWarning(Warning):
228
"""
229
A warning from coverage.py.
230
231
Used for non-fatal issues that users should be aware of,
232
such as partial coverage measurement or configuration issues.
233
"""
234
```
235
236
Usage example:
237
238
```python
239
import coverage
240
import warnings
241
242
# Configure warning handling
243
warnings.filterwarnings('default', category=coverage.CoverageWarning)
244
245
cov = coverage.Coverage()
246
cov.start()
247
248
# This might generate warnings
249
try:
250
import some_problematic_module
251
except ImportWarning:
252
pass
253
254
cov.stop()
255
256
# Warnings might be issued during reporting
257
with warnings.catch_warnings(record=True) as w:
258
warnings.simplefilter("always")
259
cov.report()
260
261
for warning in w:
262
if issubclass(warning.category, coverage.CoverageWarning):
263
print(f"Coverage warning: {warning.message}")
264
```
265
266
## Exception Handling Patterns
267
268
### Comprehensive Error Handling
269
270
Handle all coverage exceptions in a structured way:
271
272
```python
273
import coverage
274
import sys
275
276
def run_with_coverage():
277
cov = coverage.Coverage(branch=True)
278
279
try:
280
cov.start()
281
282
# Your application code here
283
import my_app
284
my_app.main()
285
286
except coverage.CoverageException as e:
287
print(f"Coverage measurement error: {e}", file=sys.stderr)
288
return 1
289
290
finally:
291
cov.stop()
292
293
try:
294
cov.save()
295
except coverage.DataError as e:
296
print(f"Failed to save coverage data: {e}", file=sys.stderr)
297
return 1
298
299
try:
300
total_coverage = cov.report()
301
print(f"Total coverage: {total_coverage:.1f}%")
302
303
if total_coverage < 80:
304
print("Coverage below threshold!")
305
return 1
306
307
except coverage.NoDataError:
308
print("No coverage data to report", file=sys.stderr)
309
return 1
310
except coverage.CoverageException as e:
311
print(f"Report generation failed: {e}", file=sys.stderr)
312
return 1
313
314
return 0
315
316
if __name__ == '__main__':
317
sys.exit(run_with_coverage())
318
```
319
320
### Specific Exception Handling
321
322
Handle specific types of coverage errors:
323
324
```python
325
import coverage
326
import os
327
328
def analyze_coverage_data(data_file):
329
"""Analyze coverage data with detailed error handling."""
330
331
if not os.path.exists(data_file):
332
print(f"Coverage data file not found: {data_file}")
333
return None
334
335
cov = coverage.Coverage(data_file=data_file)
336
337
try:
338
cov.load()
339
except coverage.DataError as e:
340
print(f"Corrupted or invalid data file: {e}")
341
return None
342
except coverage.NoDataError:
343
print("Data file exists but contains no coverage data")
344
return None
345
346
try:
347
data = cov.get_data()
348
files = data.measured_files()
349
350
if not files:
351
print("No files were measured")
352
return None
353
354
results = {}
355
for filename in files:
356
try:
357
analysis = cov.analysis2(filename)
358
results[filename] = {
359
'statements': len(analysis[1]),
360
'missing': len(analysis[3]),
361
'coverage': (len(analysis[1]) - len(analysis[3])) / len(analysis[1]) * 100
362
}
363
except coverage.NoSource:
364
print(f"Warning: Source not found for {filename}")
365
results[filename] = {'error': 'source_not_found'}
366
except coverage.NotPython:
367
print(f"Warning: {filename} is not valid Python")
368
results[filename] = {'error': 'not_python'}
369
except coverage.NoCode:
370
print(f"Warning: {filename} contains no executable code")
371
results[filename] = {'error': 'no_code'}
372
373
return results
374
375
except coverage.CoverageException as e:
376
print(f"Unexpected coverage error: {e}")
377
return None
378
379
# Usage
380
results = analyze_coverage_data('.coverage')
381
if results:
382
for filename, stats in results.items():
383
if 'error' in stats:
384
print(f"{filename}: {stats['error']}")
385
else:
386
print(f"{filename}: {stats['coverage']:.1f}% coverage")
387
```
388
389
### Plugin Error Handling
390
391
Handle plugin-related errors gracefully:
392
393
```python
394
import coverage
395
396
def create_coverage_with_plugins(plugin_names):
397
"""Create coverage instance with error handling for plugins."""
398
399
successful_plugins = []
400
failed_plugins = []
401
402
for plugin_name in plugin_names:
403
try:
404
# Test plugin individually
405
test_cov = coverage.Coverage(plugins=[plugin_name])
406
test_cov.start()
407
test_cov.stop()
408
successful_plugins.append(plugin_name)
409
except coverage.PluginError as e:
410
print(f"Plugin '{plugin_name}' failed: {e}")
411
failed_plugins.append(plugin_name)
412
except Exception as e:
413
print(f"Unexpected error with plugin '{plugin_name}': {e}")
414
failed_plugins.append(plugin_name)
415
416
if successful_plugins:
417
print(f"Using plugins: {successful_plugins}")
418
return coverage.Coverage(plugins=successful_plugins)
419
else:
420
print("No plugins could be loaded, using default coverage")
421
return coverage.Coverage()
422
423
# Usage
424
cov = create_coverage_with_plugins(['plugin1', 'plugin2', 'problematic_plugin'])
425
```
426
427
### Configuration Error Handling
428
429
Handle configuration errors with fallbacks:
430
431
```python
432
import coverage
433
434
def create_coverage_with_config(config_files):
435
"""Try multiple configuration files until one works."""
436
437
for config_file in config_files:
438
try:
439
cov = coverage.Coverage(config_file=config_file)
440
print(f"Using configuration from: {config_file}")
441
return cov
442
except coverage.ConfigError as e:
443
print(f"Configuration error in {config_file}: {e}")
444
continue
445
except FileNotFoundError:
446
print(f"Configuration file not found: {config_file}")
447
continue
448
449
print("No valid configuration found, using defaults")
450
return coverage.Coverage(config_file=False)
451
452
# Usage
453
config_files = ['pyproject.toml', '.coveragerc', 'setup.cfg']
454
cov = create_coverage_with_config(config_files)
455
```
456
457
This comprehensive exception handling enables robust coverage measurement even in complex environments with multiple potential failure points.