diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 0e9feab093..b468970fbb 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -48,6 +48,8 @@ buildifier: test_targets: ["..."] .coverage_targets_example_bzlmod: &coverage_targets_example_bzlmod coverage_targets: ["//:test"] +.coverage_targets_example_bzlmod_build_file_generation: &coverage_targets_example_bzlmod_build_file_generation + coverage_targets: ["//:bzlmod_build_file_generation_test"] .coverage_targets_example_multi_python: &coverage_targets_example_multi_python coverage_targets: - //tests:my_lib_3_10_test @@ -147,32 +149,6 @@ tasks: working_directory: examples/build_file_generation platform: windows - integration_test_build_file_generation_bzlmod_ubuntu: - <<: *minimum_supported_bzlmod_version - <<: *common_bzlmod_flags - <<: *reusable_build_test_all - name: build_file_generation_bzlmod integration tests on Ubuntu - working_directory: examples/build_file_generation - platform: ubuntu2004 - integration_test_build_file_generation_bzlmod_debian: - <<: *common_bzlmod_flags - <<: *reusable_build_test_all - name: build_file_generation_bzlmod integration tests on Debian - working_directory: examples/build_file_generation - platform: debian11 - integration_test_build_file_generation_bzlmod_macos: - <<: *common_bzlmod_flags - <<: *reusable_build_test_all - name: build_file_generation_bzlmod integration tests on macOS - working_directory: examples/build_file_generation - platform: macos - integration_test_build_file_generation_bzlmod_windows: - <<: *common_bzlmod_flags - <<: *reusable_build_test_all - name: build_file_generation_bzlmod integration tests on Windows - working_directory: examples/build_file_generation - platform: windows - integration_test_bzlmod_ubuntu_min: <<: *minimum_supported_bzlmod_version <<: *reusable_build_test_all @@ -205,6 +181,46 @@ tasks: working_directory: examples/bzlmod platform: windows + integration_test_bzlmod_generate_build_file_generation_ubuntu_min: + <<: *minimum_supported_bzlmod_version + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod_build_file_generation + name: example bzlmod build file min bazel version integration test + working_directory: examples/bzlmod_build_file_generation + platform: ubuntu2004 + integration_test_bzlmod_generation_build_files_ubuntu: + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod_build_file_generation + name: example bzlmod build file integration test + working_directory: examples/bzlmod_build_file_generation + platform: ubuntu2004 + integration_test_bzlmod_generation_build_files_ubuntu_run: + <<: *reusable_build_test_all + name: example bzlmod build file running gazelle and pip integration test + working_directory: examples/bzlmod_build_file_generation + platform: ubuntu2004 + shell_commands: + - "bazel run //:gazelle_python_manifest.update" + - "bazel run //:gazelle -- update" + integration_test_bzlmod_build_file_generation_debian: + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod_build_file_generation + name: example bzlmod build file integration test + working_directory: examples/bzlmod_build_file_generation + platform: debian11 + integration_test_bzlmod_build_file_generation_macos: + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod_build_file_generation + name: example bzlmod build file integration test + working_directory: examples/bzlmod_build_file_generation + platform: macos + integration_test_bzlmod_build_file_generation_windows: + <<: *reusable_build_test_all + # coverage is not supported on Windows + name: example bzlmod build file integration test + working_directory: examples/bzlmod_build_file_generation + platform: windows + integration_test_multi_python_versions_ubuntu_min: <<: *minimum_supported_version <<: *reusable_build_test_all @@ -509,3 +525,41 @@ tasks: name: ignore_root_user_error integration tests on Windows working_directory: tests/ignore_root_user_error platform: windows + + integration_compile_pip_requirements_test_from_external_repo_ubuntu_min: + <<: *minimum_supported_version + name: compile_pip_requirements test from external repo on Ubuntu using minimum supported Bazel version + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: ubuntu2004 + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + integration_compile_pip_requirements_test_from_external_repo_ubuntu: + name: compile_pip_requirements test from external repo on Ubuntu + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: ubuntu2004 + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + integration_compile_pip_requirements_test_from_external_repo_debian: + name: compile_pip_requirements test from external repo on Debian + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: debian11 + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + integration_compile_pip_requirements_test_from_external_repo_macos: + name: compile_pip_requirements test from external repo on macOS + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: macos + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + integration_compile_pip_requirements_test_from_external_repo_windows: + name: compile_pip_requirements test from external repo on Windows + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: windows + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + diff --git a/.bazelignore b/.bazelignore index e69de29bb2..a603a7bd8a 100644 --- a/.bazelignore +++ b/.bazelignore @@ -0,0 +1,8 @@ +# Normally these are ignored, but if you're using a custom +# build of Bazel with a custom --output_user_root value, Bazel +# tries to follow the symlinks of the other builds and finds +# the WORKSPACE, BUILD, etc files and tries to build them. +bazel-rules_python +bazel-bin +bazel-out +bazel-testlogs diff --git a/.bazelrc b/.bazelrc index d607cdd9b7..fe542b3722 100644 --- a/.bazelrc +++ b/.bazelrc @@ -3,8 +3,8 @@ # This lets us glob() up all the files inside the examples to make them inputs to tests # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it) # To update these lines, run tools/bazel_integration_test/update_deleted_packages.sh -build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/py_proto_library,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps -query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/py_proto_library,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod/entry_point,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,tests/compile_pip_requirements,tests/compile_pip_requirements_test_from_external_workspace,tests/ignore_root_user_error,tests/pip_repository_entry_points +query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod/entry_point,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,tests/compile_pip_requirements,tests/compile_pip_requirements_test_from_external_workspace,tests/ignore_root_user_error,tests/pip_repository_entry_points test --test_output=errors diff --git a/BUILD.bazel b/BUILD.bazel index dff608a1ca..35a3df892f 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -52,7 +52,6 @@ filegroup( "//python/pip_install:bzl", "//python:bzl", # Requires Bazel 0.29 onward for public visibility of these .bzl files. - "@bazel_tools//tools/python:private/defs.bzl", "@bazel_tools//tools/python:python_version.bzl", "@bazel_tools//tools/python:srcs_version.bzl", "@bazel_tools//tools/python:toolchain.bzl", diff --git a/BZLMOD_SUPPORT.md b/BZLMOD_SUPPORT.md new file mode 100644 index 0000000000..cf95d12a0e --- /dev/null +++ b/BZLMOD_SUPPORT.md @@ -0,0 +1,37 @@ +# Bzlmod support + +## `rule_python` `bzlmod` support + +- Status: Beta +- Full Feature Parity: No + +Some features are missing or broken, and the public APIs are not yet stable. + +## Configuration + +The releases page will give you the latest version number, and a basic example. The release page is located [here](/bazelbuild/rules_python/releases). + +## What is bzlmod? + +> Bazel supports external dependencies, source files (both text and binary) used in your build that are not from your workspace. For example, they could be a ruleset hosted in a GitHub repo, a Maven artifact, or a directory on your local machine outside your current workspace. +> +> As of Bazel 6.0, there are two ways to manage external dependencies with Bazel: the traditional, repository-focused WORKSPACE system, and the newer module-focused MODULE.bazel system (codenamed Bzlmod, and enabled with the flag `--enable_bzlmod`). The two systems can be used together, but Bzlmod is replacing the WORKSPACE system in future Bazel releases. +> -- https://bazel.build/external/overview + +## Examples + +We have two examples that demonstrate how to configure `bzlmod`. + +The first example is in [examples/bzlmod](examples/bzlmod), and it demonstrates basic bzlmod configuration. +A user does not use `local_path_override` stanza and would define the version in the `bazel_dep` line. + +A second example, in [examples/bzlmod_build_file_generation](examples/bzlmod_build_file_generation) demonstrates the use of `bzlmod` to configure `gazelle` support for `rules_python`. + +## Feature parity + +This rule set does not have full feature partity with the older `WORKSPACE` type configuration: + +1. Multiple python versions are not yet supported, as demonstrated in [this](examples/multi_python_versions) example. +2. Gazelle does not support finding deps in sub-modules. For instance we can have a dep like ` "@our_other_module//other_module/pkg:lib",` in a `py_test` definition. + +Check ["issues"](/bazelbuild/rules_python/issues) for an up to date list. diff --git a/DEVELOPING.md b/DEVELOPING.md index 092e3efeaf..2972d96b79 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -7,17 +7,24 @@ Start from a clean checkout at `main`. Before running through the release it's good to run the build and the tests locally, and make sure CI is passing. You can also test-drive the commit in an existing Bazel workspace to sanity check functionality. +#### Steps +1. [Determine the next semantic version number](#determining-semantic-version) +1. Create a tag and push, e.g. `git tag 0.5.0 upstream/main && git push upstream --tags` + NOTE: Pushing the tag will trigger release automation. +1. Watch the release automation run on https://github.com/bazelbuild/rules_python/actions +1. Add missing information to the release notes. The automatic release note + generation only includes commits associated with issues. + #### Determining Semantic Version **rules_python** is currently using [Zero-based versioning](https://0ver.org/) and thus backwards-incompatible API changes still come under the minor-version digit. So releases with API changes and new features bump the minor, and -those with only bug fixes and other minor changes bump the patch digit. +those with only bug fixes and other minor changes bump the patch digit. + +To find if there were any features added or incompatible changes made, review +the commit history. This can be done using github by going to the url: +`https://github.com/bazelbuild/rules_python/compare/...main`. -#### Steps -1. Determine what will be the next release, following semver. -1. Create a tag and push, e.g. `git tag 0.5.0 upstream/main && git push upstream --tags` -1. Watch the release automation run on https://github.com/bazelbuild/rules_python/actions - #### After release creation in Github 1. Ping @philwo to get the new release added to mirror.bazel.build. See [this comment on issue #400](https://github.com/bazelbuild/rules_python/issues/400#issuecomment-779159530) for more context. diff --git a/MODULE.bazel b/MODULE.bazel index 92da4020b9..ddd946c78a 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -11,7 +11,7 @@ bazel_dep(name = "bazel_skylib", version = "1.3.0") bazel_dep(name = "rules_proto", version = "5.3.0-21.7") bazel_dep(name = "protobuf", version = "21.7", repo_name = "com_google_protobuf") -internal_deps = use_extension("@rules_python//python:extensions.bzl", "internal_deps") +internal_deps = use_extension("@rules_python//python/extensions/private:internal_deps.bzl", "internal_deps") internal_deps.install() use_repo( internal_deps, @@ -46,3 +46,6 @@ use_repo( "pypi__coverage_cp39_x86_64-apple-darwin", "pypi__coverage_cp39_x86_64-unknown-linux-gnu", ) + +python = use_extension("@rules_python//python/extensions:python.bzl", "python") +use_repo(python, "pythons_hub") diff --git a/README.md b/README.md index 089837de7d..a3f18869e6 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,13 @@ Bazel team, provides support for the code. However, this repository is part of the test suite used to vet new Bazel releases. See the [How to contribute](CONTRIBUTING.md) page for information on our development workflow. +## `bzlmod` support + +- Status: Beta +- Full Feature Parity: No + +See [Bzlmod support](BZLMOD_SUPPORT.md) for more details. + ## Getting started The next two sections cover using `rules_python` with bzlmod and @@ -39,12 +46,12 @@ the older way of configuring bazel with a `WORKSPACE` file. ### Using bzlmod To import rules_python in your project, you first need to add it to your -`MODULES.bazel` file, using the snippet provided in the +`MODULE.bazel` file, using the snippet provided in the [release you choose](https://github.com/bazelbuild/rules_python/releases). #### Toolchain registration with bzlmod -To register a hermetic Python toolchain rather than rely on a system-installed interpreter for runtime execution, you can add to the `MODULES.bazel` file: +To register a hermetic Python toolchain rather than rely on a system-installed interpreter for runtime execution, you can add to the `MODULE.bazel` file: ```python # Find the latest version number here: https://github.com/bazelbuild/rules_python/releases @@ -161,7 +168,7 @@ target in the appropriate wheel repo. #### Using bzlmod -To add pip dependencies to your `MODULES.bazel` file, use the `pip.parse` extension, and call it to create the +To add pip dependencies to your `MODULE.bazel` file, use the `pip.parse` extension, and call it to create the central external repo and individual wheel external repos. ```python diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index e1163d9d0e..938ba85dd5 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -32,17 +32,6 @@ _DOCS = { # because they're only used for doc generation. This way, we avoid requiring # our users to depend on Skylib. -# Requires Bazel 0.29 onward for public visibility of these .bzl files. -bzl_library( - name = "bazel_python_tools", - srcs = [ - "@bazel_tools//tools/python:private/defs.bzl", - "@bazel_tools//tools/python:srcs_version.bzl", - "@bazel_tools//tools/python:toolchain.bzl", - "@bazel_tools//tools/python:utils.bzl", - ], -) - bzl_library( name = "bazel_repo_tools", srcs = [ @@ -57,7 +46,7 @@ bzl_library( "//python/private:reexports.bzl", ], deps = [ - ":bazel_python_tools", + ":bazel_repo_tools", "//python:defs_bzl", "//python/private:reexports_bzl", ], @@ -91,6 +80,9 @@ bzl_library( "//python/private:stamp.bzl", "//python/private:util.bzl", ], + deps = [ + "//python/private:util_bzl", + ], ) # TODO: Stardoc does not guarantee consistent outputs accross platforms (Unix/Windows). diff --git a/docs/pip_repository.md b/docs/pip_repository.md index c02058e08d..7d539c9c44 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -66,10 +66,10 @@ py_binary( | 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 | [] | | 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.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | 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//:' -> '@pip_//:pkg'. This replaces the aliases generated by the `bzlmod` tooling.", ), + "repo_name": attr.string( + mandatory = True, + doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name", + ), "requirements_darwin": attr.label( allow_single_file = True, doc = "Override the requirements_lock attribute when the host platform is Mac OS", @@ -527,7 +541,7 @@ can be passed. "isolated": attr.bool( doc = """\ 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 +the underlying pip command. Alternatively, the `RULES_PYTHON_PIP_ISOLATED` environment variable can be used to control this flag. """, default = True, @@ -550,7 +564,7 @@ of a binary found on the host's `PATH` environment variable. If no value is set 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. +python_interpreter. An example value: "@python3_x86_64-unknown-linux-gnu//:python". """, ), "quiet": attr.bool( diff --git a/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl b/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl index 462829d074..b77bf39c38 100644 --- a/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl +++ b/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl @@ -12,13 +12,20 @@ def _clean_name(name): return name.replace("-", "_").replace(".", "_").lower() def requirement(name): - return "@@%%NAME%%//:" + _clean_name(name) + "_pkg" + return "%%MACRO_TMPL%%".format(_clean_name(name), "pkg") def whl_requirement(name): - return "@@%%NAME%%//:" + _clean_name(name) + "_whl" + return "%%MACRO_TMPL%%".format(_clean_name(name), "whl") def data_requirement(name): - return "@@%%NAME%%//:" + _clean_name(name) + "_data" + return "%%MACRO_TMPL%%".format(_clean_name(name), "data") def dist_info_requirement(name): - return "@@%%NAME%%//:" + _clean_name(name) + "_dist_info" + return "%%MACRO_TMPL%%".format(_clean_name(name), "dist_info") + +def entry_point(pkg, script = None): + """entry_point returns the target of the canonical label of the package entrypoints. + """ + if not script: + script = pkg + return "@@%%NAME%%_{}//:rules_python_wheel_entry_point_{}".format(_clean_name(pkg), script) diff --git a/python/pip_install/private/test/requirements_parser_tests.bzl b/python/pip_install/private/test/requirements_parser_tests.bzl index 13c40c2956..5ea742e70d 100644 --- a/python/pip_install/private/test/requirements_parser_tests.bzl +++ b/python/pip_install/private/test/requirements_parser_tests.bzl @@ -62,6 +62,9 @@ SomeProject == 1.3 # This is a comment FooProject==1.0.0 # Comment BarProject==2.0.0 #Comment +""").requirements) + asserts.equals(env, [("requests", "requests @ https://github.com/psf/requests/releases/download/v2.29.0/requests-2.29.0.tar.gz#sha1=3897c249b51a1a405d615a8c9cb92e5fdbf0dd49")], parse("""\ +requests @ https://github.com/psf/requests/releases/download/v2.29.0/requests-2.29.0.tar.gz#sha1=3897c249b51a1a405d615a8c9cb92e5fdbf0dd49 """).requirements) # Multiline @@ -71,6 +74,11 @@ certifi==2021.10.8 \ --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 # via requests """).requirements) + asserts.equals(env, [("requests", "requests @ https://github.com/psf/requests/releases/download/v2.29.0/requests-2.29.0.tar.gz#sha1=3897c249b51a1a405d615a8c9cb92e5fdbf0dd49 --hash=sha256:eca58eb564b134e4ff521a02aa6f566c653835753e1fc8a50a20cb6bee4673cd")], parse("""\ +requests @ https://github.com/psf/requests/releases/download/v2.29.0/requests-2.29.0.tar.gz#sha1=3897c249b51a1a405d615a8c9cb92e5fdbf0dd49 \ + --hash=sha256:eca58eb564b134e4ff521a02aa6f566c653835753e1fc8a50a20cb6bee4673cd + # via requirements.txt +""").requirements) # Options asserts.equals(env, ["--pre"], parse("--pre\n").options) @@ -177,11 +185,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 six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -192,7 +200,7 @@ urllib3==1.26.7 \ # via requests yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r ./requirements.in + # via -r requirements.in # The following packages are considered to be unsafe in a requirements file: setuptools==59.6.0 \ diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index dd38c9df5b..7594471897 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -75,7 +75,7 @@ def compile_pip_requirements( # where it appears, which is to say, in @rules_python pip_compile = Label("//python/pip_install/tools/dependency_resolver:dependency_resolver.py") - loc = "$(rootpath {})" + loc = "$(rlocationpath {})" args = [ loc.format(requirements_in), @@ -99,6 +99,7 @@ def compile_pip_requirements( requirement("importlib_metadata"), requirement("zipp"), requirement("more_itertools"), + Label("//python/runfiles:runfiles"), ] + extra_deps tags = tags or [] diff --git a/python/pip_install/requirements_parser.bzl b/python/pip_install/requirements_parser.bzl index ac90b95328..3b49fdf181 100644 --- a/python/pip_install/requirements_parser.bzl +++ b/python/pip_install/requirements_parser.bzl @@ -116,7 +116,7 @@ def _handleParseOption(input, buffer, result): elif input == "\n" or input == EOF: result.options.append(buffer.rstrip("\n")) return (_STATE.ConsumeSpace, "") - elif input == "#": + elif input == "#" and (len(buffer) == 0 or buffer[-1].isspace()): return (_STATE.ConsumeComment, buffer) return (_STATE.ParseOption, buffer + input) @@ -127,7 +127,7 @@ def _handleParseRequirement(input, buffer, result): elif input == "\n" or input == EOF: result.requirements[-1] = (result.requirements[-1][0], buffer.rstrip(" \n")) return (_STATE.ConsumeSpace, "") - elif input == "#": + elif input == "#" and (len(buffer) == 0 or buffer[-1].isspace()): return (_STATE.ConsumeComment, buffer) return (_STATE.ParseRequirement, buffer + input) diff --git a/python/pip_install/tools/dependency_resolver/dependency_resolver.py b/python/pip_install/tools/dependency_resolver/dependency_resolver.py index e636febd93..89e355806c 100644 --- a/python/pip_install/tools/dependency_resolver/dependency_resolver.py +++ b/python/pip_install/tools/dependency_resolver/dependency_resolver.py @@ -23,6 +23,8 @@ import piptools.writer as piptools_writer from piptools.scripts.compile import cli +from python.runfiles import runfiles + # Replace the os.replace function with shutil.copy to work around os.replace not being able to # replace or move files across filesystems. os.replace = shutil.copy @@ -66,6 +68,15 @@ def _select_golden_requirements_file( return requirements_txt +def _locate(bazel_runfiles, file): + """Look up the file via Rlocation""" + + if not file: + return file + + return bazel_runfiles.Rlocation(file) + + if __name__ == "__main__": if len(sys.argv) < 4: print( @@ -75,6 +86,7 @@ def _select_golden_requirements_file( sys.exit(1) parse_str_none = lambda s: None if s == "None" else s + bazel_runfiles = runfiles.Create() requirements_in = sys.argv.pop(1) requirements_txt = sys.argv.pop(1) @@ -83,10 +95,25 @@ def _select_golden_requirements_file( requirements_windows = parse_str_none(sys.argv.pop(1)) update_target_label = sys.argv.pop(1) - # The requirements_in file could be generated, so we will need to remove the - # absolute prefixes in the locked requirements output file. - requirements_in_path = Path(requirements_in) - resolved_requirements_in = str(requirements_in_path.resolve()) + resolved_requirements_in = _locate(bazel_runfiles, requirements_in) + resolved_requirements_txt = _locate(bazel_runfiles, requirements_txt) + + # Files in the runfiles directory has the following naming schema: + # Main repo: __main__/ + # External repo: / + # We want to strip both __main__ and from the absolute prefix + # to keep the requirements lock file agnostic. + repository_prefix = requirements_txt[: requirements_txt.index("/") + 1] + absolute_path_prefix = resolved_requirements_txt[ + : -(len(requirements_txt) - len(repository_prefix)) + ] + + # As requirements_in might contain references to generated files we want to + # use the runfiles file first. Thus, we need to compute the relative path + # from the execution root. + # Note: Windows cannot reference generated files without runfiles support enabled. + requirements_in_relative = requirements_in[len(repository_prefix) :] + requirements_txt_relative = requirements_txt[len(repository_prefix) :] # Before loading click, set the locale for its parser. # If it leaks through to the system setting, it may fail: @@ -112,7 +139,7 @@ def _select_golden_requirements_file( ) # Those two files won't necessarily be on the same filesystem, so we can't use os.replace # or shutil.copyfile, as they will fail with OSError: [Errno 18] Invalid cross-device link. - shutil.copy(requirements_txt, requirements_out) + shutil.copy(resolved_requirements_txt, requirements_out) update_command = os.getenv("CUSTOM_COMPILE_COMMAND") or "bazel run %s" % ( update_target_label, @@ -123,24 +150,33 @@ def _select_golden_requirements_file( sys.argv.append("--generate-hashes") sys.argv.append("--output-file") - sys.argv.append(requirements_txt if UPDATE else requirements_out) + sys.argv.append(requirements_txt_relative if UPDATE else requirements_out) sys.argv.append( - requirements_in if requirements_in_path.exists() else resolved_requirements_in + requirements_in_relative + if Path(requirements_in_relative).exists() + else resolved_requirements_in ) + print(sys.argv) if UPDATE: - print("Updating " + requirements_txt) + print("Updating " + requirements_txt_relative) if "BUILD_WORKSPACE_DIRECTORY" in os.environ: workspace = os.environ["BUILD_WORKSPACE_DIRECTORY"] - requirements_txt_tree = os.path.join(workspace, requirements_txt) + requirements_txt_tree = os.path.join(workspace, requirements_txt_relative) # In most cases, requirements_txt will be a symlink to the real file in the source tree. # If symlinks are not enabled (e.g. on Windows), then requirements_txt will be a copy, # and we should copy the updated requirements back to the source tree. - if not os.path.samefile(requirements_txt, requirements_txt_tree): + if not os.path.samefile(resolved_requirements_txt, requirements_txt_tree): atexit.register( - lambda: shutil.copy(requirements_txt, requirements_txt_tree) + lambda: shutil.copy( + resolved_requirements_txt, requirements_txt_tree + ) ) cli() + requirements_txt_relative_path = Path(requirements_txt_relative) + content = requirements_txt_relative_path.read_text() + content = content.replace(absolute_path_prefix, "") + requirements_txt_relative_path.write_text(content) else: # cli will exit(0) on success try: @@ -153,7 +189,7 @@ def _select_golden_requirements_file( print( "pip-compile exited with code 2. This means that pip-compile found " "incompatible requirements or could not find a version that matches " - f"the install requirement in {requirements_in}.", + f"the install requirement in {requirements_in_relative}.", file=sys.stderr, ) sys.exit(1) @@ -164,8 +200,9 @@ def _select_golden_requirements_file( requirements_darwin, requirements_windows, ) - golden = open(golden_filename).readlines() + golden = open(_locate(bazel_runfiles, golden_filename)).readlines() out = open(requirements_out).readlines() + out = [line.replace(absolute_path_prefix, "") for line in out] if golden != out: import difflib diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 4068ea480b..f454f42cf3 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -44,7 +44,11 @@ bzl_library( bzl_library( name = "util_bzl", srcs = ["util.bzl"], - visibility = ["//python:__subpackages__"], + visibility = [ + "//docs:__subpackages__", + "//python:__subpackages__", + ], + deps = ["@bazel_skylib//lib:types"], ) # @bazel_tools can't define bzl_library itself, so we just put a wrapper around it. diff --git a/python/private/util.bzl b/python/private/util.bzl index 25a50aac6a..f0d43737a0 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -1,5 +1,7 @@ """Functionality shared by multiple pieces of code.""" +load("@bazel_skylib//lib:types.bzl", "types") + def copy_propagating_kwargs(from_kwargs, into_kwargs = None): """Copies args that must be compatible between two targets with a dependency relationship. @@ -36,8 +38,23 @@ def copy_propagating_kwargs(from_kwargs, into_kwargs = None): _MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__" def add_migration_tag(attrs): + """Add a special tag to `attrs` to aid migration off native rles. + + Args: + attrs: dict of keyword args. The `tags` key will be modified in-place. + + Returns: + The same `attrs` object, but modified. + """ if "tags" in attrs and attrs["tags"] != None: - attrs["tags"] = attrs["tags"] + [_MIGRATION_TAG] + tags = attrs["tags"] + + # Preserve the input type: this allows a test verifying the underlying + # rule can accept the tuple for the tags argument. + if types.is_tuple(tags): + attrs["tags"] = tags + (_MIGRATION_TAG,) + else: + attrs["tags"] = tags + [_MIGRATION_TAG] else: attrs["tags"] = [_MIGRATION_TAG] return attrs diff --git a/python/repositories.bzl b/python/repositories.bzl index 2429d7e026..358df4341b 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -106,11 +106,11 @@ def _python_repository_impl(rctx): python_version = rctx.attr.python_version python_short_version = python_version.rpartition(".")[0] release_filename = rctx.attr.release_filename - url = rctx.attr.urls or [rctx.attr.url] + urls = rctx.attr.urls or [rctx.attr.url] if release_filename.endswith(".zst"): rctx.download( - url = url, + url = urls, sha256 = rctx.attr.sha256, output = release_filename, ) @@ -153,7 +153,7 @@ def _python_repository_impl(rctx): fail(fail_msg) else: rctx.download_and_extract( - url = url, + url = urls, sha256 = rctx.attr.sha256, stripPrefix = rctx.attr.strip_prefix, ) @@ -348,7 +348,7 @@ py_runtime_pair( rctx.file(STANDALONE_INTERPRETER_FILENAME, "# File intentionally left blank. Indicates that this is an interpreter repo created by rules_python.") rctx.file("BUILD.bazel", build_content) - return { + attrs = { "coverage_tool": rctx.attr.coverage_tool, "distutils": rctx.attr.distutils, "distutils_content": rctx.attr.distutils_content, @@ -360,9 +360,15 @@ py_runtime_pair( "release_filename": release_filename, "sha256": rctx.attr.sha256, "strip_prefix": rctx.attr.strip_prefix, - "url": url, } + if rctx.attr.url: + attrs["url"] = rctx.attr.url + else: + attrs["urls"] = urls + + return attrs + python_repository = repository_rule( _python_repository_impl, doc = "Fetches the external tools needed for the Python toolchain.", diff --git a/python/tests/toolchains/workspace_template/WORKSPACE.tmpl b/python/tests/toolchains/workspace_template/WORKSPACE.tmpl index d0aa700928..973e020c1e 100644 --- a/python/tests/toolchains/workspace_template/WORKSPACE.tmpl +++ b/python/tests/toolchains/workspace_template/WORKSPACE.tmpl @@ -25,3 +25,15 @@ python_register_toolchains( name = "python", python_version = "%python_version%", ) + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( + name = "bazel_skylib", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + ], + sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", +) +load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") +bazel_skylib_workspace() diff --git a/python/versions.bzl b/python/versions.bzl index 662f89d04b..baf6e33a06 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -86,6 +86,17 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.8.16": { + "url": "20230116/cpython-{python_version}+20230116-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "d1f408569d8807c1053939d7822b082a17545e363697e1ce3cfb1ee75834c7be", + "aarch64-unknown-linux-gnu": "15d00bc8400ed6d94c665a797dc8ed7a491ae25c5022e738dcd665cd29beec42", + "x86_64-apple-darwin": "484ba901f64fc7888bec5994eb49343dc3f9d00ed43df17ee9c40935aad4aa18", + "x86_64-pc-windows-msvc": "b446bec833eaba1bac9063bb9b4aeadfdf67fa81783b4487a90c56d408fb7994", + "x86_64-unknown-linux-gnu": "c890de112f1ae31283a31fefd2061d5c97bdd4d1bdd795552c7abddef2697ea1", + }, + "strip_prefix": "python", + }, "3.9.10": { "url": "20220227/cpython-{python_version}+20220227-{platform}-{build}.tar.gz", "sha256": { diff --git a/tests/compile_pip_requirements/requirements_lock.txt b/tests/compile_pip_requirements/requirements_lock.txt index 8f7037ce7a..4ca4a11f3e 100644 --- a/tests/compile_pip_requirements/requirements_lock.txt +++ b/tests/compile_pip_requirements/requirements_lock.txt @@ -7,8 +7,8 @@ pip==22.3.1 \ --hash=sha256:65fd48317359f3af8e593943e6ae1506b66325085ea64b706a998c6e83eeaf38 \ --hash=sha256:908c78e6bc29b676ede1c4d57981d490cb892eb45cd8c214ab6298125119e077 - # via -r ./requirements.in + # via -r requirements.in setuptools==65.6.3 \ --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via -r ./requirements_extra.in + # via -r requirements_extra.in diff --git a/tests/compile_pip_requirements_test_from_external_workspace/.bazelrc b/tests/compile_pip_requirements_test_from_external_workspace/.bazelrc new file mode 100644 index 0000000000..b98fc09774 --- /dev/null +++ b/tests/compile_pip_requirements_test_from_external_workspace/.bazelrc @@ -0,0 +1 @@ +test --test_output=errors diff --git a/tests/compile_pip_requirements_test_from_external_workspace/.gitignore b/tests/compile_pip_requirements_test_from_external_workspace/.gitignore new file mode 100644 index 0000000000..ac51a054d2 --- /dev/null +++ b/tests/compile_pip_requirements_test_from_external_workspace/.gitignore @@ -0,0 +1 @@ +bazel-* diff --git a/tests/compile_pip_requirements_test_from_external_workspace/BUILD.bazel b/tests/compile_pip_requirements_test_from_external_workspace/BUILD.bazel new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/compile_pip_requirements_test_from_external_workspace/README.md b/tests/compile_pip_requirements_test_from_external_workspace/README.md new file mode 100644 index 0000000000..8ce77ca1f1 --- /dev/null +++ b/tests/compile_pip_requirements_test_from_external_workspace/README.md @@ -0,0 +1,3 @@ +# compile_pip_requirements_test_from_external_workspace + +This test checks that compile_pip_requirements test can be run from external workspaces without invalidating the lock file. diff --git a/tests/compile_pip_requirements_test_from_external_workspace/WORKSPACE b/tests/compile_pip_requirements_test_from_external_workspace/WORKSPACE new file mode 100644 index 0000000000..35686a1d30 --- /dev/null +++ b/tests/compile_pip_requirements_test_from_external_workspace/WORKSPACE @@ -0,0 +1,36 @@ +local_repository( + name = "rules_python", + path = "../..", +) + +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +py_repositories() + +load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") + +pip_install_dependencies() + +python_register_toolchains( + name = "python39", + python_version = "3.9", +) + +load("@python39//:defs.bzl", "interpreter") +load("@rules_python//python:pip.bzl", "pip_parse") + +local_repository( + name = "external_repository", + path = "../compile_pip_requirements", +) + +pip_parse( + name = "pypi", + python_interpreter_target = interpreter, + requirements_lock = "@external_repository//:requirements_lock.txt", +) + +load("@pypi//:requirements.bzl", "install_deps") + +# Initialize repositories for all packages in requirements_lock.txt. +install_deps() diff --git a/tests/ignore_root_user_error/WORKSPACE b/tests/ignore_root_user_error/WORKSPACE index d2f4d6ec3a..e0528e4047 100644 --- a/tests/ignore_root_user_error/WORKSPACE +++ b/tests/ignore_root_user_error/WORKSPACE @@ -10,3 +10,18 @@ python_register_toolchains( ignore_root_user_error = True, python_version = "3.9", ) + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "bazel_skylib", + sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + ], +) + +load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") + +bazel_skylib_workspace() diff --git a/tests/pip_repository_entry_points/requirements.txt b/tests/pip_repository_entry_points/requirements.txt index 90b717e7a7..a93facc03b 100644 --- a/tests/pip_repository_entry_points/requirements.txt +++ b/tests/pip_repository_entry_points/requirements.txt @@ -170,7 +170,7 @@ setuptools==59.6.0 \ --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e # via - # -r ./requirements.in + # -r requirements.in # sphinx # yamllint snowballstemmer==2.2.0 \ @@ -180,7 +180,7 @@ snowballstemmer==2.2.0 \ sphinx==4.3.2 \ --hash=sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c \ --hash=sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851 - # via -r ./requirements.in + # via -r requirements.in sphinxcontrib-applehelp==1.0.2 \ --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 @@ -212,4 +212,4 @@ urllib3==1.26.7 \ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b - # via -r ./requirements.in + # via -r requirements.in diff --git a/tests/pip_repository_entry_points/requirements_windows.txt b/tests/pip_repository_entry_points/requirements_windows.txt index 14c3dc3274..651e2b5e56 100644 --- a/tests/pip_repository_entry_points/requirements_windows.txt +++ b/tests/pip_repository_entry_points/requirements_windows.txt @@ -174,7 +174,7 @@ setuptools==59.6.0 \ --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e # via - # -r ./requirements.in + # -r requirements.in # sphinx # yamllint snowballstemmer==2.2.0 \ @@ -184,7 +184,7 @@ snowballstemmer==2.2.0 \ sphinx==4.3.2 \ --hash=sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c \ --hash=sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851 - # via -r ./requirements.in + # via -r requirements.in sphinxcontrib-applehelp==1.0.2 \ --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 @@ -216,4 +216,4 @@ urllib3==1.26.7 \ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b - # via -r ./requirements.in + # via -r requirements.in diff --git a/tools/bazel_integration_test/test_runner.py b/tools/bazel_integration_test/test_runner.py index 03599fbd0e..3940e87c37 100644 --- a/tools/bazel_integration_test/test_runner.py +++ b/tools/bazel_integration_test/test_runner.py @@ -79,6 +79,7 @@ def main(conf_file): "--override_module=rules_python=%s/rules_python" % os.environ["TEST_SRCDIR"] ) + bazel_args.append("--enable_bzlmod") # Bazel's wrapper script needs this or you get # 2020/07/13 21:58:11 could not get the user's cache directory: $HOME is not defined diff --git a/tools/bazel_integration_test/update_deleted_packages.sh b/tools/bazel_integration_test/update_deleted_packages.sh index ce7b05ada7..54db02630f 100755 --- a/tools/bazel_integration_test/update_deleted_packages.sh +++ b/tools/bazel_integration_test/update_deleted_packages.sh @@ -15,11 +15,25 @@ # For integration tests, we want to be able to glob() up the sources inside a nested package # See explanation in .bazelrc +# +# This script ensures that we only delete subtrees that have something a file +# signifying a new bazel workspace, whether it be bzlmod or classic. Generic +# algorithm: +# 1. Get all directories where a WORKSPACE or MODULE.bazel exists. +# 2. For each of the directories, get all directories that contains a BUILD.bazel file. +# 3. Sort and remove duplicates. -set -eux +set -euxo pipefail DIR="$(dirname $0)/../.." +cd $DIR + # The sed -i.bak pattern is compatible between macos and linux sed -i.bak "/^[^#].*--deleted_packages/s#=.*#=$(\ - find examples/*/* tests/*/* \( -name BUILD -or -name BUILD.bazel \) | xargs -n 1 dirname | paste -sd, -\ + find examples/*/* tests/*/* \( -name WORKSPACE -or -name MODULE.bazel \) | + xargs -n 1 dirname | + xargs -n 1 -I{} find {} \( -name BUILD -or -name BUILD.bazel \) | + xargs -n 1 dirname | + sort -u | + paste -sd, -\ )#" $DIR/.bazelrc && rm .bazelrc.bak diff --git a/tools/build_defs/python/tests/base_tests.bzl b/tools/build_defs/python/tests/base_tests.bzl index 715aea7fde..467611fcd8 100644 --- a/tools/build_defs/python/tests/base_tests.bzl +++ b/tools/build_defs/python/tests/base_tests.bzl @@ -15,7 +15,7 @@ load("@rules_testing//lib:analysis_test.bzl", "analysis_test") load("@rules_testing//lib:truth.bzl", "matching") -load("@rules_testing//lib:util.bzl", rt_util = "util") +load("@rules_testing//lib:util.bzl", "PREVENT_IMPLICIT_BUILDING_TAGS", rt_util = "util") load("//python:defs.bzl", "PyInfo") load("//tools/build_defs/python/tests:py_info_subject.bzl", "py_info_subject") load("//tools/build_defs/python/tests:util.bzl", pt_util = "util") @@ -99,5 +99,26 @@ def _test_data_sets_uses_shared_library_impl(env, target): _tests.append(_test_data_sets_uses_shared_library) +def _test_tags_can_be_tuple(name, config): + # We don't use a helper because we want to ensure that value passed is + # a tuple. + config.base_test_rule( + name = name + "_subject", + tags = ("one", "two") + tuple(PREVENT_IMPLICIT_BUILDING_TAGS), + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_tags_can_be_tuple_impl, + ) + +def _test_tags_can_be_tuple_impl(env, target): + env.expect.that_target(target).tags().contains_at_least([ + "one", + "two", + ]) + +_tests.append(_test_tags_can_be_tuple) + def create_base_tests(config): return pt_util.create_tests(_tests, config = config) diff --git a/tools/build_defs/python/tests/py_test/py_test_tests.bzl b/tools/build_defs/python/tests/py_test/py_test_tests.bzl index f2b4875b15..8bb2fc2af0 100644 --- a/tools/build_defs/python/tests/py_test/py_test_tests.bzl +++ b/tools/build_defs/python/tests/py_test/py_test_tests.bzl @@ -22,6 +22,12 @@ load( ) load("//tools/build_defs/python/tests:util.bzl", pt_util = "util") +# Explicit Label() calls are required so that it resolves in @rules_python context instead of +# @rules_testing context. +_FAKE_CC_TOOLCHAIN = Label("//tools/build_defs/python/tests:cc_toolchain_suite") +_PLATFORM_MAC = Label("//tools/build_defs/python/tests:mac") +_PLATFORM_LINUX = Label("//tools/build_defs/python/tests:linux") + _tests = [] def _test_mac_requires_darwin_for_execution(name, config): @@ -44,8 +50,8 @@ def _test_mac_requires_darwin_for_execution(name, config): target = name + "_subject", config_settings = { "//command_line_option:cpu": "darwin_x86_64", - "//command_line_option:crosstool_top": "@rules_python//tools/build_defs/python/tests:cc_toolchain_suite", - #"//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:mac", + "//command_line_option:crosstool_top": _FAKE_CC_TOOLCHAIN, + "//command_line_option:platforms": [_PLATFORM_MAC], }, ) @@ -75,8 +81,8 @@ def _test_non_mac_doesnt_require_darwin_for_execution(name, config): target = name + "_subject", config_settings = { "//command_line_option:cpu": "k8", - "//command_line_option:crosstool_top": "@rules_python//tools/build_defs/python/tests:cc_toolchain_suite", - #"//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:linux", + "//command_line_option:crosstool_top": _FAKE_CC_TOOLCHAIN, + "//command_line_option:platforms": [_PLATFORM_LINUX], }, )