http_proxy
, https_proxy
and no_proxy
Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME>
style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {}
|
| extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | []
|
| incompatible_generate_aliases | Allow generating aliases '@pip//<pkg>' -> '@pip_<pkg>//:pkg'. | Boolean | optional | False
|
-| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED
enviornment varaible can be used to control this flag. | Boolean | optional | True
|
+| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED
environment variable can be used to control this flag. | Boolean | optional | True
|
| pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | []
|
| python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH
environment variable. If no value is set python3
is defaulted for Unix systems and python.exe
for Windows. | String | optional | ""
|
-| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None
|
+| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. An example value: "@python3_x86_64-unknown-linux-gnu//:python". | Label | optional | None
|
| quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True
|
| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar"
declares that, for any time this repository depends on @foo
(such as a dependency on @foo//some:target
, it should actually resolve that dependency within globally-declared @bar
(@bar//some:target
). | Dictionary: String -> String | required | |
| repo_prefix | Prefix for the generated packages will be of the form @<prefix><sanitized-package-name>//...
| String | optional | ""
|
@@ -85,8 +85,9 @@ py_binary(
## pip_repository_bzlmod
-pip_repository_bzlmod(name, incompatible_generate_aliases, repo_mapping, requirements_darwin, - requirements_linux, requirements_lock, requirements_windows) +pip_repository_bzlmod(name, incompatible_generate_aliases, repo_mapping, repo_name, + requirements_darwin, requirements_linux, requirements_lock, + requirements_windows)A rule for bzlmod pip_repository creation. Intended for private use only. @@ -99,6 +100,7 @@ A rule for bzlmod pip_repository creation. Intended for private use only. | name | A unique name for this repository. | Name | required | | | incompatible_generate_aliases | Allow generating aliases in '@pip//:<pkg>' -> '@pip_<pkg>//:pkg'. This replaces the aliases generated by the
bzlmod
tooling. | Boolean | optional | False
|
| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar"
declares that, for any time this repository depends on @foo
(such as a dependency on @foo//some:target
, it should actually resolve that dependency within globally-declared @bar
(@bar//some:target
). | Dictionary: String -> String | required | |
+| repo_name | The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name | String | required | |
| requirements_darwin | Override the requirements_lock attribute when the host platform is Mac OS | Label | optional | None
|
| requirements_linux | Override the requirements_lock attribute when the host platform is Linux | Label | optional | None
|
| requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. | Label | optional | None
|
@@ -130,10 +132,10 @@ Instantiated from pip_repository and inherits config options from there.
| enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False
or the global Bazel option --incompatible_default_to_explicit_init_py
to prevent __init__.py
being automatically generated in every directory.False
|
| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy
, https_proxy
and no_proxy
Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME>
style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {}
|
| extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | []
|
-| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED
enviornment varaible can be used to control this flag. | Boolean | optional | True
|
+| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED
environment variable can be used to control this flag. | Boolean | optional | True
|
| pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | []
|
| python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH
environment variable. If no value is set python3
is defaulted for Unix systems and python.exe
for Windows. | String | optional | ""
|
-| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None
|
+| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. An example value: "@python3_x86_64-unknown-linux-gnu//:python". | Label | optional | None
|
| quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True
|
| repo | Pointer to parent repo name. Used to make these rules rerun if the parent repo changes. | String | required | |
| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar"
declares that, for any time this repository depends on @foo
(such as a dependency on @foo//some:target
, it should actually resolve that dependency within globally-declared @bar
(@bar//some:target
). | Dictionary: String -> String | required | |
diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel
index 3ef89054c9..feb1cfbd4e 100644
--- a/examples/BUILD.bazel
+++ b/examples/BUILD.bazel
@@ -22,6 +22,11 @@ bazel_integration_test(
timeout = "long",
)
+bazel_integration_test(
+ name = "bzlmod_build_file_generation_example",
+ timeout = "long",
+)
+
bazel_integration_test(
name = "pip_install_example",
timeout = "long",
diff --git a/examples/build_file_generation/.bazelrc b/examples/build_file_generation/.bazelrc
index f23315a7a1..28f634bef6 100644
--- a/examples/build_file_generation/.bazelrc
+++ b/examples/build_file_generation/.bazelrc
@@ -1,4 +1,4 @@
-test --test_output=errors
+test --test_output=errors --enable_runfiles
# Windows requires these for multi-python support:
build --enable_runfiles
diff --git a/examples/build_file_generation/MODULE.bazel b/examples/build_file_generation/MODULE.bazel
deleted file mode 100644
index 5f79fec486..0000000000
--- a/examples/build_file_generation/MODULE.bazel
+++ /dev/null
@@ -1,43 +0,0 @@
-module(
- name = "example_bzlmod",
- version = "0.0.0",
- compatibility_level = 1,
-)
-
-bazel_dep(name = "rules_python", version = "0.19.0")
-bazel_dep(name = "rules_python_gazelle_plugin", version = "0.19.0")
-bazel_dep(name = "gazelle", version = "0.29.0", repo_name = "bazel_gazelle")
-
-# local overrides for the packages for CI purposes.
-# for usual setups you should remove this block.
-local_path_override(
- module_name = "rules_python",
- path = "../..",
-)
-
-local_path_override(
- module_name = "rules_python_gazelle_plugin",
- path = "../../gazelle",
-)
-
-# Register python toolchain
-python = use_extension("@rules_python//python:extensions.bzl", "python")
-python.toolchain(
- name = "python3_9",
- python_version = "3.9",
-)
-use_repo(python, "python3_9_toolchains")
-
-register_toolchains(
- "@python3_9_toolchains//:all",
-)
-
-pip = use_extension("@rules_python//python:extensions.bzl", "pip")
-pip.parse(
- name = "pip",
- # Generate user friendly alias labels for each dependency that we have.
- incompatible_generate_aliases = True,
- requirements_lock = "//:requirements_lock.txt",
- requirements_windows = "//:requirements_windows.txt",
-)
-use_repo(pip, "pip")
diff --git a/examples/build_file_generation/README.md b/examples/build_file_generation/README.md
index 9b2fe1a7be..cd3cd1f109 100644
--- a/examples/build_file_generation/README.md
+++ b/examples/build_file_generation/README.md
@@ -5,7 +5,9 @@ extension, so that targets like `py_library` and `py_binary` can be
automatically created just by running
```sh
-$ bazel run //:gazelle
+bazel run //:requirements.update
+bazel run //:gazelle_python_manifest.update
+bazel run //:gazelle
```
As a demo, try creating a `__main__.py` file in this directory, then
diff --git a/examples/build_file_generation/WORKSPACE.bzlmod b/examples/build_file_generation/WORKSPACE.bzlmod
deleted file mode 100644
index 721e065154..0000000000
--- a/examples/build_file_generation/WORKSPACE.bzlmod
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file will be used when bzlmod is enabled, keep it empty
-# to ensure that all of the setup is done in MODULE.bazel
diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml
index b57e9f02bc..1000757ea5 100644
--- a/examples/build_file_generation/gazelle_python.yaml
+++ b/examples/build_file_generation/gazelle_python.yaml
@@ -115,4 +115,4 @@ manifest:
pip_repository:
name: pip
use_pip_repository_aliases: true
-integrity: 85f073e37e31339508aaaf5e0d5472adae5148fd5f054e9cc586343c026660e1
+integrity: 030d6d99b56c32d6577e616b617260d0a93588af791269162e43391a5a4fa576
diff --git a/examples/build_file_generation/requirements_lock.txt b/examples/build_file_generation/requirements_lock.txt
index f73827a36e..443db71ddc 100644
--- a/examples/build_file_generation/requirements_lock.txt
+++ b/examples/build_file_generation/requirements_lock.txt
@@ -11,7 +11,7 @@ click==8.1.3 \
flask==2.2.2 \
--hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \
--hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526
- # via -r ./requirements.in
+ # via -r requirements.in
importlib-metadata==5.2.0 \
--hash=sha256:0eafa39ba42bf225fc00e67f701d71f85aead9f878569caf13c3724f704b970f \
--hash=sha256:404d48d62bba0b7a77ff9d405efd91501bef2e67ff4ace0bed40a0cf28c3c7cd
diff --git a/examples/build_file_generation/requirements_windows.txt b/examples/build_file_generation/requirements_windows.txt
index fc097141c5..bdd536fdcf 100644
--- a/examples/build_file_generation/requirements_windows.txt
+++ b/examples/build_file_generation/requirements_windows.txt
@@ -15,7 +15,7 @@ colorama==0.4.6 \
flask==2.2.2 \
--hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \
--hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526
- # via -r ./requirements.in
+ # via -r requirements.in
importlib-metadata==5.2.0 \
--hash=sha256:0eafa39ba42bf225fc00e67f701d71f85aead9f878569caf13c3724f704b970f \
--hash=sha256:404d48d62bba0b7a77ff9d405efd91501bef2e67ff4ace0bed40a0cf28c3c7cd
diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel
index 7ecc035853..e1f5790631 100644
--- a/examples/bzlmod/BUILD.bazel
+++ b/examples/bzlmod/BUILD.bazel
@@ -1,4 +1,5 @@
-load("@pip//:requirements.bzl", "requirement")
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+load("@pip//:requirements.bzl", "all_requirements", "all_whl_requirements", "requirement")
load("@python3_9//:defs.bzl", py_test_with_transition = "py_test")
load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
@@ -34,6 +35,7 @@ py_binary(
py_test(
name = "test",
srcs = ["test.py"],
+ main = "test.py",
deps = [":lib"],
)
@@ -43,3 +45,13 @@ py_test_with_transition(
main = "test.py",
deps = [":lib"],
)
+
+build_test(
+ name = "all_wheels",
+ targets = all_whl_requirements,
+)
+
+build_test(
+ name = "all_requirements",
+ targets = all_requirements,
+)
diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel
index ce9122810c..145cebd276 100644
--- a/examples/bzlmod/MODULE.bazel
+++ b/examples/bzlmod/MODULE.bazel
@@ -4,13 +4,14 @@ module(
compatibility_level = 1,
)
+bazel_dep(name = "bazel_skylib", version = "1.4.1")
bazel_dep(name = "rules_python", version = "0.0.0")
local_path_override(
module_name = "rules_python",
path = "../..",
)
-python = use_extension("@rules_python//python:extensions.bzl", "python")
+python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(
name = "python3_9",
configure_coverage_tool = True,
@@ -23,9 +24,19 @@ register_toolchains(
"@python3_9_toolchains//:all",
)
-pip = use_extension("@rules_python//python:extensions.bzl", "pip")
+interpreter = use_extension("@rules_python//python/extensions:interpreter.bzl", "interpreter")
+interpreter.install(
+ name = "interpreter_python3_9",
+ python_name = "python3_9",
+)
+use_repo(interpreter, "interpreter_python3_9")
+
+pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
name = "pip",
+ # Intentionally set it false because the "true" case is already covered by examples/bzlmod_build_file_generation
+ incompatible_generate_aliases = False,
+ python_interpreter_target = "@interpreter_python3_9//:python",
requirements_lock = "//:requirements_lock.txt",
requirements_windows = "//:requirements_windows.txt",
)
diff --git a/examples/bzlmod/entry_point/BUILD.bazel b/examples/bzlmod/entry_point/BUILD.bazel
new file mode 100644
index 0000000000..dfc02b00a0
--- /dev/null
+++ b/examples/bzlmod/entry_point/BUILD.bazel
@@ -0,0 +1,20 @@
+load("@pip//:requirements.bzl", "entry_point")
+load("@rules_python//python:defs.bzl", "py_test")
+
+alias(
+ name = "yamllint",
+ actual = entry_point("yamllint"),
+)
+
+py_test(
+ name = "entry_point_test",
+ srcs = ["test_entry_point.py"],
+ data = [
+ ":yamllint",
+ ],
+ env = {
+ "YAMLLINT_ENTRY_POINT": "$(rlocationpath :yamllint)",
+ },
+ main = "test_entry_point.py",
+ deps = ["@rules_python//python/runfiles"],
+)
diff --git a/examples/bzlmod/entry_point/test_entry_point.py b/examples/bzlmod/entry_point/test_entry_point.py
new file mode 100644
index 0000000000..5a37458348
--- /dev/null
+++ b/examples/bzlmod/entry_point/test_entry_point.py
@@ -0,0 +1,43 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import pathlib
+import subprocess
+import unittest
+
+from python.runfiles import runfiles
+
+
+class ExampleTest(unittest.TestCase):
+ def test_entry_point(self):
+ rlocation_path = os.environ.get("YAMLLINT_ENTRY_POINT")
+ assert (
+ rlocation_path is not None
+ ), "expected 'YAMLLINT_ENTRY_POINT' env variable to be set to rlocation of the tool"
+
+ entry_point = pathlib.Path(runfiles.Create().Rlocation(rlocation_path))
+ self.assertTrue(entry_point.exists(), f"'{entry_point}' does not exist")
+
+ proc = subprocess.run(
+ [str(entry_point), "--version"],
+ check=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ self.assertEqual(proc.stdout.decode("utf-8").strip(), "yamllint 1.28.0")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/examples/bzlmod/gazelle_python.yaml b/examples/bzlmod/gazelle_python.yaml
new file mode 100644
index 0000000000..12096e5837
--- /dev/null
+++ b/examples/bzlmod/gazelle_python.yaml
@@ -0,0 +1,590 @@
+# GENERATED FILE - DO NOT EDIT!
+#
+# To update this file, run:
+# bazel run //:gazelle_python_manifest.update
+
+manifest:
+ modules_mapping:
+ S3: s3cmd
+ S3.ACL: s3cmd
+ S3.AccessLog: s3cmd
+ S3.BidirMap: s3cmd
+ S3.CloudFront: s3cmd
+ S3.Config: s3cmd
+ S3.ConnMan: s3cmd
+ S3.Crypto: s3cmd
+ S3.Custom_httplib27: s3cmd
+ S3.Custom_httplib3x: s3cmd
+ S3.Exceptions: s3cmd
+ S3.ExitCodes: s3cmd
+ S3.FileDict: s3cmd
+ S3.FileLists: s3cmd
+ S3.HashCache: s3cmd
+ S3.MultiPart: s3cmd
+ S3.PkgInfo: s3cmd
+ S3.Progress: s3cmd
+ S3.S3: s3cmd
+ S3.S3Uri: s3cmd
+ S3.SortedDict: s3cmd
+ S3.Utils: s3cmd
+ astroid: astroid
+ astroid.arguments: astroid
+ astroid.astroid_manager: astroid
+ astroid.bases: astroid
+ astroid.brain: astroid
+ astroid.brain.brain_argparse: astroid
+ astroid.brain.brain_attrs: astroid
+ astroid.brain.brain_boto3: astroid
+ astroid.brain.brain_builtin_inference: astroid
+ astroid.brain.brain_collections: astroid
+ astroid.brain.brain_crypt: astroid
+ astroid.brain.brain_ctypes: astroid
+ astroid.brain.brain_curses: astroid
+ astroid.brain.brain_dataclasses: astroid
+ astroid.brain.brain_dateutil: astroid
+ astroid.brain.brain_fstrings: astroid
+ astroid.brain.brain_functools: astroid
+ astroid.brain.brain_gi: astroid
+ astroid.brain.brain_hashlib: astroid
+ astroid.brain.brain_http: astroid
+ astroid.brain.brain_hypothesis: astroid
+ astroid.brain.brain_io: astroid
+ astroid.brain.brain_mechanize: astroid
+ astroid.brain.brain_multiprocessing: astroid
+ astroid.brain.brain_namedtuple_enum: astroid
+ astroid.brain.brain_nose: astroid
+ astroid.brain.brain_numpy_core_einsumfunc: astroid
+ astroid.brain.brain_numpy_core_fromnumeric: astroid
+ astroid.brain.brain_numpy_core_function_base: astroid
+ astroid.brain.brain_numpy_core_multiarray: astroid
+ astroid.brain.brain_numpy_core_numeric: astroid
+ astroid.brain.brain_numpy_core_numerictypes: astroid
+ astroid.brain.brain_numpy_core_umath: astroid
+ astroid.brain.brain_numpy_ma: astroid
+ astroid.brain.brain_numpy_ndarray: astroid
+ astroid.brain.brain_numpy_random_mtrand: astroid
+ astroid.brain.brain_numpy_utils: astroid
+ astroid.brain.brain_pathlib: astroid
+ astroid.brain.brain_pkg_resources: astroid
+ astroid.brain.brain_pytest: astroid
+ astroid.brain.brain_qt: astroid
+ astroid.brain.brain_random: astroid
+ astroid.brain.brain_re: astroid
+ astroid.brain.brain_responses: astroid
+ astroid.brain.brain_scipy_signal: astroid
+ astroid.brain.brain_signal: astroid
+ astroid.brain.brain_six: astroid
+ astroid.brain.brain_sqlalchemy: astroid
+ astroid.brain.brain_ssl: astroid
+ astroid.brain.brain_subprocess: astroid
+ astroid.brain.brain_threading: astroid
+ astroid.brain.brain_type: astroid
+ astroid.brain.brain_typing: astroid
+ astroid.brain.brain_unittest: astroid
+ astroid.brain.brain_uuid: astroid
+ astroid.brain.helpers: astroid
+ astroid.builder: astroid
+ astroid.const: astroid
+ astroid.context: astroid
+ astroid.decorators: astroid
+ astroid.exceptions: astroid
+ astroid.filter_statements: astroid
+ astroid.helpers: astroid
+ astroid.inference: astroid
+ astroid.inference_tip: astroid
+ astroid.interpreter: astroid
+ astroid.interpreter.dunder_lookup: astroid
+ astroid.interpreter.objectmodel: astroid
+ astroid.manager: astroid
+ astroid.mixins: astroid
+ astroid.modutils: astroid
+ astroid.node_classes: astroid
+ astroid.nodes: astroid
+ astroid.nodes.as_string: astroid
+ astroid.nodes.const: astroid
+ astroid.nodes.node_classes: astroid
+ astroid.nodes.node_ng: astroid
+ astroid.nodes.scoped_nodes: astroid
+ astroid.nodes.scoped_nodes.mixin: astroid
+ astroid.nodes.scoped_nodes.scoped_nodes: astroid
+ astroid.nodes.scoped_nodes.utils: astroid
+ astroid.nodes.utils: astroid
+ astroid.objects: astroid
+ astroid.protocols: astroid
+ astroid.raw_building: astroid
+ astroid.rebuilder: astroid
+ astroid.scoped_nodes: astroid
+ astroid.test_utils: astroid
+ astroid.transforms: astroid
+ astroid.typing: astroid
+ astroid.util: astroid
+ certifi: certifi
+ certifi.core: certifi
+ chardet: chardet
+ chardet.big5freq: chardet
+ chardet.big5prober: chardet
+ chardet.chardistribution: chardet
+ chardet.charsetgroupprober: chardet
+ chardet.charsetprober: chardet
+ chardet.cli: chardet
+ chardet.cli.chardetect: chardet
+ chardet.codingstatemachine: chardet
+ chardet.compat: chardet
+ chardet.cp949prober: chardet
+ chardet.enums: chardet
+ chardet.escprober: chardet
+ chardet.escsm: chardet
+ chardet.eucjpprober: chardet
+ chardet.euckrfreq: chardet
+ chardet.euckrprober: chardet
+ chardet.euctwfreq: chardet
+ chardet.euctwprober: chardet
+ chardet.gb2312freq: chardet
+ chardet.gb2312prober: chardet
+ chardet.hebrewprober: chardet
+ chardet.jisfreq: chardet
+ chardet.jpcntx: chardet
+ chardet.langbulgarianmodel: chardet
+ chardet.langgreekmodel: chardet
+ chardet.langhebrewmodel: chardet
+ chardet.langhungarianmodel: chardet
+ chardet.langrussianmodel: chardet
+ chardet.langthaimodel: chardet
+ chardet.langturkishmodel: chardet
+ chardet.latin1prober: chardet
+ chardet.mbcharsetprober: chardet
+ chardet.mbcsgroupprober: chardet
+ chardet.mbcssm: chardet
+ chardet.metadata: chardet
+ chardet.metadata.languages: chardet
+ chardet.sbcharsetprober: chardet
+ chardet.sbcsgroupprober: chardet
+ chardet.sjisprober: chardet
+ chardet.universaldetector: chardet
+ chardet.utf8prober: chardet
+ chardet.version: chardet
+ dateutil: python_dateutil
+ dateutil.easter: python_dateutil
+ dateutil.parser: python_dateutil
+ dateutil.parser.isoparser: python_dateutil
+ dateutil.relativedelta: python_dateutil
+ dateutil.rrule: python_dateutil
+ dateutil.tz: python_dateutil
+ dateutil.tz.tz: python_dateutil
+ dateutil.tz.win: python_dateutil
+ dateutil.tzwin: python_dateutil
+ dateutil.utils: python_dateutil
+ dateutil.zoneinfo: python_dateutil
+ dateutil.zoneinfo.rebuild: python_dateutil
+ dill: dill
+ dill.detect: dill
+ dill.logger: dill
+ dill.objtypes: dill
+ dill.pointers: dill
+ dill.session: dill
+ dill.settings: dill
+ dill.source: dill
+ dill.temp: dill
+ idna: idna
+ idna.codec: idna
+ idna.compat: idna
+ idna.core: idna
+ idna.idnadata: idna
+ idna.intranges: idna
+ idna.package_data: idna
+ idna.uts46data: idna
+ isort: isort
+ isort.api: isort
+ isort.comments: isort
+ isort.core: isort
+ isort.deprecated: isort
+ isort.deprecated.finders: isort
+ isort.exceptions: isort
+ isort.files: isort
+ isort.format: isort
+ isort.hooks: isort
+ isort.identify: isort
+ isort.io: isort
+ isort.literal: isort
+ isort.logo: isort
+ isort.main: isort
+ isort.output: isort
+ isort.parse: isort
+ isort.place: isort
+ isort.profiles: isort
+ isort.pylama_isort: isort
+ isort.sections: isort
+ isort.settings: isort
+ isort.setuptools_commands: isort
+ isort.sorting: isort
+ isort.stdlibs: isort
+ isort.stdlibs.all: isort
+ isort.stdlibs.py2: isort
+ isort.stdlibs.py27: isort
+ isort.stdlibs.py3: isort
+ isort.stdlibs.py310: isort
+ isort.stdlibs.py311: isort
+ isort.stdlibs.py36: isort
+ isort.stdlibs.py37: isort
+ isort.stdlibs.py38: isort
+ isort.stdlibs.py39: isort
+ isort.utils: isort
+ isort.wrap: isort
+ isort.wrap_modes: isort
+ lazy_object_proxy: lazy_object_proxy
+ lazy_object_proxy.compat: lazy_object_proxy
+ lazy_object_proxy.simple: lazy_object_proxy
+ lazy_object_proxy.slots: lazy_object_proxy
+ lazy_object_proxy.utils: lazy_object_proxy
+ magic: python_magic
+ magic.compat: python_magic
+ magic.loader: python_magic
+ mccabe: mccabe
+ pathspec: pathspec
+ pathspec.gitignore: pathspec
+ pathspec.pathspec: pathspec
+ pathspec.pattern: pathspec
+ pathspec.patterns: pathspec
+ pathspec.patterns.gitwildmatch: pathspec
+ pathspec.util: pathspec
+ pkg_resources: setuptools
+ pkg_resources.extern: setuptools
+ platformdirs: platformdirs
+ platformdirs.android: platformdirs
+ platformdirs.api: platformdirs
+ platformdirs.macos: platformdirs
+ platformdirs.unix: platformdirs
+ platformdirs.version: platformdirs
+ platformdirs.windows: platformdirs
+ pylint: pylint
+ pylint.checkers: pylint
+ pylint.checkers.async: pylint
+ pylint.checkers.base: pylint
+ pylint.checkers.base.basic_checker: pylint
+ pylint.checkers.base.basic_error_checker: pylint
+ pylint.checkers.base.comparison_checker: pylint
+ pylint.checkers.base.docstring_checker: pylint
+ pylint.checkers.base.name_checker: pylint
+ pylint.checkers.base.name_checker.checker: pylint
+ pylint.checkers.base.name_checker.naming_style: pylint
+ pylint.checkers.base.pass_checker: pylint
+ pylint.checkers.base_checker: pylint
+ pylint.checkers.classes: pylint
+ pylint.checkers.classes.class_checker: pylint
+ pylint.checkers.classes.special_methods_checker: pylint
+ pylint.checkers.deprecated: pylint
+ pylint.checkers.design_analysis: pylint
+ pylint.checkers.dunder_methods: pylint
+ pylint.checkers.ellipsis_checker: pylint
+ pylint.checkers.exceptions: pylint
+ pylint.checkers.format: pylint
+ pylint.checkers.imports: pylint
+ pylint.checkers.lambda_expressions: pylint
+ pylint.checkers.logging: pylint
+ pylint.checkers.mapreduce_checker: pylint
+ pylint.checkers.method_args: pylint
+ pylint.checkers.misc: pylint
+ pylint.checkers.modified_iterating_checker: pylint
+ pylint.checkers.newstyle: pylint
+ pylint.checkers.non_ascii_names: pylint
+ pylint.checkers.raw_metrics: pylint
+ pylint.checkers.refactoring: pylint
+ pylint.checkers.refactoring.implicit_booleaness_checker: pylint
+ pylint.checkers.refactoring.not_checker: pylint
+ pylint.checkers.refactoring.recommendation_checker: pylint
+ pylint.checkers.refactoring.refactoring_checker: pylint
+ pylint.checkers.similar: pylint
+ pylint.checkers.spelling: pylint
+ pylint.checkers.stdlib: pylint
+ pylint.checkers.strings: pylint
+ pylint.checkers.threading_checker: pylint
+ pylint.checkers.typecheck: pylint
+ pylint.checkers.unicode: pylint
+ pylint.checkers.unsupported_version: pylint
+ pylint.checkers.utils: pylint
+ pylint.checkers.variables: pylint
+ pylint.config: pylint
+ pylint.config.argument: pylint
+ pylint.config.arguments_manager: pylint
+ pylint.config.arguments_provider: pylint
+ pylint.config.callback_actions: pylint
+ pylint.config.config_file_parser: pylint
+ pylint.config.config_initialization: pylint
+ pylint.config.configuration_mixin: pylint
+ pylint.config.deprecation_actions: pylint
+ pylint.config.environment_variable: pylint
+ pylint.config.exceptions: pylint
+ pylint.config.find_default_config_files: pylint
+ pylint.config.help_formatter: pylint
+ pylint.config.option: pylint
+ pylint.config.option_manager_mixin: pylint
+ pylint.config.option_parser: pylint
+ pylint.config.options_provider_mixin: pylint
+ pylint.config.utils: pylint
+ pylint.constants: pylint
+ pylint.epylint: pylint
+ pylint.exceptions: pylint
+ pylint.extensions: pylint
+ pylint.extensions.bad_builtin: pylint
+ pylint.extensions.broad_try_clause: pylint
+ pylint.extensions.check_elif: pylint
+ pylint.extensions.code_style: pylint
+ pylint.extensions.comparetozero: pylint
+ pylint.extensions.comparison_placement: pylint
+ pylint.extensions.confusing_elif: pylint
+ pylint.extensions.consider_ternary_expression: pylint
+ pylint.extensions.docparams: pylint
+ pylint.extensions.docstyle: pylint
+ pylint.extensions.empty_comment: pylint
+ pylint.extensions.emptystring: pylint
+ pylint.extensions.eq_without_hash: pylint
+ pylint.extensions.for_any_all: pylint
+ pylint.extensions.mccabe: pylint
+ pylint.extensions.no_self_use: pylint
+ pylint.extensions.overlapping_exceptions: pylint
+ pylint.extensions.private_import: pylint
+ pylint.extensions.redefined_loop_name: pylint
+ pylint.extensions.redefined_variable_type: pylint
+ pylint.extensions.set_membership: pylint
+ pylint.extensions.typing: pylint
+ pylint.extensions.while_used: pylint
+ pylint.graph: pylint
+ pylint.interfaces: pylint
+ pylint.lint: pylint
+ pylint.lint.base_options: pylint
+ pylint.lint.caching: pylint
+ pylint.lint.expand_modules: pylint
+ pylint.lint.message_state_handler: pylint
+ pylint.lint.parallel: pylint
+ pylint.lint.pylinter: pylint
+ pylint.lint.report_functions: pylint
+ pylint.lint.run: pylint
+ pylint.lint.utils: pylint
+ pylint.message: pylint
+ pylint.message.message: pylint
+ pylint.message.message_definition: pylint
+ pylint.message.message_definition_store: pylint
+ pylint.message.message_id_store: pylint
+ pylint.pyreverse: pylint
+ pylint.pyreverse.diadefslib: pylint
+ pylint.pyreverse.diagrams: pylint
+ pylint.pyreverse.dot_printer: pylint
+ pylint.pyreverse.inspector: pylint
+ pylint.pyreverse.main: pylint
+ pylint.pyreverse.mermaidjs_printer: pylint
+ pylint.pyreverse.plantuml_printer: pylint
+ pylint.pyreverse.printer: pylint
+ pylint.pyreverse.printer_factory: pylint
+ pylint.pyreverse.utils: pylint
+ pylint.pyreverse.vcg_printer: pylint
+ pylint.pyreverse.writer: pylint
+ pylint.reporters: pylint
+ pylint.reporters.base_reporter: pylint
+ pylint.reporters.collecting_reporter: pylint
+ pylint.reporters.json_reporter: pylint
+ pylint.reporters.multi_reporter: pylint
+ pylint.reporters.reports_handler_mix_in: pylint
+ pylint.reporters.text: pylint
+ pylint.reporters.ureports: pylint
+ pylint.reporters.ureports.base_writer: pylint
+ pylint.reporters.ureports.nodes: pylint
+ pylint.reporters.ureports.text_writer: pylint
+ pylint.testutils: pylint
+ pylint.testutils.checker_test_case: pylint
+ pylint.testutils.configuration_test: pylint
+ pylint.testutils.constants: pylint
+ pylint.testutils.decorator: pylint
+ pylint.testutils.functional: pylint
+ pylint.testutils.functional.find_functional_tests: pylint
+ pylint.testutils.functional.lint_module_output_update: pylint
+ pylint.testutils.functional.test_file: pylint
+ pylint.testutils.functional_test_file: pylint
+ pylint.testutils.get_test_info: pylint
+ pylint.testutils.global_test_linter: pylint
+ pylint.testutils.lint_module_test: pylint
+ pylint.testutils.output_line: pylint
+ pylint.testutils.pyreverse: pylint
+ pylint.testutils.reporter_for_tests: pylint
+ pylint.testutils.tokenize_str: pylint
+ pylint.testutils.unittest_linter: pylint
+ pylint.testutils.utils: pylint
+ pylint.typing: pylint
+ pylint.utils: pylint
+ pylint.utils.ast_walker: pylint
+ pylint.utils.docs: pylint
+ pylint.utils.file_state: pylint
+ pylint.utils.linterstats: pylint
+ pylint.utils.pragma_parser: pylint
+ pylint.utils.utils: pylint
+ requests: requests
+ requests.adapters: requests
+ requests.api: requests
+ requests.auth: requests
+ requests.certs: requests
+ requests.compat: requests
+ requests.cookies: requests
+ requests.exceptions: requests
+ requests.help: requests
+ requests.hooks: requests
+ requests.models: requests
+ requests.packages: requests
+ requests.sessions: requests
+ requests.status_codes: requests
+ requests.structures: requests
+ requests.utils: requests
+ setuptools: setuptools
+ setuptools.archive_util: setuptools
+ setuptools.build_meta: setuptools
+ setuptools.command: setuptools
+ setuptools.command.alias: setuptools
+ setuptools.command.bdist_egg: setuptools
+ setuptools.command.bdist_rpm: setuptools
+ setuptools.command.build: setuptools
+ setuptools.command.build_clib: setuptools
+ setuptools.command.build_ext: setuptools
+ setuptools.command.build_py: setuptools
+ setuptools.command.develop: setuptools
+ setuptools.command.dist_info: setuptools
+ setuptools.command.easy_install: setuptools
+ setuptools.command.editable_wheel: setuptools
+ setuptools.command.egg_info: setuptools
+ setuptools.command.install: setuptools
+ setuptools.command.install_egg_info: setuptools
+ setuptools.command.install_lib: setuptools
+ setuptools.command.install_scripts: setuptools
+ setuptools.command.py36compat: setuptools
+ setuptools.command.register: setuptools
+ setuptools.command.rotate: setuptools
+ setuptools.command.saveopts: setuptools
+ setuptools.command.sdist: setuptools
+ setuptools.command.setopt: setuptools
+ setuptools.command.test: setuptools
+ setuptools.command.upload: setuptools
+ setuptools.command.upload_docs: setuptools
+ setuptools.config: setuptools
+ setuptools.config.expand: setuptools
+ setuptools.config.pyprojecttoml: setuptools
+ setuptools.config.setupcfg: setuptools
+ setuptools.dep_util: setuptools
+ setuptools.depends: setuptools
+ setuptools.discovery: setuptools
+ setuptools.dist: setuptools
+ setuptools.errors: setuptools
+ setuptools.extension: setuptools
+ setuptools.extern: setuptools
+ setuptools.glob: setuptools
+ setuptools.installer: setuptools
+ setuptools.launch: setuptools
+ setuptools.logging: setuptools
+ setuptools.monkey: setuptools
+ setuptools.msvc: setuptools
+ setuptools.namespaces: setuptools
+ setuptools.package_index: setuptools
+ setuptools.py34compat: setuptools
+ setuptools.sandbox: setuptools
+ setuptools.unicode_utils: setuptools
+ setuptools.version: setuptools
+ setuptools.wheel: setuptools
+ setuptools.windows_support: setuptools
+ six: six
+ tabulate: tabulate
+ tabulate.version: tabulate
+ tomli: tomli
+ tomlkit: tomlkit
+ tomlkit.api: tomlkit
+ tomlkit.container: tomlkit
+ tomlkit.exceptions: tomlkit
+ tomlkit.items: tomlkit
+ tomlkit.parser: tomlkit
+ tomlkit.source: tomlkit
+ tomlkit.toml_char: tomlkit
+ tomlkit.toml_document: tomlkit
+ tomlkit.toml_file: tomlkit
+ typing_extensions: typing_extensions
+ urllib3: urllib3
+ urllib3.connection: urllib3
+ urllib3.connectionpool: urllib3
+ urllib3.contrib: urllib3
+ urllib3.contrib.appengine: urllib3
+ urllib3.contrib.ntlmpool: urllib3
+ urllib3.contrib.pyopenssl: urllib3
+ urllib3.contrib.securetransport: urllib3
+ urllib3.contrib.socks: urllib3
+ urllib3.exceptions: urllib3
+ urllib3.fields: urllib3
+ urllib3.filepost: urllib3
+ urllib3.packages: urllib3
+ urllib3.packages.backports: urllib3
+ urllib3.packages.backports.makefile: urllib3
+ urllib3.packages.six: urllib3
+ urllib3.poolmanager: urllib3
+ urllib3.request: urllib3
+ urllib3.response: urllib3
+ urllib3.util: urllib3
+ urllib3.util.connection: urllib3
+ urllib3.util.proxy: urllib3
+ urllib3.util.queue: urllib3
+ urllib3.util.request: urllib3
+ urllib3.util.response: urllib3
+ urllib3.util.retry: urllib3
+ urllib3.util.ssl_: urllib3
+ urllib3.util.ssl_match_hostname: urllib3
+ urllib3.util.ssltransport: urllib3
+ urllib3.util.timeout: urllib3
+ urllib3.util.url: urllib3
+ urllib3.util.wait: urllib3
+ wrapt: wrapt
+ wrapt.arguments: wrapt
+ wrapt.decorators: wrapt
+ wrapt.importer: wrapt
+ wrapt.wrappers: wrapt
+ yaml: PyYAML
+ yaml.composer: PyYAML
+ yaml.constructor: PyYAML
+ yaml.cyaml: PyYAML
+ yaml.dumper: PyYAML
+ yaml.emitter: PyYAML
+ yaml.error: PyYAML
+ yaml.events: PyYAML
+ yaml.loader: PyYAML
+ yaml.nodes: PyYAML
+ yaml.parser: PyYAML
+ yaml.reader: PyYAML
+ yaml.representer: PyYAML
+ yaml.resolver: PyYAML
+ yaml.scanner: PyYAML
+ yaml.serializer: PyYAML
+ yaml.tokens: PyYAML
+ yamllint: yamllint
+ yamllint.cli: yamllint
+ yamllint.config: yamllint
+ yamllint.linter: yamllint
+ yamllint.parser: yamllint
+ yamllint.rules: yamllint
+ yamllint.rules.braces: yamllint
+ yamllint.rules.brackets: yamllint
+ yamllint.rules.colons: yamllint
+ yamllint.rules.commas: yamllint
+ yamllint.rules.comments: yamllint
+ yamllint.rules.comments_indentation: yamllint
+ yamllint.rules.common: yamllint
+ yamllint.rules.document_end: yamllint
+ yamllint.rules.document_start: yamllint
+ yamllint.rules.empty_lines: yamllint
+ yamllint.rules.empty_values: yamllint
+ yamllint.rules.float_values: yamllint
+ yamllint.rules.hyphens: yamllint
+ yamllint.rules.indentation: yamllint
+ yamllint.rules.key_duplicates: yamllint
+ yamllint.rules.key_ordering: yamllint
+ yamllint.rules.line_length: yamllint
+ yamllint.rules.new_line_at_end_of_file: yamllint
+ yamllint.rules.new_lines: yamllint
+ yamllint.rules.octal_values: yamllint
+ yamllint.rules.quoted_strings: yamllint
+ yamllint.rules.trailing_spaces: yamllint
+ yamllint.rules.truthy: yamllint
+ pip_repository:
+ name: pip
+ use_pip_repository_aliases: true
+integrity: d979738b10adbbaff0884837e4414688990491c6c40f6a25d58b9bb564411477
diff --git a/examples/bzlmod/requirements_lock.txt b/examples/bzlmod/requirements_lock.txt
index 482402ffb8..2160fe1163 100644
--- a/examples/bzlmod/requirements_lock.txt
+++ b/examples/bzlmod/requirements_lock.txt
@@ -64,12 +64,12 @@ platformdirs==2.6.0 \
pylint==2.15.9 \
--hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \
--hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb
- # via -r ./requirements.in
+ # via -r requirements.in
python-dateutil==2.8.2 \
--hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
--hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
# via
- # -r ./requirements.in
+ # -r requirements.in
# s3cmd
python-magic==0.4.27 \
--hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \
@@ -120,11 +120,11 @@ pyyaml==6.0 \
requests==2.25.1 \
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
- # via -r ./requirements.in
+ # via -r requirements.in
s3cmd==2.1.0 \
--hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \
--hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03
- # via -r ./requirements.in
+ # via -r requirements.in
setuptools==65.6.3 \
--hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \
--hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75
@@ -136,7 +136,7 @@ six==1.16.0 \
tabulate==0.9.0 \
--hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \
--hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f
- # via -r ./requirements.in
+ # via -r requirements.in
tomli==2.0.1 \
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
@@ -224,4 +224,4 @@ wrapt==1.14.1 \
yamllint==1.28.0 \
--hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \
--hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b
- # via -r ./requirements.in
+ # via -r requirements.in
diff --git a/examples/bzlmod/requirements_windows.txt b/examples/bzlmod/requirements_windows.txt
index 41187b9475..06cfdc332c 100644
--- a/examples/bzlmod/requirements_windows.txt
+++ b/examples/bzlmod/requirements_windows.txt
@@ -68,12 +68,12 @@ platformdirs==2.6.0 \
pylint==2.15.9 \
--hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \
--hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb
- # via -r ./requirements.in
+ # via -r requirements.in
python-dateutil==2.8.2 \
--hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
--hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
# via
- # -r ./requirements.in
+ # -r requirements.in
# s3cmd
python-magic==0.4.27 \
--hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \
@@ -124,11 +124,11 @@ pyyaml==6.0 \
requests==2.25.1 \
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
- # via -r ./requirements.in
+ # via -r requirements.in
s3cmd==2.1.0 \
--hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \
--hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03
- # via -r ./requirements.in
+ # via -r requirements.in
setuptools==65.6.3 \
--hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \
--hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75
@@ -140,7 +140,7 @@ six==1.16.0 \
tabulate==0.9.0 \
--hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \
--hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f
- # via -r ./requirements.in
+ # via -r requirements.in
tomli==2.0.1 \
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
@@ -228,4 +228,4 @@ wrapt==1.14.1 \
yamllint==1.28.0 \
--hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \
--hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b
- # via -r ./requirements.in
+ # via -r requirements.in
diff --git a/examples/bzlmod/runfiles/BUILD.bazel b/examples/bzlmod/runfiles/BUILD.bazel
index add56b3bd0..3503ac3017 100644
--- a/examples/bzlmod/runfiles/BUILD.bazel
+++ b/examples/bzlmod/runfiles/BUILD.bazel
@@ -1,5 +1,6 @@
load("@rules_python//python:defs.bzl", "py_test")
+# gazelle:ignore
py_test(
name = "runfiles_test",
srcs = ["runfiles_test.py"],
diff --git a/examples/bzlmod/test.py b/examples/bzlmod/test.py
index cdc1c89680..a36c19dc63 100644
--- a/examples/bzlmod/test.py
+++ b/examples/bzlmod/test.py
@@ -12,12 +12,57 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
+import pathlib
+import sys
import unittest
from lib import main
class ExampleTest(unittest.TestCase):
+ def test_coverage_doesnt_shadow_stdlib(self):
+ # When we try to import the html module
+ import html as html_stdlib
+
+ try:
+ import coverage.html as html_coverage
+ except ImportError:
+ self.skipTest("not running under coverage, skipping")
+
+ self.assertNotEqual(
+ html_stdlib,
+ html_coverage,
+ "'html' import should not be shadowed by coverage",
+ )
+
+ def test_coverage_sys_path(self):
+ all_paths = ",\n ".join(sys.path)
+
+ for i, path in enumerate(sys.path[1:-2]):
+ self.assertFalse(
+ "/coverage" in path,
+ f"Expected {i + 2}th '{path}' to not contain 'coverage.py' paths, "
+ f"sys.path has {len(sys.path)} items:\n {all_paths}",
+ )
+
+ first_item, last_item = sys.path[0], sys.path[-1]
+ self.assertFalse(
+ first_item.endswith("coverage"),
+ f"Expected the first item in sys.path '{first_item}' to not be related to coverage",
+ )
+ if os.environ.get("COVERAGE_MANIFEST"):
+ # we are running under the 'bazel coverage :test'
+ self.assertTrue(
+ "pypi__coverage_cp" in last_item,
+ f"Expected {last_item} to be related to coverage",
+ )
+ self.assertEqual(pathlib.Path(last_item).name, "coverage")
+ else:
+ self.assertFalse(
+ "coverage" in last_item, f"Expected coverage tooling to not be present"
+ )
+
def test_main(self):
self.assertEquals(
"""\
diff --git a/examples/bzlmod_build_file_generation/.bazelignore b/examples/bzlmod_build_file_generation/.bazelignore
new file mode 100644
index 0000000000..ab3eb1635c
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/.bazelignore
@@ -0,0 +1 @@
+other_module
diff --git a/examples/bzlmod_build_file_generation/.bazelrc b/examples/bzlmod_build_file_generation/.bazelrc
new file mode 100644
index 0000000000..1fbada7ec4
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/.bazelrc
@@ -0,0 +1,9 @@
+test --test_output=errors --enable_runfiles
+
+# Windows requires these for multi-python support:
+build --enable_runfiles
+startup --windows_enable_symlinks
+
+common --experimental_enable_bzlmod
+
+coverage --java_runtime_version=remotejdk_11
diff --git a/examples/bzlmod_build_file_generation/.bazelversion b/examples/bzlmod_build_file_generation/.bazelversion
new file mode 100644
index 0000000000..09b254e90c
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/.bazelversion
@@ -0,0 +1 @@
+6.0.0
diff --git a/examples/bzlmod_build_file_generation/.gitignore b/examples/bzlmod_build_file_generation/.gitignore
new file mode 100644
index 0000000000..ac51a054d2
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/.gitignore
@@ -0,0 +1 @@
+bazel-*
diff --git a/examples/bzlmod_build_file_generation/BUILD.bazel b/examples/bzlmod_build_file_generation/BUILD.bazel
new file mode 100644
index 0000000000..c667f1e49b
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/BUILD.bazel
@@ -0,0 +1,103 @@
+# Load various rules so that we can have bazel download
+# various rulesets and dependencies.
+# The `load` statement imports the symbol for the rule, in the defined
+# ruleset. When the symbol is loaded you can use the rule.
+
+# The following code loads the base python requirements and gazelle
+# requirements.
+load("@bazel_gazelle//:def.bzl", "gazelle")
+load("@pip//:requirements.bzl", "all_whl_requirements")
+load("@python3//:defs.bzl", py_test_with_transition = "py_test")
+load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
+load("@rules_python//python:pip.bzl", "compile_pip_requirements")
+load("@rules_python_gazelle_plugin//:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS")
+load("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest")
+load("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping")
+
+# This stanza calls a rule that generates targets for managing pip dependencies
+# with pip-compile.
+compile_pip_requirements(
+ name = "requirements",
+ extra_args = ["--allow-unsafe"],
+ requirements_in = "requirements.in",
+ requirements_txt = "requirements_lock.txt",
+ requirements_windows = "requirements_windows.txt",
+)
+
+# This repository rule fetches the metadata for python packages we
+# depend on. That data is required for the gazelle_python_manifest
+# rule to update our manifest file.
+modules_mapping(
+ name = "modules_map",
+ exclude_patterns = [
+ "^_|(\\._)+", # This is the default.
+ "(\\.tests)+", # Add a custom one to get rid of the psutil tests.
+ ],
+ wheels = all_whl_requirements,
+)
+
+# Gazelle python extension needs a manifest file mapping from
+# an import to the installed package that provides it.
+# This macro produces two targets:
+# - //:gazelle_python_manifest.update can be used with `bazel run`
+# to recalculate the manifest
+# - //:gazelle_python_manifest.test is a test target ensuring that
+# the manifest doesn't need to be updated
+# This target updates a file called gazelle_python.yaml, and
+# requires that file exist before the target is run.
+# When you are using gazelle you need to run this target first.
+gazelle_python_manifest(
+ name = "gazelle_python_manifest",
+ modules_mapping = ":modules_map",
+ pip_repository_name = "pip",
+ requirements = "//:requirements_lock.txt",
+ # NOTE: we can use this flag in order to make our setup compatible with
+ # bzlmod.
+ use_pip_repository_aliases = True,
+)
+
+# Our gazelle target points to the python gazelle binary.
+# This is the simple case where we only need one language supported.
+# If you also had proto, go, or other gazelle-supported languages,
+# you would also need a gazelle_binary rule.
+# See https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.rst#example
+# This is the primary gazelle target to run, so that you can update BUILD.bazel files.
+# You can execute:
+# - bazel run //:gazelle update
+# - bazel run //:gazelle fix
+# See: https://github.com/bazelbuild/bazel-gazelle#fix-and-update
+gazelle(
+ name = "gazelle",
+ data = GAZELLE_PYTHON_RUNTIME_DEPS,
+ gazelle = "@rules_python_gazelle_plugin//python:gazelle_binary",
+)
+
+py_test_with_transition(
+ name = "test_with_transition",
+ srcs = ["__test__.py"],
+ main = "__test__.py",
+ deps = [":bzlmod_build_file_generation"],
+)
+
+# The following targets are created and maintained by gazelle
+py_library(
+ name = "bzlmod_build_file_generation",
+ srcs = ["lib.py"],
+ visibility = ["//:__subpackages__"],
+ deps = ["@pip//tabulate"],
+)
+
+py_binary(
+ name = "bzlmod_build_file_generation_bin",
+ srcs = ["__main__.py"],
+ main = "__main__.py",
+ visibility = ["//:__subpackages__"],
+ deps = [":bzlmod_build_file_generation"],
+)
+
+py_test(
+ name = "bzlmod_build_file_generation_test",
+ srcs = ["__test__.py"],
+ main = "__test__.py",
+ deps = [":bzlmod_build_file_generation"],
+)
diff --git a/examples/bzlmod_build_file_generation/MODULE.bazel b/examples/bzlmod_build_file_generation/MODULE.bazel
new file mode 100644
index 0000000000..179fe1bdea
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/MODULE.bazel
@@ -0,0 +1,119 @@
+# This file replaces the WORKSPACE file when using bzlmod.
+
+# module declares certain properties of the Bazel module represented by the current Bazel repo.
+# These properties are either essential metadata of the module (such as the name and version),
+# or affect behavior of the current module and its dependents.
+module(
+ name = "example_bzlmod_build_file_generation",
+ version = "0.0.0",
+ compatibility_level = 1,
+)
+
+# The following stanza defines the dependency rules_python.
+# For typical setups you set the version.
+# See the releases page for available versions.
+# https://github.com/bazelbuild/rules_python/releases
+bazel_dep(name = "rules_python", version = "0.0.0")
+
+# The following loads rules_python from the file system.
+# For usual setups you should remove this local_path_override block.
+local_path_override(
+ module_name = "rules_python",
+ path = "../..",
+)
+
+# The following stanza defines the dependency rules_python_gazelle_plugin.
+# For typical setups you set the version.
+# See the releases page for available versions.
+# https://github.com/bazelbuild/rules_python/releases
+bazel_dep(name = "rules_python_gazelle_plugin", version = "0.0.0")
+
+# The following starlark loads the gazelle plugin from the file system.
+# For usual setups you should remove this local_path_override block.
+local_path_override(
+ module_name = "rules_python_gazelle_plugin",
+ path = "../../gazelle",
+)
+
+# The following stanza defines the dependency for gazelle
+# See here https://github.com/bazelbuild/bazel-gazelle/releases/ for the
+# latest version.
+bazel_dep(name = "gazelle", version = "0.30.0", repo_name = "bazel_gazelle")
+
+# The following stanze returns a proxy object representing a module extension;
+# its methods can be invoked to create module extension tags.
+python = use_extension("@rules_python//python/extensions:python.bzl", "python")
+
+# This name is passed into python.toolchain and it's use_repo statement.
+# We also use the same name for python.host_python_interpreter.
+PYTHON_NAME = "python3"
+
+# We next initialize the python toolchain using the extension.
+# You can set different Python versions in this block.
+python.toolchain(
+ # This name is used in the various use_repo statements
+ # below, and in the local extension that is in this
+ # example.
+ name = PYTHON_NAME,
+ configure_coverage_tool = True,
+ python_version = "3.9",
+)
+
+# Import the python repositories generated by the given module extension
+# into the scope of the current module.
+# All of the python3 repositories use the PYTHON_NAME as there prefix. They
+# are not catenated for ease of reading.
+use_repo(python, PYTHON_NAME, "python3_toolchains")
+
+# Register an already-defined toolchain so that Bazel can use it during
+# toolchain resolution.
+register_toolchains(
+ "@python3_toolchains//:all",
+)
+
+# The interpreter extension discovers the platform specific Python binary.
+# It creates a symlink to the binary, and we pass the label to the following
+# pip.parse call.
+interpreter = use_extension("@rules_python//python/extensions:interpreter.bzl", "interpreter")
+interpreter.install(
+ name = "interpreter_python3",
+ python_name = PYTHON_NAME,
+)
+use_repo(interpreter, "interpreter_python3")
+
+# Use the extension, pip.parse, to call the `pip_repository` rule that invokes
+# `pip`, with `incremental` set. The pip call accepts a locked/compiled
+# requirements file and installs the dependencies listed within.
+# Those dependencies become available in a generated `requirements.bzl` file.
+# You can instead check this `requirements.bzl` file into your repo.
+# Because this project has different requirements for windows vs other
+# operating systems, we have requirements for each.
+pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
+pip.parse(
+ name = "pip",
+ # When using gazelle you must use set the following flag
+ # in order for the generation of gazelle dependency resolution.
+ incompatible_generate_aliases = True,
+ # The interpreter_target attribute points to the interpreter to
+ # use for running pip commands to download the packages in the
+ # requirements file.
+ # As a best practice, we use the same interpreter as the toolchain
+ # that was configured above; this ensures the same Python version
+ # is used for both resolving dependencies and running tests/binaries.
+ # If this isn't specified, then you'll get whatever is locally installed
+ # on your system.
+ python_interpreter_target = "@interpreter_python3//:python",
+ requirements_lock = "//:requirements_lock.txt",
+ requirements_windows = "//:requirements_windows.txt",
+)
+
+# Imports the pip toolchain generated by the given module extension into the scope of the current module.
+use_repo(pip, "pip")
+
+# This project includes a different module that is on the local file system.
+# Add the module to this parent project.
+bazel_dep(name = "other_module", version = "", repo_name = "our_other_module")
+local_path_override(
+ module_name = "other_module",
+ path = "other_module",
+)
diff --git a/examples/bzlmod_build_file_generation/README.md b/examples/bzlmod_build_file_generation/README.md
new file mode 100644
index 0000000000..703fd38ebe
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/README.md
@@ -0,0 +1,28 @@
+# Bzlmod build file generation example
+
+This example demostrates how to use `rules_python` and gazelle with `bzlmod` enabled.
+[Bzlmod](https://bazel.build/external/overview#bzlmod), the new external dependency
+subsystem, does not directly work with repo definitions. Instead, it builds a dependency
+graph from modules, runs extensions on top of the graph, and defines repos accordingly.
+
+Gazelle is setup with the `rules_python`
+extension, so that targets like `py_library` and `py_binary` can be
+automatically created just by running:
+
+```sh
+$ bazel run //:gazelle update
+```
+
+The are other targets that allow you to update the gazelle dependency management
+when you update the requirements.in file. See:
+
+```bash
+bazel run //:gazelle_python_manifest.update
+```
+
+For more information on the behavior of the `rules_python` gazelle extension,
+see the [README.md](../../gazelle/README.md) file in the /gazelle folder.
+
+This example uses a `MODULE.bazel` file that configures the bzlmod dependency
+management. See comments in the `MODULE.bazel` and `BUILD.bazel` files for more
+information.
diff --git a/examples/bzlmod_build_file_generation/WORKSPACE b/examples/bzlmod_build_file_generation/WORKSPACE
new file mode 100644
index 0000000000..78cc252e57
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/WORKSPACE
@@ -0,0 +1,2 @@
+# Empty file indicating the root of a Bazel workspace.
+# Dependencies and setup are in MODULE.bazel.
diff --git a/examples/bzlmod_build_file_generation/__main__.py b/examples/bzlmod_build_file_generation/__main__.py
new file mode 100644
index 0000000000..099493b3c8
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/__main__.py
@@ -0,0 +1,18 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from lib import main
+
+if __name__ == "__main__":
+ print(main([["A", 1], ["B", 2]]))
diff --git a/examples/bzlmod_build_file_generation/__test__.py b/examples/bzlmod_build_file_generation/__test__.py
new file mode 100644
index 0000000000..cdc1c89680
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/__test__.py
@@ -0,0 +1,33 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+from lib import main
+
+
+class ExampleTest(unittest.TestCase):
+ def test_main(self):
+ self.assertEquals(
+ """\
+- -
+A 1
+B 2
+- -""",
+ main([["A", 1], ["B", 2]]),
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/examples/bzlmod_build_file_generation/gazelle_python.yaml b/examples/bzlmod_build_file_generation/gazelle_python.yaml
new file mode 100644
index 0000000000..12096e5837
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/gazelle_python.yaml
@@ -0,0 +1,590 @@
+# GENERATED FILE - DO NOT EDIT!
+#
+# To update this file, run:
+# bazel run //:gazelle_python_manifest.update
+
+manifest:
+ modules_mapping:
+ S3: s3cmd
+ S3.ACL: s3cmd
+ S3.AccessLog: s3cmd
+ S3.BidirMap: s3cmd
+ S3.CloudFront: s3cmd
+ S3.Config: s3cmd
+ S3.ConnMan: s3cmd
+ S3.Crypto: s3cmd
+ S3.Custom_httplib27: s3cmd
+ S3.Custom_httplib3x: s3cmd
+ S3.Exceptions: s3cmd
+ S3.ExitCodes: s3cmd
+ S3.FileDict: s3cmd
+ S3.FileLists: s3cmd
+ S3.HashCache: s3cmd
+ S3.MultiPart: s3cmd
+ S3.PkgInfo: s3cmd
+ S3.Progress: s3cmd
+ S3.S3: s3cmd
+ S3.S3Uri: s3cmd
+ S3.SortedDict: s3cmd
+ S3.Utils: s3cmd
+ astroid: astroid
+ astroid.arguments: astroid
+ astroid.astroid_manager: astroid
+ astroid.bases: astroid
+ astroid.brain: astroid
+ astroid.brain.brain_argparse: astroid
+ astroid.brain.brain_attrs: astroid
+ astroid.brain.brain_boto3: astroid
+ astroid.brain.brain_builtin_inference: astroid
+ astroid.brain.brain_collections: astroid
+ astroid.brain.brain_crypt: astroid
+ astroid.brain.brain_ctypes: astroid
+ astroid.brain.brain_curses: astroid
+ astroid.brain.brain_dataclasses: astroid
+ astroid.brain.brain_dateutil: astroid
+ astroid.brain.brain_fstrings: astroid
+ astroid.brain.brain_functools: astroid
+ astroid.brain.brain_gi: astroid
+ astroid.brain.brain_hashlib: astroid
+ astroid.brain.brain_http: astroid
+ astroid.brain.brain_hypothesis: astroid
+ astroid.brain.brain_io: astroid
+ astroid.brain.brain_mechanize: astroid
+ astroid.brain.brain_multiprocessing: astroid
+ astroid.brain.brain_namedtuple_enum: astroid
+ astroid.brain.brain_nose: astroid
+ astroid.brain.brain_numpy_core_einsumfunc: astroid
+ astroid.brain.brain_numpy_core_fromnumeric: astroid
+ astroid.brain.brain_numpy_core_function_base: astroid
+ astroid.brain.brain_numpy_core_multiarray: astroid
+ astroid.brain.brain_numpy_core_numeric: astroid
+ astroid.brain.brain_numpy_core_numerictypes: astroid
+ astroid.brain.brain_numpy_core_umath: astroid
+ astroid.brain.brain_numpy_ma: astroid
+ astroid.brain.brain_numpy_ndarray: astroid
+ astroid.brain.brain_numpy_random_mtrand: astroid
+ astroid.brain.brain_numpy_utils: astroid
+ astroid.brain.brain_pathlib: astroid
+ astroid.brain.brain_pkg_resources: astroid
+ astroid.brain.brain_pytest: astroid
+ astroid.brain.brain_qt: astroid
+ astroid.brain.brain_random: astroid
+ astroid.brain.brain_re: astroid
+ astroid.brain.brain_responses: astroid
+ astroid.brain.brain_scipy_signal: astroid
+ astroid.brain.brain_signal: astroid
+ astroid.brain.brain_six: astroid
+ astroid.brain.brain_sqlalchemy: astroid
+ astroid.brain.brain_ssl: astroid
+ astroid.brain.brain_subprocess: astroid
+ astroid.brain.brain_threading: astroid
+ astroid.brain.brain_type: astroid
+ astroid.brain.brain_typing: astroid
+ astroid.brain.brain_unittest: astroid
+ astroid.brain.brain_uuid: astroid
+ astroid.brain.helpers: astroid
+ astroid.builder: astroid
+ astroid.const: astroid
+ astroid.context: astroid
+ astroid.decorators: astroid
+ astroid.exceptions: astroid
+ astroid.filter_statements: astroid
+ astroid.helpers: astroid
+ astroid.inference: astroid
+ astroid.inference_tip: astroid
+ astroid.interpreter: astroid
+ astroid.interpreter.dunder_lookup: astroid
+ astroid.interpreter.objectmodel: astroid
+ astroid.manager: astroid
+ astroid.mixins: astroid
+ astroid.modutils: astroid
+ astroid.node_classes: astroid
+ astroid.nodes: astroid
+ astroid.nodes.as_string: astroid
+ astroid.nodes.const: astroid
+ astroid.nodes.node_classes: astroid
+ astroid.nodes.node_ng: astroid
+ astroid.nodes.scoped_nodes: astroid
+ astroid.nodes.scoped_nodes.mixin: astroid
+ astroid.nodes.scoped_nodes.scoped_nodes: astroid
+ astroid.nodes.scoped_nodes.utils: astroid
+ astroid.nodes.utils: astroid
+ astroid.objects: astroid
+ astroid.protocols: astroid
+ astroid.raw_building: astroid
+ astroid.rebuilder: astroid
+ astroid.scoped_nodes: astroid
+ astroid.test_utils: astroid
+ astroid.transforms: astroid
+ astroid.typing: astroid
+ astroid.util: astroid
+ certifi: certifi
+ certifi.core: certifi
+ chardet: chardet
+ chardet.big5freq: chardet
+ chardet.big5prober: chardet
+ chardet.chardistribution: chardet
+ chardet.charsetgroupprober: chardet
+ chardet.charsetprober: chardet
+ chardet.cli: chardet
+ chardet.cli.chardetect: chardet
+ chardet.codingstatemachine: chardet
+ chardet.compat: chardet
+ chardet.cp949prober: chardet
+ chardet.enums: chardet
+ chardet.escprober: chardet
+ chardet.escsm: chardet
+ chardet.eucjpprober: chardet
+ chardet.euckrfreq: chardet
+ chardet.euckrprober: chardet
+ chardet.euctwfreq: chardet
+ chardet.euctwprober: chardet
+ chardet.gb2312freq: chardet
+ chardet.gb2312prober: chardet
+ chardet.hebrewprober: chardet
+ chardet.jisfreq: chardet
+ chardet.jpcntx: chardet
+ chardet.langbulgarianmodel: chardet
+ chardet.langgreekmodel: chardet
+ chardet.langhebrewmodel: chardet
+ chardet.langhungarianmodel: chardet
+ chardet.langrussianmodel: chardet
+ chardet.langthaimodel: chardet
+ chardet.langturkishmodel: chardet
+ chardet.latin1prober: chardet
+ chardet.mbcharsetprober: chardet
+ chardet.mbcsgroupprober: chardet
+ chardet.mbcssm: chardet
+ chardet.metadata: chardet
+ chardet.metadata.languages: chardet
+ chardet.sbcharsetprober: chardet
+ chardet.sbcsgroupprober: chardet
+ chardet.sjisprober: chardet
+ chardet.universaldetector: chardet
+ chardet.utf8prober: chardet
+ chardet.version: chardet
+ dateutil: python_dateutil
+ dateutil.easter: python_dateutil
+ dateutil.parser: python_dateutil
+ dateutil.parser.isoparser: python_dateutil
+ dateutil.relativedelta: python_dateutil
+ dateutil.rrule: python_dateutil
+ dateutil.tz: python_dateutil
+ dateutil.tz.tz: python_dateutil
+ dateutil.tz.win: python_dateutil
+ dateutil.tzwin: python_dateutil
+ dateutil.utils: python_dateutil
+ dateutil.zoneinfo: python_dateutil
+ dateutil.zoneinfo.rebuild: python_dateutil
+ dill: dill
+ dill.detect: dill
+ dill.logger: dill
+ dill.objtypes: dill
+ dill.pointers: dill
+ dill.session: dill
+ dill.settings: dill
+ dill.source: dill
+ dill.temp: dill
+ idna: idna
+ idna.codec: idna
+ idna.compat: idna
+ idna.core: idna
+ idna.idnadata: idna
+ idna.intranges: idna
+ idna.package_data: idna
+ idna.uts46data: idna
+ isort: isort
+ isort.api: isort
+ isort.comments: isort
+ isort.core: isort
+ isort.deprecated: isort
+ isort.deprecated.finders: isort
+ isort.exceptions: isort
+ isort.files: isort
+ isort.format: isort
+ isort.hooks: isort
+ isort.identify: isort
+ isort.io: isort
+ isort.literal: isort
+ isort.logo: isort
+ isort.main: isort
+ isort.output: isort
+ isort.parse: isort
+ isort.place: isort
+ isort.profiles: isort
+ isort.pylama_isort: isort
+ isort.sections: isort
+ isort.settings: isort
+ isort.setuptools_commands: isort
+ isort.sorting: isort
+ isort.stdlibs: isort
+ isort.stdlibs.all: isort
+ isort.stdlibs.py2: isort
+ isort.stdlibs.py27: isort
+ isort.stdlibs.py3: isort
+ isort.stdlibs.py310: isort
+ isort.stdlibs.py311: isort
+ isort.stdlibs.py36: isort
+ isort.stdlibs.py37: isort
+ isort.stdlibs.py38: isort
+ isort.stdlibs.py39: isort
+ isort.utils: isort
+ isort.wrap: isort
+ isort.wrap_modes: isort
+ lazy_object_proxy: lazy_object_proxy
+ lazy_object_proxy.compat: lazy_object_proxy
+ lazy_object_proxy.simple: lazy_object_proxy
+ lazy_object_proxy.slots: lazy_object_proxy
+ lazy_object_proxy.utils: lazy_object_proxy
+ magic: python_magic
+ magic.compat: python_magic
+ magic.loader: python_magic
+ mccabe: mccabe
+ pathspec: pathspec
+ pathspec.gitignore: pathspec
+ pathspec.pathspec: pathspec
+ pathspec.pattern: pathspec
+ pathspec.patterns: pathspec
+ pathspec.patterns.gitwildmatch: pathspec
+ pathspec.util: pathspec
+ pkg_resources: setuptools
+ pkg_resources.extern: setuptools
+ platformdirs: platformdirs
+ platformdirs.android: platformdirs
+ platformdirs.api: platformdirs
+ platformdirs.macos: platformdirs
+ platformdirs.unix: platformdirs
+ platformdirs.version: platformdirs
+ platformdirs.windows: platformdirs
+ pylint: pylint
+ pylint.checkers: pylint
+ pylint.checkers.async: pylint
+ pylint.checkers.base: pylint
+ pylint.checkers.base.basic_checker: pylint
+ pylint.checkers.base.basic_error_checker: pylint
+ pylint.checkers.base.comparison_checker: pylint
+ pylint.checkers.base.docstring_checker: pylint
+ pylint.checkers.base.name_checker: pylint
+ pylint.checkers.base.name_checker.checker: pylint
+ pylint.checkers.base.name_checker.naming_style: pylint
+ pylint.checkers.base.pass_checker: pylint
+ pylint.checkers.base_checker: pylint
+ pylint.checkers.classes: pylint
+ pylint.checkers.classes.class_checker: pylint
+ pylint.checkers.classes.special_methods_checker: pylint
+ pylint.checkers.deprecated: pylint
+ pylint.checkers.design_analysis: pylint
+ pylint.checkers.dunder_methods: pylint
+ pylint.checkers.ellipsis_checker: pylint
+ pylint.checkers.exceptions: pylint
+ pylint.checkers.format: pylint
+ pylint.checkers.imports: pylint
+ pylint.checkers.lambda_expressions: pylint
+ pylint.checkers.logging: pylint
+ pylint.checkers.mapreduce_checker: pylint
+ pylint.checkers.method_args: pylint
+ pylint.checkers.misc: pylint
+ pylint.checkers.modified_iterating_checker: pylint
+ pylint.checkers.newstyle: pylint
+ pylint.checkers.non_ascii_names: pylint
+ pylint.checkers.raw_metrics: pylint
+ pylint.checkers.refactoring: pylint
+ pylint.checkers.refactoring.implicit_booleaness_checker: pylint
+ pylint.checkers.refactoring.not_checker: pylint
+ pylint.checkers.refactoring.recommendation_checker: pylint
+ pylint.checkers.refactoring.refactoring_checker: pylint
+ pylint.checkers.similar: pylint
+ pylint.checkers.spelling: pylint
+ pylint.checkers.stdlib: pylint
+ pylint.checkers.strings: pylint
+ pylint.checkers.threading_checker: pylint
+ pylint.checkers.typecheck: pylint
+ pylint.checkers.unicode: pylint
+ pylint.checkers.unsupported_version: pylint
+ pylint.checkers.utils: pylint
+ pylint.checkers.variables: pylint
+ pylint.config: pylint
+ pylint.config.argument: pylint
+ pylint.config.arguments_manager: pylint
+ pylint.config.arguments_provider: pylint
+ pylint.config.callback_actions: pylint
+ pylint.config.config_file_parser: pylint
+ pylint.config.config_initialization: pylint
+ pylint.config.configuration_mixin: pylint
+ pylint.config.deprecation_actions: pylint
+ pylint.config.environment_variable: pylint
+ pylint.config.exceptions: pylint
+ pylint.config.find_default_config_files: pylint
+ pylint.config.help_formatter: pylint
+ pylint.config.option: pylint
+ pylint.config.option_manager_mixin: pylint
+ pylint.config.option_parser: pylint
+ pylint.config.options_provider_mixin: pylint
+ pylint.config.utils: pylint
+ pylint.constants: pylint
+ pylint.epylint: pylint
+ pylint.exceptions: pylint
+ pylint.extensions: pylint
+ pylint.extensions.bad_builtin: pylint
+ pylint.extensions.broad_try_clause: pylint
+ pylint.extensions.check_elif: pylint
+ pylint.extensions.code_style: pylint
+ pylint.extensions.comparetozero: pylint
+ pylint.extensions.comparison_placement: pylint
+ pylint.extensions.confusing_elif: pylint
+ pylint.extensions.consider_ternary_expression: pylint
+ pylint.extensions.docparams: pylint
+ pylint.extensions.docstyle: pylint
+ pylint.extensions.empty_comment: pylint
+ pylint.extensions.emptystring: pylint
+ pylint.extensions.eq_without_hash: pylint
+ pylint.extensions.for_any_all: pylint
+ pylint.extensions.mccabe: pylint
+ pylint.extensions.no_self_use: pylint
+ pylint.extensions.overlapping_exceptions: pylint
+ pylint.extensions.private_import: pylint
+ pylint.extensions.redefined_loop_name: pylint
+ pylint.extensions.redefined_variable_type: pylint
+ pylint.extensions.set_membership: pylint
+ pylint.extensions.typing: pylint
+ pylint.extensions.while_used: pylint
+ pylint.graph: pylint
+ pylint.interfaces: pylint
+ pylint.lint: pylint
+ pylint.lint.base_options: pylint
+ pylint.lint.caching: pylint
+ pylint.lint.expand_modules: pylint
+ pylint.lint.message_state_handler: pylint
+ pylint.lint.parallel: pylint
+ pylint.lint.pylinter: pylint
+ pylint.lint.report_functions: pylint
+ pylint.lint.run: pylint
+ pylint.lint.utils: pylint
+ pylint.message: pylint
+ pylint.message.message: pylint
+ pylint.message.message_definition: pylint
+ pylint.message.message_definition_store: pylint
+ pylint.message.message_id_store: pylint
+ pylint.pyreverse: pylint
+ pylint.pyreverse.diadefslib: pylint
+ pylint.pyreverse.diagrams: pylint
+ pylint.pyreverse.dot_printer: pylint
+ pylint.pyreverse.inspector: pylint
+ pylint.pyreverse.main: pylint
+ pylint.pyreverse.mermaidjs_printer: pylint
+ pylint.pyreverse.plantuml_printer: pylint
+ pylint.pyreverse.printer: pylint
+ pylint.pyreverse.printer_factory: pylint
+ pylint.pyreverse.utils: pylint
+ pylint.pyreverse.vcg_printer: pylint
+ pylint.pyreverse.writer: pylint
+ pylint.reporters: pylint
+ pylint.reporters.base_reporter: pylint
+ pylint.reporters.collecting_reporter: pylint
+ pylint.reporters.json_reporter: pylint
+ pylint.reporters.multi_reporter: pylint
+ pylint.reporters.reports_handler_mix_in: pylint
+ pylint.reporters.text: pylint
+ pylint.reporters.ureports: pylint
+ pylint.reporters.ureports.base_writer: pylint
+ pylint.reporters.ureports.nodes: pylint
+ pylint.reporters.ureports.text_writer: pylint
+ pylint.testutils: pylint
+ pylint.testutils.checker_test_case: pylint
+ pylint.testutils.configuration_test: pylint
+ pylint.testutils.constants: pylint
+ pylint.testutils.decorator: pylint
+ pylint.testutils.functional: pylint
+ pylint.testutils.functional.find_functional_tests: pylint
+ pylint.testutils.functional.lint_module_output_update: pylint
+ pylint.testutils.functional.test_file: pylint
+ pylint.testutils.functional_test_file: pylint
+ pylint.testutils.get_test_info: pylint
+ pylint.testutils.global_test_linter: pylint
+ pylint.testutils.lint_module_test: pylint
+ pylint.testutils.output_line: pylint
+ pylint.testutils.pyreverse: pylint
+ pylint.testutils.reporter_for_tests: pylint
+ pylint.testutils.tokenize_str: pylint
+ pylint.testutils.unittest_linter: pylint
+ pylint.testutils.utils: pylint
+ pylint.typing: pylint
+ pylint.utils: pylint
+ pylint.utils.ast_walker: pylint
+ pylint.utils.docs: pylint
+ pylint.utils.file_state: pylint
+ pylint.utils.linterstats: pylint
+ pylint.utils.pragma_parser: pylint
+ pylint.utils.utils: pylint
+ requests: requests
+ requests.adapters: requests
+ requests.api: requests
+ requests.auth: requests
+ requests.certs: requests
+ requests.compat: requests
+ requests.cookies: requests
+ requests.exceptions: requests
+ requests.help: requests
+ requests.hooks: requests
+ requests.models: requests
+ requests.packages: requests
+ requests.sessions: requests
+ requests.status_codes: requests
+ requests.structures: requests
+ requests.utils: requests
+ setuptools: setuptools
+ setuptools.archive_util: setuptools
+ setuptools.build_meta: setuptools
+ setuptools.command: setuptools
+ setuptools.command.alias: setuptools
+ setuptools.command.bdist_egg: setuptools
+ setuptools.command.bdist_rpm: setuptools
+ setuptools.command.build: setuptools
+ setuptools.command.build_clib: setuptools
+ setuptools.command.build_ext: setuptools
+ setuptools.command.build_py: setuptools
+ setuptools.command.develop: setuptools
+ setuptools.command.dist_info: setuptools
+ setuptools.command.easy_install: setuptools
+ setuptools.command.editable_wheel: setuptools
+ setuptools.command.egg_info: setuptools
+ setuptools.command.install: setuptools
+ setuptools.command.install_egg_info: setuptools
+ setuptools.command.install_lib: setuptools
+ setuptools.command.install_scripts: setuptools
+ setuptools.command.py36compat: setuptools
+ setuptools.command.register: setuptools
+ setuptools.command.rotate: setuptools
+ setuptools.command.saveopts: setuptools
+ setuptools.command.sdist: setuptools
+ setuptools.command.setopt: setuptools
+ setuptools.command.test: setuptools
+ setuptools.command.upload: setuptools
+ setuptools.command.upload_docs: setuptools
+ setuptools.config: setuptools
+ setuptools.config.expand: setuptools
+ setuptools.config.pyprojecttoml: setuptools
+ setuptools.config.setupcfg: setuptools
+ setuptools.dep_util: setuptools
+ setuptools.depends: setuptools
+ setuptools.discovery: setuptools
+ setuptools.dist: setuptools
+ setuptools.errors: setuptools
+ setuptools.extension: setuptools
+ setuptools.extern: setuptools
+ setuptools.glob: setuptools
+ setuptools.installer: setuptools
+ setuptools.launch: setuptools
+ setuptools.logging: setuptools
+ setuptools.monkey: setuptools
+ setuptools.msvc: setuptools
+ setuptools.namespaces: setuptools
+ setuptools.package_index: setuptools
+ setuptools.py34compat: setuptools
+ setuptools.sandbox: setuptools
+ setuptools.unicode_utils: setuptools
+ setuptools.version: setuptools
+ setuptools.wheel: setuptools
+ setuptools.windows_support: setuptools
+ six: six
+ tabulate: tabulate
+ tabulate.version: tabulate
+ tomli: tomli
+ tomlkit: tomlkit
+ tomlkit.api: tomlkit
+ tomlkit.container: tomlkit
+ tomlkit.exceptions: tomlkit
+ tomlkit.items: tomlkit
+ tomlkit.parser: tomlkit
+ tomlkit.source: tomlkit
+ tomlkit.toml_char: tomlkit
+ tomlkit.toml_document: tomlkit
+ tomlkit.toml_file: tomlkit
+ typing_extensions: typing_extensions
+ urllib3: urllib3
+ urllib3.connection: urllib3
+ urllib3.connectionpool: urllib3
+ urllib3.contrib: urllib3
+ urllib3.contrib.appengine: urllib3
+ urllib3.contrib.ntlmpool: urllib3
+ urllib3.contrib.pyopenssl: urllib3
+ urllib3.contrib.securetransport: urllib3
+ urllib3.contrib.socks: urllib3
+ urllib3.exceptions: urllib3
+ urllib3.fields: urllib3
+ urllib3.filepost: urllib3
+ urllib3.packages: urllib3
+ urllib3.packages.backports: urllib3
+ urllib3.packages.backports.makefile: urllib3
+ urllib3.packages.six: urllib3
+ urllib3.poolmanager: urllib3
+ urllib3.request: urllib3
+ urllib3.response: urllib3
+ urllib3.util: urllib3
+ urllib3.util.connection: urllib3
+ urllib3.util.proxy: urllib3
+ urllib3.util.queue: urllib3
+ urllib3.util.request: urllib3
+ urllib3.util.response: urllib3
+ urllib3.util.retry: urllib3
+ urllib3.util.ssl_: urllib3
+ urllib3.util.ssl_match_hostname: urllib3
+ urllib3.util.ssltransport: urllib3
+ urllib3.util.timeout: urllib3
+ urllib3.util.url: urllib3
+ urllib3.util.wait: urllib3
+ wrapt: wrapt
+ wrapt.arguments: wrapt
+ wrapt.decorators: wrapt
+ wrapt.importer: wrapt
+ wrapt.wrappers: wrapt
+ yaml: PyYAML
+ yaml.composer: PyYAML
+ yaml.constructor: PyYAML
+ yaml.cyaml: PyYAML
+ yaml.dumper: PyYAML
+ yaml.emitter: PyYAML
+ yaml.error: PyYAML
+ yaml.events: PyYAML
+ yaml.loader: PyYAML
+ yaml.nodes: PyYAML
+ yaml.parser: PyYAML
+ yaml.reader: PyYAML
+ yaml.representer: PyYAML
+ yaml.resolver: PyYAML
+ yaml.scanner: PyYAML
+ yaml.serializer: PyYAML
+ yaml.tokens: PyYAML
+ yamllint: yamllint
+ yamllint.cli: yamllint
+ yamllint.config: yamllint
+ yamllint.linter: yamllint
+ yamllint.parser: yamllint
+ yamllint.rules: yamllint
+ yamllint.rules.braces: yamllint
+ yamllint.rules.brackets: yamllint
+ yamllint.rules.colons: yamllint
+ yamllint.rules.commas: yamllint
+ yamllint.rules.comments: yamllint
+ yamllint.rules.comments_indentation: yamllint
+ yamllint.rules.common: yamllint
+ yamllint.rules.document_end: yamllint
+ yamllint.rules.document_start: yamllint
+ yamllint.rules.empty_lines: yamllint
+ yamllint.rules.empty_values: yamllint
+ yamllint.rules.float_values: yamllint
+ yamllint.rules.hyphens: yamllint
+ yamllint.rules.indentation: yamllint
+ yamllint.rules.key_duplicates: yamllint
+ yamllint.rules.key_ordering: yamllint
+ yamllint.rules.line_length: yamllint
+ yamllint.rules.new_line_at_end_of_file: yamllint
+ yamllint.rules.new_lines: yamllint
+ yamllint.rules.octal_values: yamllint
+ yamllint.rules.quoted_strings: yamllint
+ yamllint.rules.trailing_spaces: yamllint
+ yamllint.rules.truthy: yamllint
+ pip_repository:
+ name: pip
+ use_pip_repository_aliases: true
+integrity: d979738b10adbbaff0884837e4414688990491c6c40f6a25d58b9bb564411477
diff --git a/examples/bzlmod_build_file_generation/lib.py b/examples/bzlmod_build_file_generation/lib.py
new file mode 100644
index 0000000000..646c6e890f
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/lib.py
@@ -0,0 +1,19 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from tabulate import tabulate
+
+
+def main(table):
+ return tabulate(table)
diff --git a/examples/bzlmod_build_file_generation/other_module/MODULE.bazel b/examples/bzlmod_build_file_generation/other_module/MODULE.bazel
new file mode 100644
index 0000000000..992e120760
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/other_module/MODULE.bazel
@@ -0,0 +1,5 @@
+module(
+ name = "other_module",
+)
+
+bazel_dep(name = "rules_python", version = "")
diff --git a/examples/bzlmod_build_file_generation/other_module/WORKSPACE b/examples/bzlmod_build_file_generation/other_module/WORKSPACE
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/examples/bzlmod_build_file_generation/other_module/other_module/pkg/BUILD.bazel b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/BUILD.bazel
new file mode 100644
index 0000000000..9a130e3554
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/BUILD.bazel
@@ -0,0 +1,11 @@
+load("@rules_python//python:defs.bzl", "py_library")
+
+py_library(
+ name = "lib",
+ srcs = ["lib.py"],
+ data = ["data/data.txt"],
+ visibility = ["//visibility:public"],
+ deps = ["@rules_python//python/runfiles"],
+)
+
+exports_files(["data/data.txt"])
diff --git a/examples/bzlmod_build_file_generation/other_module/other_module/pkg/data/data.txt b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/data/data.txt
new file mode 100644
index 0000000000..e975eaf640
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/data/data.txt
@@ -0,0 +1 @@
+Hello, other_module!
diff --git a/examples/bzlmod_build_file_generation/other_module/other_module/pkg/lib.py b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/lib.py
new file mode 100644
index 0000000000..eaf65fb46a
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/lib.py
@@ -0,0 +1,27 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from python.runfiles import runfiles
+
+
+def GetRunfilePathWithCurrentRepository():
+ r = runfiles.Create()
+ own_repo = r.CurrentRepository()
+ # For a non-main repository, the name of the runfiles directory is equal to
+ # the canonical repository name.
+ return r.Rlocation(own_repo + "/other_module/pkg/data/data.txt")
+
+
+def GetRunfilePathWithRepoMapping():
+ return runfiles.Create().Rlocation("other_module/other_module/pkg/data/data.txt")
diff --git a/examples/bzlmod_build_file_generation/requirements.in b/examples/bzlmod_build_file_generation/requirements.in
new file mode 100644
index 0000000000..a709195442
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/requirements.in
@@ -0,0 +1,6 @@
+requests~=2.25.1
+s3cmd~=2.1.0
+yamllint>=1.28.0
+tabulate~=0.9.0
+pylint~=2.15.5
+python-dateutil>=2.8.2
diff --git a/examples/bzlmod_build_file_generation/requirements_lock.txt b/examples/bzlmod_build_file_generation/requirements_lock.txt
new file mode 100644
index 0000000000..2160fe1163
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/requirements_lock.txt
@@ -0,0 +1,227 @@
+#
+# This file is autogenerated by pip-compile with Python 3.9
+# by the following command:
+#
+# bazel run //:requirements.update
+#
+astroid==2.12.13 \
+ --hash=sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907 \
+ --hash=sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7
+ # via pylint
+certifi==2022.12.7 \
+ --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \
+ --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18
+ # via requests
+chardet==4.0.0 \
+ --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
+ --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
+ # via requests
+dill==0.3.6 \
+ --hash=sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0 \
+ --hash=sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373
+ # via pylint
+idna==2.10 \
+ --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
+ --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
+ # via requests
+isort==5.11.4 \
+ --hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \
+ --hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b
+ # via pylint
+lazy-object-proxy==1.8.0 \
+ --hash=sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada \
+ --hash=sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d \
+ --hash=sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7 \
+ --hash=sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe \
+ --hash=sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd \
+ --hash=sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c \
+ --hash=sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858 \
+ --hash=sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288 \
+ --hash=sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec \
+ --hash=sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f \
+ --hash=sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891 \
+ --hash=sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c \
+ --hash=sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25 \
+ --hash=sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156 \
+ --hash=sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8 \
+ --hash=sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f \
+ --hash=sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e \
+ --hash=sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0 \
+ --hash=sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b
+ # via astroid
+mccabe==0.7.0 \
+ --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \
+ --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e
+ # via pylint
+pathspec==0.10.3 \
+ --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \
+ --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6
+ # via yamllint
+platformdirs==2.6.0 \
+ --hash=sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca \
+ --hash=sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e
+ # via pylint
+pylint==2.15.9 \
+ --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \
+ --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb
+ # via -r requirements.in
+python-dateutil==2.8.2 \
+ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
+ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
+ # via
+ # -r requirements.in
+ # s3cmd
+python-magic==0.4.27 \
+ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \
+ --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3
+ # via s3cmd
+pyyaml==6.0 \
+ --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \
+ --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \
+ --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \
+ --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \
+ --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \
+ --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \
+ --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \
+ --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \
+ --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \
+ --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \
+ --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \
+ --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \
+ --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \
+ --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \
+ --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \
+ --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \
+ --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \
+ --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \
+ --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \
+ --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \
+ --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \
+ --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \
+ --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \
+ --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \
+ --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \
+ --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \
+ --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \
+ --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \
+ --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \
+ --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \
+ --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \
+ --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \
+ --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \
+ --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \
+ --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \
+ --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \
+ --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \
+ --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \
+ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \
+ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5
+ # via yamllint
+requests==2.25.1 \
+ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
+ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
+ # via -r requirements.in
+s3cmd==2.1.0 \
+ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \
+ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03
+ # via -r requirements.in
+setuptools==65.6.3 \
+ --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \
+ --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75
+ # via yamllint
+six==1.16.0 \
+ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
+ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
+ # via python-dateutil
+tabulate==0.9.0 \
+ --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \
+ --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f
+ # via -r requirements.in
+tomli==2.0.1 \
+ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
+ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
+ # via pylint
+tomlkit==0.11.6 \
+ --hash=sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b \
+ --hash=sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73
+ # via pylint
+typing-extensions==4.4.0 \
+ --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \
+ --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e
+ # via
+ # astroid
+ # pylint
+urllib3==1.26.13 \
+ --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \
+ --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8
+ # via requests
+wrapt==1.14.1 \
+ --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \
+ --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \
+ --hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \
+ --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \
+ --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \
+ --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \
+ --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \
+ --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \
+ --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \
+ --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \
+ --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \
+ --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \
+ --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \
+ --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \
+ --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \
+ --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \
+ --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \
+ --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \
+ --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \
+ --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \
+ --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \
+ --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \
+ --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \
+ --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \
+ --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \
+ --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \
+ --hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \
+ --hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \
+ --hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \
+ --hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \
+ --hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \
+ --hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \
+ --hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \
+ --hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \
+ --hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \
+ --hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \
+ --hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \
+ --hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \
+ --hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \
+ --hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \
+ --hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \
+ --hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \
+ --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \
+ --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \
+ --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \
+ --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \
+ --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \
+ --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \
+ --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \
+ --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \
+ --hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \
+ --hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \
+ --hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \
+ --hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \
+ --hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \
+ --hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \
+ --hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \
+ --hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \
+ --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \
+ --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \
+ --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \
+ --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \
+ --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \
+ --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af
+ # via astroid
+yamllint==1.28.0 \
+ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \
+ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b
+ # via -r requirements.in
diff --git a/examples/bzlmod_build_file_generation/requirements_windows.txt b/examples/bzlmod_build_file_generation/requirements_windows.txt
new file mode 100644
index 0000000000..06cfdc332c
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/requirements_windows.txt
@@ -0,0 +1,231 @@
+#
+# This file is autogenerated by pip-compile with Python 3.9
+# by the following command:
+#
+# bazel run //:requirements.update
+#
+astroid==2.12.13 \
+ --hash=sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907 \
+ --hash=sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7
+ # via pylint
+certifi==2022.12.7 \
+ --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \
+ --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18
+ # via requests
+chardet==4.0.0 \
+ --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
+ --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
+ # via requests
+colorama==0.4.6 \
+ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
+ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
+ # via pylint
+dill==0.3.6 \
+ --hash=sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0 \
+ --hash=sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373
+ # via pylint
+idna==2.10 \
+ --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
+ --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
+ # via requests
+isort==5.11.4 \
+ --hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \
+ --hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b
+ # via pylint
+lazy-object-proxy==1.8.0 \
+ --hash=sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada \
+ --hash=sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d \
+ --hash=sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7 \
+ --hash=sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe \
+ --hash=sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd \
+ --hash=sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c \
+ --hash=sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858 \
+ --hash=sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288 \
+ --hash=sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec \
+ --hash=sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f \
+ --hash=sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891 \
+ --hash=sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c \
+ --hash=sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25 \
+ --hash=sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156 \
+ --hash=sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8 \
+ --hash=sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f \
+ --hash=sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e \
+ --hash=sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0 \
+ --hash=sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b
+ # via astroid
+mccabe==0.7.0 \
+ --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \
+ --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e
+ # via pylint
+pathspec==0.10.3 \
+ --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \
+ --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6
+ # via yamllint
+platformdirs==2.6.0 \
+ --hash=sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca \
+ --hash=sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e
+ # via pylint
+pylint==2.15.9 \
+ --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \
+ --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb
+ # via -r requirements.in
+python-dateutil==2.8.2 \
+ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
+ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
+ # via
+ # -r requirements.in
+ # s3cmd
+python-magic==0.4.27 \
+ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \
+ --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3
+ # via s3cmd
+pyyaml==6.0 \
+ --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \
+ --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \
+ --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \
+ --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \
+ --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \
+ --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \
+ --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \
+ --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \
+ --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \
+ --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \
+ --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \
+ --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \
+ --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \
+ --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \
+ --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \
+ --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \
+ --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \
+ --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \
+ --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \
+ --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \
+ --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \
+ --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \
+ --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \
+ --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \
+ --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \
+ --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \
+ --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \
+ --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \
+ --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \
+ --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \
+ --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \
+ --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \
+ --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \
+ --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \
+ --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \
+ --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \
+ --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \
+ --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \
+ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \
+ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5
+ # via yamllint
+requests==2.25.1 \
+ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
+ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
+ # via -r requirements.in
+s3cmd==2.1.0 \
+ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \
+ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03
+ # via -r requirements.in
+setuptools==65.6.3 \
+ --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \
+ --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75
+ # via yamllint
+six==1.16.0 \
+ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
+ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
+ # via python-dateutil
+tabulate==0.9.0 \
+ --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \
+ --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f
+ # via -r requirements.in
+tomli==2.0.1 \
+ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
+ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
+ # via pylint
+tomlkit==0.11.6 \
+ --hash=sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b \
+ --hash=sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73
+ # via pylint
+typing-extensions==4.4.0 \
+ --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \
+ --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e
+ # via
+ # astroid
+ # pylint
+urllib3==1.26.13 \
+ --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \
+ --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8
+ # via requests
+wrapt==1.14.1 \
+ --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \
+ --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \
+ --hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \
+ --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \
+ --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \
+ --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \
+ --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \
+ --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \
+ --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \
+ --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \
+ --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \
+ --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \
+ --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \
+ --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \
+ --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \
+ --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \
+ --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \
+ --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \
+ --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \
+ --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \
+ --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \
+ --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \
+ --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \
+ --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \
+ --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \
+ --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \
+ --hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \
+ --hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \
+ --hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \
+ --hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \
+ --hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \
+ --hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \
+ --hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \
+ --hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \
+ --hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \
+ --hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \
+ --hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \
+ --hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \
+ --hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \
+ --hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \
+ --hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \
+ --hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \
+ --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \
+ --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \
+ --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \
+ --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \
+ --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \
+ --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \
+ --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \
+ --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \
+ --hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \
+ --hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \
+ --hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \
+ --hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \
+ --hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \
+ --hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \
+ --hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \
+ --hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \
+ --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \
+ --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \
+ --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \
+ --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \
+ --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \
+ --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af
+ # via astroid
+yamllint==1.28.0 \
+ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \
+ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b
+ # via -r requirements.in
diff --git a/examples/bzlmod_build_file_generation/runfiles/BUILD.bazel b/examples/bzlmod_build_file_generation/runfiles/BUILD.bazel
new file mode 100644
index 0000000000..3503ac3017
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/runfiles/BUILD.bazel
@@ -0,0 +1,19 @@
+load("@rules_python//python:defs.bzl", "py_test")
+
+# gazelle:ignore
+py_test(
+ name = "runfiles_test",
+ srcs = ["runfiles_test.py"],
+ data = [
+ "data/data.txt",
+ "@our_other_module//other_module/pkg:data/data.txt",
+ ],
+ env = {
+ "DATA_RLOCATIONPATH": "$(rlocationpath data/data.txt)",
+ "OTHER_MODULE_DATA_RLOCATIONPATH": "$(rlocationpath @our_other_module//other_module/pkg:data/data.txt)",
+ },
+ deps = [
+ "@our_other_module//other_module/pkg:lib",
+ "@rules_python//python/runfiles",
+ ],
+)
diff --git a/examples/bzlmod_build_file_generation/runfiles/data/data.txt b/examples/bzlmod_build_file_generation/runfiles/data/data.txt
new file mode 100644
index 0000000000..fb17e0df66
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/runfiles/data/data.txt
@@ -0,0 +1 @@
+Hello, example_bzlmod!
diff --git a/examples/bzlmod_build_file_generation/runfiles/runfiles_test.py b/examples/bzlmod_build_file_generation/runfiles/runfiles_test.py
new file mode 100644
index 0000000000..a588040cfd
--- /dev/null
+++ b/examples/bzlmod_build_file_generation/runfiles/runfiles_test.py
@@ -0,0 +1,64 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import unittest
+
+from other_module.pkg import lib
+
+from python.runfiles import runfiles
+
+
+class RunfilesTest(unittest.TestCase):
+ # """Unit tests for `runfiles.Runfiles`."""
+ def testCurrentRepository(self):
+ self.assertEqual(runfiles.Create().CurrentRepository(), "")
+
+ def testRunfilesWithRepoMapping(self):
+ data_path = runfiles.Create().Rlocation("example_bzlmod_build_file_generation/runfiles/data/data.txt")
+ with open(data_path) as f:
+ self.assertEqual(f.read().strip(), "Hello, example_bzlmod!")
+
+ def testRunfileWithRlocationpath(self):
+ data_rlocationpath = os.getenv("DATA_RLOCATIONPATH")
+ data_path = runfiles.Create().Rlocation(data_rlocationpath)
+ with open(data_path) as f:
+ self.assertEqual(f.read().strip(), "Hello, example_bzlmod!")
+
+ def testRunfileInOtherModuleWithOurRepoMapping(self):
+ data_path = runfiles.Create().Rlocation(
+ "our_other_module/other_module/pkg/data/data.txt"
+ )
+ with open(data_path) as f:
+ self.assertEqual(f.read().strip(), "Hello, other_module!")
+
+ def testRunfileInOtherModuleWithItsRepoMapping(self):
+ data_path = lib.GetRunfilePathWithRepoMapping()
+ with open(data_path) as f:
+ self.assertEqual(f.read().strip(), "Hello, other_module!")
+
+ def testRunfileInOtherModuleWithCurrentRepository(self):
+ data_path = lib.GetRunfilePathWithCurrentRepository()
+ with open(data_path) as f:
+ self.assertEqual(f.read().strip(), "Hello, other_module!")
+
+ def testRunfileInOtherModuleWithRlocationpath(self):
+ data_rlocationpath = os.getenv("OTHER_MODULE_DATA_RLOCATIONPATH")
+ data_path = runfiles.Create().Rlocation(data_rlocationpath)
+ with open(data_path) as f:
+ self.assertEqual(f.read().strip(), "Hello, other_module!")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/examples/pip_install/requirements.txt b/examples/pip_install/requirements.txt
index ca8d5943a7..495a32a637 100644
--- a/examples/pip_install/requirements.txt
+++ b/examples/pip_install/requirements.txt
@@ -7,7 +7,7 @@
boto3==1.14.63 \
--hash=sha256:25c716b7c01d4664027afc6a6418a06459e311a610c7fd39a030a1ced1b72ce4 \
--hash=sha256:37158c37a151eab5b9080968305621a40168171fda9584d50a309ceb4e5e6964
- # via -r ./requirements.in
+ # via -r requirements.in
botocore==1.17.63 \
--hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \
--hash=sha256:aa88eafc6295132f4bc606f1df32b3248e0fa611724c0a216aceda767948ac75
@@ -84,7 +84,7 @@ pyyaml==6.0 \
s3cmd==2.1.0 \
--hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \
--hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03
- # via -r ./requirements.in
+ # via -r requirements.in
s3transfer==0.3.7 \
--hash=sha256:35627b86af8ff97e7ac27975fe0a98a312814b46c6333d8a6b889627bcd80994 \
--hash=sha256:efa5bd92a897b6a8d5c1383828dca3d52d0790e0756d49740563a3fb6ed03246
@@ -100,11 +100,11 @@ six==1.16.0 \
tree-sitter==0.20.0 ; sys_platform != "win32" \
--hash=sha256:1940f64be1e8c9c3c0e34a2258f1e4c324207534d5b1eefc5ab2960a9d98f668 \
--hash=sha256:51a609a7c1bd9d9e75d92ee128c12c7852ae70a482900fbbccf3d13a79e0378c
- # via -r ./requirements.in
+ # via -r requirements.in
urllib3==1.25.11 \
--hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \
--hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e
# via botocore
yamllint==1.26.3 \
--hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e
- # via -r ./requirements.in
+ # via -r requirements.in
diff --git a/examples/pip_install/requirements_windows.txt b/examples/pip_install/requirements_windows.txt
index c4279cb6d7..b87192f9d0 100644
--- a/examples/pip_install/requirements_windows.txt
+++ b/examples/pip_install/requirements_windows.txt
@@ -7,7 +7,7 @@
boto3==1.14.63 \
--hash=sha256:25c716b7c01d4664027afc6a6418a06459e311a610c7fd39a030a1ced1b72ce4 \
--hash=sha256:37158c37a151eab5b9080968305621a40168171fda9584d50a309ceb4e5e6964
- # via -r ./requirements.in
+ # via -r requirements.in
botocore==1.17.63 \
--hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \
--hash=sha256:aa88eafc6295132f4bc606f1df32b3248e0fa611724c0a216aceda767948ac75
@@ -84,7 +84,7 @@ pyyaml==6.0 \
s3cmd==2.1.0 \
--hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \
--hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03
- # via -r ./requirements.in
+ # via -r requirements.in
s3transfer==0.3.7 \
--hash=sha256:35627b86af8ff97e7ac27975fe0a98a312814b46c6333d8a6b889627bcd80994 \
--hash=sha256:efa5bd92a897b6a8d5c1383828dca3d52d0790e0756d49740563a3fb6ed03246
@@ -103,4 +103,4 @@ urllib3==1.25.11 \
# via botocore
yamllint==1.26.3 \
--hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e
- # via -r ./requirements.in
+ # via -r requirements.in
diff --git a/examples/pip_parse/requirements_lock.txt b/examples/pip_parse/requirements_lock.txt
index d60295c0bf..3cbe57f28c 100644
--- a/examples/pip_parse/requirements_lock.txt
+++ b/examples/pip_parse/requirements_lock.txt
@@ -73,11 +73,11 @@ pyyaml==6.0 \
requests==2.25.1 \
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
- # via -r ./requirements.in
+ # via -r requirements.in
s3cmd==2.1.0 \
--hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \
--hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03
- # via -r ./requirements.in
+ # via -r requirements.in
setuptools==65.6.3 \
--hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \
--hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75
@@ -92,4 +92,4 @@ urllib3==1.26.13 \
# via requests
yamllint==1.26.3 \
--hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e
- # via -r ./requirements.in
+ # via -r requirements.in
diff --git a/examples/pip_parse_vendored/requirements.txt b/examples/pip_parse_vendored/requirements.txt
index 6a70e036b4..ff1a3633a2 100644
--- a/examples/pip_parse_vendored/requirements.txt
+++ b/examples/pip_parse_vendored/requirements.txt
@@ -19,7 +19,7 @@ idna==3.4 \
requests==2.28.1 \
--hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \
--hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349
- # via -r ./requirements.in
+ # via -r requirements.in
urllib3==1.26.13 \
--hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \
--hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8
diff --git a/examples/pip_repository_annotations/requirements.txt b/examples/pip_repository_annotations/requirements.txt
index f599f7a457..9fde0a922f 100644
--- a/examples/pip_repository_annotations/requirements.txt
+++ b/examples/pip_repository_annotations/requirements.txt
@@ -21,7 +21,7 @@ idna==3.4 \
requests[security]==2.28.1 \
--hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \
--hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349
- # via -r ./requirements.in
+ # via -r requirements.in
urllib3==1.26.13 \
--hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \
--hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8
@@ -29,4 +29,4 @@ urllib3==1.26.13 \
wheel==0.38.4 \
--hash=sha256:965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac \
--hash=sha256:b60533f3f5d530e971d6737ca6d58681ee434818fab630c83a734bb10c083ce8
- # via -r ./requirements.in
+ # via -r requirements.in
diff --git a/examples/py_proto_library/MODULE.bazel b/examples/py_proto_library/MODULE.bazel
index 5ce0924a99..6fb1a05548 100644
--- a/examples/py_proto_library/MODULE.bazel
+++ b/examples/py_proto_library/MODULE.bazel
@@ -12,7 +12,7 @@ local_path_override(
path = "../..",
)
-python = use_extension("@rules_python//python:extensions.bzl", "python")
+python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(
name = "python3_9",
configure_coverage_tool = True,
diff --git a/gazelle/README.md b/gazelle/README.md
index e9a8052353..e36f3a303a 100644
--- a/gazelle/README.md
+++ b/gazelle/README.md
@@ -15,7 +15,10 @@ without using bzlmod as your dependency manager.
## Example
-We have an example of using Gazelle with Python located [here](https://github.com/bazelbuild/rules_python/tree/main/examples/build_file_generation).
+We have an example of using Gazelle with Python located [here](https://github.com/bazelbuild/rules_python/tree/main/examples/bzlmod).
+A fully-working example without using bzlmod is in [`examples/build_file_generation`](../examples/build_file_generation).
+
+The following documentation covers using bzlmod.
## Adding Gazelle to your project
@@ -40,10 +43,37 @@ bazel_dep(name = "rules_python_gazelle_plugin", version = "0.20.0")
# The following stanza defines the dependency rules_python.
bazel_dep(name = "gazelle", version = "0.30.0", repo_name = "bazel_gazelle")
-```
-You will also need to do the other usual configuration for `rules_python` in your
-`MODULE.bazel` file.
+# Import the python repositories generated by the given module extension into the scope of the current module.
+use_repo(python, "python3_9")
+use_repo(python, "python3_9_toolchains")
+
+# Register an already-defined toolchain so that Bazel can use it during toolchain resolution.
+register_toolchains(
+ "@python3_9_toolchains//:all",
+)
+
+# Use the pip extension
+pip = use_extension("@rules_python//python:extensions.bzl", "pip")
+
+# Use the extension to call the `pip_repository` rule that invokes `pip`, with `incremental` set.
+# Accepts a locked/compiled requirements file and installs the dependencies listed within.
+# Those dependencies become available in a generated `requirements.bzl` file.
+# You can instead check this `requirements.bzl` file into your repo.
+# Because this project has different requirements for windows vs other
+# operating systems, we have requirements for each.
+pip.parse(
+ name = "pip",
+ # When using gazelle you must use set the following flag
+ # in order for the generation of gazelle dependency resolution.
+ incompatible_generate_aliases = True,
+ requirements_lock = "//:requirements_lock.txt",
+ requirements_windows = "//:requirements_windows.txt",
+)
+
+# Imports the pip toolchain generated by the given module extension into the scope of the current module.
+use_repo(pip, "pip")
+```
Next, we'll fetch metadata about your Python dependencies, so that gazelle can
determine which package a given import statement comes from. This is provided
by the `modules_mapping` rule. We'll make a target for consuming this
@@ -86,6 +116,9 @@ gazelle_python_manifest(
# This should point to wherever we declare our python dependencies
# (the same as what we passed to the modules_mapping rule in WORKSPACE)
requirements = "//:requirements_lock.txt",
+ # NOTE: we can use this flag in order to make our setup compatible with
+ # bzlmod.
+ use_pip_repository_aliases = True,
)
```
@@ -93,7 +126,7 @@ Finally, you create a target that you'll invoke to run the Gazelle tool
with the rules_python extension included. This typically goes in your root
`/BUILD.bazel` file:
-```
+```starlark
load("@bazel_gazelle//:def.bzl", "gazelle")
load("@rules_python_gazelle_plugin//:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS")
@@ -112,8 +145,6 @@ gazelle(
That's it, now you can finally run `bazel run //:gazelle` anytime
you edit Python code, and it should update your `BUILD` files correctly.
-A fully-working example is in [`examples/build_file_generation`](../examples/build_file_generation).
-
## Usage
Gazelle is non-destructive.
diff --git a/internal_deps.bzl b/internal_deps.bzl
index 8f52b0e7d7..e4d2f69d41 100644
--- a/internal_deps.bzl
+++ b/internal_deps.bzl
@@ -20,6 +20,9 @@ load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
def rules_python_internal_deps():
"""Fetches all required dependencies for rules_python tests and tools."""
+ # This version is also used in python/tests/toolchains/workspace_template/WORKSPACE.tmpl
+ # and tests/ignore_root_user_error/WORKSPACE.
+ # If you update this dependency, please update the tests as well.
maybe(
http_archive,
name = "bazel_skylib",
@@ -42,9 +45,9 @@ def rules_python_internal_deps():
maybe(
http_archive,
name = "rules_testing",
- url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.0.1/rules_testing-v0.0.1.tar.gz",
- sha256 = "47db8fc9c3c1837491333cdcedebf267285479bd709a1ff0a47b19a324817def",
- strip_prefix = "rules_testing-0.0.1",
+ sha256 = "0c2abee201f566a088c720e12bc1d968bc56e6a51b692d9c81b1fe861bdf2be2",
+ strip_prefix = "rules_testing-0.0.5",
+ url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.0.5/rules_testing-v0.0.5.tar.gz",
)
maybe(
diff --git a/python/extensions/BUILD.bazel b/python/extensions/BUILD.bazel
new file mode 100644
index 0000000000..7f6873d581
--- /dev/null
+++ b/python/extensions/BUILD.bazel
@@ -0,0 +1,23 @@
+# Copyright 2017 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+filegroup(
+ name = "distribution",
+ srcs = glob(["**"]),
+ visibility = ["//extensions:__pkg__"],
+)
diff --git a/python/extensions/interpreter.bzl b/python/extensions/interpreter.bzl
new file mode 100644
index 0000000000..b9afe1abda
--- /dev/null
+++ b/python/extensions/interpreter.bzl
@@ -0,0 +1,75 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"Module extension that finds the current toolchain Python binary and creates a symlink to it."
+
+load("@pythons_hub//:interpreters.bzl", "INTERPRETER_LABELS")
+
+def _interpreter_impl(mctx):
+ for mod in mctx.modules:
+ for install_attr in mod.tags.install:
+ _interpreter_repo(
+ name = install_attr.name,
+ python_name = install_attr.python_name,
+ )
+
+interpreter = module_extension(
+ doc = """\
+This extension is used to expose the underlying platform-specific
+interpreter registered as a toolchain. It is used by users to get
+a label to the interpreter for use with pip.parse
+in the MODULES.bazel file.
+""",
+ implementation = _interpreter_impl,
+ tag_classes = {
+ "install": tag_class(
+ attrs = {
+ "name": attr.string(
+ doc = "Name of the interpreter, we use this name to set the interpreter for pip.parse",
+ mandatory = True,
+ ),
+ "python_name": attr.string(
+ doc = "The name set in the previous python.toolchain call.",
+ mandatory = True,
+ ),
+ },
+ ),
+ },
+)
+
+def _interpreter_repo_impl(rctx):
+ rctx.file("BUILD.bazel", "")
+
+ actual_interpreter_label = INTERPRETER_LABELS.get(rctx.attr.python_name)
+ if actual_interpreter_label == None:
+ fail("Unable to find interpreter with name {}".format(rctx.attr.python_name))
+
+ rctx.symlink(actual_interpreter_label, "python")
+
+_interpreter_repo = repository_rule(
+ doc = """\
+Load the INTERPRETER_LABELS map. This map contain of all of the Python binaries
+by name and a label the points to the interpreter binary. The
+binaries are downloaded as part of the python toolchain setup.
+The rule finds the label and creates a symlink named "python" to that
+label. This symlink is then used by pip.
+""",
+ implementation = _interpreter_repo_impl,
+ attrs = {
+ "python_name": attr.string(
+ mandatory = True,
+ doc = "Name of the Python toolchain",
+ ),
+ },
+)
diff --git a/python/extensions.bzl b/python/extensions/pip.bzl
similarity index 64%
rename from python/extensions.bzl
rename to python/extensions/pip.bzl
index 2b0c188554..ce5eea30d4 100644
--- a/python/extensions.bzl
+++ b/python/extensions/pip.bzl
@@ -12,59 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"Module extensions for use with bzlmod"
+"pip module extension for use with bzlmod"
-load("@rules_python//python:repositories.bzl", "python_register_toolchains")
load("@rules_python//python/pip_install:pip_repository.bzl", "locked_requirements_label", "pip_repository_attrs", "pip_repository_bzlmod", "use_isolated", "whl_library")
-load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies")
load("@rules_python//python/pip_install:requirements_parser.bzl", parse_requirements = "parse")
-load("@rules_python//python/private:coverage_deps.bzl", "install_coverage_deps")
-
-def _python_impl(module_ctx):
- for mod in module_ctx.modules:
- for attr in mod.tags.toolchain:
- python_register_toolchains(
- name = attr.name,
- python_version = attr.python_version,
- bzlmod = True,
- # Toolchain registration in bzlmod is done in MODULE file
- register_toolchains = False,
- register_coverage_tool = attr.configure_coverage_tool,
- ignore_root_user_error = attr.ignore_root_user_error,
- )
-
-python = module_extension(
- implementation = _python_impl,
- tag_classes = {
- "toolchain": tag_class(
- attrs = {
- "configure_coverage_tool": attr.bool(
- mandatory = False,
- doc = "Whether or not to configure the default coverage tool for the toolchains.",
- ),
- "ignore_root_user_error": attr.bool(
- default = False,
- doc = "Whether the check for root should be ignored or not. This causes cache misses with .pyc files.",
- mandatory = False,
- ),
- "name": attr.string(mandatory = True),
- "python_version": attr.string(mandatory = True),
- },
- ),
- },
-)
-
-# buildifier: disable=unused-variable
-def _internal_deps_impl(module_ctx):
- pip_install_dependencies()
- install_coverage_deps()
-
-internal_deps = module_extension(
- implementation = _internal_deps_impl,
- tag_classes = {
- "install": tag_class(attrs = dict()),
- },
-)
def _pip_impl(module_ctx):
for mod in module_ctx.modules:
@@ -83,6 +34,7 @@ def _pip_impl(module_ctx):
# this does not create the install_deps() macro.
pip_repository_bzlmod(
name = attr.name,
+ repo_name = attr.name,
requirements_lock = attr.requirements_lock,
incompatible_generate_aliases = attr.incompatible_generate_aliases,
)
@@ -122,6 +74,10 @@ def _pip_parse_ext_attrs():
return attrs
pip = module_extension(
+ doc = """\
+This extension is used to create a pip respository and create the various wheel libaries if
+provided in a requirements file.
+""",
implementation = _pip_impl,
tag_classes = {
"parse": tag_class(attrs = _pip_parse_ext_attrs()),
diff --git a/python/extensions/private/BUILD.bazel b/python/extensions/private/BUILD.bazel
new file mode 100644
index 0000000000..f367b71a78
--- /dev/null
+++ b/python/extensions/private/BUILD.bazel
@@ -0,0 +1,23 @@
+# Copyright 2022 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package(default_visibility = ["//visibility:private"])
+
+licenses(["notice"])
+
+filegroup(
+ name = "distribution",
+ srcs = glob(["**"]),
+ visibility = ["//python/extensions/private:__pkg__"],
+)
diff --git a/python/extensions/private/internal_deps.bzl b/python/extensions/private/internal_deps.bzl
new file mode 100644
index 0000000000..dfa3e2682f
--- /dev/null
+++ b/python/extensions/private/internal_deps.bzl
@@ -0,0 +1,25 @@
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"Python toolchain module extension for internal rule use"
+
+load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies")
+load("@rules_python//python/private:coverage_deps.bzl", "install_coverage_deps")
+
+# buildifier: disable=unused-variable
+def _internal_deps_impl(module_ctx):
+ pip_install_dependencies()
+ install_coverage_deps()
+
+internal_deps = module_extension(
+ doc = "This extension to register internal rules_python dependecies.",
+ implementation = _internal_deps_impl,
+ tag_classes = {
+ "install": tag_class(attrs = dict()),
+ },
+)
diff --git a/python/extensions/private/interpreter_hub.bzl b/python/extensions/private/interpreter_hub.bzl
new file mode 100644
index 0000000000..f1ca670cf2
--- /dev/null
+++ b/python/extensions/private/interpreter_hub.bzl
@@ -0,0 +1,58 @@
+# Copyright 2023 The Bazel Authors. All rights reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"Repo rule used by bzlmod extension to create a repo that has a map of Python interpreters and their labels"
+
+load("//python:versions.bzl", "WINDOWS_NAME")
+load("//python/private:toolchains_repo.bzl", "get_host_os_arch", "get_host_platform")
+
+_build_file_for_hub_template = """
+INTERPRETER_LABELS = {{
+{lines}
+}}
+"""
+
+_line_for_hub_template = """\
+ "{name}": Label("@{name}_{platform}//:{path}"),
+"""
+
+def _hub_repo_impl(rctx):
+ (os, arch) = get_host_os_arch(rctx)
+ platform = get_host_platform(os, arch)
+
+ rctx.file("BUILD.bazel", "")
+ is_windows = (os == WINDOWS_NAME)
+ path = "python.exe" if is_windows else "bin/python3"
+
+ lines = "\n".join([_line_for_hub_template.format(
+ name = name,
+ platform = platform,
+ path = path,
+ ) for name in rctx.attr.toolchains])
+
+ rctx.file("interpreters.bzl", _build_file_for_hub_template.format(lines = lines))
+
+hub_repo = repository_rule(
+ doc = """\
+This private rule create a repo with a BUILD file that contains a map of interpreter names
+and the labels to said interpreters. This map is used to by the interpreter hub extension.
+""",
+ implementation = _hub_repo_impl,
+ attrs = {
+ "toolchains": attr.string_list(
+ doc = "List of the base names the toolchain repo defines.",
+ mandatory = True,
+ ),
+ },
+)
diff --git a/python/extensions/python.bzl b/python/extensions/python.bzl
new file mode 100644
index 0000000000..9a3d9ed959
--- /dev/null
+++ b/python/extensions/python.bzl
@@ -0,0 +1,64 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"Python toolchain module extensions for use with bzlmod"
+
+load("@rules_python//python:repositories.bzl", "python_register_toolchains")
+load("@rules_python//python/extensions/private:interpreter_hub.bzl", "hub_repo")
+
+def _python_impl(module_ctx):
+ toolchains = []
+ for mod in module_ctx.modules:
+ for toolchain_attr in mod.tags.toolchain:
+ python_register_toolchains(
+ name = toolchain_attr.name,
+ python_version = toolchain_attr.python_version,
+ bzlmod = True,
+ # Toolchain registration in bzlmod is done in MODULE file
+ register_toolchains = False,
+ register_coverage_tool = toolchain_attr.configure_coverage_tool,
+ ignore_root_user_error = toolchain_attr.ignore_root_user_error,
+ )
+
+ # We collect all of the toolchain names to create
+ # the INTERPRETER_LABELS map. This is used
+ # by interpreter_extensions.bzl
+ toolchains.append(toolchain_attr.name)
+
+ hub_repo(
+ name = "pythons_hub",
+ toolchains = toolchains,
+ )
+
+python = module_extension(
+ doc = "Bzlmod extension that is used to register a Python toolchain.",
+ implementation = _python_impl,
+ tag_classes = {
+ "toolchain": tag_class(
+ attrs = {
+ "configure_coverage_tool": attr.bool(
+ mandatory = False,
+ doc = "Whether or not to configure the default coverage tool for the toolchains.",
+ ),
+ "ignore_root_user_error": attr.bool(
+ default = False,
+ doc = "Whether the check for root should be ignored or not. This causes cache misses with .pyc files.",
+ mandatory = False,
+ ),
+ "name": attr.string(mandatory = True),
+ "python_version": attr.string(mandatory = True),
+ },
+ ),
+ },
+)
diff --git a/python/packaging.bzl b/python/packaging.bzl
index fffd239c15..45d5c963b9 100644
--- a/python/packaging.bzl
+++ b/python/packaging.bzl
@@ -172,6 +172,7 @@ def py_wheel(name, twine = None, **kwargs):
imports = ["."],
main = twine_main,
deps = [twine],
+ visibility = kwargs.get("visibility"),
)
py_wheel_rule = _py_wheel
diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl
index fce0dcdd47..5239fd5f9c 100644
--- a/python/pip_install/pip_repository.bzl
+++ b/python/pip_install/pip_repository.bzl
@@ -128,7 +128,7 @@ def _get_toolchain_unix_cflags(rctx):
er = rctx.execute([
rctx.path(rctx.attr.python_interpreter_target).realpath,
"-c",
- "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}')",
+ "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}', end='')",
])
if er.return_code != 0:
fail("could not get python version from interpreter (status {}): {}".format(er.return_code, er.stderr))
@@ -358,7 +358,7 @@ def _pip_repository_bzlmod_impl(rctx):
bzl_packages = sorted([name for name, _ in packages])
- repo_name = rctx.attr.name.split("~")[-1]
+ repo_name = rctx.attr.repo_name
build_contents = _BUILD_FILE_CONTENTS
@@ -367,16 +367,26 @@ def _pip_repository_bzlmod_impl(rctx):
else:
build_contents += _bzlmod_pkg_aliases(repo_name, bzl_packages)
+ # NOTE: we are using the canonical name with the double '@' in order to
+ # always uniquely identify a repository, as the labels are being passed as
+ # a string and the resolution of the label happens at the call-site of the
+ # `requirement`, et al. macros.
+ if rctx.attr.incompatible_generate_aliases:
+ macro_tmpl = "@@{name}//{{}}:{{}}".format(name = rctx.attr.name)
+ else:
+ macro_tmpl = "@@{name}//:{{}}_{{}}".format(name = rctx.attr.name)
+
rctx.file("BUILD.bazel", build_contents)
rctx.template("requirements.bzl", rctx.attr._template, substitutions = {
"%%ALL_REQUIREMENTS%%": _format_repr_list([
- "@{}//{}".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:pkg".format(rctx.attr.name, p)
+ macro_tmpl.format(p, p) if rctx.attr.incompatible_generate_aliases else macro_tmpl.format(p, "pkg")
for p in bzl_packages
]),
"%%ALL_WHL_REQUIREMENTS%%": _format_repr_list([
- "@{}//{}:whl".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:whl".format(rctx.attr.name, p)
+ macro_tmpl.format(p, "whl")
for p in bzl_packages
]),
+ "%%MACRO_TMPL%%": macro_tmpl,
"%%NAME%%": rctx.attr.name,
"%%REQUIREMENTS_LOCK%%": str(requirements_txt),
})
@@ -386,6 +396,10 @@ pip_repository_bzlmod_attrs = {
default = False,
doc = "Allow generating aliases in '@pip//:Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: