diff --git a/defs.bzl b/defs.bzl index 1b82520dcc..cb1375ff5f 100644 --- a/defs.bzl +++ b/defs.bzl @@ -46,6 +46,11 @@ def _pip_repository_impl(rctx): struct(exclude = rctx.attr.pip_data_exclude).to_json(), ] + if rctx.attr.enable_implicit_namespace_pkgs: + args += [ + "--enable_implicit_namespace_pkgs" + ] + result = rctx.execute( args, environment = { @@ -80,6 +85,16 @@ python_interpreter. "pip_data_exclude": attr.string_list( doc = "Additional data exclusion parameters to add to the pip packages BUILD file.", ), + "enable_implicit_namespace_pkgs": attr.bool( + default = False, + doc = """ +If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary +and py_test targets must specify either `legacy_create_init=False` or the global Bazel option +`--incompatible_default_to_explicit_init_py` to prevent `__init__.py` being automatically generated in every directory. + +This option is required to support some packages which cannot handle the conversion to pkg-util style. + """, + ), }, implementation = _pip_repository_impl, ) diff --git a/extract_wheels/__init__.py b/extract_wheels/__init__.py index fccf1b0cb9..8184dac6aa 100644 --- a/extract_wheels/__init__.py +++ b/extract_wheels/__init__.py @@ -65,15 +65,18 @@ def main() -> None: help="The external repo name to install dependencies. In the format '@{REPO_NAME}'", ) parser.add_argument( - "--extra_pip_args", - action="store", - help=("Extra arguments to pass down to pip."), + "--extra_pip_args", action="store", help="Extra arguments to pass down to pip.", ) parser.add_argument( "--pip_data_exclude", action="store", help="Additional data exclusion parameters to add to the pip packages BUILD file.", ) + parser.add_argument( + "--enable_implicit_namespace_pkgs", + action="store_true", + help="Disables conversion of implicit namespace packages into pkg-util style packages.", + ) args = parser.parse_args() pip_args = [sys.executable, "-m", "pip", "wheel", "-r", args.requirements] @@ -91,7 +94,13 @@ def main() -> None: pip_data_exclude = [] targets = [ - '"%s%s"' % (args.repo, bazel.extract_wheel(whl, extras, pip_data_exclude)) + '"%s%s"' + % ( + args.repo, + bazel.extract_wheel( + whl, extras, pip_data_exclude, args.enable_implicit_namespace_pkgs + ), + ) for whl in glob.glob("*.whl") ] diff --git a/extract_wheels/lib/bazel.py b/extract_wheels/lib/bazel.py index 85ba965d48..acda4c29fa 100644 --- a/extract_wheels/lib/bazel.py +++ b/extract_wheels/lib/bazel.py @@ -120,13 +120,18 @@ def setup_namespace_pkg_compatibility(wheel_dir: str) -> None: def extract_wheel( - wheel_file: str, extras: Dict[str, Set[str]], pip_data_exclude: List[str] + wheel_file: str, + extras: Dict[str, Set[str]], + pip_data_exclude: List[str], + enable_implicit_namespace_pkgs: bool, ) -> str: """Extracts wheel into given directory and creates a py_library target. Args: wheel_file: the filepath of the .whl extras: a list of extras to add as dependencies for the installed wheel + pip_data_exclude: list of file patterns to exclude from the generated data section of the py_library + enable_implicit_namespace_pkgs: if true, disables conversion of implicit namespace packages and will unzip as-is Returns: The Bazel label for the extracted wheel, in the form '//path/to/wheel'. @@ -140,7 +145,9 @@ def extract_wheel( # Note: Order of operations matters here purelib.spread_purelib_into_root(directory) - setup_namespace_pkg_compatibility(directory) + + if not enable_implicit_namespace_pkgs: + setup_namespace_pkg_compatibility(directory) extras_requested = extras[whl.name] if whl.name in extras else set()