8000 Merge branch 'main' into feat/entry-point-bzlmod-minimal · bazel-contrib/rules_python@c5966cd · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit c5966cd

Browse files
authored
Merge branch 'main' into feat/entry-point-bzlmod-minimal
2 parents 8e3c9b0 + 1383bd4 commit c5966cd

File tree

10 files changed

+96
-14
lines changed

10 files changed

+96
-14
lines changed

docs/pip_repository.md

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/build_file_generation/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ extension, so that targets like `py_library` and `py_binary` can be
55
automatically created just by running
66

77
```sh
8-
$ bazel run //:gazelle
8+
bazel run //:requirements.update
9+
bazel run //:gazelle_python_manifest.update
10+
bazel run //:gazelle
911
```
1012

1113
As a demo, try creating a `__main__.py` file in this directory, then

examples/bzlmod/BUILD.bazel

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
load("@pip//:requirements.bzl", "requirement")
1+
load("@bazel_skylib//rules:build_test.bzl", "build_test")
2+
load("@pip//:requirements.bzl", "all_requirements", "all_whl_requirements", "requirement")
23
load("@python3_9//:defs.bzl", py_test_with_transition = "py_test")
34
load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
45
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
@@ -44,3 +45,13 @@ py_test_with_transition(
4445
main = "test.py",
4546
deps = [":lib"],
4647
)
48+
49+
build_test(
50+
name = "all_wheels",
51+
targets = all_whl_requirements,
52+
)
53+
54+
build_test(
55+
name = "all_requirements",
56+
targets = all_requirements,
57+
)

examples/bzlmod/MODULE.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module(
44
compatibility_level = 1,
55
)
66

7+
bazel_dep(name = "bazel_skylib", version = "1.4.1")
78
bazel_dep(name = "rules_python", version = "0.0.0")
89
local_path_override(
910
module_name = "rules_python",
@@ -34,6 +35,8 @@ pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
3435
pip.parse(
3536
name = "pip",
3637
python_interpreter_target = "@interpreter_python3_9//:python",
38+
# Intentionally set it false because the "true" case is already covered by examples/bzlmod_build_file_generation
39+
incompatible_generate_aliases = False,
3740
requirements_lock = "//:requirements_lock.txt",
3841
requirements_windows = "//:requirements_windows.txt",
3942
)

examples/bzlmod/test.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,57 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import os
16+
import pathlib
17+
import sys
1518
import unittest
1619

1720
from lib import main
1821

1922

2023
class ExampleTest(unittest.TestCase):
24+
def test_coverage_doesnt_shadow_stdlib(self):
25+
# When we try to import the html module
26+
import html as html_stdlib
27+
28+
try:
29+
import coverage.html as html_coverage
30+
except ImportError:
31+
self.skipTest("not running under coverage, skipping")
32+
33+
self.assertNotEqual(
34+
html_stdlib,
35+
html_coverage,
36+
"'html' import should not be shadowed by coverage",
37+
)
38+
39+
def test_coverage_sys_path(self):
40+
all_paths = ",\n ".join(sys.path)
41+
42+
for i, path in enumerate(sys.path[1:-2]):
43+
self.assertFalse(
44+
"/coverage" in path,
45+
f"Expected {i + 2}th '{path}' to not contain 'coverage.py' paths, "
46+
f"sys.path has {len(sys.path)} items:\n {all_paths}",
47+
)
48+
49+
first_item, last_item = sys.path[0], sys.path[-1]
50+
self.assertFalse(
51+
first_item.endswith("coverage"),
52+
f"Expected the first item in sys.path '{first_item}' to not be related to coverage",
53+
)
54+
if os.environ.get("COVERAGE_MANIFEST"):
55+
# we are running under the 'bazel coverage :test'
56+
self.assertTrue(
57+
"pypi__coverage_cp" in last_item,
58+
f"Expected {last_item} to be related to coverage",
59+
)
60+
self.assertEqual(pathlib.Path(last_item).name, "coverage")
61+
else:
62+
self.assertFalse(
63+
"coverage" in last_item, f"Expected coverage tooling to not be present"
64+
)
65+
2166
def test_main(self):
2267
self.assertEquals(
2368
"""\

python/extensions/pip.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def _pip_impl(module_ctx):
3434
# this does not create the install_deps() macro.
3535
pip_repository_bzlmod(
3636
name = attr.name,
37+
repo_name = attr.name,
3738
requirements_lock = attr.requirements_lock,
3839
incompatible_generate_aliases = attr.incompatible_generate_aliases,
3940
)

python/pip_install/pip_repository.bzl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ def _pip_repository_bzlmod_impl(rctx):
358358

359359
bzl_packages = sorted([name for name, _ in packages])
360360

361-
repo_name = rctx.attr.name.split("~")[-1]
361+
repo_name = rctx.attr.repo_name
362362

363363
build_contents = _BUILD_FILE_CONTENTS
364364

@@ -379,11 +379,11 @@ def _pip_repository_bzlmod_impl(rctx):
379379
rctx.file("BUILD.bazel", build_contents)
380380
rctx.template("requirements.bzl", rctx.attr._template, substitutions = {
381381
"%%ALL_REQUIREMENTS%%": _format_repr_list([
382-
"@{}//{}".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:pkg".format(rctx.attr.name, p)
382+
macro_tmpl.format(p, p) if rctx.attr.incompatible_generate_aliases else macro_tmpl.format(p, "pkg")
383383
for p in bzl_packages
384384
]),
385385
"%%ALL_WHL_REQUIREMENTS%%": _format_repr_list([
386-
"@{}//{}:whl".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:whl".format(rctx.attr.name, p)
386+
macro_tmpl.format(p, "whl")
387387
for p in bzl_packages
388388
]),
389389
"%%MACRO_TMPL%%": macro_tmpl,
@@ -396,6 +396,10 @@ pip_repository_bzlmod_attrs = {
396396
default = False,
397397
doc = "Allow generating aliases in '@pip//:<pkg>' -> '@pip_<pkg>//:pkg'. This replaces the aliases generated by the `bzlmod` tooling.",
398398
),
399+
"repo_name": attr.string(
400+
mandatory = True,
401+
doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name",
402+
),
399403
"requirements_darwin": attr.label(
400404
allow_single_file = True,
401405
doc = "Override the requirements_lock attribute when the host platform is Mac OS",

python/pip_install/private/test/requirements_parser_tests.bzl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ SomeProject == 1.3 # This is a comment
6262
FooProject==1.0.0
6363
# Comment
6464
BarProject==2.0.0 #Comment
65+
""").requirements)
66+
asserts.equals(env, [("requests", "requests @ https://github.com/psf/requests/releases/download/v2.29.0/requests-2.29.0.tar.gz#sha1=3897c249b51a1a405d615a8c9cb92e5fdbf0dd49")], parse("""\
67+
requests @ https://github.com/psf/requests/releases/download/v2.29.0/requests-2.29.0.tar.gz#sha1=3897c249b51a1a405d615a8c9cb92e5fdbf0dd49
6568
""").requirements)
6669

