@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 29d69332aa
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 2, 08:30 UTC

[BugFix] Fix `_has_module` to verify native deps via trial import (#44035)

Signed-off-by: esmeetu <jasonailu87@gmail.com> Signed-off-by: Jeffrey Wang <jeffreywang@anyscale.com> Signed-off-by: Nick Hill <nickhill123@gmail.com> Co-authored-by: esmeetu <jasonailu87@gmail.com> Co-authored-by: Nick Hill <nickhill123@gmail.com>

Jeffrey Wang committed May 31, 2026 at 22:06 UTC 29d69332aa658a96698a456e044763321f4bbd82
2 files changed +110 -5
tests/utils_/test_import_utils.py
+94 -1
@@ -1,8 +1,10 @@
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 +from unittest.mock import MagicMock, patch
4 +
5 import pytest
6
5 -from vllm.utils.import_utils import PlaceholderModule
7 +from vllm.utils.import_utils import PlaceholderModule, _has_module
8
9
10 def _raises_module_not_found():
@@ -44,3 +46,94 @@ def test_placeholder_module_error_handling():
46 with _raises_module_not_found():
47 # Test conflict with internal __module attribute
48 _ = placeholder_attr.module
49 +
50 +
51 +class TestHasModule:
52 + """Tests for _has_module with trial import verification."""
53 +
54 + def setup_method(self):
55 + # Clear the @cache between tests so each test gets a fresh call
56 + _has_module.cache_clear()
57 +
58 + def test_returns_true_for_importable_stdlib_module(self):
59 + assert _has_module("json") is True
60 +
61 + def test_returns_false_for_nonexistent_module(self):
62 + assert _has_module("nonexistent_module_xyz_12345") is False
63 +
64 + def test_returns_false_when_find_spec_succeeds_but_import_fails(self):
65 + """Simulate a native extension whose shared library is missing.
66 +
67 + ``find_spec`` finds the package on disk, but the actual import
68 + raises ``ImportError`` (e.g. missing ``libcudart.so``).
69 + """
70 + fake_spec = MagicMock()
71 +
72 + with (
73 + patch(
74 + "vllm.utils.import_utils.importlib.util.find_spec",
75 + return_value=fake_spec,
76 + ),
77 + patch(
78 + "vllm.utils.import_utils.importlib.import_module",
79 + side_effect=ImportError(
80 + "libcudart.so.12: cannot open shared object file"
81 + ),
82 + ),
83 + ):
84 + assert _has_module("fake_native_ext") is False
85 +
86 + def test_returns_false_on_os_error_during_import(self):
87 + """Some shared-library failures surface as ``OSError``."""
88 + fake_spec = MagicMock()
89 +
90 + with (
91 + patch(
92 + "vllm.utils.import_utils.importlib.util.find_spec",
93 + return_value=fake_spec,
94 + ),
95 + patch(
96 + "vllm.utils.import_utils.importlib.import_module",
97 + side_effect=OSError("cannot load library"),
98 + ),
99 + ):
100 + assert _has_module("fake_native_ext_os") is False
101 +
102 + def test_returns_false_on_unexpected_error_during_import(self):
103 + """A broken extension may raise a non-import error (e.g. ``RuntimeError``).
104 +
105 + Such modules are not usable, so ``_has_module`` should still return
106 + ``False`` rather than letting the exception propagate.
107 + """
108 + fake_spec = MagicMock()
109 +
110 + with (
111 + patch(
112 + "vllm.utils.import_utils.importlib.util.find_spec",
113 + return_value=fake_spec,
114 + ),
115 + patch(
116 + "vllm.utils.import_utils.importlib.import_module",
117 + side_effect=RuntimeError("CUDA driver version is insufficient"),
118 + ),
119 + ):
120 + assert _has_module("fake_broken_ext") is False
121 +
122 + def test_returns_false_when_find_spec_raises(self):
123 + """``find_spec`` itself can raise for dotted names whose parent package
124 + fails to import. This should be treated as the module being unavailable.
125 + """
126 + with patch(
127 + "vllm.utils.import_utils.importlib.util.find_spec",
128 + side_effect=ModuleNotFoundError("No module named 'fake_parent'"),
129 + ):
130 + assert _has_module("fake_parent.child") is False
131 +
132 + def test_result_is_cached(self):
133 + """Verify the @cache decorator prevents repeated imports."""
134 + _has_module("json") # prime the cache
135 +
136 + with patch("vllm.utils.import_utils.importlib.util.find_spec") as mock_spec:
137 + result = _has_module("json") # should hit cache
138 + mock_spec.assert_not_called()
139 + assert result is True
vllm/utils/import_utils.py
+16 -4
@@ -392,12 +392,24 @@ class LazyLoader(ModuleType):
392 # Optional dependency detection utilities
393 @cache
394 def _has_module(module_name: str) -> bool:
395 - """Return True if *module_name* can be found in the current environment.
395 + """Return True if *module_name* can be imported in the current environment.
396
397 - The result is cached so that subsequent queries for the same module incur
398 - no additional overhead.
397 + Uses ``importlib.util.find_spec`` as a fast pre-check, then performs a
398 + trial import to verify that native dependencies (shared libraries, etc.)
399 + are also satisfied. Any failure during the trial import is treated as the
400 + module being unavailable. The result is cached so that subsequent queries
401 + for the same module incur no additional overhead.
402 """
400 - return importlib.util.find_spec(module_name) is not None
403 + try:
404 + if importlib.util.find_spec(module_name) is None:
405 + return False
406 + importlib.import_module(module_name)
407 + except ImportError:
408 + logger.warning(
409 + "Module %s was found but failed to import", module_name, exc_info=True
410 + )
411 + return False
412 + return True
413
414
415 def has_deep_ep() -> bool: