Python interface to coveralls.io API for uploading code coverage results
—
The coverage processing module extends coverage.py functionality to generate coveralls-specific reports with line-by-line coverage data and source file information. It handles data transformation, source file reading, and optional merging of JavaScript coverage results.
Extends the standard coverage.py Coverage class with coveralls-specific report generation functionality.
class coveralls(Coverage):
"""
Extended Coverage class with coveralls report generation.
Inherits all standard coverage.py functionality and adds:
- coveralls() method for generating coveralls-formatted reports
- Integration with CoverallsReporter for data formatting
"""
def coveralls(self, base_dir, ignore_errors=False, merge_file=None):
"""
Generate coveralls-formatted coverage report.
Args:
base_dir (str): Project root directory for relative path calculation
ignore_errors (bool): If True, skip files that cannot be read or analyzed
merge_file (str, optional): Path to JSON file containing additional coverage data
Returns:
list[SourceFile]: List of source files with coverage information
"""Specialized reporter that transforms coverage.py data into the coveralls.io format with line-by-line coverage arrays and source content.
class CoverallsReporter(Reporter):
"""
Coverage reporter that generates coveralls.io compatible format.
Extends coverage.py Reporter to produce JSON-compatible data structure
with source content and line-by-line coverage arrays.
"""
def report(self, base_dir, ignore_errors=False, merge_file=None):
"""
Generate detailed coverage report for coveralls.io.
Args:
base_dir (str): Project root directory for relative paths
ignore_errors (bool): Skip files with read/analysis errors
merge_file (str, optional): JSON file with additional coverage data to merge
Returns:
list[dict]: List of source file dictionaries with:
- name: str - relative file path
- source: str - complete file content
- coverage: list[int|None] - line coverage (None=non-executable, 0=missed, 1=hit)
Raises:
IOError: If source files cannot be read and ignore_errors=False
NotPython: If files cannot be analyzed and ignore_errors=False
"""# Line-by-line coverage representation
coverage_array: list[int | None]
# None: Line is not executable (comments, blank lines, etc.)
# 0: Line is executable but was not executed (missed)
# 1: Line is executable and was executed (hit)
# Example for a 5-line file:
coverage_example = [None, 1, 1, 0, None]
# Line 1: Non-executable (None)
# Line 2: Hit (1)
# Line 3: Hit (1)
# Line 4: Missed (0)
# Line 5: Non-executable (None)from coveralls.control import coveralls
# Create coverage instance
cov = coveralls()
cov.load()
# Generate coveralls report
source_files = cov.coveralls(
base_dir='/path/to/project',
ignore_errors=False
)
# Each source file contains:
for file_info in source_files:
print(f"File: {file_info['name']}")
print(f"Lines: {len(file_info['coverage'])}")
print(f"Source length: {len(file_info['source'])}")# Ignore files that cannot be read or analyzed
source_files = cov.coveralls(
base_dir='/path/to/project',
ignore_errors=True # Skip problematic files
)
# Strict mode (default) - raise exceptions
try:
source_files = cov.coveralls(base_dir='/path/to/project')
except IOError as e:
print(f"Source file read error: {e}")
except NotPython as e:
print(f"File analysis error: {e}")# Merge JavaScript coverage data
source_files = cov.coveralls(
base_dir='/path/to/project',
merge_file='coverage/js-coverage.json'
)
# The merge file should contain JSON in format:
merge_format = {
"source_files": [
{
"name": "src/app.js",
"source": "function hello() { return 'world'; }",
"coverage": [1, 1, 1]
}
]
}from coverage.control import Coverage
from coveralls.report import CoverallsReporter
# Standard coverage.py setup
cov = Coverage()
cov.load()
# Create coveralls reporter
reporter = CoverallsReporter(cov, cov.config)
reporter.find_file_reporters(None)
# Generate report directly
source_files = reporter.report(
base_dir='/path/to/project',
ignore_errors=False,
merge_file=None
)The module integrates seamlessly with coverage.py configuration:
# .coveragerc
[run]
source = mypackage
omit =
*/tests/*
*/venv/*
setup.py
[report]
exclude_lines =
pragma: no cover
def __repr__
raise AssertionError# Standard coverage.py
coverage run -m pytest
coverage report
coveralls
# pytest-cov
pytest --cov=mypackage
coveralls
# nose with nosexcover
nosetests --with-xcoverage --cover-package=mypackage
coverallsignore_errors=True to skip problematic files# Robust coverage processing
try:
cov = coveralls()
cov.load()
source_files = cov.coveralls(
base_dir=os.path.abspath('.'),
ignore_errors=True, # Skip problematic files
merge_file='coverage.json' if os.path.exists('coverage.json') else None
)
if not source_files:
print("Warning: No coverage data found")
except Exception as e:
print(f"Coverage processing failed: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-python-coveralls