6770
# Multiline
@@ -71,6 +74,11 @@ certifi==2021.10.8 \
7174
--hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569
7275
# via requests
7376
""").requirements)
77+
asserts.equals(env, [("requests", "requests @ https://github.com/psf/requests/releases/download/v2.29.0/requests-2.29.0.tar.gz#sha1=3897c249b51a1a405d615a8c9cb92e5fdbf0dd49 --hash=sha256:eca58eb564b134e4ff521a02aa6f566c653835753e1fc8a50a20cb6bee4673cd")], parse("""\
78+
requests @ https://github.com/psf/requests/releases/download/v2.29.0/requests-2.29.0.tar.gz#sha1=3897c249b51a1a405d615a8c9cb92e5fdbf0dd49 \
79+
--hash=sha256:eca58eb564b134e4ff521a02aa6f566c653835753e1fc8a50a20cb6bee4673cd
80+
# via requirements.txt
81+
""").requirements)
7482

7583
# Options
7684
asserts.equals(env, ["--pre"], parse("--pre\n").options)

python/pip_install/requirements_parser.bzl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def _handleParseOption(input, buffer, result):
116116
elif input == "\n" or input == EOF:
117117
result.options.append(buffer.rstrip("\n"))
118118
return (_STATE.ConsumeSpace, "")
119-
elif input == "#":
119+
elif input == "#" and (len(buffer) == 0 or buffer[-1].isspace()):
120120
return (_STATE.ConsumeComment, buffer)
121121

122122
return (_STATE.ParseOption, buffer + input)
@@ -127,7 +127,7 @@ def _handleParseRequirement(input, buffer, result):
127127
elif input == "\n" or input == EOF:
128128
result.requirements[-1] = (result.requirements[-1][0], buffer.rstrip(" \n"))
129129
return (_STATE.ConsumeSpace, "")
130-
elif input == "#":
130+
elif input == "#" and (len(buffer) == 0 or buffer[-1].isspace()):
131131
return (_STATE.ConsumeComment, buffer)
132132

133133
return (_STATE.ParseRequirement, buffer + input)

python/repositories.bzl

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,11 @@ def _python_repository_impl(rctx):
106106
python_version = rctx.attr.python_version
107107
python_short_version = python_version.rpartition(".")[0]
108108
release_filename = rctx.attr.release_filename
109-
url = rctx.attr.urls or [rctx.attr.url]
109+
urls = rctx.attr.urls or [rctx.attr.url]
110110

111111
if release_filename.endswith(".zst"):
112112
rctx.download(
113-
url = url,
113+
url = urls,
114114
sha256 = rctx.attr.sha256,
115115
output = release_filename,
116116
)
@@ -153,7 +153,7 @@ def _python_repository_impl(rctx):
153153
fail(fail_msg)
154154
else:
155155
rctx.download_and_extract(
156-
url = url,
156+
url = urls,
157157
sha256 = rctx.attr.sha256,
158158
stripPrefix = rctx.attr.strip_prefix,
159159
)
@@ -348,7 +348,7 @@ py_runtime_pair(
348348
rctx.file(STANDALONE_INTERPRETER_FILENAME, "# File intentionally left blank. Indicates that this is an interpreter repo created by rules_python.")
349349
rctx.file("BUILD.bazel", build_content)
350350

351-
return {
351+
attrs = {
352352
"coverage_tool": rctx.attr.coverage_tool,
353353
"distutils": rctx.attr.distutils,
354354
"distutils_content": rctx.attr.distutils_content,
@@ -360,9 +360,15 @@ py_runtime_pair(
360360
"release_filename": release_filename,
361361
"sha256": rctx.attr.sha256,
362362
"strip_prefix": rctx.attr.strip_prefix,
363-
"url": url,
364363
}
365364

365+
if rctx.attr.url:
366+
attrs["url"] = rctx.attr.url
367+
else:
368+
attrs["urls"] = urls
369+
370+
return attrs
371+
366372
python_repository = repository_rule(
367373
_python_repository_impl,
368374
doc = "Fetches the external tools needed for the Python toolchain.",

0 commit comments

Comments
 (0)
0