0
# Codacy Coverage
1
2
A Python coverage reporter that uploads code coverage data from Python projects to the Codacy platform for code quality analysis and monitoring. It parses XML coverage reports generated by Python coverage tools and provides both command-line and programmatic interfaces for integration into CI/CD pipelines.
3
4
## Package Information
5
6
- **Package Name**: codacy-coverage
7
- **Language**: Python
8
- **Installation**: `pip install codacy-coverage`
9
10
## Core Imports
11
12
```python
13
import codacy
14
```
15
16
For programmatic access to specific functions:
17
18
```python
19
from codacy import reporter
20
from codacy.reporter import (
21
parse_report_file, merge_and_round_reports, upload_report,
22
get_git_revision_hash, get_git_directory, generate_filename, run
23
)
24
```
25
26
For internal session management utilities:
27
28
```python
29
import contextlib
30
from codacy.reporter import _request_session, _Retry
31
```
32
33
## Basic Usage
34
35
### Command Line Usage
36
37
The primary usage is through the command-line interface:
38
39
```bash
40
# Basic usage with default coverage.xml file
41
python-codacy-coverage
42
43
# Specify custom coverage report file
44
python-codacy-coverage -r coverage.xml
45
46
# Upload with explicit configuration
47
python-codacy-coverage -r coverage.xml -c abc123commit -t your_project_token
48
49
# Verbose output for debugging
50
python-codacy-coverage -r coverage.xml -v
51
```
52
53
### Programmatic Usage
54
55
```python
56
import codacy
57
58
# Run the coverage reporter
59
codacy.main()
60
```
61
62
## Environment Variables
63
64
The package recognizes these environment variables:
65
66
- **CODACY_PROJECT_TOKEN**: Required project token for API authentication
67
- **CODACY_API_BASE_URL**: Optional API base URL (defaults to https://api.codacy.com)
68
69
## Capabilities
70
71
### Coverage Report Upload
72
73
Main entry point for uploading coverage reports to Codacy platform.
74
75
```python { .api }
76
def run(prog=None):
77
"""
78
Main function that handles argument parsing and executes coverage upload.
79
80
Processes command line arguments, validates input files, parses coverage reports,
81
merges multiple reports if provided, and uploads to Codacy API. Handles all
82
error conditions with appropriate exit codes.
83
84
Parameters:
85
- prog (str, optional): Program name for argument parser
86
87
Environment Variables:
88
- CODACY_PROJECT_TOKEN: Required project token (if --token not provided)
89
- CODACY_API_BASE_URL: Optional API base URL (defaults to https://api.codacy.com)
90
91
Command Line Arguments:
92
-r, --report: Coverage report file (can be specified multiple times, defaults to 'coverage.xml')
93
-c, --commit: Git commit hash (auto-detected via git rev-parse HEAD if not provided)
94
-t, --token: Codacy project token (overrides CODACY_PROJECT_TOKEN env var)
95
-d, --directory: Git top level directory (auto-detected via git rev-parse --show-toplevel if not provided)
96
-v, --verbose: Show debug information (sets logging level to DEBUG)
97
98
Behavior:
99
- Validates all report files exist before processing any
100
- Auto-detects git commit and directory if not provided
101
- Processes multiple coverage files and merges them
102
- Rounds all coverage percentages to integers
103
- Exits with code 1 on missing token or missing coverage files
104
105
Returns:
106
None (exits with status code 0 on success, 1 on error)
107
"""
108
```
109
110
### Package Entry Point
111
112
Convenience function for running the coverage reporter.
113
114
```python { .api }
115
def main():
116
"""
117
Entry point function that runs the coverage reporter.
118
119
Returns:
120
Result from reporter.run()
121
"""
122
```
123
124
### Coverage Report Processing
125
126
Parses XML coverage reports and converts them to Codacy API format.
127
128
```python { .api }
129
def parse_report_file(report_file, git_directory):
130
"""
131
Parse XML coverage report and convert to Codacy API format.
132
133
Parameters:
134
- report_file (str): Path to coverage XML file
135
- git_directory (str): Git repository root directory
136
137
Returns:
138
dict: Parsed coverage report structure with format:
139
{
140
'language': 'python',
141
'total': int, # Overall coverage percentage
142
'codeLines': int, # Total lines of code
143
'fileReports': [ # List of file-level reports
144
{
145
'filename': str, # Relative file path
146
'total': int, # File coverage percentage
147
'codeLines': int, # Lines in file
148
'coverage': dict # Line-by-line hit counts
149
}
150
]
151
}
152
"""
153
```
154
155
```python { .api }
156
def merge_and_round_reports(report_list):
157
"""
158
Merges multiple coverage reports and rounds all values to integers.
159
160
Parameters:
161
- report_list (list): List of parsed report dictionaries
162
163
Returns:
164
dict: Merged and rounded coverage report with same structure as parse_report_file
165
"""
166
```
167
168
### API Communication
169
170
Uploads processed coverage data to the Codacy platform with built-in retry logic and session management.
171
172
```python { .api }
173
def upload_report(report, token, commit):
174
"""
175
Uploads coverage report to Codacy API with automatic retry on failures.
176
177
Parameters:
178
- report (dict): Coverage report data from parse_report_file/merge_and_round_reports
179
- token (str): Codacy project token
180
- commit (str): Git commit hash
181
182
Returns:
183
None
184
185
Raises:
186
requests.HTTPError: On API communication failure after all retries
187
"""
188
```
189
190
### HTTP Session Management
191
192
Internal utilities for managing HTTP sessions with retry logic.
193
194
```python { .api }
195
@contextlib.contextmanager
196
def _request_session():
197
"""
198
Context manager that provides HTTP session with automatic retry configuration.
199
200
Creates a requests.Session with custom retry logic that retries on all
201
status codes >= 400, configured for up to MAX_RETRIES attempts.
202
203
Yields:
204
requests.Session: Configured session with retry adapter
205
"""
206
```
207
208
```python { .api }
209
class _Retry(urllib3_util.Retry):
210
"""
211
Custom retry strategy that forces retries on HTTP status codes >= 400.
212
213
Extends urllib3.util.Retry to override is_forced_retry() method,
214
enabling retries on client and server errors (4xx, 5xx status codes).
215
"""
216
217
def is_forced_retry(self, method, status_code):
218
"""
219
Determines if a retry should be forced based on status code.
220
221
Parameters:
222
- method (str): HTTP method
223
- status_code (int): HTTP response status code
224
225
Returns:
226
bool: True if status_code >= 400, False otherwise
227
"""
228
```
229
230
### Git Utilities
231
232
Helper functions for Git repository information.
233
234
```python { .api }
235
def get_git_revision_hash():
236
"""
237
Gets current git commit hash using git rev-parse HEAD.
238
239
Returns:
240
str: Git commit hash
241
242
Raises:
243
subprocess.CalledProcessError: If git command fails
244
"""
245
```
246
247
```python { .api }
248
def get_git_directory():
249
"""
250
Gets git repository root directory using git rev-parse --show-toplevel.
251
252
Returns:
253
str: Git root directory path
254
255
Raises:
256
subprocess.CalledProcessError: If git command fails
257
"""
258
```
259
260
### File Processing
261
262
Utilities for handling coverage report file paths.
263
264
```python { .api }
265
def generate_filename(sources, filename, git_directory):
266
"""
267
Generates relative filename path for coverage reports by finding the file
268
in source directories and creating a path relative to git repository root.
269
270
Parameters:
271
- sources (list): List of source directories from coverage XML
272
- filename (str): Original filename from coverage report
273
- git_directory (str): Git root directory path
274
275
Returns:
276
str: Relative file path or original filename if not found
277
"""
278
```
279
280
## Constants
281
282
```python { .api }
283
CODACY_BASE_API_URL = 'https://api.codacy.com' # Configurable via CODACY_API_BASE_URL env var
284
URL = CODACY_BASE_API_URL + '/2.0/coverage/{commit}/python' # API endpoint template
285
DEFAULT_REPORT_FILE = 'coverage.xml' # Default coverage report filename
286
MAX_RETRIES = 3 # Maximum HTTP request retries
287
BAD_REQUEST = 400 # HTTP bad request status code
288
```
289
290
## Error Handling
291
292
The package handles several error conditions with specific patterns:
293
294
- **Missing project token**: Logs error message "environment variable CODACY_PROJECT_TOKEN is not defined." and exits with code 1 if CODACY_PROJECT_TOKEN is not set and no --token provided
295
- **Missing coverage files**: Logs error message "Coverage report {filename} not found." and exits with code 1 if any specified coverage report files don't exist
296
- **Git command failures**: Functions like get_git_revision_hash() and get_git_directory() raise subprocess.CalledProcessError when git commands fail
297
- **API failures**: upload_report() raises requests.HTTPError on communication failures after all retry attempts
298
- **HTTP retries**: Uses custom _Retry class to automatically retry failed requests (status >= 400) up to MAX_RETRIES times
299
- **API response handling**: Logs success messages from API responses or error messages on failure
300
- **File not found during processing**: generate_filename() logs debug message "File not found: {filename}" and returns original filename when source file cannot be located
301
302
## Usage Examples
303
304
### CI/CD Integration
305
306
Common patterns for continuous integration environments:
307
308
```bash
309
# GitHub Actions
310
python-codacy-coverage -r coverage.xml
311
312
# With custom commit (e.g., AppVeyor)
313
python-codacy-coverage -c $APPVEYOR_REPO_COMMIT -d $APPVEYOR_BUILD_FOLDER -r coverage.xml
314
315
# Multiple coverage files
316
python-codacy-coverage -r coverage.xml -r integration_coverage.xml
317
```
318
319
### Programmatic Usage
320
321
```python
322
from codacy.reporter import parse_report_file, upload_report, get_git_revision_hash
323
import os
324
325
# Parse coverage report
326
git_dir = '/path/to/repo'
327
report = parse_report_file('coverage.xml', git_dir)
328
329
# Upload to Codacy
330
token = os.getenv('CODACY_PROJECT_TOKEN')
331
commit = get_git_revision_hash()
332
upload_report(report, token, commit)
333
```