move rules_python_external out of experimental

- mv experimental/rules_python_external -> python/pip_install
- mv examples/rules_python_external -> examples/pip_install

This promotes rules_python_external as a public API in rules_python.
In a follow-up PR we'll update the documentation to indicate this and instruct users how to switch.
diff --git a/.bazelrc b/.bazelrc
index ca4af76..92711d8 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/rules_python_external
-query --deleted_packages=examples/pip/boto,examples/pip/extras,examples/pip/helloworld,examples/rules_python_external
+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
 
 test --test_output=errors
diff --git a/BUILD b/BUILD
index d3487d2..8458bc7 100644
--- a/BUILD
+++ b/BUILD
@@ -27,7 +27,7 @@
         "LICENSE",
         "internal_deps.bzl",
         "internal_setup.bzl",
-        "//experimental/rules_python_external:distribution",
+        "//python/pip_install:distribution",
         "//python:distribution",
         "//tools:distribution",
     ],
diff --git a/docs/BUILD b/docs/BUILD
index b84e250..4da9d80 100644
--- a/docs/BUILD
+++ b/docs/BUILD
@@ -39,6 +39,13 @@
 )
 
 bzl_library(
+    name = "bazel_repo_tools",
+    srcs = [
+        "@bazel_tools//tools:bzl_srcs",
+    ]
+)
+
+bzl_library(
     name = "defs",
     srcs = [
         "//python:defs.bzl",
@@ -62,6 +69,10 @@
     name = "pip-docs",
     out = "pip.md",
     input = "//python:pip.bzl",
+    deps = [
+        ":bazel_repo_tools",
+        "//python/pip_install:bzl",
+    ],
 )
 
 stardoc(
diff --git a/examples/BUILD b/examples/BUILD
index 2d9bdaa..92d899d 100644
--- a/examples/BUILD
+++ b/examples/BUILD
@@ -23,6 +23,6 @@
 )
 
 bazel_integration_test(
-    name = "rules_python_external_example",
+    name = "pip_install_example",
     timeout = "long",
 )
diff --git a/examples/rules_python_external/BUILD b/examples/pip_install/BUILD
similarity index 100%
rename from examples/rules_python_external/BUILD
rename to examples/pip_install/BUILD
diff --git a/examples/pip_install/README.md b/examples/pip_install/README.md
new file mode 100644
index 0000000..7657787
--- /dev/null
+++ b/examples/pip_install/README.md
@@ -0,0 +1,4 @@
+# pip_install example
+
+This example shows how to use pip to fetch external dependencies from a requirements.txt file,
+then use them in BUILD files as dependencies of Bazel targets.
diff --git a/examples/rules_python_external/WORKSPACE b/examples/pip_install/WORKSPACE
similarity index 96%
rename from examples/rules_python_external/WORKSPACE
rename to examples/pip_install/WORKSPACE
index 81dcd9b..c492d19 100644
--- a/examples/rules_python_external/WORKSPACE
+++ b/examples/pip_install/WORKSPACE
@@ -12,7 +12,7 @@
 
 py_repositories()
 
-load("@rules_python//experimental/rules_python_external:defs.bzl", "pip_install")
+load("@rules_python//python:pip.bzl", "pip_install")
 
 pip_install(
     # (Optional) You can provide extra parameters to pip.
diff --git a/examples/rules_python_external/main.py b/examples/pip_install/main.py
similarity index 100%
rename from examples/rules_python_external/main.py
rename to examples/pip_install/main.py
diff --git a/examples/rules_python_external/requirements.txt b/examples/pip_install/requirements.txt
similarity index 100%
rename from examples/rules_python_external/requirements.txt
rename to examples/pip_install/requirements.txt
diff --git a/examples/rules_python_external/test.py b/examples/pip_install/test.py
similarity index 100%
rename from examples/rules_python_external/test.py
rename to examples/pip_install/test.py
diff --git a/examples/rules_python_external/README.md b/examples/rules_python_external/README.md
deleted file mode 100644
index b432f0b..0000000
--- a/examples/rules_python_external/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# rules_python_external example
-
-This example shows how to use rules_python_external which was developed as an alternative
-to packaging rules in rules_python.
-
-We will soon migrate this example to be the canonical one for rules_python.
-See https://github.com/bazelbuild/rules_python/pull/352 for the longer plan.
diff --git a/experimental/rules_python_external/BUILD b/experimental/rules_python_external/BUILD
deleted file mode 100644
index 657c956..0000000
--- a/experimental/rules_python_external/BUILD
+++ /dev/null
@@ -1,8 +0,0 @@
-filegroup(
-    name = "distribution",
-    srcs = glob(["*.bzl"]) + [
-        "BUILD",
-        "//experimental/rules_python_external/extract_wheels:distribution",
-    ],
-    visibility = ["//:__pkg__"],
-)
diff --git a/experimental/rules_python_external/extract_wheels/BUILD b/experimental/rules_python_external/extract_wheels/BUILD
deleted file mode 100644
index f780b0d..0000000
--- a/experimental/rules_python_external/extract_wheels/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-load("@rules_python//python:defs.bzl", "py_binary")
-
-py_binary(
-    name = "extract_wheels",
-    srcs = [
-        "__init__.py",
-        "__main__.py",
-    ],
-    main = "__main__.py",
-    deps = ["//experimental/rules_python_external/extract_wheels/lib"],
-)
-
-filegroup(
-    name = "distribution",
-    srcs = glob(["*"]) + [
-        "//experimental/rules_python_external/extract_wheels/lib:distribution",
-    ],
-    visibility = ["//experimental/rules_python_external:__subpackages__"],
-)
diff --git a/experimental/rules_python_external/extract_wheels/__main__.py b/experimental/rules_python_external/extract_wheels/__main__.py
deleted file mode 100644
index 6aed7cd..0000000
--- a/experimental/rules_python_external/extract_wheels/__main__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-"""Main entry point."""
-from experimental.rules_python_external.extract_wheels import main
-
-if __name__ == "__main__":
-    main()
diff --git a/internal_setup.bzl b/internal_setup.bzl
index 646b86c..8609915 100644
--- a/internal_setup.bzl
+++ b/internal_setup.bzl
@@ -7,8 +7,8 @@
     "@piptool_deps//:requirements.bzl",
     _piptool_install = "pip_install",
 )
-
 load("//:version.bzl", "SUPPORTED_BAZEL_VERSIONS")
+load("//python/pip_install:repositories.bzl", "pip_install_dependencies")
 
 def rules_python_internal_setup():
     """Setup for rules_python tests and tools."""
@@ -16,5 +16,8 @@
     # Requirements for building our piptool.
     _piptool_install()
 
+    # Because we don't use the pip_install rule, we have to call this to fetch its deps
+    pip_install_dependencies()
+
     # Depend on the Bazel binaries for running bazel-in-bazel tests
     bazel_binaries(versions = SUPPORTED_BAZEL_VERSIONS)
diff --git a/python/pip.bzl b/python/pip.bzl
index e6c8f63..bbaca94 100644
--- a/python/pip.bzl
+++ b/python/pip.bzl
@@ -13,6 +13,9 @@
 # limitations under the License.
 """Import pip requirements into Bazel."""
 
+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."""
 
@@ -171,3 +174,43 @@
 """
         message += "=" * 79
         fail(message)
+
+def pip_install(requirements, name = "pip", **kwargs):
+    """Imports a `requirements.txt` file and generates a new `requirements.bzl` file.
+
+    This is used via the `WORKSPACE` pattern:
+
+    ```python
+    pip_install(
+        requirements = ":requirements.txt",
+    )
+    ```
+
+    You can then reference imported dependencies from your `BUILD` file with:
+
+    ```python
+    load("@pip//:requirements.bzl", "requirement")
+    py_library(
+        name = "bar",
+        ...
+        deps = [
+           "//my/other:dep",
+           requirement("requests"),
+           requirement("numpy"),
+        ],
+    )
+    ```
+
+    Args:
+      requirements: A 'requirements.txt' pip requirements file.
+      name: A unique name for the created external repository (default 'pip').
+      **kwargs: Keyword arguments passed directly to the `pip_repository` repository rule.
+    """
+    # Just in case our dependencies weren't already fetched
+    pip_install_dependencies()
+
+    pip_repository(
+        name = name,
+        requirements = requirements,
+        **kwargs
+    )
diff --git a/experimental/rules_python_external/.gitignore b/python/pip_install/.gitignore
similarity index 100%
rename from experimental/rules_python_external/.gitignore
rename to python/pip_install/.gitignore
diff --git a/python/pip_install/BUILD b/python/pip_install/BUILD
new file mode 100644
index 0000000..b37170e
--- /dev/null
+++ b/python/pip_install/BUILD
@@ -0,0 +1,19 @@
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+filegroup(
+    name = "distribution",
+    srcs = glob(["*.bzl"]) + [
+        "BUILD",
+        "//python/pip_install/extract_wheels:distribution",
+    ],
+    visibility = ["//:__pkg__"],
+)
+
+bzl_library(
+    name = "bzl",
+    srcs = [
+        "pip_repository.bzl",
+        "repositories.bzl",
+    ],
+    visibility = ["//docs:__pkg__"],
+)
diff --git a/experimental/rules_python_external/README.md b/python/pip_install/README.md
similarity index 100%
rename from experimental/rules_python_external/README.md
rename to python/pip_install/README.md
diff --git a/python/pip_install/extract_wheels/BUILD b/python/pip_install/extract_wheels/BUILD
new file mode 100644
index 0000000..92a0c7a
--- /dev/null
+++ b/python/pip_install/extract_wheels/BUILD
@@ -0,0 +1,19 @@
+load("@rules_python//python:defs.bzl", "py_binary")
+
+py_binary(
+    name = "extract_wheels",
+    srcs = [
+        "__init__.py",
+        "__main__.py",
+    ],
+    main = "__main__.py",
+    deps = ["//python/pip_install/extract_wheels/lib"],
+)
+
+filegroup(
+    name = "distribution",
+    srcs = glob(["*"]) + [
+        "//python/pip_install/extract_wheels/lib:distribution",
+    ],
+    visibility = ["//python/pip_install:__subpackages__"],
+)
diff --git a/experimental/rules_python_external/extract_wheels/__init__.py b/python/pip_install/extract_wheels/__init__.py
similarity index 97%
rename from experimental/rules_python_external/extract_wheels/__init__.py
rename to python/pip_install/extract_wheels/__init__.py
index 79f87e5..879b676 100644
--- a/experimental/rules_python_external/extract_wheels/__init__.py
+++ b/python/pip_install/extract_wheels/__init__.py
@@ -12,7 +12,7 @@
 import sys
 import json
 
-from experimental.rules_python_external.extract_wheels.lib import bazel, requirements
+from python.pip_install.extract_wheels.lib import bazel, requirements
 
 
 def configure_reproducible_wheels() -> None:
diff --git a/python/pip_install/extract_wheels/__main__.py b/python/pip_install/extract_wheels/__main__.py
new file mode 100644
index 0000000..40b690e
--- /dev/null
+++ b/python/pip_install/extract_wheels/__main__.py
@@ -0,0 +1,5 @@
+"""Main entry point."""
+from python.pip_install.extract_wheels import main
+
+if __name__ == "__main__":
+    main()
diff --git a/experimental/rules_python_external/extract_wheels/lib/BUILD b/python/pip_install/extract_wheels/lib/BUILD
similarity index 76%
rename from experimental/rules_python_external/extract_wheels/lib/BUILD
rename to python/pip_install/extract_wheels/lib/BUILD
index c78c517..001e333 100644
--- a/experimental/rules_python_external/extract_wheels/lib/BUILD
+++ b/python/pip_install/extract_wheels/lib/BUILD
@@ -1,5 +1,5 @@
 load("@rules_python//python:defs.bzl", "py_library", "py_test")
-load("//experimental/rules_python_external:repositories.bzl", "requirement")
+load("//python/pip_install:repositories.bzl", "requirement")
 
 py_library(
     name = "lib",
@@ -10,7 +10,7 @@
         "requirements.py",
         "wheel.py",
     ],
-    visibility = ["//experimental/rules_python_external/extract_wheels:__subpackages__"],
+    visibility = ["//python/pip_install/extract_wheels:__subpackages__"],
     deps = [
         requirement("pkginfo"),
         requirement("setuptools"),
@@ -47,5 +47,5 @@
         ["*"],
         exclude = ["*_test.py"],
     ),
-    visibility = ["//experimental/rules_python_external:__subpackages__"],
+    visibility = ["//python/pip_install:__subpackages__"],
 )
