move pip_import rule to legacy_pip_import BREAKING CHANGE: The load statement for "pip_import" and "pip_repositories" has moved to //python/legacy_pip_import:pip.bzl Use of the old load site will print a failure message indicating this.
diff --git a/.bazelrc b/.bazelrc index 92711d8..1afaedb 100644 --- a/.bazelrc +++ b/.bazelrc
@@ -3,7 +3,7 @@ # 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/pip/boto,examples/pip/extras,examples/pip/helloworld,examples/pip_install -query --deleted_packages=examples/pip/boto,examples/pip/extras,examples/pip/helloworld,examples/pip_install +build --deleted_packages=examples/legacy_pip_import/boto,examples/legacy_pip_import/extras,examples/legacy_pip_import/helloworld,examples/pip_install +query --deleted_packages=examples/legacy_pip_import/boto,examples/legacy_pip_import/extras,examples/legacy_pip_import/helloworld,examples/pip_install test --test_output=errors
diff --git a/examples/BUILD b/examples/BUILD index 92d899d..092ad40 100644 --- a/examples/BUILD +++ b/examples/BUILD
@@ -18,7 +18,7 @@ licenses(["notice"]) # Apache 2.0 bazel_integration_test( - name = "pip_example", + name = "legacy_pip_import_example", timeout = "long", )
diff --git a/examples/pip/.bazelrc b/examples/legacy_pip_import/.bazelrc similarity index 100% rename from examples/pip/.bazelrc rename to examples/legacy_pip_import/.bazelrc
diff --git a/examples/pip/README.md b/examples/legacy_pip_import/README.md similarity index 64% rename from examples/pip/README.md rename to examples/legacy_pip_import/README.md index 0c4ffa8..8ce8438 100644 --- a/examples/pip/README.md +++ b/examples/legacy_pip_import/README.md
@@ -1,4 +1,6 @@ -# pip example +# LEGACY pip example + +This feature has been replaced by the pip_install rule, please see the latest release notes to migrate. This shows how you can point Bazel at your requirements.txt file to get dependencies automatically installed.
diff --git a/examples/pip/WORKSPACE b/examples/legacy_pip_import/WORKSPACE similarity index 90% rename from examples/pip/WORKSPACE rename to examples/legacy_pip_import/WORKSPACE index 5c8d22a..af84004 100644 --- a/examples/pip/WORKSPACE +++ b/examples/legacy_pip_import/WORKSPACE
@@ -8,7 +8,7 @@ sha256 = "e46612e9bb0dae8745de6a0643be69e8665a03f63163ac6610c210e80d14c3e4", ) -load("@rules_python//python:pip.bzl", "pip_import", "pip_repositories") +load("@rules_python//python/legacy_pip_import:pip.bzl", "pip_import", "pip_repositories") pip_repositories()
diff --git a/examples/pip/boto/BUILD b/examples/legacy_pip_import/boto/BUILD similarity index 100% rename from examples/pip/boto/BUILD rename to examples/legacy_pip_import/boto/BUILD
diff --git a/examples/pip/boto/boto_test.py b/examples/legacy_pip_import/boto/boto_test.py similarity index 100% rename from examples/pip/boto/boto_test.py rename to examples/legacy_pip_import/boto/boto_test.py
diff --git a/examples/pip/boto/requirements.txt b/examples/legacy_pip_import/boto/requirements.txt similarity index 100% rename from examples/pip/boto/requirements.txt rename to examples/legacy_pip_import/boto/requirements.txt
diff --git a/examples/pip/extras/BUILD b/examples/legacy_pip_import/extras/BUILD similarity index 100% rename from examples/pip/extras/BUILD rename to examples/legacy_pip_import/extras/BUILD
diff --git a/examples/pip/extras/extras_test.py b/examples/legacy_pip_import/extras/extras_test.py similarity index 100% rename from examples/pip/extras/extras_test.py rename to examples/legacy_pip_import/extras/extras_test.py
diff --git a/examples/pip/extras/requirements.txt b/examples/legacy_pip_import/extras/requirements.txt similarity index 100% rename from examples/pip/extras/requirements.txt rename to examples/legacy_pip_import/extras/requirements.txt
diff --git a/examples/pip/extras/version_test.py b/examples/legacy_pip_import/extras/version_test.py similarity index 100% rename from examples/pip/extras/version_test.py rename to examples/legacy_pip_import/extras/version_test.py
diff --git a/examples/pip/helloworld/BUILD b/examples/legacy_pip_import/helloworld/BUILD similarity index 100% rename from examples/pip/helloworld/BUILD rename to examples/legacy_pip_import/helloworld/BUILD
diff --git a/examples/pip/helloworld/helloworld.py b/examples/legacy_pip_import/helloworld/helloworld.py similarity index 100% rename from examples/pip/helloworld/helloworld.py rename to examples/legacy_pip_import/helloworld/helloworld.py
diff --git a/examples/pip/helloworld/helloworld_test.py b/examples/legacy_pip_import/helloworld/helloworld_test.py similarity index 100% rename from examples/pip/helloworld/helloworld_test.py rename to examples/legacy_pip_import/helloworld/helloworld_test.py
diff --git a/examples/pip/helloworld/requirements.txt b/examples/legacy_pip_import/helloworld/requirements.txt similarity index 100% rename from examples/pip/helloworld/requirements.txt rename to examples/legacy_pip_import/helloworld/requirements.txt
diff --git a/internal_deps.bzl b/internal_deps.bzl index 15fe0a5..e731cc8 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl
@@ -3,7 +3,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") -load("@rules_python//python:pip.bzl", "pip_import") +load("@rules_python//python/legacy_pip_import:pip.bzl", "pip_import") def rules_python_internal_deps(): """Fetches all required dependencies for rules_python tests and tools."""
diff --git a/python/BUILD b/python/BUILD index e5891c0..124ddd0 100644 --- a/python/BUILD +++ b/python/BUILD
@@ -32,6 +32,7 @@ name = "distribution", srcs = glob(["**"]) + [ "//python/constraints:distribution", + "//python/legacy_pip_import:distribution", "//python/runfiles:distribution", ], visibility = ["//:__pkg__"],
diff --git a/python/legacy_pip_import/BUILD b/python/legacy_pip_import/BUILD new file mode 100644 index 0000000..d76747a --- /dev/null +++ b/python/legacy_pip_import/BUILD
@@ -0,0 +1,8 @@ +filegroup( + name = "distribution", + srcs = [ + "BUILD", + "pip.bzl", + ], + visibility = ["//python:__pkg__"], +)
diff --git a/python/legacy_pip_import/pip.bzl b/python/legacy_pip_import/pip.bzl new file mode 100644 index 0000000..ff7977b --- /dev/null +++ b/python/legacy_pip_import/pip.bzl
@@ -0,0 +1,143 @@ +# 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. +"""Import pip requirements into Bazel.""" + +def _pip_import_impl(repository_ctx): + """Core implementation of pip_import.""" + + # Add an empty top-level BUILD file. + # This is because Bazel requires BUILD files along all paths accessed + # via //this/sort/of:path and we wouldn't be able to load our generated + # requirements.bzl without it. + repository_ctx.file("BUILD", "") + + interpreter_path = repository_ctx.attr.python_interpreter + if repository_ctx.attr.python_interpreter_target != None: + target = repository_ctx.attr.python_interpreter_target + interpreter_path = repository_ctx.path(target) + + args = [ + interpreter_path, + repository_ctx.path(repository_ctx.attr._script), + "--python_interpreter", + interpreter_path, + "--name", + repository_ctx.attr.name, + "--input", + repository_ctx.path(repository_ctx.attr.requirements), + "--output", + repository_ctx.path("requirements.bzl"), + "--directory", + repository_ctx.path(""), + ] + if repository_ctx.attr.extra_pip_args: + args += [ + "--extra_pip_args", + "\"" + " ".join(repository_ctx.attr.extra_pip_args) + "\"", + ] + + # To see the output, pass: quiet=False + result = repository_ctx.execute(args, timeout=repository_ctx.attr.timeout) + + if result.return_code: + fail("pip_import failed: %s (%s)" % (result.stdout, result.stderr)) + +pip_import = repository_rule( + attrs = { + "extra_pip_args": attr.string_list( + doc = "Extra arguments to pass on to pip. Must not contain spaces.", + ), + "python_interpreter": attr.string(default = "python", doc = """ +The command to run the Python interpreter used to invoke pip and unpack the +wheels. +"""), + "python_interpreter_target": attr.label(allow_single_file = True, doc = """ +If you are using a custom python interpreter built by another repository rule, +use this attribute to specify its BUILD target. This allows pip_import to invoke +pip using the same interpreter as your toolchain. If set, takes precedence over +python_interpreter. +"""), + "requirements": attr.label( + mandatory = True, + allow_single_file = True, + doc = "The label of the requirements.txt file.", + ), + "timeout": attr.int( + default = 600, + doc = "Timeout (in seconds) for repository fetch." + ), + "_script": attr.label( + executable = True, + default = Label("//tools:piptool.par"), + cfg = "host", + ), + }, + implementation = _pip_import_impl, + doc = """A rule for importing `requirements.txt` dependencies into Bazel. + +This rule imports a `requirements.txt` file and generates a new +`requirements.bzl` file. This is used via the `WORKSPACE` pattern: + +```python +pip_import( + name = "foo", + requirements = ":requirements.txt", +) +load("@foo//:requirements.bzl", "pip_install") +pip_install() +``` + +You can then reference imported dependencies from your `BUILD` file with: + +```python +load("@foo//:requirements.bzl", "requirement") +py_library( + name = "bar", + ... + deps = [ + "//my/other:dep", + requirement("futures"), + requirement("mock"), + ], +) +``` + +Or alternatively: +```python +load("@foo//:requirements.bzl", "all_requirements") +py_binary( + name = "baz", + ... + deps = [ + ":foo", + ] + all_requirements, +) +``` +""", +) + +# We don't provide a `pip2_import` that would use the `python2` system command +# because this command does not exist on all platforms. On most (but not all) +# systems, `python` means Python 2 anyway. See also #258. + +def pip3_import(**kwargs): + """A wrapper around pip_import that uses the `python3` system command. + + Use this for requirements of PY3 programs. + """ + pip_import(python_interpreter = "python3", **kwargs) + +def pip_repositories(): + # buildifier: disable=print + print("DEPRECATED: the pip_import rule has been replaced with pip_install, please see release notes")
diff --git a/python/pip.bzl b/python/pip.bzl index bbaca94..6a0bcb9 100644 --- a/python/pip.bzl +++ b/python/pip.bzl
@@ -16,165 +16,6 @@ load("//python/pip_install:pip_repository.bzl", "pip_repository") load("//python/pip_install:repositories.bzl", "pip_install_dependencies") -def _pip_import_impl(repository_ctx): - """Core implementation of pip_import.""" - - # Add an empty top-level BUILD file. - # This is because Bazel requires BUILD files along all paths accessed - # via //this/sort/of:path and we wouldn't be able to load our generated - # requirements.bzl without it. - repository_ctx.file("BUILD", "") - - interpreter_path = repository_ctx.attr.python_interpreter - if repository_ctx.attr.python_interpreter_target != None: - target = repository_ctx.attr.python_interpreter_target - interpreter_path = repository_ctx.path(target) - - args = [ - interpreter_path, - repository_ctx.path(repository_ctx.attr._script), - "--python_interpreter", - interpreter_path, - "--name", - repository_ctx.attr.name, - "--input", - repository_ctx.path(repository_ctx.attr.requirements), - "--output", - repository_ctx.path("requirements.bzl"), - "--directory", - repository_ctx.path(""), - ] - if repository_ctx.attr.extra_pip_args: - args += [ - "--extra_pip_args", - "\"" + " ".join(repository_ctx.attr.extra_pip_args) + "\"", - ] - - # To see the output, pass: quiet=False - result = repository_ctx.execute(args, timeout=repository_ctx.attr.timeout) - - if result.return_code: - fail("pip_import failed: %s (%s)" % (result.stdout, result.stderr)) - -pip_import = repository_rule( - attrs = { - "extra_pip_args": attr.string_list( - doc = "Extra arguments to pass on to pip. Must not contain spaces.", - ), - "python_interpreter": attr.string(default = "python", doc = """ -The command to run the Python interpreter used to invoke pip and unpack the -wheels. -"""), - "python_interpreter_target": attr.label(allow_single_file = True, doc = """ -If you are using a custom python interpreter built by another repository rule, -use this attribute to specify its BUILD target. This allows pip_import to invoke -pip using the same interpreter as your toolchain. If set, takes precedence over -python_interpreter. -"""), - "requirements": attr.label( - mandatory = True, - allow_single_file = True, - doc = "The label of the requirements.txt file.", - ), - "timeout": attr.int( - default = 600, - doc = "Timeout (in seconds) for repository fetch." - ), - "_script": attr.label( - executable = True, - default = Label("//tools:piptool.par"), - cfg = "host", - ), - }, - implementation = _pip_import_impl, - doc = """A rule for importing `requirements.txt` dependencies into Bazel. - -This rule imports a `requirements.txt` file and generates a new -`requirements.bzl` file. This is used via the `WORKSPACE` pattern: - -```python -pip_import( - name = "foo", - requirements = ":requirements.txt", -) -load("@foo//:requirements.bzl", "pip_install") -pip_install() -``` - -You can then reference imported dependencies from your `BUILD` file with: - -```python -load("@foo//:requirements.bzl", "requirement") -py_library( - name = "bar", - ... - deps = [ - "//my/other:dep", - requirement("futures"), - requirement("mock"), - ], -) -``` - -Or alternatively: -```python -load("@foo//:requirements.bzl", "all_requirements") -py_binary( - name = "baz", - ... - deps = [ - ":foo", - ] + all_requirements, -) -``` -""", -) - -# We don't provide a `pip2_import` that would use the `python2` system command -# because this command does not exist on all platforms. On most (but not all) -# systems, `python` means Python 2 anyway. See also #258. - -def pip3_import(**kwargs): - """A wrapper around pip_import that uses the `python3` system command. - - Use this for requirements of PY3 programs. - """ - pip_import(python_interpreter = "python3", **kwargs) - -def pip_repositories(): - """Pull in dependencies needed to use the packaging rules.""" - - # At the moment this is a placeholder, in that it does not actually pull in - # any dependencies. However, it does do some validation checking. - # - # As a side effect of migrating our canonical workspace name from - # "@io_bazel_rules_python" to "@rules_python" (#203), users who still - # imported us by the old name would get a confusing error about a - # repository dependency cycle in their workspace. (The cycle is likely - # related to the fact that our repo name is hardcoded into the template - # in piptool.py.) - # - # To produce a more informative error message in this situation, we - # fail-fast here if we detect that we're not being imported by the new - # name. (I believe we have always had the requirement that we're imported - # by the canonical name, because of the aforementioned hardcoding.) - # - # Users who, against best practice, do not call pip_repositories() in their - # workspace will not benefit from this check. - if "rules_python" not in native.existing_rules(): - message = "=" * 79 + """\n\ -It appears that you are trying to import rules_python without using its -canonical name, "@rules_python". This does not work. Please change your -WORKSPACE file to import this repo with `name = "rules_python"` instead. -""" - if "io_bazel_rules_python" in native.existing_rules(): - message += """\n\ -Note that the previous name of "@io_bazel_rules_python" is no longer used. -See https://github.com/bazelbuild/rules_python/issues/203 for context. -""" - message += "=" * 79 - fail(message) - def pip_install(requirements, name = "pip", **kwargs): """Imports a `requirements.txt` file and generates a new `requirements.bzl` file. @@ -214,3 +55,9 @@ requirements = requirements, **kwargs ) + +def pip_import(**kwargs): + fail("=" * 79 + """\n + pip_import has been replaced with pip_install, please see the release notes. + To continue using it, you can load from "@rules_python//python/legacy_pip_import:pip.bzl" + """)