-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rules/python: Add a coverage_tool
attribute to py_runtime
.
#15590
Changes from 20 commits
72a0f9e
80a6cb9
55f1aed
de88f81
437934e
37b4286
b472c21
f2c9cd2
57d88fb
e9d5582
9bb352d
4d628d3
1746437
fed8618
baed9a2
337f928
fc21d6a
7c9b34f
4550f70
ec50345
3b892de
1e8ee96
4242f74
b95db8e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -188,8 +188,61 @@ py_test( | |||||
], | ||||||
) | ||||||
``` | ||||||
<!-- TODO: Allow specifying a target for `PYTHON_COVERAGE`, instead of having to use `$(location)` --> | ||||||
|
||||||
If you are using a hermetic python toolchain, instead of adding an attribute to | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
every `py_test` rule you can instead add the coverage tool to the toolchain | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
configuration. | ||||||
|
||||||
Because the [pip_install][pip_install_rule] rule depends on the python | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
toolchain, it cannot be used to fetch the `coverage` module. | ||||||
Instead, add in your `WORKSPACE` e.g. | ||||||
|
||||||
```starlark | ||||||
http_archive( | ||||||
name = "coverage_linux_x86_64"", | ||||||
build_file_content = """ | ||||||
py_library( | ||||||
name = "coverage", | ||||||
srcs = ["coverage/__main__.py"], | ||||||
data = glob(["coverage/*", "coverage/**/*.py"]), | ||||||
visibility = ["//visibility:public"], | ||||||
) | ||||||
""", | ||||||
sha256 = "84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3", | ||||||
type = "zip", | ||||||
urls = [ | ||||||
"https://files.pythonhosted.org/packages/74/0d/0f3c522312fd27c32e1abe2fb5c323b583a5c108daf2c26d6e8dfdd5a105/coverage-6.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", | ||||||
], | ||||||
) | ||||||
``` | ||||||
|
||||||
Then configure your python toolchain as e.g. | ||||||
|
||||||
```starlark | ||||||
py_runtime( | ||||||
name = "py3_runtime_linux_x86_64", | ||||||
coverage_tool = "@coverage_linux_x86_64//:coverage", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is probably an optimization to be made somewhere in here to only have the coverage dependency when coverage is enabled. The isCodeCoverage() check in the Java code prevents it from being included at runtime, but it still causes Bazel to do various target and config resolution steps. Coverage being enabled can be detected with a config setting, e.g.
I'm not sure how that fits into toolchain registration; can selects be used within WORKSPACE? In any case, I'm find with figuring this out in a separate PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Declaration of the toolchain is in a BUILD file, not the WORKSPACE. However, I am not sure either about how |
||||||
files = ["@python3_9_x86_64-unknown-linux-gnu//:files"], | ||||||
interpreter = "@python3_9_x86_64-unknown-linux-gnu//:bin/python3", | ||||||
python_version = "PY3", | ||||||
) | ||||||
|
||||||
py_runtime_pair( | ||||||
name = "python_runtimes_linux_x86_64", | ||||||
py2_runtime = None, | ||||||
py3_runtime = ":py3_runtime_linux_x86_64", | ||||||
) | ||||||
|
||||||
toolchain( | ||||||
name = "python_toolchain_linux_x86_64", | ||||||
exec_compatible_with = [ | ||||||
"@platforms//os:linux", | ||||||
"@platforms//cpu:x86_64", | ||||||
], | ||||||
toolchain = ":python_runtimes_linux_x86_64", | ||||||
toolchain_type = "@bazel_tools//tools/python:toolchain_type", | ||||||
) | ||||||
``` | ||||||
|
||||||
[lcov]: https://github.com/linux-test-project/lcov | ||||||
[rules_python]: https://github.com/bazelbuild/rules_python | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -92,12 +92,18 @@ public boolean prohibitHyphensInPackagePaths() { | |||||||||
public void collectRunfilesForBinary( | ||||||||||
RuleContext ruleContext, Runfiles.Builder builder, PyCommon common, CcInfo ccInfo) { | ||||||||||
addRuntime(ruleContext, common, builder); | ||||||||||
if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
addCoverageSupport(ruleContext, common, builder); | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
@Override | ||||||||||
public void collectDefaultRunfilesForBinary( | ||||||||||
RuleContext ruleContext, PyCommon common, Runfiles.Builder builder) { | ||||||||||
addRuntime(ruleContext, common, builder); | ||||||||||
if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { | ||||||||||
addCoverageSupport(ruleContext, common, builder); | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
@Override | ||||||||||
|
@@ -154,6 +160,9 @@ private static void createStubFile( | |||||||||
// first-stage. | ||||||||||
String pythonBinary = getPythonBinary(ruleContext, common, bazelConfig); | ||||||||||
|
||||||||||
// The python code coverage tool to use, if any. | ||||||||||
String coverageTool = getCoverageTool(ruleContext, common, bazelConfig); | ||||||||||
|
||||||||||
// Version information for host config diagnostic warning. | ||||||||||
PythonVersion attrVersion = PyCommon.readPythonVersionFromAttribute(ruleContext.attributes()); | ||||||||||
boolean attrVersionSpecifiedExplicitly = attrVersion != null; | ||||||||||
|
@@ -172,6 +181,7 @@ private static void createStubFile( | |||||||||
Substitution.of( | ||||||||||
"%main%", common.determineMainExecutableSource(/*withWorkspaceName=*/ true)), | ||||||||||
Substitution.of("%python_binary%", pythonBinary), | ||||||||||
Substitution.of("%coverage_tool%", coverageTool == null ? "" : coverageTool), | ||||||||||
Substitution.of("%imports%", Joiner.on(":").join(common.getImports().toList())), | ||||||||||
Substitution.of("%workspace_name%", ruleContext.getWorkspaceName()), | ||||||||||
Substitution.of("%is_zipfile%", boolToLiteral(isForZipFile)), | ||||||||||
|
@@ -461,6 +471,32 @@ private static String getPythonBinary( | |||||||||
return pythonBinary; | ||||||||||
} | ||||||||||
|
||||||||||
private static void addCoverageSupport( | ||||||||||
RuleContext ruleContext, PyCommon common, Runfiles.Builder builder) { | ||||||||||
PyRuntimeInfo provider = getRuntime(ruleContext, common); | ||||||||||
if (provider != null && provider.getCoverageTool() != null) { | ||||||||||
builder.addArtifact(provider.getCoverageTool()); | ||||||||||
builder.addTransitiveArtifacts(provider.getCoverageToolFiles()); | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
@Nullable | ||||||||||
private static String getCoverageTool( | ||||||||||
RuleContext ruleContext, PyCommon common, BazelPythonConfiguration bazelConfig) { | ||||||||||
if (!ruleContext.getConfiguration().isCodeCoverageEnabled()) { | ||||||||||
return null; | ||||||||||
} | ||||||||||
String coverageTool = null; | ||||||||||
PyRuntimeInfo provider = getRuntime(ruleContext, common); | ||||||||||
if (provider != null && provider.getCoverageTool() != null) { | ||||||||||
PathFragment workspaceName = | ||||||||||
PathFragment.create(ruleContext.getRule().getPackage().getWorkspaceName()); | ||||||||||
coverageTool = | ||||||||||
workspaceName.getRelative(provider.getCoverageTool().getRunfilesPath()).getPathString(); | ||||||||||
} | ||||||||||
return coverageTool; | ||||||||||
} | ||||||||||
|
||||||||||
private static String getStubShebang(RuleContext ruleContext, PyCommon common) { | ||||||||||
PyRuntimeInfo provider = getRuntime(ruleContext, common); | ||||||||||
if (provider != null) { | ||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.