diff --git a/build-support/bin/check_inits.py b/build-support/bin/check_inits.py index 9d3a559ee80..5d946f0009e 100755 --- a/build-support/bin/check_inits.py +++ b/build-support/bin/check_inits.py @@ -21,11 +21,17 @@ def main() -> None: files = itertools.chain.from_iterable( [Path().glob(f"{d}/**/__init__.py") for d in DIRS_TO_CHECK] ) - bad_inits = [f for f in files if bool(f.read_text())] - if bad_inits: + root_init = Path("src/python/pants/__init__.py") + if '__import__("pkg_resources").declare_namespace(__name__)' not in root_init.read_text(): + die( + f"{root_init} must have the line " + '`__import__("pkg_resources").declare_namespace(__name__)` in it.' + ) + non_empty_inits = [f for f in files if bool(f.read_text()) and f != root_init] + if non_empty_inits: die( "All `__init__.py` file should be empty, but the following had content: " - f"{', '.join(str(f) for f in bad_inits)}" + f"{', '.join(str(f) for f in non_empty_inits)}" ) diff --git a/src/python/pants/__init__.py b/src/python/pants/__init__.py index 5284146ebf2..4f581f30081 100644 --- a/src/python/pants/__init__.py +++ b/src/python/pants/__init__.py @@ -1 +1,3 @@ +# NB: We need to declare a namespace package because we have the dists `pantsbuild.pants` and +# `pantsbuild.pants.testutil`, which both have the module `pants`. __import__("pkg_resources").declare_namespace(__name__) diff --git a/src/python/pants/backend/python/goals/setup_py.py b/src/python/pants/backend/python/goals/setup_py.py index 488107e4e8a..eb4895b3f91 100644 --- a/src/python/pants/backend/python/goals/setup_py.py +++ b/src/python/pants/backend/python/goals/setup_py.py @@ -531,13 +531,19 @@ async def generate_chroot(request: SetupPyChrootRequest) -> SetupPyChroot: target = exported_target.target resolved_setup_kwargs = await Get(SetupKwargs, ExportedTarget, exported_target) setup_kwargs = resolved_setup_kwargs.kwargs.copy() + # NB: We are careful to not overwrite these values, but we also don't expect them to have been + # set. The user must have have gone out of their way to use a `SetupKwargs` plugin, and to have + # specified `SetupKwargs(_allow_banned_keys=True)`. setup_kwargs.update( { - "package_dir": {"": CHROOT_SOURCE_ROOT}, - "packages": sources.packages, - "namespace_packages": sources.namespace_packages, - "package_data": dict(sources.package_data), - "install_requires": tuple(requirements), + "package_dir": {"": CHROOT_SOURCE_ROOT, **setup_kwargs.get("package_dir", {})}, + "packages": (*sources.packages, *(setup_kwargs.get("packages", []))), + "namespace_packages": ( + *sources.namespace_packages, + *setup_kwargs.get("namespace_packages", []), + ), + "package_data": {**dict(sources.package_data), **setup_kwargs.get("package_data", {})}, + "install_requires": (*requirements, *setup_kwargs.get("install_requires", [])), } ) key_to_binary_spec = exported_target.provides.binaries