From 727508e66da5e4a79fa0a7017fae919365e4c8c5 Mon Sep 17 00:00:00 2001
From: Greg Roodt
Date: Sun, 28 Aug 2022 19:27:21 +1000
Subject: [PATCH 1/8] Standardise on pip_parse
---
.bazelci/presubmit.yml | 1 -
README.md | 78 +++-----
docs/pip.md | 75 +-------
docs/pip_repository.md | 22 +--
examples/BUILD | 5 -
examples/pip_install/BUILD | 6 +-
examples/pip_install/WORKSPACE | 5 +
examples/pip_install/pip_install_test.py | 24 +--
examples/pip_install/requirements.txt | 8 +-
examples/pip_install/requirements_windows.txt | 6 +-
examples/pip_parse/requirements_lock.txt | 6 +-
examples/pip_parse_vendored/requirements.bzl | 2 +-
examples/pip_parse_vendored/requirements.txt | 2 +-
examples/pip_repository_annotations/BUILD | 2 +-
examples/pip_repository_annotations/WORKSPACE | 8 +-
.../requirements.txt | 2 +-
examples/relative_requirements/BUILD | 10 -
examples/relative_requirements/README.md | 4 -
examples/relative_requirements/WORKSPACE | 21 --
examples/relative_requirements/main.py | 5 -
.../relative_package_name/__init__.py | 2 -
.../relative_package/setup.py | 7 -
.../relative_requirements/requirements.txt | 1 -
python/pip.bzl | 94 ++-------
python/pip_install/extract_wheels/BUILD | 9 -
.../pip_install/extract_wheels/arguments.py | 6 -
.../extract_wheels/extract_single_wheel.py | 29 ++-
.../extract_wheels/extract_wheels.py | 132 -------------
python/pip_install/pip_compile.py | 17 +-
python/pip_install/pip_repository.bzl | 181 +++++++++---------
python/pip_install/private/srcs.bzl | 1 -
python/repositories.bzl | 26 ++-
tests/BUILD | 5 -
tests/pip_deps/BUILD | 19 --
tests/pip_deps/README.md | 1 -
tests/pip_deps/WORKSPACE | 26 ---
tests/pip_deps/pip_deps.bzl | 55 ------
tests/pip_deps/requirements.txt | 136 -------------
tests/pip_deps/test.sh | 4 -
tests/pip_repository_entry_points/WORKSPACE | 8 +-
.../requirements.txt | 6 +-
41 files changed, 247 insertions(+), 810 deletions(-)
delete mode 100644 examples/relative_requirements/BUILD
delete mode 100644 examples/relative_requirements/README.md
delete mode 100644 examples/relative_requirements/WORKSPACE
delete mode 100644 examples/relative_requirements/main.py
delete mode 100644 examples/relative_requirements/relative_package/relative_package_name/__init__.py
delete mode 100644 examples/relative_requirements/relative_package/setup.py
delete mode 100644 examples/relative_requirements/requirements.txt
delete mode 100644 python/pip_install/extract_wheels/extract_wheels.py
delete mode 100644 tests/pip_deps/BUILD
delete mode 100644 tests/pip_deps/README.md
delete mode 100644 tests/pip_deps/WORKSPACE
delete mode 100644 tests/pip_deps/pip_deps.bzl
delete mode 100644 tests/pip_deps/requirements.txt
delete mode 100755 tests/pip_deps/test.sh
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 03687d442c..1cc121a4e7 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -36,6 +36,5 @@ platforms:
- "-//gazelle/..."
# The dependencies needed for this test are not cross-platform: https://github.com/bazelbuild/rules_python/issues/260
- "-//tests:pip_repository_entry_points_example"
- - "-//tests:pip_deps_example"
test_flags:
- "--test_tag_filters=-fix-windows"
\ No newline at end of file
diff --git a/README.md b/README.md
index 7359a2ae4e..e0335241d3 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,7 @@
This repository is the home of the core Python rules -- `py_library`,
`py_binary`, `py_test`, and related symbols that provide the basis for Python
-support in Bazel. It also contains packaging rules for integrating with PyPI
-(`pip`). Documentation lives in the
+support in Bazel. It also contains package installation rules for integrating with PyPI and other package indices. Documentation lives in the
[`docs/`](https://github.com/bazelbuild/rules_python/tree/main/docs)
directory and in the
[Bazel Build Encyclopedia](https://docs.bazel.build/versions/master/be/python.html).
@@ -24,7 +23,7 @@ Once they are fully migrated to rules_python, they may evolve at a different
rate, but this repository will still follow
[semantic versioning](https://semver.org).
-The packaging rules (`pip_install`, etc.) are less stable. We may make breaking
+The package installation rules (`pip_install`, `pip_parse` etc.) are less stable. We may make breaking
changes as they evolve.
This repository is maintained by the Bazel community. Neither Google, nor the
@@ -101,14 +100,14 @@ py_binary(
)
```
-## Using the packaging rules
+## Using the package installation rules
Usage of the packaging rules involves two main steps.
-1. [Installing `pip` dependencies](#installing-pip-dependencies)
-2. [Consuming `pip` dependencies](#consuming-pip-dependencies)
+1. [Installing third_party packages](#installing-third_party-packages)
+2. [Using third_party packages as dependencies](#using-third_party-packages-as-dependencies)
-The packaging rules create two kinds of repositories: A central external repo that holds
+The package installation rules create two kinds of repositories: A central external repo that holds
downloaded wheel files, and individual external repos for each wheel's extracted
contents. Users only need to interact with the central external repo; the wheel repos
are essentially an implementation detail. The central external repo provides a
@@ -116,55 +115,12 @@ are essentially an implementation detail. The central external repo provides a
`BUILD` files that translates a pip package name into the label of a `py_library`
target in the appropriate wheel repo.
-### Installing `pip` dependencies
+### Installing third_party packages
To add pip dependencies to your `WORKSPACE`, load the `pip_install` function, and call it to create the
central external repo and individual wheel external repos.
-```python
-load("@rules_python//python:pip.bzl", "pip_install")
-
-# Create a central external repo, @my_deps, that contains Bazel targets for all the
-# third-party packages specified in the requirements.txt file.
-pip_install(
- name = "my_deps",
- requirements = "//path/to:requirements.txt",
-)
-```
-
-Note that since `pip_install` is a repository rule and therefore executes pip at WORKSPACE-evaluation time, Bazel has no
-information about the Python toolchain and cannot enforce that the interpreter
-used to invoke pip matches the interpreter used to run `py_binary` targets. By
-default, `pip_install` uses the system command `"python3"`. This can be overridden by passing the
-`python_interpreter` attribute or `python_interpreter_target` attribute to `pip_install`.
-
-You can have multiple `pip_install`s in the same workspace. This will create multiple external repos that have no relation to
-one another, and may result in downloading the same wheels multiple times.
-
-As with any repository rule, if you would like to ensure that `pip_install` is
-re-executed in order to pick up a non-hermetic change to your environment (e.g.,
-updating your system `python` interpreter), you can force it to re-execute by running
-`bazel sync --only [pip_install name]`.
-
-### Fetch `pip` dependencies lazily
-
-One pain point with `pip_install` is the need to download all dependencies resolved by
-your requirements.txt before the bazel analysis phase can start. For large python monorepos
-this can take a long time, especially on slow connections.
-
-`pip_parse` provides a solution to this problem. If you can provide a lock
-file of all your python dependencies `pip_parse` will translate each requirement into its own external repository.
-Bazel will only fetch/build wheels for the requirements in the subgraph of your build target.
-
-There are API differences between `pip_parse` and `pip_install`:
-1. `pip_parse` requires a fully resolved lock file of your python dependencies. You can generate this by using the `compile_pip_requirements` rule,
- running `pip-compile` directly, or using virtualenv and `pip freeze`. `pip_parse` uses a label argument called `requirements_lock` instead of
- `requirements` to make this distinction clear.
-2. `pip_parse` translates your requirements into a starlark macro called `install_deps`. You must call this macro in your WORKSPACE to
- declare your dependencies.
-
-
```python
load("@rules_python//python:pip.bzl", "pip_parse")
@@ -174,14 +130,30 @@ pip_parse(
name = "my_deps",
requirements_lock = "//path/to:requirements_lock.txt",
)
-
# Load the starlark macro which will define your dependencies.
load("@my_deps//:requirements.bzl", "install_deps")
# Call it to define repos for your requirements.
install_deps()
```
-### Consuming `pip` dependencies
+Note that since `pip_parse` is a repository rule and therefore executes pip at WORKSPACE-evaluation time, Bazel has no
+information about the Python toolchain and cannot enforce that the interpreter
+used to invoke pip matches the interpreter used to run `py_binary` targets. By
+default, `pip_parse` uses the system command `"python3"`. This can be overridden by passing the
+`python_interpreter` attribute or `python_interpreter_target` attribute to `pip_parse`.
+
+You can have multiple `pip_parse`s in the same workspace. This will create multiple external repos that have no relation to
+one another, and may result in downloading the same wheels multiple times.
+
+As with any repository rule, if you would like to ensure that `pip_parse` is
+re-executed in order to pick up a non-hermetic change to your environment (e.g.,
+updating your system `python` interpreter), you can force it to re-execute by running
+`bazel sync --only [pip_parse name]`.
+
+Note: The `pip_install` rule is deprecated. `pip_parse` offers identical functionality and both `pip_install`
+and `pip_parse` now have the same implementation. The name `pip_install` may be removed in a future version of the rules.
+
+### Using third_party packages as dependencies
Each extracted wheel repo contains a `py_library` target representing
the wheel's contents. There are two ways to access this library. The
diff --git a/docs/pip.md b/docs/pip.md
index 4853e5252d..b302ccfbeb 100644
--- a/docs/pip.md
+++ b/docs/pip.md
@@ -73,70 +73,6 @@ Annotations to apply to the BUILD file content from package generated from a `pi
pip_install(requirements, name, kwargs)
-Accepts a `requirements.txt` file and installs the dependencies listed within.
-
-Those dependencies become available in a generated `requirements.bzl` file.
-
-This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`.
-In your WORKSPACE file:
-
-```python
-pip_install(
- requirements = ":requirements.txt",
-)
-```
-
-You can then reference installed dependencies from a `BUILD` file with:
-
-```python
-load("@pip//:requirements.bzl", "requirement")
-py_library(
- name = "bar",
- ...
- deps = [
- "//my/other:dep",
- requirement("requests"),
- requirement("numpy"),
- ],
-)
-```
-
-> Note that this convenience comes with a cost.
-> Analysis of any BUILD file which loads the requirements helper in this way will
-> cause an eager-fetch of all the pip dependencies,
-> even if no python targets are requested to be built.
-> In a multi-language repo, this may cause developers to fetch dependencies they don't need,
-> so consider using the long form for dependencies if this happens.
-
-In addition to the `requirement` macro, which is used to access the `py_library`
-target generated from a package's wheel, the generated `requirements.bzl` file contains
-functionality for exposing [entry points][whl_ep] as `py_binary` targets.
-
-[whl_ep]: https://packaging.python.org/specifications/entry-points/
-
-```python
-load("@pip_deps//:requirements.bzl", "entry_point")
-
-alias(
- name = "pip-compile",
- actual = entry_point(
- pkg = "pip-tools",
- script = "pip-compile",
- ),
-)
-```
-
-Note that for packages whose name and script are the same, only the name of the package
-is needed when calling the `entry_point` macro.
-
-```python
-load("@pip_deps//:requirements.bzl", "entry_point")
-
-alias(
- name = "flake8",
- actual = entry_point("flake8"),
-)
-```
**PARAMETERS**
@@ -144,9 +80,9 @@ alias(
| Name | Description | Default Value |
| :-------------: | :-------------: | :-------------: |
-| requirements | A 'requirements.txt' pip requirements file. | None |
-| name | A unique name for the created external repository (default 'pip'). | "pip" |
-| kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none |
+| requirements | -
| None |
+| name | -
| "pip" |
+| kwargs | -
| none |
@@ -154,7 +90,7 @@ alias(
## pip_parse
-pip_parse(requirements_lock, name, kwargs)
+pip_parse(requirements, requirements_lock, name, kwargs)
Accepts a locked/compiled requirements file and installs the dependencies listed within.
@@ -247,7 +183,8 @@ See the example in rules_python/examples/pip_parse_vendored.
| Name | Description | Default Value |
| :-------------: | :-------------: | :-------------: |
-| 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'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | none |
+| requirements | Deprecated. See requirements_lock. | 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'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | None |
| name | The name of the generated repository. The generated repositories containing each requirement will be of the form <name>_<requirement-name>. | "pip_parsed_deps" |
| kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none |
diff --git a/docs/pip_repository.md b/docs/pip_repository.md
index c66d8bfd91..9294cf1a5b 100644
--- a/docs/pip_repository.md
+++ b/docs/pip_repository.md
@@ -5,10 +5,10 @@
## pip_repository
-pip_repository(name, annotations, download_only, enable_implicit_namespace_pkgs, environment,
- extra_pip_args, incremental, isolated, pip_data_exclude, python_interpreter,
- python_interpreter_target, quiet, repo_prefix, requirements, requirements_darwin,
- requirements_linux, requirements_lock, requirements_windows, timeout)
+pip_repository(name, annotations, enable_implicit_namespace_pkgs, environment, extra_pip_args,
+ isolated, pip_data_exclude, python_interpreter, python_interpreter_target, quiet,
+ repo_prefix, requirements_darwin, requirements_linux, requirements_lock,
+ requirements_windows, timeout)
A rule for importing `requirements.txt` dependencies into Bazel.
@@ -58,18 +58,15 @@ py_binary(
| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: |
| name | A unique name for this repository. | Name | required | |
| annotations | Optional annotations to apply to packages | Dictionary: String -> String | optional | {} |
-| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False |
| 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 | [] |
-| incremental | Create the repository in incremental mode. | 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 |
| 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 |
| quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True |
-| repo_prefix | Prefix for the generated packages. For non-incremental mode the packages will be of the form
@<name>//<prefix><sanitized-package-name>/...
For incremental mode the packages will be of the form
@<prefix><sanitized-package-name>//... | String | optional | "" |
-| requirements | A 'requirements.txt' pip requirements file. | Label | optional | None |
+| repo_prefix | Prefix for the generated packages will be of the form
@<prefix><sanitized-package-name>//... | String | optional | "" |
| 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 |
@@ -82,9 +79,9 @@ py_binary(
## whl_library
-whl_library(name, annotation, download_only, enable_implicit_namespace_pkgs, environment,
- extra_pip_args, isolated, pip_data_exclude, python_interpreter, python_interpreter_target,
- quiet, repo, repo_prefix, requirement, timeout)
+whl_library(name, annotation, enable_implicit_namespace_pkgs, environment, extra_pip_args, isolated,
+ pip_data_exclude, python_interpreter, python_interpreter_target, quiet, repo, repo_prefix,
+ requirement, timeout)
@@ -98,7 +95,6 @@ Instantiated from pip_repository and inherits config options from there.
| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: |
| name | A unique name for this repository. | Name | required | |
| annotation | Optional json encoded file containing annotation to apply to the extracted wheel. See package_annotation | Label | optional | None |
-| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False |
| 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 | [] |
@@ -108,7 +104,7 @@ Instantiated from pip_repository and inherits config options from there.
| 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 |
| 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_prefix | Prefix for the generated packages. For non-incremental mode the packages will be of the form
@<name>//<prefix><sanitized-package-name>/...
For incremental mode the packages will be of the form
@<prefix><sanitized-package-name>//... | String | optional | "" |
+| repo_prefix | Prefix for the generated packages will be of the form
@<prefix><sanitized-package-name>//... | String | optional | "" |
| requirement | Python requirement string describing the package to make available | String | required | |
| timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 |
diff --git a/examples/BUILD b/examples/BUILD
index 41dd87505a..ee4d7e4861 100644
--- a/examples/BUILD
+++ b/examples/BUILD
@@ -38,11 +38,6 @@ bazel_integration_test(
timeout = "long",
)
-bazel_integration_test(
- name = "relative_requirements_example",
- timeout = "long",
-)
-
bazel_integration_test(
name = "bzlmod_example",
)
diff --git a/examples/pip_install/BUILD b/examples/pip_install/BUILD
index ad983b2f54..35f5a9338a 100644
--- a/examples/pip_install/BUILD
+++ b/examples/pip_install/BUILD
@@ -88,9 +88,9 @@ py_test(
genquery(
name = "yamllint_lib_by_version",
expression = """
- attr("tags", "\\bpypi_version=1.26.3\\b", "@pip//pypi__yamllint")
+ attr("tags", "\\bpypi_version=1.26.3\\b", "@pip_yamllint//:pkg")
intersect
- attr("tags", "\\bpypi_name=yamllint\\b", "@pip//pypi__yamllint")
+ attr("tags", "\\bpypi_name=yamllint\\b", "@pip_yamllint//:pkg")
""",
scope = [requirement("yamllint")],
)
@@ -99,7 +99,7 @@ write_file(
name = "write_expected",
out = "expected",
content = [
- "@pip//pypi__yamllint:pypi__yamllint",
+ "@pip_yamllint//:pkg",
"",
],
)
diff --git a/examples/pip_install/WORKSPACE b/examples/pip_install/WORKSPACE
index 0b33a2b390..f63d928013 100644
--- a/examples/pip_install/WORKSPACE
+++ b/examples/pip_install/WORKSPACE
@@ -57,6 +57,11 @@ pip_install(
requirements = "//:requirements.txt",
)
+load("@pip//:requirements.bzl", "install_deps")
+
+# Initialize repositories for all packages in requirements.txt.
+install_deps()
+
# You could optionally use an in-build, compiled python interpreter as a toolchain,
# and also use it to execute pip.
#
diff --git a/examples/pip_install/pip_install_test.py b/examples/pip_install/pip_install_test.py
index 6092768da6..9fe51fa3a4 100644
--- a/examples/pip_install/pip_install_test.py
+++ b/examples/pip_install/pip_install_test.py
@@ -37,11 +37,11 @@ def test_data(self):
self.assertListEqual(
env.split(" "),
[
- "external/pip/pypi__s3cmd/data/share/doc/packages/s3cmd/INSTALL.md",
- "external/pip/pypi__s3cmd/data/share/doc/packages/s3cmd/LICENSE",
- "external/pip/pypi__s3cmd/data/share/doc/packages/s3cmd/NEWS",
- "external/pip/pypi__s3cmd/data/share/doc/packages/s3cmd/README.md",
- "external/pip/pypi__s3cmd/data/share/man/man1/s3cmd.1",
+ "external/pip_s3cmd/data/share/doc/packages/s3cmd/INSTALL.md",
+ "external/pip_s3cmd/data/share/doc/packages/s3cmd/LICENSE",
+ "external/pip_s3cmd/data/share/doc/packages/s3cmd/NEWS",
+ "external/pip_s3cmd/data/share/doc/packages/s3cmd/README.md",
+ "external/pip_s3cmd/data/share/man/man1/s3cmd.1",
],
)
@@ -51,13 +51,13 @@ def test_dist_info(self):
self.assertListEqual(
env.split(" "),
[
- "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/DESCRIPTION.rst",
- "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/INSTALLER",
- "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/METADATA",
- "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/RECORD",
- "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/WHEEL",
- "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/metadata.json",
- "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/top_level.txt",
+ "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/DESCRIPTION.rst",
+ "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/INSTALLER",
+ "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/METADATA",
+ "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/RECORD",
+ "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/WHEEL",
+ "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/metadata.json",
+ "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/top_level.txt",
],
)
diff --git a/examples/pip_install/requirements.txt b/examples/pip_install/requirements.txt
index db76801f39..8a06da02b6 100644
--- a/examples/pip_install/requirements.txt
+++ b/examples/pip_install/requirements.txt
@@ -7,7 +7,7 @@
boto3==1.14.51 \
--hash=sha256:a6bdb808e948bd264af135af50efb76253e85732c451fa605b7a287faf022432 \
--hash=sha256:f9dbccbcec916051c6588adbccae86547308ac4cd154f1eb7cf6422f0e391a71
- # via -r requirements.in
+ # via -r ./requirements.in
botocore==1.17.63 \
--hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \
--hash=sha256:aa88eafc6295132f4bc606f1df32b3248e0fa611724c0a216aceda767948ac75
@@ -77,7 +77,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
@@ -89,14 +89,14 @@ 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
# The following packages are considered to be unsafe in a requirements file:
setuptools==59.6.0 \
diff --git a/examples/pip_install/requirements_windows.txt b/examples/pip_install/requirements_windows.txt
index 26de1adaac..09a6a83c5d 100644
--- a/examples/pip_install/requirements_windows.txt
+++ b/examples/pip_install/requirements_windows.txt
@@ -7,7 +7,7 @@
boto3==1.14.51 \
--hash=sha256:a6bdb808e948bd264af135af50efb76253e85732c451fa605b7a287faf022432 \
--hash=sha256:f9dbccbcec916051c6588adbccae86547308ac4cd154f1eb7cf6422f0e391a71
- # via -r requirements.in
+ # via -r ./requirements.in
botocore==1.17.63 \
--hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \
--hash=sha256:aa88eafc6295132f4bc606f1df32b3248e0fa611724c0a216aceda767948ac75
@@ -77,7 +77,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
@@ -92,7 +92,7 @@ urllib3==1.25.11 \
# via botocore
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/examples/pip_parse/requirements_lock.txt b/examples/pip_parse/requirements_lock.txt
index d3cb1f5bc9..a54d912d6a 100644
--- a/examples/pip_parse/requirements_lock.txt
+++ b/examples/pip_parse/requirements_lock.txt
@@ -66,11 +66,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
@@ -81,7 +81,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/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl
index 58c6e7bad1..038b612309 100644
--- a/examples/pip_parse_vendored/requirements.bzl
+++ b/examples/pip_parse_vendored/requirements.bzl
@@ -12,7 +12,7 @@ all_requirements = ["@pip_certifi//:pkg", "@pip_charset_normalizer//:pkg", "@pip
all_whl_requirements = ["@pip_certifi//:whl", "@pip_charset_normalizer//:whl", "@pip_idna//:whl", "@pip_requests//:whl", "@pip_urllib3//:whl"]
_packages = [("pip_certifi", "certifi==2021.10.8 --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"), ("pip_charset_normalizer", "charset-normalizer==2.0.12 --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"), ("pip_idna", "idna==3.3 --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"), ("pip_requests", "requests==2.27.1 --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"), ("pip_urllib3", "urllib3==1.26.9 --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e")]
-_config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600}
+_config = {"enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600}
_annotations = {}
def _clean_name(name):
diff --git a/examples/pip_parse_vendored/requirements.txt b/examples/pip_parse_vendored/requirements.txt
index 81b56154c2..d2dfc20576 100644
--- a/examples/pip_parse_vendored/requirements.txt
+++ b/examples/pip_parse_vendored/requirements.txt
@@ -19,7 +19,7 @@ idna==3.3 \
requests==2.27.1 \
--hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \
--hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d
- # via -r requirements.in
+ # via -r ./requirements.in
urllib3==1.26.9 \
--hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 \
--hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e
diff --git a/examples/pip_repository_annotations/BUILD b/examples/pip_repository_annotations/BUILD
index 8c69c40aff..4fd124e6c7 100644
--- a/examples/pip_repository_annotations/BUILD
+++ b/examples/pip_repository_annotations/BUILD
@@ -27,7 +27,7 @@ py_test(
py_test(
name = "pip_install_annotations_test",
srcs = ["pip_repository_annotations_test.py"],
- env = {"WHEEL_PKG_DIR": "pip_installed/pypi__wheel"},
+ env = {"WHEEL_PKG_DIR": "pip_installed_wheel"},
main = "pip_repository_annotations_test.py",
deps = [
requirement("wheel"),
diff --git a/examples/pip_repository_annotations/WORKSPACE b/examples/pip_repository_annotations/WORKSPACE
index 8ee885d468..aeea84207c 100644
--- a/examples/pip_repository_annotations/WORKSPACE
+++ b/examples/pip_repository_annotations/WORKSPACE
@@ -54,9 +54,9 @@ pip_parse(
requirements_lock = "//:requirements.txt",
)
-load("@pip_parsed//:requirements.bzl", "install_deps")
+load("@pip_parsed//:requirements.bzl", install_pip_parse_deps = "install_deps")
-install_deps()
+install_pip_parse_deps()
# For a more thorough example of `pip_install`. See `@rules_python//examples/pip_install`
pip_install(
@@ -65,3 +65,7 @@ pip_install(
python_interpreter_target = interpreter,
requirements = "//:requirements.txt",
)
+
+load("@pip_installed//:requirements.bzl", install_pip_install_deps = "install_deps")
+
+install_pip_install_deps()
diff --git a/examples/pip_repository_annotations/requirements.txt b/examples/pip_repository_annotations/requirements.txt
index e1c53c27e3..a2f161392a 100644
--- a/examples/pip_repository_annotations/requirements.txt
+++ b/examples/pip_repository_annotations/requirements.txt
@@ -9,4 +9,4 @@
wheel==0.37.1 \
--hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a \
--hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4
- # via -r requirements.in
+ # via -r ./requirements.in
diff --git a/examples/relative_requirements/BUILD b/examples/relative_requirements/BUILD
deleted file mode 100644
index d24ee5f72b..0000000000
--- a/examples/relative_requirements/BUILD
+++ /dev/null
@@ -1,10 +0,0 @@
-load("@pip//:requirements.bzl", "requirement")
-load("@rules_python//python:defs.bzl", "py_test")
-
-py_test(
- name = "main",
- srcs = ["main.py"],
- deps = [
- requirement("relative_package_name"),
- ],
-)
diff --git a/examples/relative_requirements/README.md b/examples/relative_requirements/README.md
deleted file mode 100644
index 4b9258e370..0000000000
--- a/examples/relative_requirements/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# relative_requirements example
-
-This example shows how to use pip to fetch relative dependencies from a requirements.txt file,
-then use them in BUILD files as dependencies of Bazel targets.
diff --git a/examples/relative_requirements/WORKSPACE b/examples/relative_requirements/WORKSPACE
deleted file mode 100644
index 4ae91c39d8..0000000000
--- a/examples/relative_requirements/WORKSPACE
+++ /dev/null
@@ -1,21 +0,0 @@
-workspace(name = "example_repo")
-
-local_repository(
- name = "rules_python",
- path = "../..",
-)
-
-load("@rules_python//python:repositories.bzl", "python_register_toolchains")
-
-python_register_toolchains(
- name = "python39",
- python_version = "3.9",
-)
-
-load("@python39//:defs.bzl", "interpreter")
-load("@rules_python//python:pip.bzl", "pip_install")
-
-pip_install(
- python_interpreter_target = interpreter,
- requirements = "//:requirements.txt",
-)
diff --git a/examples/relative_requirements/main.py b/examples/relative_requirements/main.py
deleted file mode 100644
index b8ac021e90..0000000000
--- a/examples/relative_requirements/main.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import relative_package_name
-
-if __name__ == "__main__":
- # Run a function from the relative package
- print(relative_package_name.test())
diff --git a/examples/relative_requirements/relative_package/relative_package_name/__init__.py b/examples/relative_requirements/relative_package/relative_package_name/__init__.py
deleted file mode 100644
index c031192907..0000000000
--- a/examples/relative_requirements/relative_package/relative_package_name/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-def test():
- return True
diff --git a/examples/relative_requirements/relative_package/setup.py b/examples/relative_requirements/relative_package/setup.py
deleted file mode 100644
index 052b519345..0000000000
--- a/examples/relative_requirements/relative_package/setup.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from setuptools import setup
-
-setup(
- name="relative_package_name",
- version="1.0.0",
- packages=["relative_package_name"],
-)
diff --git a/examples/relative_requirements/requirements.txt b/examples/relative_requirements/requirements.txt
deleted file mode 100644
index 9a81317e1e..0000000000
--- a/examples/relative_requirements/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-./relative_package
diff --git a/python/pip.bzl b/python/pip.bzl
index 954317f4b7..2419660b5f 100644
--- a/python/pip.bzl
+++ b/python/pip.bzl
@@ -21,88 +21,11 @@ compile_pip_requirements = _compile_pip_requirements
package_annotation = _package_annotation
def pip_install(requirements = None, name = "pip", **kwargs):
- """Accepts a `requirements.txt` file and installs the dependencies listed within.
+ # pip_install is now considered deprecated.
+ # In future, this may log a warning and eventually be removed.
+ pip_parse(requirements = requirements, name = name, **kwargs)
- Those dependencies become available in a generated `requirements.bzl` file.
-
- This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`.
- In your WORKSPACE file:
-
- ```python
- pip_install(
- requirements = ":requirements.txt",
- )
- ```
-
- You can then reference installed dependencies from a `BUILD` file with:
-
- ```python
- load("@pip//:requirements.bzl", "requirement")
- py_library(
- name = "bar",
- ...
- deps = [
- "//my/other:dep",
- requirement("requests"),
- requirement("numpy"),
- ],
- )
- ```
-
- > Note that this convenience comes with a cost.
- > Analysis of any BUILD file which loads the requirements helper in this way will
- > cause an eager-fetch of all the pip dependencies,
- > even if no python targets are requested to be built.
- > In a multi-language repo, this may cause developers to fetch dependencies they don't need,
- > so consider using the long form for dependencies if this happens.
-
- In addition to the `requirement` macro, which is used to access the `py_library`
- target generated from a package's wheel, the generated `requirements.bzl` file contains
- functionality for exposing [entry points][whl_ep] as `py_binary` targets.
-
- [whl_ep]: https://packaging.python.org/specifications/entry-points/
-
- ```python
- load("@pip_deps//:requirements.bzl", "entry_point")
-
- alias(
- name = "pip-compile",
- actual = entry_point(
- pkg = "pip-tools",
- script = "pip-compile",
- ),
- )
- ```
-
- Note that for packages whose name and script are the same, only the name of the package
- is needed when calling the `entry_point` macro.
-
- ```python
- load("@pip_deps//:requirements.bzl", "entry_point")
-
- alias(
- name = "flake8",
- actual = entry_point("flake8"),
- )
- ```
-
- Args:
- requirements (Label): A 'requirements.txt' pip requirements file.
- name (str, optional): A unique name for the created external repository (default 'pip').
- **kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule.
- """
-
- # Just in case our dependencies weren't already fetched
- pip_install_dependencies()
-
- pip_repository(
- name = name,
- requirements = requirements,
- repo_prefix = "pypi__",
- **kwargs
- )
-
-def pip_parse(requirements_lock, name = "pip_parsed_deps", **kwargs):
+def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_deps", **kwargs):
"""Accepts a locked/compiled requirements file and installs the dependencies listed within.
Those dependencies become available in a generated `requirements.bzl` file.
@@ -195,6 +118,7 @@ def pip_parse(requirements_lock, name = "pip_parsed_deps", **kwargs):
fetched/built only for the targets specified by 'build/run/test'.
Note that if your lockfile is platform-dependent, you can use the `requirements_[platform]`
attributes.
+ requirements (Label): Deprecated. See requirements_lock.
name (str, optional): The name of the generated repository. The generated repositories
containing each requirement will be of the form _.
**kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule.
@@ -203,10 +127,14 @@ def pip_parse(requirements_lock, name = "pip_parsed_deps", **kwargs):
# Just in case our dependencies weren't already fetched
pip_install_dependencies()
+ # Temporary compatibility shim
+ # pip_install was previously document to use requirements while pip_parse was using requirements_lock
+ # We would prefer everyone move to using requirements_lock, but we maintain a temporary shim
+ reqs_to_use = requirements_lock if requirements_lock else requirements
+
pip_repository(
name = name,
- requirements_lock = requirements_lock,
+ requirements_lock = reqs_to_use,
repo_prefix = "{}_".format(name),
- incremental = True,
**kwargs
)
diff --git a/python/pip_install/extract_wheels/BUILD b/python/pip_install/extract_wheels/BUILD
index 158d34ba27..bc11885026 100644
--- a/python/pip_install/extract_wheels/BUILD
+++ b/python/pip_install/extract_wheels/BUILD
@@ -9,7 +9,6 @@ py_library(
"arguments.py",
"bazel.py",
"extract_single_wheel.py",
- "extract_wheels.py",
"namespace_pkgs.py",
"parse_requirements_to_bzl.py",
"requirements.py",
@@ -21,14 +20,6 @@ py_library(
],
)
-py_binary(
- name = "extract_wheels",
- srcs = [
- "extract_wheels.py",
- ],
- deps = [":lib"],
-)
-
py_binary(
name = "extract_single_wheel",
srcs = [
diff --git a/python/pip_install/extract_wheels/arguments.py b/python/pip_install/extract_wheels/arguments.py
index ce77bb028e..d7d34523a7 100644
--- a/python/pip_install/extract_wheels/arguments.py
+++ b/python/pip_install/extract_wheels/arguments.py
@@ -39,12 +39,6 @@ def parse_common_args(parser: ArgumentParser) -> ArgumentParser:
required=True,
help="Prefix to prepend to packages",
)
- parser.add_argument(
- "--download_only",
- action="store_true",
- help="Use 'pip download' instead of 'pip wheel'. Disables building wheels from source, but allows use of "
- "--platform, --python-version, --implementation, and --abi in --extra_pip_args.",
- )
return parser
diff --git a/python/pip_install/extract_wheels/extract_single_wheel.py b/python/pip_install/extract_wheels/extract_single_wheel.py
index a7cc672a76..1160dbf98d 100644
--- a/python/pip_install/extract_wheels/extract_single_wheel.py
+++ b/python/pip_install/extract_wheels/extract_single_wheel.py
@@ -8,11 +8,32 @@
from python.pip_install.extract_wheels import arguments, bazel, requirements
from python.pip_install.extract_wheels.annotation import annotation_from_str_path
-from python.pip_install.extract_wheels.extract_wheels import (
- configure_reproducible_wheels,
-)
+def configure_reproducible_wheels() -> None:
+ """Modifies the environment to make wheel building reproducible.
+ Wheels created from sdists are not reproducible by default. We can however workaround this by
+ patching in some configuration with environment variables.
+ """
+
+ # wheel, by default, enables debug symbols in GCC. This incidentally captures the build path in the .so file
+ # We can override this behavior by disabling debug symbols entirely.
+ # https://github.com/pypa/pip/issues/6505
+ if "CFLAGS" in os.environ:
+ os.environ["CFLAGS"] += " -g0"
+ else:
+ os.environ["CFLAGS"] = "-g0"
+
+ # set SOURCE_DATE_EPOCH to 1980 so that we can use python wheels
+ # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md#python-setuppy-bdist_wheel-cannot-create-whl
+ if "SOURCE_DATE_EPOCH" not in os.environ:
+ os.environ["SOURCE_DATE_EPOCH"] = "315532800"
+
+ # Python wheel metadata files can be unstable.
+ # See https://bitbucket.org/pypa/wheel/pull-requests/74/make-the-output-of-metadata-files/diff
+ if "PYTHONHASHSEED" not in os.environ:
+ os.environ["PYTHONHASHSEED"] = "0"
+
def main() -> None:
parser = argparse.ArgumentParser(
description="Build and/or fetch a single wheel based on the requirement passed in"
@@ -38,7 +59,7 @@ def main() -> None:
pip_args = (
[sys.executable, "-m", "pip"]
+ (["--isolated"] if args.isolated else [])
- + ["download" if args.download_only else "wheel", "--no-deps"]
+ + ["wheel", "--no-deps"]
+ deserialized_args["extra_pip_args"]
)
diff --git a/python/pip_install/extract_wheels/extract_wheels.py b/python/pip_install/extract_wheels/extract_wheels.py
deleted file mode 100644
index 2addaf89fd..0000000000
--- a/python/pip_install/extract_wheels/extract_wheels.py
+++ /dev/null
@@ -1,132 +0,0 @@
-"""extract_wheels
-
-extract_wheels resolves and fetches artifacts transitively from the Python Package Index (PyPI) based on a
-requirements.txt. It generates the required BUILD files to consume these packages as Python libraries.
-
-Under the hood, it depends on the `pip wheel` command to do resolution, download, and compilation into wheels.
-"""
-import argparse
-import glob
-import os
-import pathlib
-import subprocess
-import sys
-
-from python.pip_install.extract_wheels import (
- annotation,
- arguments,
- bazel,
- requirements,
- wheel,
-)
-
-
-def configure_reproducible_wheels() -> None:
- """Modifies the environment to make wheel building reproducible.
-
- Wheels created from sdists are not reproducible by default. We can however workaround this by
- patching in some configuration with environment variables.
- """
-
- # wheel, by default, enables debug symbols in GCC. This incidentally captures the build path in the .so file
- # We can override this behavior by disabling debug symbols entirely.
- # https://github.com/pypa/pip/issues/6505
- if "CFLAGS" in os.environ:
- os.environ["CFLAGS"] += " -g0"
- else:
- os.environ["CFLAGS"] = "-g0"
-
- # set SOURCE_DATE_EPOCH to 1980 so that we can use python wheels
- # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md#python-setuppy-bdist_wheel-cannot-create-whl
- if "SOURCE_DATE_EPOCH" not in os.environ:
- os.environ["SOURCE_DATE_EPOCH"] = "315532800"
-
- # Python wheel metadata files can be unstable.
- # See https://bitbucket.org/pypa/wheel/pull-requests/74/make-the-output-of-metadata-files/diff
- if "PYTHONHASHSEED" not in os.environ:
- os.environ["PYTHONHASHSEED"] = "0"
-
-
-def main() -> None:
- """Main program.
-
- Exits zero on successful program termination, non-zero otherwise.
- """
-
- configure_reproducible_wheels()
-
- parser = argparse.ArgumentParser(
- description="Resolve and fetch artifacts transitively from PyPI"
- )
- parser.add_argument(
- "--requirements",
- action="store",
- required=True,
- help="Path to requirements.txt from where to install dependencies",
- )
- parser.add_argument(
- "--annotations",
- type=annotation.annotations_map_from_str_path,
- help="A json encoded file containing annotations for rendered packages.",
- )
- arguments.parse_common_args(parser)
- args = parser.parse_args()
- deserialized_args = dict(vars(args))
- arguments.deserialize_structured_args(deserialized_args)
-
- # Pip is run with the working directory changed to the folder containing the requirements.txt file, to allow for
- # relative requirements to be correctly resolved. The --wheel-dir is therefore required to be repointed back to the
- # current calling working directory (the repo root in .../external/name), where the wheel files should be written to
- pip_args = (
- [sys.executable, "-m", "pip"]
- + (["--isolated"] if args.isolated else [])
- + ["download" if args.download_only else "wheel", "-r", args.requirements]
- + ["--wheel-dir", os.getcwd()]
- + deserialized_args["extra_pip_args"]
- )
-
- env = os.environ.copy()
- env.update(deserialized_args["environment"])
-
- # Assumes any errors are logged by pip so do nothing. This command will fail if pip fails
- subprocess.run(
- pip_args,
- check=True,
- env=env,
- cwd=str(pathlib.Path(args.requirements).parent.resolve()),
- )
-
- extras = requirements.parse_extras(args.requirements)
-
- repo_label = "@%s" % args.repo
-
- # Locate all wheels
- wheels = [whl for whl in glob.glob("*.whl")]
-
- # Collect all annotations
- reqs = {whl: wheel.Wheel(whl).name for whl in wheels}
- annotations = args.annotations.collect(reqs.values())
-
- targets = [
- '"{}{}"'.format(
- repo_label,
- bazel.extract_wheel(
- wheel_file=whl,
- extras=extras,
- pip_data_exclude=deserialized_args["pip_data_exclude"],
- enable_implicit_namespace_pkgs=args.enable_implicit_namespace_pkgs,
- repo_prefix=args.repo_prefix,
- annotation=annotations.get(name),
- ),
- )
- for whl, name in reqs.items()
- ]
-
- with open("requirements.bzl", "w") as requirement_file:
- requirement_file.write(
- bazel.generate_requirements_file_contents(repo_label, targets)
- )
-
-
-if __name__ == "__main__":
- main()
diff --git a/python/pip_install/pip_compile.py b/python/pip_install/pip_compile.py
index 09b3c9b035..09f07fefd5 100644
--- a/python/pip_install/pip_compile.py
+++ b/python/pip_install/pip_compile.py
@@ -35,20 +35,11 @@ def _select_golden_requirements_file(
parse_str_none = lambda s: None if s == "None" else s
- requirements_in = os.path.relpath(sys.argv.pop(1))
- requirements_txt = os.path.relpath(sys.argv.pop(1))
+ requirements_in = sys.argv.pop(1)
+ requirements_txt = sys.argv.pop(1)
requirements_linux = parse_str_none(sys.argv.pop(1))
requirements_darwin = parse_str_none(sys.argv.pop(1))
requirements_windows = parse_str_none(sys.argv.pop(1))
- parts = requirements_in.split(os.path.sep, 2)
- if parts[0] == "external":
- requirements_in = parts[2]
- requirements_txt = (
- requirements_txt
- if "BUILD_WORKSPACE_DIRECTORY" in os.environ
- else os.path.join("..", "..", requirements_txt)
- )
- os.chdir(os.path.join(parts[0], parts[1]))
update_target_label = sys.argv.pop(1)
# Before loading click, set the locale for its parser.
@@ -83,9 +74,7 @@ def _select_golden_requirements_file(
#
# Changing to the WORKSPACE root avoids 'file not found' errors when the `.update` target is run
# from different directories within the WORKSPACE.
- requirements_txt = os.path.join(
- os.environ["BUILD_WORKSPACE_DIRECTORY"], requirements_txt
- )
+ os.chdir(os.environ["BUILD_WORKSPACE_DIRECTORY"])
else:
err_msg = (
"Expected to find BUILD_WORKSPACE_DIRECTORY (running under `bazel run`) or "
diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl
index eab59f35cd..2f5e9f7e35 100644
--- a/python/pip_install/pip_repository.bzl
+++ b/python/pip_install/pip_repository.bzl
@@ -1,6 +1,6 @@
""
-load("//python:repositories.bzl", "STANDALONE_INTERPRETER_FILENAME")
+load("//python:repositories.bzl", "is_standalone_interpreter")
load("//python/pip_install:repositories.bzl", "all_requirements")
load("//python/pip_install/private:srcs.bzl", "PIP_INSTALL_PY_SRCS")
@@ -66,35 +66,68 @@ def _resolve_python_interpreter(rctx):
fail("python interpreter `{}` not found in PATH".format(python_interpreter))
return python_interpreter
-def _maybe_set_xcode_location_cflags(rctx, environment):
- """Patch environment with CPPFLAGS of xcode sdk location.
+def _get_xcode_location_cflags(rctx):
+ """Query the xcode sdk location to update cflags
Figure out if this interpreter target comes from rules_python, and patch the xcode sdk location if so.
Pip won't be able to compile c extensions from sdists with the pre built python distributions from indygreg
otherwise. See https://github.com/indygreg/python-build-standalone/issues/103
"""
- if (
- rctx.os.name.lower().startswith("mac os") and
- rctx.attr.python_interpreter_target != None and
- # This is a rules_python provided toolchain.
- rctx.execute([
- "ls",
- "{}/{}".format(
- rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname,
- STANDALONE_INTERPRETER_FILENAME,
- ),
- ]).return_code == 0 and
- not environment.get(CPPFLAGS)
- ):
- xcode_sdk_location = rctx.execute(["xcode-select", "--print-path"])
- if xcode_sdk_location.return_code == 0:
- xcode_root = xcode_sdk_location.stdout.strip()
- if COMMAND_LINE_TOOLS_PATH_SLUG not in xcode_root.lower():
- # This is a full xcode installation somewhere like /Applications/Xcode13.0.app/Contents/Developer
- # so we need to change the path to to the macos specific tools which are in a different relative
- # path than xcode installed command line tools.
- xcode_root = "{}/Platforms/MacOSX.platform/Developer".format(xcode_root)
- environment[CPPFLAGS] = "-isysroot {}/SDKs/MacOSX.sdk".format(xcode_root)
+
+ # Only run on MacOS hosts
+ if not rctx.os.name.lower().startswith("mac os"):
+ return []
+
+ # Only update the location when using a hermetic toolchain.
+ if not is_standalone_interpreter(rctx, rctx.attr.python_interpreter_target):
+ return []
+
+ # Locate xcode-select
+ xcode_select = rctx.which("xcode-select")
+
+ xcode_sdk_location = rctx.execute([xcode_select, "--print-path"])
+ if xcode_sdk_location.return_code != 0:
+ return []
+
+ xcode_root = xcode_sdk_location.stdout.strip()
+ if COMMAND_LINE_TOOLS_PATH_SLUG not in xcode_root.lower():
+ # This is a full xcode installation somewhere like /Applications/Xcode13.0.app/Contents/Developer
+ # so we need to change the path to to the macos specific tools which are in a different relative
+ # path than xcode installed command line tools.
+ xcode_root = "{}/Platforms/MacOSX.platform/Developer".format(xcode_root)
+ return [
+ "-isysroot {}/SDKs/MacOSX.sdk".format(xcode_root),
+ ]
+
+def _get_toolchain_unix_cflags(rctx):
+ """Gather cflags from a standalone toolchain for unix systems.
+
+ Pip won't be able to compile c extensions from sdists with the pre built python distributions from indygreg
+ otherwise. See https://github.com/indygreg/python-build-standalone/issues/103
+ """
+
+ # Only run on Unix systems
+ if not rctx.os.name.lower().startswith(("mac os", "linux")):
+ return []
+
+ # Only update the location when using a standalone toolchain.
+ if not is_standalone_interpreter(rctx, rctx.attr.python_interpreter_target):
+ return []
+
+ er = rctx.execute([
+ rctx.path(rctx.attr.python_interpreter_target).realpath,
+ "-c",
+ "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}')",
+ ])
+ if er.return_code != 0:
+ fail("could not get python version from interpreter (status {}): {}".format(er.return_code, er.stderr))
+ _python_version = er.stdout
+ include_path = "{}/include/python{}".format(
+ rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname.realpath,
+ _python_version,
+ )
+
+ return ["-isystem {}".format(include_path)]
def _parse_optional_attrs(rctx, args):
"""Helper function to parse common attributes of pip_repository and whl_library repository rules.
@@ -130,9 +163,6 @@ def _parse_optional_attrs(rctx, args):
struct(arg = rctx.attr.extra_pip_args).to_json(),
]
- if rctx.attr.download_only:
- args.append("--download_only")
-
if rctx.attr.pip_data_exclude != None:
args += [
"--pip_data_exclude",
@@ -155,10 +185,20 @@ def _create_repository_execution_environment(rctx):
Args:
rctx: The repository context.
- Returns: Dictionary of envrionment variable suitable to pass to rctx.execute.
+ Returns:
+ Dictionary of environment variable suitable to pass to rctx.execute.
"""
- env = {"PYTHONPATH": _construct_pypath(rctx)}
- _maybe_set_xcode_location_cflags(rctx, env)
+
+ # Gather any available CPPFLAGS values
+ cppflags = []
+ cppflags.extend(_get_xcode_location_cflags(rctx))
+ cppflags.extend(_get_toolchain_unix_cflags(rctx))
+
+ env = {
+ "PYTHONPATH": _construct_pypath(rctx),
+ CPPFLAGS: " ".join(cppflags),
+ }
+
return env
_BUILD_FILE_CONTENTS = """\
@@ -179,8 +219,7 @@ def _locked_requirements(rctx):
requirements_txt = rctx.attr.requirements_windows
if not requirements_txt:
fail("""\
-Incremental mode requires a requirements_lock attribute be specified,
-or a platform-specific lockfile using one of the requirements_* attributes.
+A requirements_lock attribute must be specified, or a platform-specific lockfile using one of the requirements_* attributes.
""")
return requirements_txt
@@ -192,40 +231,28 @@ def _pip_repository_impl(rctx):
annotations_file = rctx.path("annotations.json")
rctx.file(annotations_file, json.encode_indent(annotations, indent = " " * 4))
- if rctx.attr.incremental:
- requirements_txt = _locked_requirements(rctx)
- args = [
- python_interpreter,
- "-m",
- "python.pip_install.extract_wheels.parse_requirements_to_bzl",
- "--requirements_lock",
- rctx.path(requirements_txt),
- "--requirements_lock_label",
- str(requirements_txt),
- # pass quiet and timeout args through to child repos.
- "--quiet",
- str(rctx.attr.quiet),
- "--timeout",
- str(rctx.attr.timeout),
- "--annotations",
- annotations_file,
- ]
+ requirements_txt = _locked_requirements(rctx)
+ args = [
+ python_interpreter,
+ "-m",
+ "python.pip_install.extract_wheels.parse_requirements_to_bzl",
+ "--requirements_lock",
+ rctx.path(requirements_txt),
+ "--requirements_lock_label",
+ str(requirements_txt),
+ # pass quiet and timeout args through to child repos.
+ "--quiet",
+ str(rctx.attr.quiet),
+ "--timeout",
+ str(rctx.attr.timeout),
+ "--annotations",
+ annotations_file,
+ ]
- args += ["--python_interpreter", _get_python_interpreter_attr(rctx)]
- if rctx.attr.python_interpreter_target:
- args += ["--python_interpreter_target", str(rctx.attr.python_interpreter_target)]
- progress_message = "Parsing requirements to starlark"
- else:
- args = [
- python_interpreter,
- "-m",
- "python.pip_install.extract_wheels.extract_wheels",
- "--requirements",
- rctx.path(rctx.attr.requirements),
- "--annotations",
- annotations_file,
- ]
- progress_message = "Extracting wheels"
+ args += ["--python_interpreter", _get_python_interpreter_attr(rctx)]
+ if rctx.attr.python_interpreter_target:
+ args += ["--python_interpreter_target", str(rctx.attr.python_interpreter_target)]
+ progress_message = "Parsing requirements to starlark"
args += ["--repo", rctx.attr.name, "--repo-prefix", rctx.attr.repo_prefix]
args = _parse_optional_attrs(rctx, args)
@@ -253,13 +280,6 @@ common_env = [
]
common_attrs = {
- "download_only": attr.bool(
- doc = """
-Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of
---platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different
-platform from the host platform.
- """,
- ),
"enable_implicit_namespace_pkgs": attr.bool(
default = False,
doc = """
@@ -318,12 +338,7 @@ python_interpreter.
),
"repo_prefix": attr.string(
doc = """
-Prefix for the generated packages. For non-incremental mode the
-packages will be of the form
-
-@///...
-
-For incremental mode the packages will be of the form
+Prefix for the generated packages will be of the form
@//...
""",
@@ -344,14 +359,6 @@ pip_repository_attrs = {
"annotations": attr.string_dict(
doc = "Optional annotations to apply to packages",
),
- "incremental": attr.bool(
- default = False,
- doc = "Create the repository in incremental mode.",
- ),
- "requirements": attr.label(
- allow_single_file = True,
- doc = "A 'requirements.txt' pip requirements file.",
- ),
"requirements_darwin": attr.label(
allow_single_file = True,
doc = "Override the requirements_lock attribute when the host platform is Mac OS",
diff --git a/python/pip_install/private/srcs.bzl b/python/pip_install/private/srcs.bzl
index bdd76b17d4..e42bb8e5ed 100644
--- a/python/pip_install/private/srcs.bzl
+++ b/python/pip_install/private/srcs.bzl
@@ -12,7 +12,6 @@ PIP_INSTALL_PY_SRCS = [
"@rules_python//python/pip_install/extract_wheels:arguments.py",
"@rules_python//python/pip_install/extract_wheels:bazel.py",
"@rules_python//python/pip_install/extract_wheels:extract_single_wheel.py",
- "@rules_python//python/pip_install/extract_wheels:extract_wheels.py",
"@rules_python//python/pip_install/extract_wheels:namespace_pkgs.py",
"@rules_python//python/pip_install/extract_wheels:parse_requirements_to_bzl.py",
"@rules_python//python/pip_install/extract_wheels:requirements.py",
diff --git a/python/repositories.bzl b/python/repositories.bzl
index f897904e70..dc2c49e722 100644
--- a/python/repositories.bzl
+++ b/python/repositories.bzl
@@ -37,6 +37,30 @@ def py_repositories():
STANDALONE_INTERPRETER_FILENAME = "STANDALONE_INTERPRETER"
+def is_standalone_interpreter(rctx, python_interpreter_target):
+ """Query a python interpreter target for whether or not it's a rules_rust provided toolchain
+
+ Args:
+ rctx (repository_ctx): The repository rule's context object.
+ python_interpreter_target (Target): A target representing a python interpreter.
+
+ Returns:
+ bool: Whether or not the target is from a rules_python generated toolchain.
+ """
+
+ # Only update the location when using a hermetic toolchain.
+ if not python_interpreter_target:
+ return False
+
+ # This is a rules_python provided toolchain.
+ return rctx.execute([
+ "ls",
+ "{}/{}".format(
+ rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname,
+ STANDALONE_INTERPRETER_FILENAME,
+ ),
+ ]).return_code == 0
+
def _python_repository_impl(rctx):
if rctx.attr.distutils and rctx.attr.distutils_content:
fail("Only one of (distutils, distutils_content) should be set.")
@@ -117,7 +141,7 @@ def _python_repository_impl(rctx):
exec_result.stderr,
)
fail(fail_msg)
- exec_result = rctx.execute(["touch", "lib/.test"])
+ exec_result = rctx.execute(["touch", "{}/.test".format(lib_dir)])
if exec_result.return_code == 0:
exec_result = rctx.execute(["id", "-u"])
if exec_result.return_code != 0:
diff --git a/tests/BUILD b/tests/BUILD
index 46d8739622..b37a5a4232 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -8,8 +8,3 @@ bazel_integration_test(
name = "pip_repository_entry_points_example",
timeout = "long",
)
-
-bazel_integration_test(
- name = "pip_deps_example",
- timeout = "long",
-)
diff --git a/tests/pip_deps/BUILD b/tests/pip_deps/BUILD
deleted file mode 100644
index 6a0412c718..0000000000
--- a/tests/pip_deps/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-filegroup(
- name = "requirements_txt",
- srcs = ["requirements.txt"],
- visibility = ["//visibility:public"],
-)
-
-test_suite(
- name = "external_tests",
- tests = [
- "@unpinned_pip//:pin_test",
- ],
-)
-
-sh_test(
- name = "no_external_test",
- srcs = ["test.sh"],
- args = ["$(rootpath :requirements_txt)"],
- data = [":requirements_txt"],
-)
diff --git a/tests/pip_deps/README.md b/tests/pip_deps/README.md
deleted file mode 100644
index d9151baf11..0000000000
--- a/tests/pip_deps/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Run `bazel run @unpinned_pip//:pin.update` to keep `PIP_PACKAGES` in `//:WORKSPACE` in sync with `//:requirements.txt`.
diff --git a/tests/pip_deps/WORKSPACE b/tests/pip_deps/WORKSPACE
deleted file mode 100644
index 83ecf85e37..0000000000
--- a/tests/pip_deps/WORKSPACE
+++ /dev/null
@@ -1,26 +0,0 @@
-workspace(name = "pip_deps")
-
-local_repository(
- name = "rules_python",
- path = "../..",
-)
-
-load("@rules_python//python:repositories.bzl", "python_register_toolchains")
-
-# This toolchain is explicitly 3.10 while `rules_python` is 3.9 to act as
-# a regression test, ensuring 3.10 is functional
-python_register_toolchains(
- name = "python310",
- python_version = "3.10",
-)
-
-load("@python310//:defs.bzl", "interpreter")
-load("//:pip_deps.bzl", "pip_deps")
-
-PIP_PACKAGES = {"sphinx": "4.5.0"}
-
-pip_deps(
- name = "pip",
- packages = PIP_PACKAGES,
- python_interpreter_target = interpreter,
-)
diff --git a/tests/pip_deps/pip_deps.bzl b/tests/pip_deps/pip_deps.bzl
deleted file mode 100644
index 93426a6911..0000000000
--- a/tests/pip_deps/pip_deps.bzl
+++ /dev/null
@@ -1,55 +0,0 @@
-""" A demo implementation for pip_deps which provides @unpinned_pip//:pin. """
-
-load("@rules_python//python:pip.bzl", "pip_parse")
-
-def _requirements_in_impl(repository_ctx):
- repository_ctx.file(
- "requirements.in",
- content = "".join(["{package} == {version}\n".format(
- package = package,
- version = version,
- ) for (package, version) in repository_ctx.attr.packages.items()]),
- )
- repository_ctx.file("WORKSPACE", content = "")
- repository_ctx.file("BUILD", content = """
-load("@rules_python//python:pip.bzl", "compile_pip_requirements")
-
-compile_pip_requirements(
- name = "pin",
- extra_args = ["--allow-unsafe"],
- requirements_in = "requirements.in",
- requirements_txt = "@{workspace_name}//{package}:{name}",
-)
-""".format(
- workspace_name = repository_ctx.attr.requirements_lock.workspace_name,
- package = repository_ctx.attr.requirements_lock.package,
- name = repository_ctx.attr.requirements_lock.name,
- ))
-
-_requirements_in = repository_rule(
- implementation = _requirements_in_impl,
- attrs = {
- "packages": attr.string_dict(),
- "requirements_lock": attr.label(allow_single_file = True),
- },
-)
-
-def pip_deps(
- *,
- name = "pip",
- packages = {},
- requirements_lock_target = Label("//:requirements_txt"),
- requirements_lock_file = Label("//:requirements.txt"),
- python_interpreter_target = None,
- **kwargs):
- _requirements_in(
- name = "unpinned_" + name,
- packages = packages,
- requirements_lock = requirements_lock_target,
- )
- pip_parse(
- name = name,
- requirements_lock = requirements_lock_file,
- python_interpreter_target = python_interpreter_target,
- **kwargs
- )
diff --git a/tests/pip_deps/requirements.txt b/tests/pip_deps/requirements.txt
deleted file mode 100644
index d5fa9e7254..0000000000
--- a/tests/pip_deps/requirements.txt
+++ /dev/null
@@ -1,136 +0,0 @@
-#
-# This file is autogenerated by pip-compile with python 3.10
-# To update, run:
-#
-# bazel run //:pin.update
-#
-alabaster==0.7.12 \
- --hash=sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359 \
- --hash=sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02
- # via sphinx
-babel==2.10.1 \
- --hash=sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2 \
- --hash=sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13
- # via sphinx
-certifi==2021.10.8 \
- --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \
- --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569
- # via requests
-charset-normalizer==2.0.12 \
- --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 \
- --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df
- # via requests
-docutils==0.17.1 \
- --hash=sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125 \
- --hash=sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61
- # via sphinx
-idna==3.3 \
- --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff \
- --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d
- # via requests
-imagesize==1.3.0 \
- --hash=sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c \
- --hash=sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d
- # via sphinx
-jinja2==3.1.2 \
- --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \
- --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
- # via sphinx
-markupsafe==2.1.1 \
- --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \
- --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \
- --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \
- --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \
- --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \
- --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \
- --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \
- --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \
- --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \
- --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \
- --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \
- --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \
- --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \
- --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \
- --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \
- --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \
- --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \
- --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \
- --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \
- --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \
- --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \
- --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \
- --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \
- --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \
- --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \
- --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \
- --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \
- --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \
- --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \
- --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \
- --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \
- --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \
- --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \
- --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \
- --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \
- --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \
- --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \
- --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \
- --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \
- --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7
- # via jinja2
-packaging==21.3 \
- --hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \
- --hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522
- # via sphinx
-pygments==2.12.0 \
- --hash=sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb \
- --hash=sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519
- # via sphinx
-pyparsing==3.0.8 \
- --hash=sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954 \
- --hash=sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06
- # via packaging
-pytz==2022.1 \
- --hash=sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7 \
- --hash=sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c
- # via babel
-requests==2.27.1 \
- --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \
- --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d
- # via sphinx
-snowballstemmer==2.2.0 \
- --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \
- --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a
- # via sphinx
-sphinx==4.5.0 \
- --hash=sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6 \
- --hash=sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226
- # via -r requirements.in
-sphinxcontrib-applehelp==1.0.2 \
- --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \
- --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58
- # via sphinx
-sphinxcontrib-devhelp==1.0.2 \
- --hash=sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e \
- --hash=sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4
- # via sphinx
-sphinxcontrib-htmlhelp==2.0.0 \
- --hash=sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07 \
- --hash=sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2
- # via sphinx
-sphinxcontrib-jsmath==1.0.1 \
- --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \
- --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8
- # via sphinx
-sphinxcontrib-qthelp==1.0.3 \
- --hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \
- --hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6
- # via sphinx
-sphinxcontrib-serializinghtml==1.1.5 \
- --hash=sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd \
- --hash=sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952
- # via sphinx
-urllib3==1.26.9 \
- --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 \
- --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e
- # via requests
diff --git a/tests/pip_deps/test.sh b/tests/pip_deps/test.sh
deleted file mode 100755
index 5c356fd500..0000000000
--- a/tests/pip_deps/test.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-set -euo pipefail
-
-! grep external "$1"
diff --git a/tests/pip_repository_entry_points/WORKSPACE b/tests/pip_repository_entry_points/WORKSPACE
index 07a5d3aad0..dd80db47fa 100644
--- a/tests/pip_repository_entry_points/WORKSPACE
+++ b/tests/pip_repository_entry_points/WORKSPACE
@@ -24,9 +24,9 @@ pip_parse(
requirements_lock = "//:requirements.txt",
)
-load("@pip_parsed//:requirements.bzl", "install_deps")
+load("@pip_parsed//:requirements.bzl", install_pip_parse_deps = "install_deps")
-install_deps()
+install_pip_parse_deps()
# For a more thorough example of `pip_install`. See `@rules_python//examples/pip_install`
pip_install(
@@ -34,3 +34,7 @@ pip_install(
python_interpreter_target = interpreter,
requirements = "//:requirements.txt",
)
+
+load("@pip_installed//:requirements.bzl", install_pip_install_deps = "install_deps")
+
+install_pip_install_deps()
diff --git a/tests/pip_repository_entry_points/requirements.txt b/tests/pip_repository_entry_points/requirements.txt
index 02bc8751b0..279aed0e80 100644
--- a/tests/pip_repository_entry_points/requirements.txt
+++ b/tests/pip_repository_entry_points/requirements.txt
@@ -173,7 +173,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
@@ -204,13 +204,13 @@ 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 \
--hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \
--hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e
# via
- # -r requirements.in
+ # -r ./requirements.in
# sphinx
# yamllint
From b4f1d4270650d46d8f67c51c6e293aa5c3a672f2 Mon Sep 17 00:00:00 2001
From: Greg Roodt
Date: Tue, 30 Aug 2022 20:09:36 +1000
Subject: [PATCH 2/8] Update python/pip.bzl
Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com>
---
python/pip.bzl | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/python/pip.bzl b/python/pip.bzl
index 2419660b5f..d7287a8aa8 100644
--- a/python/pip.bzl
+++ b/python/pip.bzl
@@ -127,9 +127,9 @@ def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_
# Just in case our dependencies weren't already fetched
pip_install_dependencies()
- # Temporary compatibility shim
- # pip_install was previously document to use requirements while pip_parse was using requirements_lock
- # We would prefer everyone move to using requirements_lock, but we maintain a temporary shim
+ # Temporary compatibility shim.
+ # pip_install was previously document to use requirements while pip_parse was using requirements_lock.
+ # We would prefer everyone move to using requirements_lock, but we maintain a temporary shim.
reqs_to_use = requirements_lock if requirements_lock else requirements
pip_repository(
From 6be2498bdc02568607f1502d0969bd5831fc06c5 Mon Sep 17 00:00:00 2001
From: Greg Roodt
Date: Wed, 31 Aug 2022 20:21:49 +1000
Subject: [PATCH 3/8] Updates after initial review.
---
docs/pip.md | 22 +++++++++++++++++++---
python/pip.bzl | 28 ++++++++++++++++++++++++++--
2 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/docs/pip.md b/docs/pip.md
index b302ccfbeb..0930a7d00f 100644
--- a/docs/pip.md
+++ b/docs/pip.md
@@ -73,6 +73,22 @@ Annotations to apply to the BUILD file content from package generated from a `pi
pip_install(requirements, name, kwargs)
+Accepts a locked/compiled requirements file and installs the dependencies listed within.
+
+Usage:
+
+```python
+load("@rules_python//python:pip.bzl", "pip_install")
+
+pip_install(
+ name = "pip_deps",
+ requirements = ":requirements.txt",
+)
+
+load("@pip_deps//:requirements.bzl", "install_deps")
+
+install_deps()
+```
**PARAMETERS**
@@ -80,9 +96,9 @@ pip_install(requirements, -
| None |
-| name | -
| "pip" |
-| kwargs | -
| none |
+| requirements | A 'requirements.txt' pip requirements file. | None |
+| name | A unique name for the created external repository (default 'pip'). | "pip" |
+| kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none |
diff --git a/python/pip.bzl b/python/pip.bzl
index 2419660b5f..47dfe5f7a1 100644
--- a/python/pip.bzl
+++ b/python/pip.bzl
@@ -21,8 +21,32 @@ compile_pip_requirements = _compile_pip_requirements
package_annotation = _package_annotation
def pip_install(requirements = None, name = "pip", **kwargs):
- # pip_install is now considered deprecated.
- # In future, this may log a warning and eventually be removed.
+ """Accepts a locked/compiled requirements file and installs the dependencies listed within.
+
+ Usage:
+
+ ```python
+ load("@rules_python//python:pip.bzl", "pip_install")
+
+ pip_install(
+ name = "pip_deps",
+ requirements = ":requirements.txt",
+ )
+
+ load("@pip_deps//:requirements.bzl", "install_deps")
+
+ install_deps()
+ ```
+
+ Args:
+ requirements (Label): A 'requirements.txt' pip requirements file.
+ name (str, optional): A unique name for the created external repository (default 'pip').
+ **kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule.
+
+ Deprecated:
+ Please use pip_parse.
+ """
+ print("pip_install is deprecated. Please switch to pip_parse. pip_install will be removed in a future release.")
pip_parse(requirements = requirements, name = name, **kwargs)
def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_deps", **kwargs):
From faf4ce81c5023cc483d024e61ae00a5393dee825 Mon Sep 17 00:00:00 2001
From: Greg Roodt
Date: Wed, 31 Aug 2022 20:34:50 +1000
Subject: [PATCH 4/8] Updates after initial review.
---
python/pip.bzl | 3 ---
1 file changed, 3 deletions(-)
diff --git a/python/pip.bzl b/python/pip.bzl
index c8669f6b2d..6a7a8f091d 100644
--- a/python/pip.bzl
+++ b/python/pip.bzl
@@ -42,9 +42,6 @@ def pip_install(requirements = None, name = "pip", **kwargs):
requirements (Label): A 'requirements.txt' pip requirements file.
name (str, optional): A unique name for the created external repository (default 'pip').
**kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule.
-
- Deprecated:
- Please use pip_parse.
"""
print("pip_install is deprecated. Please switch to pip_parse. pip_install will be removed in a future release.")
pip_parse(requirements = requirements, name = name, **kwargs)
From 617b4d0265c91f5f647f580125df691f614ca288 Mon Sep 17 00:00:00 2001
From: Greg Roodt
Date: Wed, 31 Aug 2022 20:38:32 +1000
Subject: [PATCH 5/8] Updates after initial review.
---
docs/pip.md | 2 --
python/pip.bzl | 2 --
2 files changed, 4 deletions(-)
diff --git a/docs/pip.md b/docs/pip.md
index 0930a7d00f..f6d8430adc 100644
--- a/docs/pip.md
+++ b/docs/pip.md
@@ -75,8 +75,6 @@ pip_install(requirements,
Date: Wed, 31 Aug 2022 20:42:23 +1000
Subject: [PATCH 6/8] Updates after initial review.
---
python/pip.bzl | 1 +
1 file changed, 1 insertion(+)
diff --git a/python/pip.bzl b/python/pip.bzl
index b76e9093af..f34acaf351 100644
--- a/python/pip.bzl
+++ b/python/pip.bzl
@@ -41,6 +41,7 @@ def pip_install(requirements = None, name = "pip", **kwargs):
name (str, optional): A unique name for the created external repository (default 'pip').
**kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule.
"""
+ # buildifier: disable=print
print("pip_install is deprecated. Please switch to pip_parse. pip_install will be removed in a future release.")
pip_parse(requirements = requirements, name = name, **kwargs)
From cc3a096ea58478f62e7fbef100943f3072243424 Mon Sep 17 00:00:00 2001
From: Greg Roodt
Date: Wed, 31 Aug 2022 20:43:39 +1000
Subject: [PATCH 7/8] Updates after initial review.
---
python/pip.bzl | 1 +
1 file changed, 1 insertion(+)
diff --git a/python/pip.bzl b/python/pip.bzl
index f34acaf351..dfafefe38d 100644
--- a/python/pip.bzl
+++ b/python/pip.bzl
@@ -41,6 +41,7 @@ def pip_install(requirements = None, name = "pip", **kwargs):
name (str, optional): A unique name for the created external repository (default 'pip').
**kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule.
"""
+
# buildifier: disable=print
print("pip_install is deprecated. Please switch to pip_parse. pip_install will be removed in a future release.")
pip_parse(requirements = requirements, name = name, **kwargs)
From faae18778a5dd23a4e94f21fe2d912165799c014 Mon Sep 17 00:00:00 2001
From: Greg
Date: Fri, 23 Sep 2022 09:29:36 +1000
Subject: [PATCH 8/8] Include notice about resolving deps for pip_install
---
README.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/README.md b/README.md
index e0335241d3..944493c6a9 100644
--- a/README.md
+++ b/README.md
@@ -152,6 +152,9 @@ updating your system `python` interpreter), you can force it to re-execute by ru
Note: The `pip_install` rule is deprecated. `pip_parse` offers identical functionality and both `pip_install`
and `pip_parse` now have the same implementation. The name `pip_install` may be removed in a future version of the rules.
+The maintainers have taken all reasonable efforts to faciliate a smooth transition, but some users of `pip_install` will
+need to replace their existing `requirements.txt` with a fully resolved set of dependencies using a tool such as
+`pip-tools` or the `compile_pip_requirements` repository rule.
### Using third_party packages as dependencies