Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
d025fdfb
Commit
d025fdfb
authored
Feb 20, 2015
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
coverage: support reporting in a separate run (when we haven't traced any files ourselves)
parent
396fee59
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
164 additions
and
12 deletions
+164
-12
Cython/Coverage.py
Cython/Coverage.py
+33
-12
tests/run/coverage_cmd.srctree
tests/run/coverage_cmd.srctree
+131
-0
No files found.
Cython/Coverage.py
View file @
d025fdfb
...
@@ -38,13 +38,6 @@ class Plugin(CoveragePlugin):
...
@@ -38,13 +38,6 @@ class Plugin(CoveragePlugin):
if
not
c_file
:
if
not
c_file
:
return
None
return
None
try
:
with
open
(
c_file
,
'rb'
)
as
f
:
if
b'/* Generated by Cython '
not
in
f
.
read
(
30
):
return
None
# not a Cython file
except
(
IOError
,
OSError
):
return
None
# parse all source file paths and lines from C file
# parse all source file paths and lines from C file
# to learn about all relevant source files right away (pyx/pxi/pxd)
# to learn about all relevant source files right away (pyx/pxi/pxd)
# FIXME: this might already be too late if the first executed line
# FIXME: this might already be too late if the first executed line
...
@@ -59,11 +52,13 @@ class Plugin(CoveragePlugin):
...
@@ -59,11 +52,13 @@ class Plugin(CoveragePlugin):
return
None
# let coverage.py handle it (e.g. .py files)
return
None
# let coverage.py handle it (e.g. .py files)
filename
=
os
.
path
.
abspath
(
filename
)
filename
=
os
.
path
.
abspath
(
filename
)
if
not
self
.
_c_files_map
or
filename
not
in
self
.
_c_files_map
:
if
self
.
_c_files_map
and
filename
in
self
.
_c_files_map
:
return
None
# unknown file
c_file
,
rel_file_path
,
code
,
excluded
=
self
.
_c_files_map
[
filename
]
c_file
,
rel_file_path
,
code
,
excluded
=
self
.
_c_files_map
[
filename
]
if
code
is
None
:
else
:
c_file
,
_
=
self
.
_find_source_files
(
filename
)
if
not
c_file
:
return
None
# unknown file
return
None
# unknown file
rel_file_path
,
code
,
excluded
=
self
.
_parse_lines
(
c_file
,
filename
)
return
CythonModuleReporter
(
c_file
,
filename
,
rel_file_path
,
code
,
excluded
)
return
CythonModuleReporter
(
c_file
,
filename
,
rel_file_path
,
code
,
excluded
)
def
_find_source_files
(
self
,
filename
):
def
_find_source_files
(
self
,
filename
):
...
@@ -94,6 +89,13 @@ class Plugin(CoveragePlugin):
...
@@ -94,6 +89,13 @@ class Plugin(CoveragePlugin):
if
not
os
.
path
.
exists
(
py_source_file
):
if
not
os
.
path
.
exists
(
py_source_file
):
py_source_file
=
None
py_source_file
=
None
try
:
with
open
(
c_file
,
'rb'
)
as
f
:
if
b'/* Generated by Cython '
not
in
f
.
read
(
30
):
return
None
# not a Cython file
except
(
IOError
,
OSError
):
c_file
=
None
return
c_file
,
py_source_file
return
c_file
,
py_source_file
def
_parse_lines
(
self
,
c_file
,
sourcefile
):
def
_parse_lines
(
self
,
c_file
,
sourcefile
):
...
@@ -189,3 +191,22 @@ class CythonModuleReporter(FileReporter):
...
@@ -189,3 +191,22 @@ class CythonModuleReporter(FileReporter):
def
excluded_statements
(
self
):
def
excluded_statements
(
self
):
return
self
.
_excluded
return
self
.
_excluded
def
_iter_source_lines
(
self
):
current_line
=
1
for
line_no
,
code_line
in
sorted
(
self
.
_code
.
iteritems
()):
while
line_no
>
current_line
:
yield
''
current_line
+=
1
yield
code_line
def
source
(
self
):
if
os
.
path
.
exists
(
self
.
source_file
):
with
open
(
self
.
source_file
)
as
f
:
return
f
.
read
()
else
:
return
'
\
n
'
.
join
(
self
.
_iter_source_lines
())
def
source_token_lines
(
self
):
for
line
in
self
.
_iter_source_lines
():
yield
[(
'txt'
,
line
)]
tests/run/coverage_cmd.srctree
0 → 100644
View file @
d025fdfb
# 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 -m coverage run coverage_test.py
PYTHON collect_coverage.py
"""
######## setup.py ########
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize([
'coverage_test_*.py*',
'pkg/coverage_test_*.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
######## coverage_test.py ########
import os.path
try:
# io.StringIO in Py2.x cannot handle str ...
from StringIO import StringIO
except ImportError:
from io import StringIO
from pkg import coverage_test_py
from pkg import coverage_test_pyx
import coverage_test_include_pyx
for module in [coverage_test_py, coverage_test_pyx, coverage_test_include_pyx]:
assert not any(module.__file__.endswith(ext) for ext in '.py .pyc .pyo .pyw .pyx .pxi'.split()), \
module.__file__
def run_coverage(module):
module_name = module.__name__
module_path = module_name.replace('.', os.path.sep) + '.' + module_name.rsplit('_', 1)[-1]
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)
if __name__ == '__main__':
run_coverage(coverage_test_py)
run_coverage(coverage_test_pyx)
run_coverage(coverage_test_include_pyx)
######## collect_coverage.py ########
import sys
import os
import os.path
import subprocess
def run_report():
env = dict(os.environ, LANG='', LC_ALL='C')
process = subprocess.Popen(
[sys.executable, '-m', 'coverage', 'report', '--show-missing'],
stdout=subprocess.PIPE, env=env)
stdout, _ = process.communicate()
stdout = stdout.decode('iso8859-1') # 'safe' decoding
lines = stdout.splitlines()
print(stdout)
# FIXME: 'coverage_test_pyx.pxi' may not be found if coverage.py requests it before the .pyx file
for module_path in ('coverage_test_py.py', 'coverage_test_pyx.pyx', 'coverage_test_include_pyx.pyx'):
assert any(module_path in line for line in lines), "'%s' not found in coverage report:\n\n%s" % (
module_path, stdout)
if __name__ == '__main__':
run_report()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment