refactor!: do not use a wrapper macro for pip_parse (#1514)

This brings back the generated documentation for the pip_parse
attributes making switches to default values more prominent.

Towards #1496.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c1c0b7..2f593b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,11 +29,16 @@
   `GAZELLE_PYTHON_RUNTIME_DEPS` from `@rules_python_gazelle_plugin//:def.bzl` is
   no longer necessary.
 
+* The installation of `pip_parse` repository rule toolchain dependencies is now
+  done as part of `py_repositories` call.
+
 Breaking changes:
 
 * (pip) `pip_install` repository rule in this release has been disabled and
   will fail by default. The API symbol is going to be removed in the next
-  version, please migrate to `pip_parse` as a replacement.
+  version, please migrate to `pip_parse` as a replacement. The `pip_parse`
+  rule no longer supports `requirements` attribute, please use
+  `requirements_lock` instead.
 
 * (py_wheel) switch `incompatible_normalize_name` and
   `incompatible_normalize_version` to `True` by default to enforce `PEP440`
diff --git a/python/pip.bzl b/python/pip.bzl
index 0d206e8..b779f83 100644
--- a/python/pip.bzl
+++ b/python/pip.bzl
@@ -20,7 +20,6 @@
 """
 
 load("//python/pip_install:pip_repository.bzl", "pip_repository", _package_annotation = "package_annotation")
-load("//python/pip_install:repositories.bzl", "pip_install_dependencies")
 load("//python/pip_install:requirements.bzl", _compile_pip_requirements = "compile_pip_requirements")
 load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")
 load("//python/private:full_version.bzl", "full_version")
@@ -28,6 +27,7 @@
 
 compile_pip_requirements = _compile_pip_requirements
 package_annotation = _package_annotation
+pip_parse = pip_repository
 
 def pip_install(requirements = None, name = "pip", allow_pip_install = False, **kwargs):
     """Will be removed in 0.28.0
@@ -44,41 +44,6 @@
     else:
         fail("pip_install support has been disabled, please use pip_parse as a replacement.")
 
-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 as addressable targets and
-    in a generated `requirements.bzl` file. The `requirements.bzl` file can
-    be checked into source control, if desired; see {ref}`vendoring-requirements`
-
-    For more information, see {ref}`pip-integration`.
-
-    Args:
-        requirements_lock (Label): 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.
-        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 `<name>_<requirement-name>`.
-        **kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule.
-    """
-    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 = reqs_to_use,
-        **kwargs
-    )
-
 def _multi_pip_parse_impl(rctx):
     rules_python = rctx.attr._rules_python_workspace.workspace_name
     load_statements = []
diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl
index f9d3676..36a777b 100644
--- a/python/pip_install/pip_repository.bzl
+++ b/python/pip_install/pip_repository.bzl
@@ -454,10 +454,14 @@
     ),
     "requirements_lock": attr.label(
         allow_single_file = True,
-        doc = """
-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'.
+        doc = """\
+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.
 """,
     ),
     "requirements_windows": attr.label(
@@ -473,22 +477,32 @@
 
 pip_repository = repository_rule(
     attrs = pip_repository_attrs,
-    doc = """A rule for importing `requirements.txt` dependencies into Bazel.
+    doc = """Accepts a locked/compiled requirements file and installs the dependencies listed within.
 
-This rule imports a `requirements.txt` file and generates a new
-`requirements.bzl` file.  This is used via the `WORKSPACE` pattern:
+Those dependencies become available in a generated `requirements.bzl` file.
+You can instead check this `requirements.bzl` file into your repo, see the "vendoring" section below.
 
-```python
-pip_repository(
-    name = "foo",
-    requirements = ":requirements.txt",
+This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`.
+In your WORKSPACE file:
+
+```starlark
+load("@rules_python//python:pip.bzl", "pip_parse")
+
+pip_parse(
+    name = "pip_deps",
+    requirements_lock = ":requirements.txt",
 )
+
+load("@pip_deps//:requirements.bzl", "install_deps")
+
+install_deps()
 ```
 
-You can then reference imported dependencies from your `BUILD` file with:
+You can then reference installed dependencies from a `BUILD` file with:
 
-```python
-load("@foo//:requirements.bzl", "requirement")
+```starlark
+load("@pip_deps//:requirements.bzl", "requirement")
+
 py_library(
     name = "bar",
     ...
@@ -500,17 +514,52 @@
 )
 ```
 
-Or alternatively:
-```python
-load("@foo//:requirements.bzl", "all_requirements")
-py_binary(
-    name = "baz",
-    ...
-    deps = [
-       ":foo",
-    ] + all_requirements,
+In addition to the `requirement` macro, which is used to access the generated `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 as well.
+
+[whl_ep]: https://packaging.python.org/specifications/entry-points/
+
+```starlark
+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.
+
+```starlark
+load("@pip_deps//:requirements.bzl", "entry_point")
+
+alias(
+    name = "flake8",
+    actual = entry_point("flake8"),
+)
+```
+
+## Vendoring the requirements.bzl file
+
+In some cases you may not want to generate the requirements.bzl file as a repository rule
+while Bazel is fetching dependencies. For example, if you produce a reusable Bazel module
+such as a ruleset, you may want to include the requirements.bzl file rather than make your users
+install the WORKSPACE setup to generate it.
+See https://github.com/bazelbuild/rules_python/issues/608
+
+This is the same workflow as Gazelle, which creates `go_repository` rules with
+[`update-repos`](https://github.com/bazelbuild/bazel-gazelle#update-repos)
+
+To do this, use the "write to source file" pattern documented in
+https://blog.aspect.dev/bazel-can-write-to-the-source-folder
+to put a copy of the generated requirements.bzl into your project.
+Then load the requirements.bzl file directly rather than from the generated repository.
+See the example in rules_python/examples/pip_parse_vendored.
 """,
     implementation = _pip_repository_impl,
     environ = common_env,
diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl
index b322a70..37500a6 100644
--- a/python/pip_install/repositories.bzl
+++ b/python/pip_install/repositories.bzl
@@ -14,10 +14,8 @@
 
 ""
 
-load("@bazel_skylib//lib:versions.bzl", "versions")
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
-load("//:version.bzl", "MINIMUM_BAZEL_VERSION")
 
 _RULE_DEPS = [
     # START: maintained by 'bazel run //tools/private:update_pip_deps'
@@ -137,13 +135,6 @@
 
     (However we call it from pip_install, making it optional for users to do so.)
     """
-
-    # We only support Bazel LTS and rolling releases.
-    # Give the user an obvious error to upgrade rather than some obscure missing symbol later.
-    # It's not guaranteed that users call this function, but it's used by all the pip fetch
-    # repository rules so it's likely that most users get the right error.
-    versions.check(MINIMUM_BAZEL_VERSION)
-
     for (name, url, sha256) in _RULE_DEPS:
         maybe(
             http_archive,
diff --git a/python/repositories.bzl b/python/repositories.bzl
index 5333c2d..498c80f 100644
--- a/python/repositories.bzl
+++ b/python/repositories.bzl
@@ -19,6 +19,7 @@
 
 load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive")
 load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe", "read_netrc", "read_user_netrc", "use_netrc")
+load("//python/pip_install:repositories.bzl", "pip_install_dependencies")
 load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")
 load("//python/private:coverage_deps.bzl", "coverage_dep")
 load("//python/private:full_version.bzl", "full_version")
@@ -59,6 +60,7 @@
             "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
         ],
     )
+    pip_install_dependencies()
 
 ########
 # Remaining content of the file is only used to support toolchains.