tests(pypi): add tests for namespace shims generation (#3066)

This adds functional tests for the generated pkgutil namespace files.

The test works by creating two wheels with the necessary structure:
* An `__init__.py` file isn't in the wheel for the namespace package
* They are both part of the namespace package.
* The test verifies both are importable.

These are the tests for
https://github.com/bazel-contrib/rules_python/pull/3059
diff --git a/.bazelrc b/.bazelrc
index 8997db9..d7e1771 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -4,8 +4,8 @@
 # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it)
 # To update these lines, execute
 # `bazel run @rules_bazel_integration_test//tools:update_deleted_packages`
-build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data,tests/whl_with_build_files/testdata,tests/whl_with_build_files/testdata/somepkg,tests/whl_with_build_files/testdata/somepkg-1.0.dist-info,tests/whl_with_build_files/testdata/somepkg/subpkg
-query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data,tests/whl_with_build_files/testdata,tests/whl_with_build_files/testdata/somepkg,tests/whl_with_build_files/testdata/somepkg-1.0.dist-info,tests/whl_with_build_files/testdata/somepkg/subpkg
+build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,rules_python-repro,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data,tests/whl_with_build_files/testdata,tests/whl_with_build_files/testdata/somepkg,tests/whl_with_build_files/testdata/somepkg-1.0.dist-info,tests/whl_with_build_files/testdata/somepkg/subpkg
+query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,rules_python-repro,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data,tests/whl_with_build_files/testdata,tests/whl_with_build_files/testdata/somepkg,tests/whl_with_build_files/testdata/somepkg-1.0.dist-info,tests/whl_with_build_files/testdata/somepkg/subpkg
 
 test --test_output=errors
 
diff --git a/MODULE.bazel b/MODULE.bazel
index a9b5195..9db287d 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -158,6 +158,8 @@
 use_repo(
     internal_dev_deps,
     "buildkite_config",
+    "implicit_namespace_ns_sub1",
+    "implicit_namespace_ns_sub2",
     "rules_python_runtime_env_tc_info",
     "somepkg_with_build_files",
     "whl_with_build_files",
diff --git a/python/private/internal_dev_deps.bzl b/python/private/internal_dev_deps.bzl
index bb7d76f..ca34dc6 100644
--- a/python/private/internal_dev_deps.bzl
+++ b/python/private/internal_dev_deps.bzl
@@ -30,6 +30,7 @@
     )
     runtime_env_repo(name = "rules_python_runtime_env_tc_info")
 
+    # Setup for //tests/whl_with_build_files
     whl_from_dir_repo(
         name = "whl_with_build_files",
         root = "//tests/whl_with_build_files:testdata/BUILD.bazel",
@@ -41,6 +42,31 @@
         requirement = "somepkg",
     )
 
+    # Setup for //tests/implicit_namespace_packages
+    whl_from_dir_repo(
+        name = "implicit_namespace_ns_sub1_whl",
+        root = "//tests/implicit_namespace_packages:testdata/ns-sub1/BUILD.bazel",
+        output = "ns_sub1-1.0-any-none-any.whl",
+    )
+    whl_library(
+        name = "implicit_namespace_ns_sub1",
+        whl_file = "@implicit_namespace_ns_sub1_whl//:ns_sub1-1.0-any-none-any.whl",
+        requirement = "ns-sub1",
+        enable_implicit_namespace_pkgs = False,
+    )
+
+    whl_from_dir_repo(
+        name = "implicit_namespace_ns_sub2_whl",
+        root = "//tests/implicit_namespace_packages:testdata/ns-sub2/BUILD.bazel",
+        output = "ns_sub2-1.0-any-none-any.whl",
+    )
+    whl_library(
+        name = "implicit_namespace_ns_sub2",
+        whl_file = "@implicit_namespace_ns_sub2_whl//:ns_sub2-1.0-any-none-any.whl",
+        requirement = "ns-sub2",
+        enable_implicit_namespace_pkgs = False,
+    )
+
 internal_dev_deps = module_extension(
     implementation = _internal_dev_deps_impl,
     doc = "This extension creates internal rules_python dev dependencies.",
diff --git a/python/private/pypi/whl_library_targets.bzl b/python/private/pypi/whl_library_targets.bzl
index 474f39a..95c1f5e 100644
--- a/python/private/pypi/whl_library_targets.bzl
+++ b/python/private/pypi/whl_library_targets.bzl
@@ -30,7 +30,7 @@
     "WHEEL_FILE_IMPL_LABEL",
     "WHEEL_FILE_PUBLIC_LABEL",
 )
-load(":namespace_pkgs.bzl", "create_inits")
+load(":namespace_pkgs.bzl", _create_inits = "create_inits")
 load(":pep508_deps.bzl", "deps")
 
 def whl_library_targets_from_requires(
@@ -120,6 +120,7 @@
             py_binary = py_binary,
             py_library = py_library,
             env_marker_setting = env_marker_setting,
+            create_inits = _create_inits,
         )):
     """Create all of the whl_library targets.
 
@@ -334,7 +335,7 @@
         if not enable_implicit_namespace_pkgs:
             srcs = srcs + getattr(native, "select", select)({
                 Label("//python/config_settings:is_venvs_site_packages"): [],
-                "//conditions:default": create_inits(
+                "//conditions:default": rules.create_inits(
                     srcs = srcs + data + pyi_srcs,
                     ignored_dirnames = [],  # If you need to ignore certain folders, you can patch rules_python here to do so.
                     root = "site-packages",
diff --git a/tests/implicit_namespace_packages/BUILD.bazel b/tests/implicit_namespace_packages/BUILD.bazel
new file mode 100644
index 0000000..42aca9b
--- /dev/null
+++ b/tests/implicit_namespace_packages/BUILD.bazel
@@ -0,0 +1,12 @@
+load("//python:py_test.bzl", "py_test")
+load("//tests/support:support.bzl", "SUPPORTS_BZLMOD_UNIXY")
+
+py_test(
+    name = "namespace_packages_test",
+    srcs = ["namespace_packages_test.py"],
+    target_compatible_with = SUPPORTS_BZLMOD_UNIXY,
+    deps = [
+        "@implicit_namespace_ns_sub1//:pkg",
+        "@implicit_namespace_ns_sub2//:pkg",
+    ],
+)
diff --git a/tests/implicit_namespace_packages/namespace_packages_test.py b/tests/implicit_namespace_packages/namespace_packages_test.py
new file mode 100644
index 0000000..ea47c08
--- /dev/null
+++ b/tests/implicit_namespace_packages/namespace_packages_test.py
@@ -0,0 +1,24 @@
+import unittest
+
+
+class NamespacePackagesTest(unittest.TestCase):
+
+    def test_both_importable(self):
+        import nspkg
+        import nspkg.subpkg1
+        import nspkg.subpkg1.subpkgmod
+        import nspkg.subpkg2.subpkgmod
+
+        self.assertEqual("nspkg.subpkg1", nspkg.subpkg1.expected_name)
+        self.assertEqual(
+            "nspkg.subpkg1.subpkgmod", nspkg.subpkg1.subpkgmod.expected_name
+        )
+
+        self.assertEqual("nspkg.subpkg2", nspkg.subpkg2.expected_name)
+        self.assertEqual(
+            "nspkg.subpkg2.subpkgmod", nspkg.subpkg2.subpkgmod.expected_name
+        )
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/METADATA b/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/METADATA
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/METADATA
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/RECORD b/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/RECORD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/RECORD
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/WHEEL b/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/WHEEL
new file mode 100644
index 0000000..a64521a
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub1/ns-sub1-1.0.dist-info/WHEEL
@@ -0,0 +1 @@
+Wheel-Version: 1.0
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub1/nspkg/subpkg1/__init__.py b/tests/implicit_namespace_packages/testdata/ns-sub1/nspkg/subpkg1/__init__.py
new file mode 100644
index 0000000..6657257
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub1/nspkg/subpkg1/__init__.py
@@ -0,0 +1 @@
+expected_name = "nspkg.subpkg1"
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub1/nspkg/subpkg1/subpkgmod.py b/tests/implicit_namespace_packages/testdata/ns-sub1/nspkg/subpkg1/subpkgmod.py
new file mode 100644
index 0000000..b03bf39
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub1/nspkg/subpkg1/subpkgmod.py
@@ -0,0 +1 @@
+expected_name = "nspkg.subpkg1.subpkgmod"
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/METADATA b/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/METADATA
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/METADATA
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/RECORD b/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/RECORD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/RECORD
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/WHEEL b/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/WHEEL
new file mode 100644
index 0000000..a64521a
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub2/ns_sub2-1.0.dist-info/WHEEL
@@ -0,0 +1 @@
+Wheel-Version: 1.0
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub2/nspkg/subpkg2/__init__.py b/tests/implicit_namespace_packages/testdata/ns-sub2/nspkg/subpkg2/__init__.py
new file mode 100644
index 0000000..29bfb67
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub2/nspkg/subpkg2/__init__.py
@@ -0,0 +1 @@
+expected_name = "nspkg.subpkg2"
diff --git a/tests/implicit_namespace_packages/testdata/ns-sub2/nspkg/subpkg2/subpkgmod.py b/tests/implicit_namespace_packages/testdata/ns-sub2/nspkg/subpkg2/subpkgmod.py
new file mode 100644
index 0000000..45a28eb
--- /dev/null
+++ b/tests/implicit_namespace_packages/testdata/ns-sub2/nspkg/subpkg2/subpkgmod.py
@@ -0,0 +1 @@
+expected_name = "nspkg.subpkg2.subpkgmod"
diff --git a/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl b/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl
index 22fe3ab..bc58be9 100644
--- a/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl
+++ b/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl
@@ -16,18 +16,14 @@
 
 load("@rules_testing//lib:test_suite.bzl", "test_suite")
 load("//python/private:glob_excludes.bzl", "glob_excludes")  # buildifier: disable=bzl-visibility
-load("//python/private/pypi:whl_library_targets.bzl", _whl_library_targets = "whl_library_targets", _whl_library_targets_from_requires = "whl_library_targets_from_requires")  # buildifier: disable=bzl-visibility
+load(
+    "//python/private/pypi:whl_library_targets.bzl",
+    "whl_library_targets",
+    "whl_library_targets_from_requires",
+)  # buildifier: disable=bzl-visibility
 
 _tests = []
 
-def whl_library_targets(**kwargs):
-    # Let's skip testing this for now
-    _whl_library_targets(enable_implicit_namespace_pkgs = True, **kwargs)
-
-def whl_library_targets_from_requires(**kwargs):
-    # Let's skip testing this for now
-    _whl_library_targets_from_requires(enable_implicit_namespace_pkgs = True, **kwargs)
-
 def _test_filegroups(env):
     calls = []
 
@@ -190,6 +186,12 @@
     py_library_calls = []
     env_marker_setting_calls = []
 
+    mock_glob = _mock_glob()
+
+    mock_glob.results.append(["site-packages/foo/SRCS.py"])
+    mock_glob.results.append(["site-packages/foo/DATA.txt"])
+    mock_glob.results.append(["site-packages/foo/PYI.pyi"])
+
     whl_library_targets_from_requires(
         name = "foo-0-py3-none-any.whl",
         metadata_name = "Foo",
@@ -208,12 +210,13 @@
         native = struct(
             filegroup = lambda **kwargs: filegroup_calls.append(kwargs),
             config_setting = lambda **_: None,
-            glob = _glob,
+            glob = mock_glob.glob,
             select = _select,
         ),
         rules = struct(
             py_library = lambda **kwargs: py_library_calls.append(kwargs),
             env_marker_setting = lambda **kwargs: env_marker_setting_calls.append(kwargs),
+            create_inits = lambda *args, **kwargs: ["_create_inits_target"],
         ),
     )
 
@@ -228,34 +231,51 @@
             "visibility": ["//visibility:public"],
         },
     ])  # buildifier: @unsorted-dict-items
-    env.expect.that_collection(py_library_calls).contains_exactly([
-        {
-            "name": "pkg",
-            "srcs": _glob(
-                ["site-packages/**/*.py"],
-                exclude = [],
-                allow_empty = True,
-            ),
-            "pyi_srcs": _glob(["site-packages/**/*.pyi"], allow_empty = True),
-            "data": [] + _glob(
-                ["site-packages/**/*"],
-                exclude = [
-                    "**/*.py",
-                    "**/*.pyc",
-                    "**/*.pyc.*",
-                    "**/*.dist-info/RECORD",
-                ] + glob_excludes.version_dependent_exclusions(),
-            ),
-            "imports": ["site-packages"],
-            "deps": ["@pypi//bar:pkg"] + _select({
-                ":is_include_bar_baz_true": ["@pypi//bar_baz:pkg"],
-                "//conditions:default": [],
-            }),
-            "tags": ["pypi_name=Foo", "pypi_version=0"],
-            "visibility": ["//visibility:public"],
-            "experimental_venvs_site_packages": Label("//python/config_settings:venvs_site_packages"),
-        },
-    ])  # buildifier: @unsorted-dict-items
+
+    env.expect.that_collection(py_library_calls).has_size(1)
+    if len(py_library_calls) != 1:
+        return
+    py_library_call = py_library_calls[0]
+
+    env.expect.that_dict(py_library_call).contains_exactly({
+        "name": "pkg",
+        "srcs": ["site-packages/foo/SRCS.py"] + _select({
+            Label("//python/config_settings:is_venvs_site_packages"): [],
+            "//conditions:default": ["_create_inits_target"],
+        }),
+        "pyi_srcs": ["site-packages/foo/PYI.pyi"],
+        "data": ["site-packages/foo/DATA.txt"],
+        "imports": ["site-packages"],
+        "deps": ["@pypi//bar:pkg"] + _select({
+            ":is_include_bar_baz_true": ["@pypi//bar_baz:pkg"],
+            "//conditions:default": [],
+        }),
+        "tags": ["pypi_name=Foo", "pypi_version=0"],
+        "visibility": ["//visibility:public"],
+        "experimental_venvs_site_packages": Label("//python/config_settings:venvs_site_packages"),
+    })  # buildifier: @unsorted-dict-items
+
+    env.expect.that_collection(mock_glob.calls).contains_exactly([
+        # srcs call
+        _glob_call(
+            ["site-packages/**/*.py"],
+            exclude = [],
+            allow_empty = True,
+        ),
+        # data call
+        _glob_call(
+            ["site-packages/**/*"],
+            exclude = [
+                "**/*.py",
+                "**/*.pyc",
+                "**/*.pyc.*",
+                "**/*.dist-info/RECORD",
+            ] + glob_excludes.version_dependent_exclusions(),
+        ),
+        # pyi call
+        _glob_call(["site-packages/**/*.pyi"], allow_empty = True),
+    ])
+
     env.expect.that_collection(env_marker_setting_calls).contains_exactly([
         {
             "name": "include_bar_baz",
@@ -269,6 +289,10 @@
 def _test_whl_and_library_deps(env):
     filegroup_calls = []
     py_library_calls = []
+    mock_glob = _mock_glob()
+    mock_glob.results.append(["site-packages/foo/SRCS.py"])
+    mock_glob.results.append(["site-packages/foo/DATA.txt"])
+    mock_glob.results.append(["site-packages/foo/PYI.pyi"])
 
     whl_library_targets(
         name = "foo.whl",
@@ -290,11 +314,12 @@
         native = struct(
             filegroup = lambda **kwargs: filegroup_calls.append(kwargs),
             config_setting = lambda **_: None,
-            glob = _glob,
+            glob = mock_glob.glob,
             select = _select,
         ),
         rules = struct(
             py_library = lambda **kwargs: py_library_calls.append(kwargs),
+            create_inits = lambda **kwargs: ["_create_inits_target"],
         ),
     )
 
@@ -320,45 +345,38 @@
             "visibility": ["//visibility:public"],
         },
     ])  # buildifier: @unsorted-dict-items
-    env.expect.that_collection(py_library_calls).contains_exactly([
-        {
-            "name": "pkg",
-            "srcs": _glob(
-                ["site-packages/**/*.py"],
-                exclude = [],
-                allow_empty = True,
-            ),
-            "pyi_srcs": _glob(["site-packages/**/*.pyi"], allow_empty = True),
-            "data": [] + _glob(
-                ["site-packages/**/*"],
-                exclude = [
-                    "**/*.py",
-                    "**/*.pyc",
-                    "**/*.pyc.*",
-                    "**/*.dist-info/RECORD",
-                ] + glob_excludes.version_dependent_exclusions(),
-            ),
-            "imports": ["site-packages"],
-            "deps": [
-                "@pypi_bar_baz//:pkg",
-                "@pypi_foo//:pkg",
-            ] + _select(
-                {
-                    Label("//python/config_settings:is_python_3.9"): ["@pypi_py39_dep//:pkg"],
-                    "@platforms//cpu:aarch64": ["@pypi_arm_dep//:pkg"],
-                    "@platforms//os:windows": ["@pypi_win_dep//:pkg"],
-                    ":is_python_3.10_linux_ppc64le": ["@pypi_py310_linux_ppc64le_dep//:pkg"],
-                    ":is_python_3.9_anyos_aarch64": ["@pypi_py39_arm_dep//:pkg"],
-                    ":is_python_3.9_linux_anyarch": ["@pypi_py39_linux_dep//:pkg"],
-                    ":is_linux_x86_64": ["@pypi_linux_intel_dep//:pkg"],
-                    "//conditions:default": [],
-                },
-            ),
-            "tags": ["tag1", "tag2"],
-            "visibility": ["//visibility:public"],
-            "experimental_venvs_site_packages": Label("//python/config_settings:venvs_site_packages"),
-        },
-    ])  # buildifier: @unsorted-dict-items
+
+    env.expect.that_collection(py_library_calls).has_size(1)
+    if len(py_library_calls) != 1:
+        return
+    env.expect.that_dict(py_library_calls[0]).contains_exactly({
+        "name": "pkg",
+        "srcs": ["site-packages/foo/SRCS.py"] + _select({
+            Label("//python/config_settings:is_venvs_site_packages"): [],
+            "//conditions:default": ["_create_inits_target"],
+        }),
+        "pyi_srcs": ["site-packages/foo/PYI.pyi"],
+        "data": ["site-packages/foo/DATA.txt"],
+        "imports": ["site-packages"],
+        "deps": [
+            "@pypi_bar_baz//:pkg",
+            "@pypi_foo//:pkg",
+        ] + _select(
+            {
+                Label("//python/config_settings:is_python_3.9"): ["@pypi_py39_dep//:pkg"],
+                "@platforms//cpu:aarch64": ["@pypi_arm_dep//:pkg"],
+                "@platforms//os:windows": ["@pypi_win_dep//:pkg"],
+                ":is_python_3.10_linux_ppc64le": ["@pypi_py310_linux_ppc64le_dep//:pkg"],
+                ":is_python_3.9_anyos_aarch64": ["@pypi_py39_arm_dep//:pkg"],
+                ":is_python_3.9_linux_anyarch": ["@pypi_py39_linux_dep//:pkg"],
+                ":is_linux_x86_64": ["@pypi_linux_intel_dep//:pkg"],
+                "//conditions:default": [],
+            },
+        ),
+        "tags": ["tag1", "tag2"],
+        "visibility": ["//visibility:public"],
+        "experimental_venvs_site_packages": Label("//python/config_settings:venvs_site_packages"),
+    })  # buildifier: @unsorted-dict-items
 
 _tests.append(_test_whl_and_library_deps)
 
@@ -366,6 +384,11 @@
     alias_calls = []
     py_library_calls = []
 
+    mock_glob = _mock_glob()
+    mock_glob.results.append(["site-packages/foo/srcs.py"])
+    mock_glob.results.append(["site-packages/foo/data.txt"])
+    mock_glob.results.append(["site-packages/foo/pyi.pyi"])
+
     whl_library_targets(
         name = "foo.whl",
         dep_template = "@pypi_{name}//:{target}",
@@ -384,12 +407,13 @@
         filegroups = {},
         native = struct(
             config_setting = lambda **_: None,
-            glob = _glob,
+            glob = mock_glob.glob,
             alias = lambda **kwargs: alias_calls.append(kwargs),
             select = _select,
         ),
         rules = struct(
             py_library = lambda **kwargs: py_library_calls.append(kwargs),
+            create_inits = lambda **kwargs: ["_create_inits_target"],
         ),
     )
 
@@ -397,39 +421,69 @@
         {"name": "pkg", "actual": "@pypi__groups//:qux_pkg", "visibility": ["//visibility:public"]},
         {"name": "whl", "actual": "@pypi__groups//:qux_whl", "visibility": ["//visibility:public"]},
     ])  # buildifier: @unsorted-dict-items
-    env.expect.that_collection(py_library_calls).contains_exactly([
-        {
-            "name": "_pkg",
-            "srcs": _glob(["site-packages/**/*.py"], exclude = [], allow_empty = True),
-            "pyi_srcs": _glob(["site-packages/**/*.pyi"], allow_empty = True),
-            "data": [] + _glob(
-                ["site-packages/**/*"],
-                exclude = [
-                    "**/*.py",
-                    "**/*.pyc",
-                    "**/*.pyc.*",
-                    "**/*.dist-info/RECORD",
-                ] + glob_excludes.version_dependent_exclusions(),
-            ),
-            "imports": ["site-packages"],
-            "deps": ["@pypi_bar_baz//:pkg"] + _select({
-                "@platforms//os:linux": ["@pypi_box//:pkg"],
-                ":is_linux_x86_64": ["@pypi_box//:pkg", "@pypi_box_amd64//:pkg"],
-                "//conditions:default": [],
-            }),
-            "tags": [],
-            "visibility": ["@pypi__groups//:__pkg__"],
-            "experimental_venvs_site_packages": Label("//python/config_settings:venvs_site_packages"),
-        },
-    ])  # buildifier: @unsorted-dict-items
+
+    env.expect.that_collection(py_library_calls).has_size(1)
+    if len(py_library_calls) != 1:
+        return
+
+    py_library_call = py_library_calls[0]
+    env.expect.where(case = "verify py library call").that_dict(
+        py_library_call,
+    ).contains_exactly({
+        "name": "_pkg",
+        "srcs": ["site-packages/foo/srcs.py"] + _select({
+            Label("//python/config_settings:is_venvs_site_packages"): [],
+            "//conditions:default": ["_create_inits_target"],
+        }),
+        "pyi_srcs": ["site-packages/foo/pyi.pyi"],
+        "data": ["site-packages/foo/data.txt"],
+        "imports": ["site-packages"],
+        "deps": ["@pypi_bar_baz//:pkg"] + _select({
+            "@platforms//os:linux": ["@pypi_box//:pkg"],
+            ":is_linux_x86_64": ["@pypi_box//:pkg", "@pypi_box_amd64//:pkg"],
+            "//conditions:default": [],
+        }),
+        "tags": [],
+        "visibility": ["@pypi__groups//:__pkg__"],
+        "experimental_venvs_site_packages": Label("//python/config_settings:venvs_site_packages"),
+    })  # buildifier: @unsorted-dict-items
+
+    env.expect.that_collection(mock_glob.calls, expr = "glob calls").contains_exactly([
+        _glob_call(["site-packages/**/*.py"], exclude = [], allow_empty = True),
+        _glob_call(["site-packages/**/*"], exclude = [
+            "**/*.py",
+            "**/*.pyc",
+            "**/*.pyc.*",
+            "**/*.dist-info/RECORD",
+        ]),
+        _glob_call(["site-packages/**/*.pyi"], allow_empty = True),
+    ])
 
 _tests.append(_test_group)
 
-def _glob(*args, **kwargs):
-    return [struct(
+def _glob_call(*args, **kwargs):
+    return struct(
         glob = args,
         kwargs = kwargs,
-    )]
+    )
+
+def _mock_glob():
+    # buildifier: disable=uninitialized
+    def glob(*args, **kwargs):
+        mock.calls.append(_glob_call(*args, **kwargs))
+        if not mock.results:
+            fail("Mock glob missing for invocation: args={} kwargs={}".format(
+                args,
+                kwargs,
+            ))
+        return mock.results.pop(0)
+
+    mock = struct(
+        calls = [],
+        results = [],
+        glob = glob,
+    )
+    return mock
 
 def _select(*args, **kwargs):
     """We need to have this mock select because we still need to support bazel 6."""