@@ -454,10 +454,14 @@ pip_repository_attrs = {
454454 ),
455455 "requirements_lock" : attr .label (
456456 allow_single_file = True ,
457- doc = """
458- A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead
459- of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that
460- wheels are fetched/built only for the targets specified by 'build/run/test'.
457+ doc = """\
458+ A fully resolved 'requirements.txt' pip requirement file containing the
459+ transitive set of your dependencies. If this file is passed instead of
460+ 'requirements' no resolve will take place and pip_repository will create
461+ individual repositories for each of your dependencies so that wheels are
462+ fetched/built only for the targets specified by 'build/run/test'. Note that if
463+ your lockfile is platform-dependent, you can use the `requirements_[platform]`
464+ attributes.
461465""" ,
462466 ),
463467 "requirements_windows" : attr .label (
@@ -473,22 +477,32 @@ pip_repository_attrs.update(**common_attrs)
473477
474478pip_repository = repository_rule (
475479 attrs = pip_repository_attrs ,
476- doc = """A rule for importing `requirements.txt` dependencies into Bazel.
480+ doc = """Accepts a locked/compiled requirements file and installs the dependencies listed within.
481+
482+ Those dependencies become available in a generated `requirements.bzl` file.
483+ You can instead check this `requirements.bzl` file into your repo, see the "vendoring" section below.
477484
478- This rule imports a `requirements.txt` file and generates a new
479- `requirements.bzl` file. This is used via the ` WORKSPACE` pattern :
485+ This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`.
486+ In your WORKSPACE file :
480487
481- ```python
482- pip_repository(
483- name = "foo",
484- requirements = ":requirements.txt",
488+ ```starlark
489+ load("@rules_python//python:pip.bzl", "pip_parse")
490+
491+ pip_parse(
492+ name = "pip_deps",
493+ requirements_lock = ":requirements.txt",
485494)
495+
496+ load("@pip_deps//:requirements.bzl", "install_deps")
497+
498+ install_deps()
486499```
487500
488- You can then reference imported dependencies from your `BUILD` file with:
501+ You can then reference installed dependencies from a `BUILD` file with:
502+
503+ ```starlark
504+ load("@pip_deps//:requirements.bzl", "requirement")
489505
490- ```python
491- load("@foo//:requirements.bzl", "requirement")
492506py_library(
493507 name = "bar",
494508 ...
@@ -500,17 +514,52 @@ py_library(
500514)
501515```
502516
503- Or alternatively:
504- ```python
505- load("@foo//:requirements.bzl", "all_requirements")
506- py_binary(
507- name = "baz",
508- ...
509- deps = [
510- ":foo",
511- ] + all_requirements,
517+ In addition to the `requirement` macro, which is used to access the generated `py_library`
518+ target generated from a package's wheel, The generated `requirements.bzl` file contains
519+ functionality for exposing [entry points][whl_ep] as `py_binary` targets as well.
520+
521+ [whl_ep]: https://packaging.python.org/specifications/entry-points/
522+
523+ ```starlark
524+ load("@pip_deps//:requirements.bzl", "entry_point")
525+
526+ alias(
527+ name = "pip-compile",
528+ actual = entry_point(
529+ pkg = "pip-tools",
530+ script = "pip-compile",
531+ ),
512532)
513533```
534+
535+ Note that for packages whose name and script are the same, only the name of the package
536+ is needed when calling the `entry_point` macro.
537+
538+ ```starlark
539+ load("@pip_deps//:requirements.bzl", "entry_point")
540+
541+ alias(
542+ name = "flake8",
543+ actual = entry_point("flake8"),
544+ )
545+ ```
546+
547+ ## Vendoring the requirements.bzl file
548+
549+ In some cases you may not want to generate the requirements.bzl file as a repository rule
550+ while Bazel is fetching dependencies. For example, if you produce a reusable Bazel module
551+ such as a ruleset, you may want to include the requirements.bzl file rather than make your users
552+ install the WORKSPACE setup to generate it.
553+ See https://github.com/bazelbuild/rules_python/issues/608
554+
555+ This is the same workflow as Gazelle, which creates `go_repository` rules with
556+ [`update-repos`](https://github.com/bazelbuild/bazel-gazelle#update-repos)
557+
558+ To do this, use the "write to source file" pattern documented in
559+ https://blog.aspect.dev/bazel-can-write-to-the-source-folder
560+ to put a copy of the generated requirements.bzl into your project.
561+ Then load the requirements.bzl file directly rather than from the generated repository.
562+ See the example in rules_python/examples/pip_parse_vendored.
514563""" ,
515564 implementation = _pip_repository_impl ,
516565 environ = common_env ,
0 commit comments