Codacy coverage reporter for Python that uploads code coverage data from Python projects to Codacy platform
npx @tessl/cli install tessl/pypi-codacy-coverage@1.3.0A 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.
pip install codacy-coverageimport codacyFor programmatic access to specific functions:
from codacy import reporter
from codacy.reporter import (
parse_report_file, merge_and_round_reports, upload_report,
get_git_revision_hash, get_git_directory, generate_filename, run
)For internal session management utilities:
import contextlib
from codacy.reporter import _request_session, _RetryThe primary usage is through the command-line interface:
# Basic usage with default coverage.xml file
python-codacy-coverage
# Specify custom coverage report file
python-codacy-coverage -r coverage.xml
# Upload with explicit configuration
python-codacy-coverage -r coverage.xml -c abc123commit -t your_project_token
# Verbose output for debugging
python-codacy-coverage -r coverage.xml -vimport codacy
# Run the coverage reporter
codacy.main()The package recognizes these environment variables:
Main entry point for uploading coverage reports to Codacy platform.
def run(prog=None):
"""
Main function that handles argument parsing and executes coverage upload.
Processes command line arguments, validates input files, parses coverage reports,
merges multiple reports if provided, and uploads to Codacy API. Handles all
error conditions with appropriate exit codes.
Parameters:
- prog (str, optional): Program name for argument parser
Environment Variables:
- CODACY_PROJECT_TOKEN: Required project token (if --token not provided)
- CODACY_API_BASE_URL: Optional API base URL (defaults to https://api.codacy.com)
Command Line Arguments:
-r, --report: Coverage report file (can be specified multiple times, defaults to 'coverage.xml')
-c, --commit: Git commit hash (auto-detected via git rev-parse HEAD if not provided)
-t, --token: Codacy project token (overrides CODACY_PROJECT_TOKEN env var)
-d, --directory: Git top level directory (auto-detected via git rev-parse --show-toplevel if not provided)
-v, --verbose: Show debug information (sets logging level to DEBUG)
Behavior:
- Validates all report files exist before processing any
- Auto-detects git commit and directory if not provided
- Processes multiple coverage files and merges them
- Rounds all coverage percentages to integers
- Exits with code 1 on missing token or missing coverage files
Returns:
None (exits with status code 0 on success, 1 on error)
"""Convenience function for running the coverage reporter.
def main():
"""
Entry point function that runs the coverage reporter.
Returns:
Result from reporter.run()
"""Parses XML coverage reports and converts them to Codacy API format.
def parse_report_file(report_file, git_directory):
"""
Parse XML coverage report and convert to Codacy API format.
Parameters:
- report_file (str): Path to coverage XML file
- git_directory (str): Git repository root directory
Returns:
dict: Parsed coverage report structure with format:
{
'language': 'python',
'total': int, # Overall coverage percentage
'codeLines': int, # Total lines of code
'fileReports': [ # List of file-level reports
{
'filename': str, # Relative file path
'total': int, # File coverage percentage
'codeLines': int, # Lines in file
'coverage': dict # Line-by-line hit counts
}
]
}
"""def merge_and_round_reports(report_list):
"""
Merges multiple coverage reports and rounds all values to integers.
Parameters:
- report_list (list): List of parsed report dictionaries
Returns:
dict: Merged and rounded coverage report with same structure as parse_report_file
"""Uploads processed coverage data to the Codacy platform with built-in retry logic and session management.
def upload_report(report, token, commit):
"""
Uploads coverage report to Codacy API with automatic retry on failures.
Parameters:
- report (dict): Coverage report data from parse_report_file/merge_and_round_reports
- token (str): Codacy project token
- commit (str): Git commit hash
Returns:
None
Raises:
requests.HTTPError: On API communication failure after all retries
"""Internal utilities for managing HTTP sessions with retry logic.
@contextlib.contextmanager
def _request_session():
"""
Context manager that provides HTTP session with automatic retry configuration.
Creates a requests.Session with custom retry logic that retries on all
status codes >= 400, configured for up to MAX_RETRIES attempts.
Yields:
requests.Session: Configured session with retry adapter
"""class _Retry(urllib3_util.Retry):
"""
Custom retry strategy that forces retries on HTTP status codes >= 400.
Extends urllib3.util.Retry to override is_forced_retry() method,
enabling retries on client and server errors (4xx, 5xx status codes).
"""
def is_forced_retry(self, method, status_code):
"""
Determines if a retry should be forced based on status code.
Parameters:
- method (str): HTTP method
- status_code (int): HTTP response status code
Returns:
bool: True if status_code >= 400, False otherwise
"""Helper functions for Git repository information.
def get_git_revision_hash():
"""
Gets current git commit hash using git rev-parse HEAD.
Returns:
str: Git commit hash
Raises:
subprocess.CalledProcessError: If git command fails
"""def get_git_directory():
"""
Gets git repository root directory using git rev-parse --show-toplevel.
Returns:
str: Git root directory path
Raises:
subprocess.CalledProcessError: If git command fails
"""Utilities for handling coverage report file paths.
def generate_filename(sources, filename, git_directory):
"""
Generates relative filename path for coverage reports by finding the file
in source directories and creating a path relative to git repository root.
Parameters:
- sources (list): List of source directories from coverage XML
- filename (str): Original filename from coverage report
- git_directory (str): Git root directory path
Returns:
str: Relative file path or original filename if not found
"""CODACY_BASE_API_URL = 'https://api.codacy.com' # Configurable via CODACY_API_BASE_URL env var
URL = CODACY_BASE_API_URL + '/2.0/coverage/{commit}/python' # API endpoint template
DEFAULT_REPORT_FILE = 'coverage.xml' # Default coverage report filename
MAX_RETRIES = 3 # Maximum HTTP request retries
BAD_REQUEST = 400 # HTTP bad request status codeThe package handles several error conditions with specific patterns:
Common patterns for continuous integration environments:
# GitHub Actions
python-codacy-coverage -r coverage.xml
# With custom commit (e.g., AppVeyor)
python-codacy-coverage -c $APPVEYOR_REPO_COMMIT -d $APPVEYOR_BUILD_FOLDER -r coverage.xml
# Multiple coverage files
python-codacy-coverage -r coverage.xml -r integration_coverage.xmlfrom codacy.reporter import parse_report_file, upload_report, get_git_revision_hash
import os
# Parse coverage report
git_dir = '/path/to/repo'
report = parse_report_file('coverage.xml', git_dir)
# Upload to Codacy
token = os.getenv('CODACY_PROJECT_TOKEN')
commit = get_git_revision_hash()
upload_report(report, token, commit)