fix(internal): add WORKSPACE.bzlmod to ensure dependency separation (#1806)

Before this PR, WORKSPACE file would be also used when using
'rules_python' under bzlmod and when developing locally it would yield
to inconsistent behaviour between the examples and the main workspace.

This PR ensures that the `dev_pip` is used via `bzlmod`. Whilst there
may be a little bit of duplication from now on, it ensures that
non-bzlmod code paths do not leak into the bzlmod dev setup.
diff --git a/BUILD.bazel b/BUILD.bazel
index cd4cbc5..c97f41d 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -35,6 +35,7 @@
         "BUILD.bazel",
         "MODULE.bazel",
         "WORKSPACE",
+        "WORKSPACE.bzlmod",
         "internal_deps.bzl",
         "internal_setup.bzl",
         "version.bzl",
diff --git a/MODULE.bazel b/MODULE.bazel
index 3ed92db..15a33c8 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -12,7 +12,7 @@
 bazel_dep(name = "rules_proto", version = "5.3.0-21.7")
 bazel_dep(name = "protobuf", version = "21.7", repo_name = "com_google_protobuf")
 
-internal_deps = use_extension("@rules_python//python/private/bzlmod:internal_deps.bzl", "internal_deps")
+internal_deps = use_extension("//python/private/bzlmod:internal_deps.bzl", "internal_deps")
 internal_deps.install()
 use_repo(
     internal_deps,
@@ -38,7 +38,7 @@
 
 # We need to do another use_extension call to expose the "pythons_hub"
 # repo.
-python = use_extension("@rules_python//python/extensions:python.bzl", "python")
+python = use_extension("//python/extensions:python.bzl", "python")
 
 # The default toolchain to use if nobody configures a toolchain.
 # NOTE: This is not a stable version. It is provided for convenience, but will
@@ -56,6 +56,13 @@
 # ===== DEV ONLY DEPS AND SETUP BELOW HERE =====
 bazel_dep(name = "stardoc", version = "0.6.2", dev_dependency = True, repo_name = "io_bazel_stardoc")
 bazel_dep(name = "rules_bazel_integration_test", version = "0.20.0", dev_dependency = True)
+bazel_dep(name = "rules_testing", version = "0.5.0", dev_dependency = True)
+bazel_dep(name = "rules_cc", version = "0.0.9", dev_dependency = True)
+
+# Extra gazelle plugin deps so that WORKSPACE.bzlmod can continue including it for e2e tests.
+# We use `WORKSPACE.bzlmod` because it is impossible to have dev-only local overrides.
+bazel_dep(name = "rules_go", version = "0.41.0", dev_dependency = True, repo_name = "io_bazel_rules_go")
+bazel_dep(name = "gazelle", version = "0.33.0", dev_dependency = True, repo_name = "bazel_gazelle")
 
 dev_pip = use_extension(
     "//python/extensions:pip.bzl",
@@ -78,6 +85,26 @@
     requirements_lock = "//docs/sphinx:requirements.txt",
 )
 
+#####################
+# Install twine for our own runfiles wheel publishing.
+# Eventually we might want to install twine automatically for users too, see:
+# https://github.com/bazelbuild/rules_python/issues/1016.
+
+dev_pip.parse(
+    hub_name = "publish_deps",
+    python_version = "3.11",
+    requirements_darwin = "//tools/publish:requirements_darwin.txt",
+    requirements_lock = "//tools/publish:requirements.txt",
+    requirements_windows = "//tools/publish:requirements_windows.txt",
+)
+use_repo(
+    dev_pip,
+    "dev_pip",
+    publish_deps_twine = "publish_deps_311_twine",
+)
+
+# Bazel integration test setup below
+
 bazel_binaries = use_extension(
     "@rules_bazel_integration_test//:extensions.bzl",
     "bazel_binaries",
diff --git a/WORKSPACE.bzlmod b/WORKSPACE.bzlmod
new file mode 100644
index 0000000..ca89afe
--- /dev/null
+++ b/WORKSPACE.bzlmod
@@ -0,0 +1,62 @@
+# Copyright 2024 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.
+
+# This file contains everything that is needed when using bzlmod
+workspace(name = "rules_python")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
+
+# Used for Bazel CI
+http_archive(
+    name = "bazelci_rules",
+    sha256 = "eca21884e6f66a88c358e580fd67a6b148d30ab57b1680f62a96c00f9bc6a07e",
+    strip_prefix = "bazelci_rules-1.0.0",
+    url = "https://github.com/bazelbuild/continuous-integration/releases/download/rules-1.0.0/bazelci_rules-1.0.0.tar.gz",
+)
+
+load("@bazelci_rules//:rbe_repo.bzl", "rbe_preconfig")
+
+# Creates a default toolchain config for RBE.
+# Use this as is if you are using the rbe_ubuntu16_04 container,
+# otherwise refer to RBE docs.
+rbe_preconfig(
+    name = "buildkite_config",
+    toolchain = "ubuntu1804-bazel-java11",
+)
+
+# Add gazelle plugin so that we can run the gazelle example as an e2e integration
+# test and include the distribution files.
+local_repository(
+    name = "rules_python_gazelle_plugin",
+    path = "gazelle",
+)
+
+#####################
+
+# This wheel is purely here to validate the wheel extraction code. It's not
+# intended for anything else.
+http_file(
+    name = "wheel_for_testing",
+    downloaded_file_path = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+    sha256 = "0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2",
+    urls = [
+        "https://files.pythonhosted.org/packages/50/67/3e966d99a07d60a21a21d7ec016e9e4c2642a86fea251ec68677daf71d4d/numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+    ],
+)
+
+# rules_proto expects //external:python_headers to point at the python headers.
+bind(
+    name = "python_headers",
+    actual = "//python/cc:current_py_cc_headers",
+)
diff --git a/examples/bzlmod_build_file_generation/.bazelversion b/examples/bzlmod_build_file_generation/.bazelversion
deleted file mode 100644
index 19b860c..0000000
--- a/examples/bzlmod_build_file_generation/.bazelversion
+++ /dev/null
@@ -1 +0,0 @@
-6.4.0
diff --git a/python/private/common/attributes.bzl b/python/private/common/attributes.bzl
index 2111419..5ddca72 100644
--- a/python/private/common/attributes.bzl
+++ b/python/private/common/attributes.bzl
@@ -146,6 +146,7 @@
 COMMON_ATTRS = union_attrs(
     DATA_ATTRS,
     NATIVE_RULES_ALLOWLIST_ATTRS,
+    # buildifier: disable=attr-licenses
     {
         # NOTE: This attribute is deprecated and slated for removal.
         "distribs": attr.string_list(),