diff --git a/experimental/rules_python_external/extract_wheels/lib/__init__.py b/python/pip_install/extract_wheels/lib/__init__.py
similarity index 100%
rename from experimental/rules_python_external/extract_wheels/lib/__init__.py
rename to python/pip_install/extract_wheels/lib/__init__.py
diff --git a/experimental/rules_python_external/extract_wheels/lib/bazel.py b/python/pip_install/extract_wheels/lib/bazel.py
similarity index 97%
rename from experimental/rules_python_external/extract_wheels/lib/bazel.py
rename to python/pip_install/extract_wheels/lib/bazel.py
index fb92c0a..978f3a9 100644
--- a/experimental/rules_python_external/extract_wheels/lib/bazel.py
+++ b/python/pip_install/extract_wheels/lib/bazel.py
@@ -4,7 +4,7 @@
 import json
 from typing import Iterable, List, Dict, Set
 
-from experimental.rules_python_external.extract_wheels.lib import namespace_pkgs, wheel, purelib
+from python.pip_install.extract_wheels.lib import namespace_pkgs, wheel, purelib
 
 
 def generate_build_file_contents(
diff --git a/experimental/rules_python_external/extract_wheels/lib/namespace_pkgs.py b/python/pip_install/extract_wheels/lib/namespace_pkgs.py
similarity index 96%
rename from experimental/rules_python_external/extract_wheels/lib/namespace_pkgs.py
rename to python/pip_install/extract_wheels/lib/namespace_pkgs.py
index 8f7e57f..82804c5 100644
--- a/experimental/rules_python_external/extract_wheels/lib/namespace_pkgs.py
+++ b/python/pip_install/extract_wheels/lib/namespace_pkgs.py
@@ -3,7 +3,7 @@
 import textwrap
 from typing import Set, List, Optional
 
-from experimental.rules_python_external.extract_wheels.lib import wheel
+from python.pip_install.extract_wheels.lib import wheel
 
 
 def implicit_namespace_packages(
diff --git a/experimental/rules_python_external/extract_wheels/lib/namespace_pkgs_test.py b/python/pip_install/extract_wheels/lib/namespace_pkgs_test.py
similarity index 95%
rename from experimental/rules_python_external/extract_wheels/lib/namespace_pkgs_test.py
rename to python/pip_install/extract_wheels/lib/namespace_pkgs_test.py
index f1b299e..5eec5c3 100644
--- a/experimental/rules_python_external/extract_wheels/lib/namespace_pkgs_test.py
+++ b/python/pip_install/extract_wheels/lib/namespace_pkgs_test.py
@@ -4,7 +4,7 @@
 from typing import Optional
 import unittest
 
-from experimental.rules_python_external.extract_wheels.lib import namespace_pkgs
+from python.pip_install.extract_wheels.lib import namespace_pkgs
 
 
 class TempDir:
diff --git a/experimental/rules_python_external/extract_wheels/lib/purelib.py b/python/pip_install/extract_wheels/lib/purelib.py
similarity index 96%
rename from experimental/rules_python_external/extract_wheels/lib/purelib.py
rename to python/pip_install/extract_wheels/lib/purelib.py
index 830ce70..99f6299 100644
--- a/experimental/rules_python_external/extract_wheels/lib/purelib.py
+++ b/python/pip_install/extract_wheels/lib/purelib.py
@@ -2,7 +2,7 @@
 import pathlib
 import shutil
 
-from experimental.rules_python_external.extract_wheels.lib import wheel
+from python.pip_install.extract_wheels.lib import wheel
 
 
 def spread_purelib_into_root(wheel_dir: str) -> None:
diff --git a/experimental/rules_python_external/extract_wheels/lib/requirements.py b/python/pip_install/extract_wheels/lib/requirements.py
similarity index 100%
rename from experimental/rules_python_external/extract_wheels/lib/requirements.py
rename to python/pip_install/extract_wheels/lib/requirements.py
diff --git a/experimental/rules_python_external/extract_wheels/lib/requirements_test.py b/python/pip_install/extract_wheels/lib/requirements_test.py
similarity index 92%
rename from experimental/rules_python_external/extract_wheels/lib/requirements_test.py
rename to python/pip_install/extract_wheels/lib/requirements_test.py
index c06297a..ba7ee13 100644
--- a/experimental/rules_python_external/extract_wheels/lib/requirements_test.py
+++ b/python/pip_install/extract_wheels/lib/requirements_test.py
@@ -1,6 +1,6 @@
 import unittest
 
-from experimental.rules_python_external.extract_wheels.lib import requirements
+from python.pip_install.extract_wheels.lib import requirements
 
 
 class TestRequirementExtrasParsing(unittest.TestCase):
diff --git a/experimental/rules_python_external/extract_wheels/lib/wheel.py b/python/pip_install/extract_wheels/lib/wheel.py
similarity index 100%
rename from experimental/rules_python_external/extract_wheels/lib/wheel.py
rename to python/pip_install/extract_wheels/lib/wheel.py
diff --git a/experimental/rules_python_external/defs.bzl b/python/pip_install/pip_repository.bzl
similarity index 77%
rename from experimental/rules_python_external/defs.bzl
rename to python/pip_install/pip_repository.bzl
index 6f894e6..b2cb0a8 100644
--- a/experimental/rules_python_external/defs.bzl
+++ b/python/pip_install/pip_repository.bzl
@@ -1,8 +1,6 @@
 ""
 
-load("//experimental/rules_python_external:repositories.bzl", "all_requirements", "rules_python_external_dependencies")
-
-DEFAULT_REPOSITORY_NAME = "pip"
+load("//python/pip_install:repositories.bzl", "all_requirements")
 
 def _pip_repository_impl(rctx):
     python_interpreter = rctx.attr.python_interpreter
@@ -30,7 +28,7 @@
     args = [
         python_interpreter,
         "-m",
-        "experimental.rules_python_external.extract_wheels",
+        "python.pip_install.extract_wheels",
         "--requirements",
         rctx.path(rctx.attr.requirements),
         "--repo",
@@ -147,43 +145,3 @@
 ```
 """,
 )
-
-def pip_install(requirements, name = DEFAULT_REPOSITORY_NAME, **kwargs):
-    """Imports a `requirements.txt` file and generates a new `requirements.bzl` file.
-
-    This is used via the `WORKSPACE` pattern:
-
-    ```python
-    pip_install(
-        requirements = ":requirements.txt",
-    )
-    ```
-
-    You can then reference imported dependencies from your `BUILD` file with:
-
-    ```python
-    load("@pip//:requirements.bzl", "requirement")
-    py_library(
-        name = "bar",
-        ...
-        deps = [
-           "//my/other:dep",
-           requirement("requests"),
-           requirement("numpy"),
-        ],
-    )
-    ```
-
-    Args:
-      requirements: A 'requirements.txt' pip requirements file.
-      name: A unique name for the created external repository (default 'pip').
-      **kwargs: Keyword arguments passed directly to the `pip_repository` repository rule.
-    """
-    # Just in case our dependencies weren't already fetched
-    rules_python_external_dependencies()
-
-    pip_repository(
-        name = name,
-        requirements = requirements,
-        **kwargs
-    )
diff --git a/experimental/rules_python_external/repositories.bzl b/python/pip_install/repositories.bzl
similarity index 92%
rename from experimental/rules_python_external/repositories.bzl
rename to python/pip_install/repositories.bzl
index 00dc900..df63674 100644
--- a/experimental/rules_python_external/repositories.bzl
+++ b/python/pip_install/repositories.bzl
@@ -47,9 +47,11 @@
 def requirement(pkg):
     return "@pypi__" + pkg + "//:lib"
 
-def rules_python_external_dependencies():
+def pip_install_dependencies():
     """
-    Fetch dependencies these rules depend on. Workspaces that use the rules_python_external should call this.
+    Fetch dependencies these rules depend on. Workspaces that use the pip_install rule can call this.
+    
+    (However we call it from pip_install, making it optional for users to do so.)
     """
     for (name, url, sha256) in _RULE_DEPS:
         maybe(