diff --git a/.ci/scripts/wheel/test_clean_install.py b/.ci/scripts/wheel/test_clean_install.py index 65943277324..13840ed8807 100644 --- a/.ci/scripts/wheel/test_clean_install.py +++ b/.ci/scripts/wheel/test_clean_install.py @@ -215,10 +215,10 @@ def run_tests(work_dir: Path) -> None: # Reads its arguments from stdin, blocks the named modules, then imports. A blocked module -# raises ModuleNotFoundError exactly as it would be absent, so the traceback shows the import -# chain that wanted it. +# behaves like a missing one to import and find_spec, so the traceback shows the import chain +# that wanted it. _IMPORT_PROBE = """ -import importlib.abc, importlib.util, json, os, sys +import importlib, json, os, sys # Drop the working directory, which `python -c` puts first. The equivalent flag, -P, is only # available from 3.11. @@ -229,19 +229,23 @@ def run_tests(work_dir: Path) -> None: request = json.load(sys.stdin) blocked = set(request["blocked"]) - -class _Blocker(importlib.abc.MetaPathFinder): - def find_spec(self, fullname, path=None, target=None): - if fullname.split(".")[0] in blocked: - raise ModuleNotFoundError( - f"No module named {fullname!r} (not declared by the executorch wheel)", - name=fullname, - ) - return None - - -sys.meta_path.insert(0, _Blocker()) -importlib.import_module(request["module"]) +# A None entry in sys.modules makes an import raise ModuleNotFoundError while +# importlib.util.find_spec returns None, which is how a missing package behaves. A finder that +# raises from find_spec instead breaks code that probes for optional packages, such as +# torch._dynamo, which looks up hypothesis that way. +for name in blocked: + sys.modules[name] = None + +try: + importlib.import_module(request["module"]) +except ModuleNotFoundError as error: + package = (error.name or "").split(".")[0] + if package in blocked: + raise ModuleNotFoundError( + f"No module named {package!r} (not declared by the executorch wheel)", + name=package, + ) from error + raise """ diff --git a/requirements-dev.txt b/requirements-dev.txt index e9575084648..a6f33b6f885 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -21,3 +21,8 @@ pytest-xdist pytest-rerunfailures==15.1 pytest-json-report gguf # For extension/llm/export/test/test_gguf.py (GGUF Q4_K/Q6_K dequant tests). +# Needed only by tests and development tools, so the executorch package does not depend on them. +expecttest +hypothesis +kgb +parameterized diff --git a/setup.py b/setup.py index c3d73287242..811619321ec 100644 --- a/setup.py +++ b/setup.py @@ -1154,15 +1154,11 @@ def _base_dependencies() -> List[str]: project's runtime needs. """ return [ - "expecttest", "flatbuffers", - "hypothesis", - "kgb", "mpmath==1.3.0", "numpy>=2.0.0; python_version >= '3.10'", "packaging", "pandas>=2.2.2; python_version >= '3.10'", - "parameterized", # The Qualcomm backend needs both, on different paths. Any lowering reads the CPU vendor # to disable an mkldnn path that crashes on AMD, whether or not an SDK is already set up. # Fetching an SDK additionally needs requests, which its downloader imports at module