# mode: run
# tag: coverage,trace
"""
PYTHON -c "import shutil; shutil.copy('pkg/coverage_test_pyx.pyx', 'pkg/coverage_test_pyx.pxi')"
PYTHON setup.py build_ext -i
PYTHON coverage_test.py
"""
######## setup.py ########
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize([
'coverage_test_*.py*',
'pkg/coverage_test_*.py*',
'Package2/CoverageTest_*.py*'
]))
######## .coveragerc ########
[run]
plugins = Cython.Coverage
######## pkg/__init__.py ########
######## pkg/coverage_test_py.py ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1
def func1(a, b):
x = 1 # 5
c = func2(a) + b # 6
return x + c # 7
def func2(a):
return a * 2 # 11
######## pkg/coverage_test_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1
def func1(int a, int b):
cdef int x = 1 # 5
c = func2(a) + b # 6
return x + c # 7
def func2(int a):
return a * 2 # 11
######## coverage_test_include_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1
cdef int x = 5 # 4
cdef int cfunc1(int x): # 6
return x * 3 # 7
include "pkg/coverage_test_pyx.pxi" # 9
def main_func(int x): # 11
return cfunc1(x) + func1(x, 4) + func2(x) # 12
######## Package2/__init__.py ########
# Add MixedCase package and filenames to test if the files are found
######## Package2/CoverageTest_py.py ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1
def func1(a, b):
x = 1 # 5
c = func2(a) + b # 6
return x + c # 7
def func2(a):
return a * 2 # 11
######## Package2/CoverageTest_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1
def func1(int a, int b):
cdef int x = 1 # 5
c = func2(a) + b # 6
return x + c # 7
def func2(int a):
return a * 2 # 11
######## coverage_test_include_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1
cdef int x = 5 # 4
cdef int cfunc1(int x): # 6
return x * 3 # 7
include "pkg/coverage_test_pyx.pxi" # 9
def main_func(int x): # 11
return cfunc1(x) + func1(x, 4) + func2(x) # 12
######## coverage_test.py ########
import re
import os.path
try:
# io.StringIO in Py2.x cannot handle str ...
from StringIO import StringIO
except ImportError:
from io import StringIO
from coverage import coverage
from pkg import coverage_test_py
from pkg import coverage_test_pyx
import coverage_test_include_pyx
# test the MixedCase Files and packages
from Package2 import CoverageTest_py
from Package2 import CoverageTest_pyx
for module in [coverage_test_py, coverage_test_pyx, coverage_test_include_pyx,
CoverageTest_py, CoverageTest_pyx]:
assert not any(module.__file__.endswith(ext) for ext in '.py .pyc .pyo .pyw .pyx .pxi'.split()), \
module.__file__
def source_file_for(module):
module_name = module.__name__
path, ext = os.path.splitext(module.__file__)
if ext == '.so':
# Linux/Unix/Mac extension module
platform_suffix = re.search(r'[.](?:cpython|pypy)-[0-9]+[-_a-z0-9]*$', path, re.I)
if platform_suffix:
path = path[:platform_suffix.start()]
elif ext == '.pyd':
# Windows extension module
platform_suffix = re.search(r'[.]cp[0-9]+-win[_a-z0-9]*$', path, re.I)
if platform_suffix:
path = path[:platform_suffix.start()]
source_filepath = path + '.' + module_name.rsplit('_', 1)[-1]
return source_filepath
def run_coverage(module):
module_name = module.__name__
module_path = module_name.replace('.', os.path.sep) + '.' + module_name.rsplit('_', 1)[-1]
cov = coverage()
cov.start()
assert module.func1(1, 2) == (1 * 2) + 2 + 1
assert module.func2(2) == 2 * 2
if '_include_' in module_name:
assert module.main_func(2) == (2 * 3) + ((2 * 2) + 4 + 1) + (2 * 2)
cov.stop()
out = StringIO()
cov.report(file=out)
#cov.report([module], file=out)
lines = out.getvalue().splitlines()
assert any(module_path in line for line in lines), "'%s' not found in coverage report:\n\n%s" % (
module_path, out.getvalue())
mod_file, exec_lines, excl_lines, missing_lines, _ = cov.analysis2(source_file_for(module))
assert module_path in mod_file
if '_include_' in module_name:
executed = set(exec_lines) - set(missing_lines)
assert all(line in executed for line in [7, 12]), '%s / %s' % (exec_lines, missing_lines)
# rest of test if for include file
mod_file, exec_lines, excl_lines, missing_lines, _ = cov.analysis2(
os.path.join(os.path.dirname(module.__file__), "pkg", "coverage_test_pyx.pxi"))
executed = set(exec_lines) - set(missing_lines)
assert all(line in executed for line in [5, 6, 7, 11]), '%s / %s' % (exec_lines, missing_lines)
if __name__ == '__main__':
run_coverage(coverage_test_py)
run_coverage(coverage_test_pyx)
run_coverage(coverage_test_include_pyx)
run_coverage(CoverageTest_py)
run_coverage(CoverageTest_pyx)