Skip to content

Commit 6e9d55e

Browse files
committed
Python coverage: experimental first steps
- Add lcov_merger as an attribute to the py_test rule so that it does not immediately fall over - Add a small section to python_stub_template.txt to perform minimal setup for coverage integration I was able to get this to work manually by using a modified version of coverage.py, see: nedbat/coveragepy#863 Note that the patch does not work out of the box. It's basically ~impossible to add integration tests until we get a working version of coverage.py, but this is the minimum change required in Bazel to get a basic working version.
1 parent d122855 commit 6e9d55e

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPyTestRule.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
5757
attr("$launcher", LABEL)
5858
.cfg(HostTransition.createFactory())
5959
.value(env.getToolsLabel("//tools/launcher:launcher")))
60+
.add(attr(":lcov_merger", LABEL).value(BaseRuleClasses.getCoverageOutputGeneratorLabel()))
6061
.build();
6162
}
6263

src/main/java/com/google/devtools/build/lib/bazel/rules/python/python_stub_template.txt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,26 @@ def Main():
307307
program = python_program = FindPythonBinary(module_space)
308308
if python_program is None:
309309
raise AssertionError('Could not find python binary: ' + PYTHON_BINARY)
310-
args = [python_program, main_filename] + args
310+
311+
cov_tool = os.environ.get('PYTHON_COVERAGE')
312+
if cov_tool:
313+
# Inhibit infinite recursion:
314+
del os.environ['PYTHON_COVERAGE']
315+
if not os.path.exists(cov_tool):
316+
raise EnvironmentError('Python coverage tool %s not found.' % cov_tool)
317+
args = [python_program, cov_tool, 'run', '-a', '--branch', main_filename] + args
318+
# coverage library expects sys.path[0] to contain the library, and replaces
319+
# it with the directory of the program it starts. Our actual sys.path[0] is
320+
# the runfiles directory, which must not be replaced.
321+
# CoverageScript.do_execute() undoes this sys.path[0] setting.
322+
#
323+
# Update sys.path such that python finds the coverage package. The coverage
324+
# entry point is coverage.coverage_main, so we need to do twice the dirname.
325+
new_env['PYTHONPATH'] = \
326+
new_env['PYTHONPATH'] + ':' + os.path.dirname(os.path.dirname(cov_tool))
327+
new_env['PYTHON_LCOV_FILE'] = os.environ.get('COVERAGE_DIR') + '/pylcov.dat'
328+
else:
329+
args = [python_program, main_filename] + args
311330

312331
os.environ.update(new_env)
313332

0 commit comments

Comments
 (0)