From 42c8b0edefa586ff41aa89da29bb9463d0840647 Mon Sep 17 00:00:00 2001 From: DarkLight1337 Date: Thu, 16 Oct 2025 12:49:27 +0000 Subject: [PATCH 1/6] [Chore] Separate out `vllm.utils.importlib` Signed-off-by: DarkLight1337 --- .../tensorizer_loader/test_tensorizer.py | 2 +- tests/utils_/test_importlib.py | 46 +++ tests/utils_/test_utils.py | 41 --- tests/v1/attention/utils.py | 2 +- vllm/assets/audio.py | 2 +- vllm/assets/video.py | 2 +- vllm/attention/backends/registry.py | 2 +- vllm/attention/selector.py | 3 +- vllm/benchmarks/datasets.py | 2 +- vllm/compilation/backends.py | 3 +- vllm/compilation/decorators.py | 3 +- vllm/config/compilation.py | 3 +- vllm/config/model.py | 3 +- vllm/config/speculative.py | 2 +- vllm/distributed/parallel_state.py | 2 +- vllm/entrypoints/openai/protocol.py | 3 +- vllm/entrypoints/openai/speech_to_text.py | 2 +- .../tool_parsers/abstract_tool_parser.py | 2 +- vllm/lora/punica_wrapper/punica_selector.py | 2 +- vllm/model_executor/layers/pooler.py | 2 +- .../model_executor/model_loader/tensorizer.py | 3 +- .../model_loader/weight_utils.py | 2 +- vllm/multimodal/audio.py | 2 +- vllm/multimodal/inputs.py | 2 +- vllm/multimodal/parse.py | 2 +- vllm/platforms/__init__.py | 3 +- vllm/plugins/io_processors/__init__.py | 2 +- vllm/reasoning/abs_reasoning_parsers.py | 2 +- vllm/transformers_utils/runai_utils.py | 2 +- vllm/transformers_utils/s3_utils.py | 2 +- vllm/utils/__init__.py | 257 -------------- vllm/utils/importlib.py | 326 ++++++++++++++++++ vllm/v1/engine/core.py | 2 +- vllm/v1/executor/abstract.py | 2 +- vllm/v1/structured_output/__init__.py | 2 +- vllm/v1/structured_output/backend_guidance.py | 2 +- .../backend_lm_format_enforcer.py | 2 +- vllm/v1/structured_output/backend_outlines.py | 2 +- vllm/v1/structured_output/backend_xgrammar.py | 2 +- vllm/v1/structured_output/utils.py | 2 +- vllm/v1/worker/worker_base.py | 2 +- 41 files changed, 417 insertions(+), 335 deletions(-) create mode 100644 tests/utils_/test_importlib.py create mode 100644 vllm/utils/importlib.py diff --git a/tests/model_executor/model_loader/tensorizer_loader/test_tensorizer.py b/tests/model_executor/model_loader/tensorizer_loader/test_tensorizer.py index 57db1f98baed..c2829e202e6c 100644 --- a/tests/model_executor/model_loader/tensorizer_loader/test_tensorizer.py +++ b/tests/model_executor/model_loader/tensorizer_loader/test_tensorizer.py @@ -27,7 +27,7 @@ from vllm.model_executor.model_loader.tensorizer_loader import ( BLACKLISTED_TENSORIZER_ARGS, ) -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule from .conftest import DummyExecutor, assert_from_collective_rpc diff --git a/tests/utils_/test_importlib.py b/tests/utils_/test_importlib.py new file mode 100644 index 000000000000..8d0ca649eca8 --- /dev/null +++ b/tests/utils_/test_importlib.py @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +import pytest + +from vllm.utils.importlib import PlaceholderModule + + +def _raises_module_not_found(): + return pytest.raises(ModuleNotFoundError, match="No module named") + + +def test_placeholder_module_error_handling(): + placeholder = PlaceholderModule("placeholder_1234") + + with _raises_module_not_found(): + int(placeholder) + + with _raises_module_not_found(): + placeholder() + + with _raises_module_not_found(): + _ = placeholder.some_attr + + with _raises_module_not_found(): + # Test conflict with internal __name attribute + _ = placeholder.name + + # OK to print the placeholder or use it in a f-string + _ = repr(placeholder) + _ = str(placeholder) + + # No error yet; only error when it is used downstream + placeholder_attr = placeholder.placeholder_attr("attr") + + with _raises_module_not_found(): + int(placeholder_attr) + + with _raises_module_not_found(): + placeholder_attr() + + with _raises_module_not_found(): + _ = placeholder_attr.some_attr + + with _raises_module_not_found(): + # Test conflict with internal __module attribute + _ = placeholder_attr.module diff --git a/tests/utils_/test_utils.py b/tests/utils_/test_utils.py index efc83c0a31b8..8b9411975e15 100644 --- a/tests/utils_/test_utils.py +++ b/tests/utils_/test_utils.py @@ -24,7 +24,6 @@ from vllm.utils import ( FlexibleArgumentParser, MemorySnapshot, - PlaceholderModule, bind_kv_cache, common_broadcastable_dtype, current_stream, @@ -475,46 +474,6 @@ def test_common_broadcastable_dtype(dtypes, expected_result): assert common_broadcastable_dtype(dtypes) == expected_result -def test_placeholder_module_error_handling(): - placeholder = PlaceholderModule("placeholder_1234") - - def build_ctx(): - return pytest.raises(ModuleNotFoundError, match="No module named") - - with build_ctx(): - int(placeholder) - - with build_ctx(): - placeholder() - - with build_ctx(): - _ = placeholder.some_attr - - with build_ctx(): - # Test conflict with internal __name attribute - _ = placeholder.name - - # OK to print the placeholder or use it in a f-string - _ = repr(placeholder) - _ = str(placeholder) - - # No error yet; only error when it is used downstream - placeholder_attr = placeholder.placeholder_attr("attr") - - with build_ctx(): - int(placeholder_attr) - - with build_ctx(): - placeholder_attr() - - with build_ctx(): - _ = placeholder_attr.some_attr - - with build_ctx(): - # Test conflict with internal __module attribute - _ = placeholder_attr.module - - def test_model_specification( parser_with_config, cli_config_file, cli_config_file_with_model ): diff --git a/tests/v1/attention/utils.py b/tests/v1/attention/utils.py index 66a0169cbbd0..23488791ee27 100644 --- a/tests/v1/attention/utils.py +++ b/tests/v1/attention/utils.py @@ -20,7 +20,7 @@ VllmConfig, ) from vllm.config.model import ModelDType -from vllm.utils import resolve_obj_by_qualname +from vllm.utils.importlib import resolve_obj_by_qualname from vllm.v1.attention.backends.utils import ( AttentionMetadataBuilder, CommonAttentionMetadata, diff --git a/vllm/assets/audio.py b/vllm/assets/audio.py index 61c2dbf55fe3..92087f7f5d3c 100644 --- a/vllm/assets/audio.py +++ b/vllm/assets/audio.py @@ -8,7 +8,7 @@ import numpy.typing as npt -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule from .base import VLLM_S3_BUCKET_URL, get_vllm_public_assets diff --git a/vllm/assets/video.py b/vllm/assets/video.py index 277c8ea1bf0d..0e960cccfec1 100644 --- a/vllm/assets/video.py +++ b/vllm/assets/video.py @@ -10,7 +10,7 @@ from huggingface_hub import hf_hub_download from PIL import Image -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule from .base import get_cache_dir diff --git a/vllm/attention/backends/registry.py b/vllm/attention/backends/registry.py index dc6de483d6ae..927935cf55f3 100644 --- a/vllm/attention/backends/registry.py +++ b/vllm/attention/backends/registry.py @@ -4,7 +4,7 @@ import enum -from vllm.utils import resolve_obj_by_qualname +from vllm.utils.importlib import resolve_obj_by_qualname class _Backend(enum.Enum): diff --git a/vllm/attention/selector.py b/vllm/attention/selector.py index 187274133904..87d2db0b4dab 100644 --- a/vllm/attention/selector.py +++ b/vllm/attention/selector.py @@ -13,7 +13,8 @@ from vllm.attention.backends.abstract import AttentionBackend from vllm.attention.backends.registry import _Backend, backend_name_to_enum from vllm.logger import init_logger -from vllm.utils import STR_BACKEND_ENV_VAR, resolve_obj_by_qualname +from vllm.utils import STR_BACKEND_ENV_VAR +from vllm.utils.importlib import resolve_obj_by_qualname logger = init_logger(__name__) diff --git a/vllm/benchmarks/datasets.py b/vllm/benchmarks/datasets.py index 20a15bbc31e3..72af30be8aab 100644 --- a/vllm/benchmarks/datasets.py +++ b/vllm/benchmarks/datasets.py @@ -39,7 +39,7 @@ from vllm.multimodal import MultiModalDataDict from vllm.multimodal.image import convert_image_mode from vllm.transformers_utils.tokenizer import AnyTokenizer -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule try: from datasets import load_dataset diff --git a/vllm/compilation/backends.py b/vllm/compilation/backends.py index 91be7e85af51..c77173209502 100644 --- a/vllm/compilation/backends.py +++ b/vllm/compilation/backends.py @@ -24,7 +24,8 @@ from vllm.config import CompilationConfig, CUDAGraphMode, VllmConfig from vllm.logger import init_logger from vllm.platforms import current_platform -from vllm.utils import is_torch_equal_or_newer, resolve_obj_by_qualname +from vllm.utils import is_torch_equal_or_newer +from vllm.utils.importlib import resolve_obj_by_qualname from .caching import VllmSerializableFunction from .compiler_interface import ( diff --git a/vllm/compilation/decorators.py b/vllm/compilation/decorators.py index 20d4681e2c78..f24c528fcaee 100644 --- a/vllm/compilation/decorators.py +++ b/vllm/compilation/decorators.py @@ -21,7 +21,8 @@ from vllm.config import CompilationMode, VllmConfig, set_current_vllm_config from vllm.logger import init_logger from vllm.sequence import IntermediateTensors -from vllm.utils import resolve_obj_by_qualname, supports_dynamo +from vllm.utils import supports_dynamo +from vllm.utils.importlib import resolve_obj_by_qualname from .monitor import start_monitoring_torch_compile diff --git a/vllm/config/compilation.py b/vllm/config/compilation.py index a34fb0bf920c..bd71f4ca477b 100644 --- a/vllm/config/compilation.py +++ b/vllm/config/compilation.py @@ -16,7 +16,8 @@ from vllm.config.utils import config from vllm.logger import init_logger from vllm.platforms import current_platform -from vllm.utils import is_torch_equal_or_newer, resolve_obj_by_qualname +from vllm.utils import is_torch_equal_or_newer +from vllm.utils.importlib import resolve_obj_by_qualname if TYPE_CHECKING: from vllm.config import VllmConfig diff --git a/vllm/config/model.py b/vllm/config/model.py index ebad9bfb9c90..49e4621ef65f 100644 --- a/vllm/config/model.py +++ b/vllm/config/model.py @@ -41,7 +41,8 @@ ) from vllm.transformers_utils.runai_utils import ObjectStorageModel, is_runai_obj_uri from vllm.transformers_utils.utils import maybe_model_redirect -from vllm.utils import LayerBlockType, LazyLoader, common_broadcastable_dtype +from vllm.utils import LayerBlockType, common_broadcastable_dtype +from vllm.utils.importlib import LazyLoader if TYPE_CHECKING: from transformers import PretrainedConfig diff --git a/vllm/config/speculative.py b/vllm/config/speculative.py index aa254a9b35f6..4e9a553cf55e 100644 --- a/vllm/config/speculative.py +++ b/vllm/config/speculative.py @@ -13,7 +13,7 @@ from vllm.config.parallel import ParallelConfig from vllm.config.utils import config from vllm.logger import init_logger -from vllm.utils import LazyLoader +from vllm.utils.importlib import LazyLoader if TYPE_CHECKING: from transformers import PretrainedConfig diff --git a/vllm/distributed/parallel_state.py b/vllm/distributed/parallel_state.py index 67a8c6f7c053..b5da72146b93 100644 --- a/vllm/distributed/parallel_state.py +++ b/vllm/distributed/parallel_state.py @@ -52,9 +52,9 @@ from vllm.utils import ( direct_register_custom_op, get_distributed_init_method, - resolve_obj_by_qualname, supports_custom_op, ) +from vllm.utils.importlib import resolve_obj_by_qualname @dataclass diff --git a/vllm/entrypoints/openai/protocol.py b/vllm/entrypoints/openai/protocol.py index 5b8a118280da..d3f96a8152ee 100644 --- a/vllm/entrypoints/openai/protocol.py +++ b/vllm/entrypoints/openai/protocol.py @@ -81,7 +81,8 @@ SamplingParams, StructuredOutputsParams, ) -from vllm.utils import random_uuid, resolve_obj_by_qualname +from vllm.utils import random_uuid +from vllm.utils.importlib import resolve_obj_by_qualname EMBED_DTYPE_TO_TORCH_DTYPE = { "float32": torch.float32, diff --git a/vllm/entrypoints/openai/speech_to_text.py b/vllm/entrypoints/openai/speech_to_text.py index e012f43260c2..0a69e3fb617d 100644 --- a/vllm/entrypoints/openai/speech_to_text.py +++ b/vllm/entrypoints/openai/speech_to_text.py @@ -32,7 +32,7 @@ from vllm.logger import init_logger from vllm.model_executor.models import SupportsTranscription from vllm.outputs import RequestOutput -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule try: import librosa diff --git a/vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py b/vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py index c7363e442cdd..ebe5bbc1a63b 100644 --- a/vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py +++ b/vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py @@ -12,8 +12,8 @@ ) from vllm.logger import init_logger from vllm.transformers_utils.tokenizer import AnyTokenizer -from vllm.utils import import_from_path from vllm.utils.collections import is_list_of +from vllm.utils.importlib import import_from_path logger = init_logger(__name__) diff --git a/vllm/lora/punica_wrapper/punica_selector.py b/vllm/lora/punica_wrapper/punica_selector.py index c017721803fe..929e43310ca7 100644 --- a/vllm/lora/punica_wrapper/punica_selector.py +++ b/vllm/lora/punica_wrapper/punica_selector.py @@ -3,7 +3,7 @@ from vllm.logger import init_logger from vllm.platforms import current_platform -from vllm.utils import resolve_obj_by_qualname +from vllm.utils.importlib import resolve_obj_by_qualname from .punica_base import PunicaWrapperBase diff --git a/vllm/model_executor/layers/pooler.py b/vllm/model_executor/layers/pooler.py index 84e176f0ea89..06a51daf96a2 100644 --- a/vllm/model_executor/layers/pooler.py +++ b/vllm/model_executor/layers/pooler.py @@ -17,7 +17,7 @@ from vllm.model_executor.models.adapters import _load_st_projector from vllm.pooling_params import PoolingParams from vllm.tasks import PoolingTask -from vllm.utils import resolve_obj_by_qualname +from vllm.utils.importlib import resolve_obj_by_qualname from vllm.v1.outputs import PoolerOutput from vllm.v1.pool.metadata import PoolingCursor, PoolingMetadata diff --git a/vllm/model_executor/model_loader/tensorizer.py b/vllm/model_executor/model_loader/tensorizer.py index 4ebfba65ac80..052ad7ea0d28 100644 --- a/vllm/model_executor/model_loader/tensorizer.py +++ b/vllm/model_executor/model_loader/tensorizer.py @@ -26,7 +26,8 @@ from vllm.logger import init_logger from vllm.model_executor.layers.vocab_parallel_embedding import VocabParallelEmbedding from vllm.platforms import current_platform -from vllm.utils import FlexibleArgumentParser, PlaceholderModule +from vllm.utils import FlexibleArgumentParser +from vllm.utils.importlib import PlaceholderModule if TYPE_CHECKING: from vllm.engine.arg_utils import EngineArgs diff --git a/vllm/model_executor/model_loader/weight_utils.py b/vllm/model_executor/model_loader/weight_utils.py index c2d68029f4c7..f5dd2a6352fa 100644 --- a/vllm/model_executor/model_loader/weight_utils.py +++ b/vllm/model_executor/model_loader/weight_utils.py @@ -34,7 +34,7 @@ get_quantization_config, ) from vllm.platforms import current_platform -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule try: from runai_model_streamer import SafetensorsStreamer diff --git a/vllm/multimodal/audio.py b/vllm/multimodal/audio.py index a483837d4fb6..8b6d854e3bcc 100644 --- a/vllm/multimodal/audio.py +++ b/vllm/multimodal/audio.py @@ -8,7 +8,7 @@ import numpy as np import numpy.typing as npt -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule from .base import MediaIO diff --git a/vllm/multimodal/inputs.py b/vllm/multimodal/inputs.py index 9eab33b45e8a..12d1c7809686 100644 --- a/vllm/multimodal/inputs.py +++ b/vllm/multimodal/inputs.py @@ -22,8 +22,8 @@ import numpy as np from typing_extensions import NotRequired, TypeVar, deprecated -from vllm.utils import LazyLoader from vllm.utils.collections import full_groupby, is_list_of +from vllm.utils.importlib import LazyLoader from vllm.utils.jsontree import json_map_leaves if TYPE_CHECKING: diff --git a/vllm/multimodal/parse.py b/vllm/multimodal/parse.py index 71e577f0c0ad..41e3d11e3394 100644 --- a/vllm/multimodal/parse.py +++ b/vllm/multimodal/parse.py @@ -19,8 +19,8 @@ import torch from typing_extensions import assert_never -from vllm.utils import LazyLoader from vllm.utils.collections import is_list_of +from vllm.utils.importlib import LazyLoader from .audio import AudioResampler from .inputs import ( diff --git a/vllm/platforms/__init__.py b/vllm/platforms/__init__.py index b9140b4fe676..f11b47c17aab 100644 --- a/vllm/platforms/__init__.py +++ b/vllm/platforms/__init__.py @@ -7,7 +7,8 @@ from vllm import envs from vllm.plugins import PLATFORM_PLUGINS_GROUP, load_plugins_by_group -from vllm.utils import resolve_obj_by_qualname, supports_xccl +from vllm.utils import supports_xccl +from vllm.utils.importlib import resolve_obj_by_qualname from .interface import CpuArchEnum, Platform, PlatformEnum diff --git a/vllm/plugins/io_processors/__init__.py b/vllm/plugins/io_processors/__init__.py index c7b01ae34144..3318c6c93906 100644 --- a/vllm/plugins/io_processors/__init__.py +++ b/vllm/plugins/io_processors/__init__.py @@ -6,7 +6,7 @@ from vllm.config import VllmConfig from vllm.plugins import IO_PROCESSOR_PLUGINS_GROUP, load_plugins_by_group from vllm.plugins.io_processors.interface import IOProcessor -from vllm.utils import resolve_obj_by_qualname +from vllm.utils.importlib import resolve_obj_by_qualname logger = logging.getLogger(__name__) diff --git a/vllm/reasoning/abs_reasoning_parsers.py b/vllm/reasoning/abs_reasoning_parsers.py index cbebca09e7b8..9325ee1d6227 100644 --- a/vllm/reasoning/abs_reasoning_parsers.py +++ b/vllm/reasoning/abs_reasoning_parsers.py @@ -8,8 +8,8 @@ from typing import TYPE_CHECKING, Any from vllm.logger import init_logger -from vllm.utils import import_from_path from vllm.utils.collections import is_list_of +from vllm.utils.importlib import import_from_path if TYPE_CHECKING: from vllm.entrypoints.openai.protocol import ( diff --git a/vllm/transformers_utils/runai_utils.py b/vllm/transformers_utils/runai_utils.py index 3f61a22adeb9..ede2980c296d 100644 --- a/vllm/transformers_utils/runai_utils.py +++ b/vllm/transformers_utils/runai_utils.py @@ -9,7 +9,7 @@ from vllm import envs from vllm.assets.base import get_cache_dir from vllm.logger import init_logger -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule logger = init_logger(__name__) diff --git a/vllm/transformers_utils/s3_utils.py b/vllm/transformers_utils/s3_utils.py index c580361f92f9..f5608b4b9013 100644 --- a/vllm/transformers_utils/s3_utils.py +++ b/vllm/transformers_utils/s3_utils.py @@ -4,7 +4,7 @@ import fnmatch from typing import TYPE_CHECKING, Optional -from vllm.utils import PlaceholderModule +from vllm.utils.importlib import PlaceholderModule if TYPE_CHECKING: from botocore.client import BaseClient diff --git a/vllm/utils/__init__.py b/vllm/utils/__init__.py index 94cf6d0ff153..e8149c157e36 100644 --- a/vllm/utils/__init__.py +++ b/vllm/utils/__init__.py @@ -68,7 +68,6 @@ from packaging import version from packaging.version import Version from torch.library import Library -from typing_extensions import Never import vllm.envs as envs from vllm.logger import enable_trace_function_call, init_logger @@ -1560,253 +1559,6 @@ def get_cuda_view_from_cpu_tensor(cpu_tensor: torch.Tensor) -> torch.Tensor: return torch.ops._C.get_cuda_view_from_cpu_tensor(cpu_tensor) -def import_from_path(module_name: str, file_path: str | os.PathLike): - """ - Import a Python file according to its file path. - - Based on the official recipe: - https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly - """ - spec = importlib.util.spec_from_file_location(module_name, file_path) - if spec is None: - raise ModuleNotFoundError(f"No module named '{module_name}'") - - assert spec.loader is not None - - module = importlib.util.module_from_spec(spec) - sys.modules[module_name] = module - spec.loader.exec_module(module) - return module - - -@cache -def get_vllm_optional_dependencies(): - metadata = importlib.metadata.metadata("vllm") - requirements = metadata.get_all("Requires-Dist", []) - extras = metadata.get_all("Provides-Extra", []) - - return { - extra: [ - re.split(r";|>=|<=|==", req)[0] - for req in requirements - if req.endswith(f'extra == "{extra}"') - ] - for extra in extras - } - - -class _PlaceholderBase: - """ - Disallows downstream usage of placeholder modules. - - We need to explicitly override each dunder method because - [`__getattr__`][vllm.utils._PlaceholderBase.__getattr__] - is not called when they are accessed. - - Info: - [Special method lookup](https://docs.python.org/3/reference/datamodel.html#special-lookup) - """ - - def __getattr__(self, key: str) -> Never: - """ - The main class should implement this to throw an error - for attribute accesses representing downstream usage. - """ - raise NotImplementedError - - # [Basic customization] - - def __lt__(self, other: object): - return self.__getattr__("__lt__") - - def __le__(self, other: object): - return self.__getattr__("__le__") - - def __eq__(self, other: object): - return self.__getattr__("__eq__") - - def __ne__(self, other: object): - return self.__getattr__("__ne__") - - def __gt__(self, other: object): - return self.__getattr__("__gt__") - - def __ge__(self, other: object): - return self.__getattr__("__ge__") - - def __hash__(self): - return self.__getattr__("__hash__") - - def __bool__(self): - return self.__getattr__("__bool__") - - # [Callable objects] - - def __call__(self, *args: object, **kwargs: object): - return self.__getattr__("__call__") - - # [Container types] - - def __len__(self): - return self.__getattr__("__len__") - - def __getitem__(self, key: object): - return self.__getattr__("__getitem__") - - def __setitem__(self, key: object, value: object): - return self.__getattr__("__setitem__") - - def __delitem__(self, key: object): - return self.__getattr__("__delitem__") - - # __missing__ is optional according to __getitem__ specification, - # so it is skipped - - # __iter__ and __reversed__ have a default implementation - # based on __len__ and __getitem__, so they are skipped. - - # [Numeric Types] - - def __add__(self, other: object): - return self.__getattr__("__add__") - - def __sub__(self, other: object): - return self.__getattr__("__sub__") - - def __mul__(self, other: object): - return self.__getattr__("__mul__") - - def __matmul__(self, other: object): - return self.__getattr__("__matmul__") - - def __truediv__(self, other: object): - return self.__getattr__("__truediv__") - - def __floordiv__(self, other: object): - return self.__getattr__("__floordiv__") - - def __mod__(self, other: object): - return self.__getattr__("__mod__") - - def __divmod__(self, other: object): - return self.__getattr__("__divmod__") - - def __pow__(self, other: object, modulo: object = ...): - return self.__getattr__("__pow__") - - def __lshift__(self, other: object): - return self.__getattr__("__lshift__") - - def __rshift__(self, other: object): - return self.__getattr__("__rshift__") - - def __and__(self, other: object): - return self.__getattr__("__and__") - - def __xor__(self, other: object): - return self.__getattr__("__xor__") - - def __or__(self, other: object): - return self.__getattr__("__or__") - - # r* and i* methods have lower priority than - # the methods for left operand so they are skipped - - def __neg__(self): - return self.__getattr__("__neg__") - - def __pos__(self): - return self.__getattr__("__pos__") - - def __abs__(self): - return self.__getattr__("__abs__") - - def __invert__(self): - return self.__getattr__("__invert__") - - # __complex__, __int__ and __float__ have a default implementation - # based on __index__, so they are skipped. - - def __index__(self): - return self.__getattr__("__index__") - - def __round__(self, ndigits: object = ...): - return self.__getattr__("__round__") - - def __trunc__(self): - return self.__getattr__("__trunc__") - - def __floor__(self): - return self.__getattr__("__floor__") - - def __ceil__(self): - return self.__getattr__("__ceil__") - - # [Context managers] - - def __enter__(self): - return self.__getattr__("__enter__") - - def __exit__(self, *args: object, **kwargs: object): - return self.__getattr__("__exit__") - - -class PlaceholderModule(_PlaceholderBase): - """ - A placeholder object to use when a module does not exist. - - This enables more informative errors when trying to access attributes - of a module that does not exist. - """ - - def __init__(self, name: str) -> None: - super().__init__() - - # Apply name mangling to avoid conflicting with module attributes - self.__name = name - - def placeholder_attr(self, attr_path: str): - return _PlaceholderModuleAttr(self, attr_path) - - def __getattr__(self, key: str): - name = self.__name - - try: - importlib.import_module(name) - except ImportError as exc: - for extra, names in get_vllm_optional_dependencies().items(): - if name in names: - msg = f"Please install vllm[{extra}] for {extra} support" - raise ImportError(msg) from exc - - raise exc - - raise AssertionError( - "PlaceholderModule should not be used " - "when the original module can be imported" - ) - - -class _PlaceholderModuleAttr(_PlaceholderBase): - def __init__(self, module: PlaceholderModule, attr_path: str) -> None: - super().__init__() - - # Apply name mangling to avoid conflicting with module attributes - self.__module = module - self.__attr_path = attr_path - - def placeholder_attr(self, attr_path: str): - return _PlaceholderModuleAttr(self.__module, f"{self.__attr_path}.{attr_path}") - - def __getattr__(self, key: str): - getattr(self.__module, f"{self.__attr_path}.{key}") - - raise AssertionError( - "PlaceholderModule should not be used " - "when the original module can be imported" - ) - - # create a library to hold the custom op vllm_lib = Library("vllm", "FRAGMENT") # noqa @@ -1871,15 +1623,6 @@ def direct_register_custom_op( my_lib._register_fake(op_name, fake_impl) -def resolve_obj_by_qualname(qualname: str) -> Any: - """ - Resolve an object by its fully-qualified class name. - """ - module_name, obj_name = qualname.rsplit(".", 1) - module = importlib.import_module(module_name) - return getattr(module, obj_name) - - def kill_process_tree(pid: int): """ Kills all descendant processes of the given pid by sending SIGKILL. diff --git a/vllm/utils/importlib.py b/vllm/utils/importlib.py new file mode 100644 index 000000000000..f666b3e44cba --- /dev/null +++ b/vllm/utils/importlib.py @@ -0,0 +1,326 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +""" +Contains helpers related to importing modules. + +This is similar in concept to the `importlib` module. +""" + +import importlib.metadata +import importlib.util +import os +import sys +from functools import cache +from types import ModuleType +from typing import Any + +import regex as re +from typing_extensions import Never + + +def import_from_path(module_name: str, file_path: str | os.PathLike): + """ + Import a Python file according to its file path. + + Based on the official recipe: + https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly + """ + spec = importlib.util.spec_from_file_location(module_name, file_path) + if spec is None: + raise ModuleNotFoundError(f"No module named {module_name!r}") + + assert spec.loader is not None + + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + return module + + +def resolve_obj_by_qualname(qualname: str) -> Any: + """ + Resolve an object by its fully-qualified class name. + """ + module_name, obj_name = qualname.rsplit(".", 1) + module = importlib.import_module(module_name) + return getattr(module, obj_name) + + +@cache +def get_vllm_optional_dependencies(): + metadata = importlib.metadata.metadata("vllm") + requirements = metadata.get_all("Requires-Dist", []) + extras = metadata.get_all("Provides-Extra", []) + + return { + extra: [ + re.split(r";|>=|<=|==", req)[0] + for req in requirements + if req.endswith(f'extra == "{extra}"') + ] + for extra in extras + } + + +class _PlaceholderBase: + """ + Disallows downstream usage of placeholder modules. + + We need to explicitly override each dunder method because + [`__getattr__`][vllm.utils._PlaceholderBase.__getattr__] + is not called when they are accessed. + + Info: + [Special method lookup](https://docs.python.org/3/reference/datamodel.html#special-lookup) + """ + + def __getattr__(self, key: str) -> Never: + """ + The main class should implement this to throw an error + for attribute accesses representing downstream usage. + """ + raise NotImplementedError + + # [Basic customization] + + def __lt__(self, other: object): + return self.__getattr__("__lt__") + + def __le__(self, other: object): + return self.__getattr__("__le__") + + def __eq__(self, other: object): + return self.__getattr__("__eq__") + + def __ne__(self, other: object): + return self.__getattr__("__ne__") + + def __gt__(self, other: object): + return self.__getattr__("__gt__") + + def __ge__(self, other: object): + return self.__getattr__("__ge__") + + def __hash__(self): + return self.__getattr__("__hash__") + + def __bool__(self): + return self.__getattr__("__bool__") + + # [Callable objects] + + def __call__(self, *args: object, **kwargs: object): + return self.__getattr__("__call__") + + # [Container types] + + def __len__(self): + return self.__getattr__("__len__") + + def __getitem__(self, key: object): + return self.__getattr__("__getitem__") + + def __setitem__(self, key: object, value: object): + return self.__getattr__("__setitem__") + + def __delitem__(self, key: object): + return self.__getattr__("__delitem__") + + # __missing__ is optional according to __getitem__ specification, + # so it is skipped + + # __iter__ and __reversed__ have a default implementation + # based on __len__ and __getitem__, so they are skipped. + + # [Numeric Types] + + def __add__(self, other: object): + return self.__getattr__("__add__") + + def __sub__(self, other: object): + return self.__getattr__("__sub__") + + def __mul__(self, other: object): + return self.__getattr__("__mul__") + + def __matmul__(self, other: object): + return self.__getattr__("__matmul__") + + def __truediv__(self, other: object): + return self.__getattr__("__truediv__") + + def __floordiv__(self, other: object): + return self.__getattr__("__floordiv__") + + def __mod__(self, other: object): + return self.__getattr__("__mod__") + + def __divmod__(self, other: object): + return self.__getattr__("__divmod__") + + def __pow__(self, other: object, modulo: object = ...): + return self.__getattr__("__pow__") + + def __lshift__(self, other: object): + return self.__getattr__("__lshift__") + + def __rshift__(self, other: object): + return self.__getattr__("__rshift__") + + def __and__(self, other: object): + return self.__getattr__("__and__") + + def __xor__(self, other: object): + return self.__getattr__("__xor__") + + def __or__(self, other: object): + return self.__getattr__("__or__") + + # r* and i* methods have lower priority than + # the methods for left operand so they are skipped + + def __neg__(self): + return self.__getattr__("__neg__") + + def __pos__(self): + return self.__getattr__("__pos__") + + def __abs__(self): + return self.__getattr__("__abs__") + + def __invert__(self): + return self.__getattr__("__invert__") + + # __complex__, __int__ and __float__ have a default implementation + # based on __index__, so they are skipped. + + def __index__(self): + return self.__getattr__("__index__") + + def __round__(self, ndigits: object = ...): + return self.__getattr__("__round__") + + def __trunc__(self): + return self.__getattr__("__trunc__") + + def __floor__(self): + return self.__getattr__("__floor__") + + def __ceil__(self): + return self.__getattr__("__ceil__") + + # [Context managers] + + def __enter__(self): + return self.__getattr__("__enter__") + + def __exit__(self, *args: object, **kwargs: object): + return self.__getattr__("__exit__") + + +class PlaceholderModule(_PlaceholderBase): + """ + A placeholder object to use when a module does not exist. + + This enables more informative errors when trying to access attributes + of a module that does not exist. + """ + + def __init__(self, name: str) -> None: + super().__init__() + + # Apply name mangling to avoid conflicting with module attributes + self.__name = name + + def placeholder_attr(self, attr_path: str): + return _PlaceholderModuleAttr(self, attr_path) + + def __getattr__(self, key: str) -> Never: + name = self.__name + + try: + importlib.import_module(name) + except ImportError as exc: + for extra, names in get_vllm_optional_dependencies().items(): + if name in names: + msg = f"Please install vllm[{extra}] for {extra} support" + raise ImportError(msg) from exc + + raise exc + + raise AssertionError( + "PlaceholderModule should not be used " + "when the original module can be imported" + ) + + +class _PlaceholderModuleAttr(_PlaceholderBase): + def __init__(self, module: PlaceholderModule, attr_path: str) -> None: + super().__init__() + + # Apply name mangling to avoid conflicting with module attributes + self.__module = module + self.__attr_path = attr_path + + def placeholder_attr(self, attr_path: str): + return _PlaceholderModuleAttr(self.__module, f"{self.__attr_path}.{attr_path}") + + def __getattr__(self, key: str) -> Never: + getattr(self.__module, f"{self.__attr_path}.{key}") + + raise AssertionError( + "PlaceholderModule should not be used " + "when the original module can be imported" + ) + + +class LazyLoader(ModuleType): + """ + LazyLoader module borrowed from Tensorflow + https://github.com/tensorflow/tensorflow/blob/main/tensorflow/python/util/lazy_loader.py + with an addition of "module caching". + + Lazily import a module, mainly to avoid pulling in large dependencies. + Modules such as `xgrammar` might do additional side effects, so we + only want to use this when it is needed, delaying all eager effects + """ + + def __init__( + self, + local_name: str, + parent_module_globals: dict[str, Any], + name: str, + ): + self._local_name = local_name + self._parent_module_globals = parent_module_globals + self._module: ModuleType | None = None + + super().__init__(str(name)) + + def _load(self) -> ModuleType: + # Import the target module and insert it into the parent's namespace + try: + module = importlib.import_module(self.__name__) + self._parent_module_globals[self._local_name] = module + # The additional add to sys.modules + # ensures library is actually loaded. + sys.modules[self._local_name] = module + except ModuleNotFoundError as err: + raise err from None + + # Update this object's dict so that if someone keeps a + # reference to the LazyLoader, lookups are efficient + # (__getattr__ is only called on lookups that fail). + self.__dict__.update(module.__dict__) + return module + + def __getattr__(self, item: Any) -> Any: + if self._module is None: + self._module = self._load() + return getattr(self._module, item) + + def __dir__(self) -> list[str]: + if self._module is None: + self._module = self._load() + return dir(self._module) diff --git a/vllm/v1/engine/core.py b/vllm/v1/engine/core.py index a21f0715704a..fb3c47c9e0e4 100644 --- a/vllm/v1/engine/core.py +++ b/vllm/v1/engine/core.py @@ -32,10 +32,10 @@ decorate_logs, get_hash_fn_by_name, make_zmq_socket, - resolve_obj_by_qualname, set_process_title, ) from vllm.utils.gc_utils import maybe_attach_gc_debug_callback +from vllm.utils.importlib import resolve_obj_by_qualname from vllm.v1.core.kv_cache_utils import ( BlockHash, generate_scheduler_kv_cache_config, diff --git a/vllm/v1/executor/abstract.py b/vllm/v1/executor/abstract.py index 53617645f52c..167d6ff59659 100644 --- a/vllm/v1/executor/abstract.py +++ b/vllm/v1/executor/abstract.py @@ -14,7 +14,7 @@ ExecutorWithExternalLauncher as ExecutorWithExternalLauncherV0, ) from vllm.executor.uniproc_executor import UniProcExecutor as UniProcExecutorV0 # noqa -from vllm.utils import resolve_obj_by_qualname +from vllm.utils.importlib import resolve_obj_by_qualname from vllm.v1.core.sched.output import SchedulerOutput from vllm.v1.kv_cache_interface import KVCacheConfig, KVCacheSpec from vllm.v1.outputs import DraftTokenIds, ModelRunnerOutput diff --git a/vllm/v1/structured_output/__init__.py b/vllm/v1/structured_output/__init__.py index 8d7f4b5d6896..b641be008379 100644 --- a/vllm/v1/structured_output/__init__.py +++ b/vllm/v1/structured_output/__init__.py @@ -8,7 +8,7 @@ from vllm.logger import init_logger from vllm.reasoning import ReasoningParserManager from vllm.transformers_utils.tokenizer import init_tokenizer_from_configs -from vllm.utils import LazyLoader +from vllm.utils.importlib import LazyLoader from vllm.v1.structured_output.backend_guidance import GuidanceBackend from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, diff --git a/vllm/v1/structured_output/backend_guidance.py b/vllm/v1/structured_output/backend_guidance.py index 8e75b99f8481..beca182630dd 100644 --- a/vllm/v1/structured_output/backend_guidance.py +++ b/vllm/v1/structured_output/backend_guidance.py @@ -11,7 +11,7 @@ from vllm.logger import init_logger from vllm.sampling_params import SamplingParams -from vllm.utils import LazyLoader +from vllm.utils.importlib import LazyLoader from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, StructuredOutputGrammar, diff --git a/vllm/v1/structured_output/backend_lm_format_enforcer.py b/vllm/v1/structured_output/backend_lm_format_enforcer.py index c20e976d8487..650489c0e0c1 100644 --- a/vllm/v1/structured_output/backend_lm_format_enforcer.py +++ b/vllm/v1/structured_output/backend_lm_format_enforcer.py @@ -10,7 +10,7 @@ from transformers import PreTrainedTokenizerBase from vllm.sampling_params import SamplingParams -from vllm.utils import LazyLoader +from vllm.utils.importlib import LazyLoader from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, StructuredOutputGrammar, diff --git a/vllm/v1/structured_output/backend_outlines.py b/vllm/v1/structured_output/backend_outlines.py index 2355f8ab8f89..01ef9f935d3c 100644 --- a/vllm/v1/structured_output/backend_outlines.py +++ b/vllm/v1/structured_output/backend_outlines.py @@ -12,7 +12,7 @@ from regex import escape as regex_escape from vllm.sampling_params import SamplingParams -from vllm.utils import LazyLoader +from vllm.utils.importlib import LazyLoader from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, StructuredOutputGrammar, diff --git a/vllm/v1/structured_output/backend_xgrammar.py b/vllm/v1/structured_output/backend_xgrammar.py index 1b430157560c..60325fa373e6 100644 --- a/vllm/v1/structured_output/backend_xgrammar.py +++ b/vllm/v1/structured_output/backend_xgrammar.py @@ -11,7 +11,7 @@ from vllm.logger import init_logger from vllm.sampling_params import SamplingParams from vllm.transformers_utils.tokenizers.mistral import MistralTokenizer -from vllm.utils import LazyLoader +from vllm.utils.importlib import LazyLoader from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, StructuredOutputGrammar, diff --git a/vllm/v1/structured_output/utils.py b/vllm/v1/structured_output/utils.py index 4b793b9a72fd..06014e485a0d 100644 --- a/vllm/v1/structured_output/utils.py +++ b/vllm/v1/structured_output/utils.py @@ -13,7 +13,7 @@ import vllm.envs as envs from vllm.logger import init_logger -from vllm.utils import LazyLoader +from vllm.utils.importlib import LazyLoader if TYPE_CHECKING: import outlines_core as oc diff --git a/vllm/v1/worker/worker_base.py b/vllm/v1/worker/worker_base.py index 85436b443f7c..4368ddbd8f3e 100644 --- a/vllm/v1/worker/worker_base.py +++ b/vllm/v1/worker/worker_base.py @@ -15,11 +15,11 @@ from vllm.multimodal.cache import worker_receiver_cache_from_config from vllm.utils import ( enable_trace_function_call_for_thread, - resolve_obj_by_qualname, run_method, update_environment_variables, warn_for_unimplemented_methods, ) +from vllm.utils.importlib import resolve_obj_by_qualname from vllm.v1.kv_cache_interface import KVCacheSpec if TYPE_CHECKING: From 1cf89c854a4f902e2a0fac16594aff9d69599e53 Mon Sep 17 00:00:00 2001 From: DarkLight1337 Date: Thu, 16 Oct 2025 12:52:44 +0000 Subject: [PATCH 2/6] Fix Signed-off-by: DarkLight1337 --- vllm/utils/__init__.py | 52 ----------------------------------------- vllm/utils/importlib.py | 6 ++--- 2 files changed, 3 insertions(+), 55 deletions(-) diff --git a/vllm/utils/__init__.py b/vllm/utils/__init__.py index e8149c157e36..603f76353fcd 100644 --- a/vllm/utils/__init__.py +++ b/vllm/utils/__init__.py @@ -25,7 +25,6 @@ import threading import time import traceback -import types import uuid import warnings import weakref @@ -2170,57 +2169,6 @@ def wrapped_init(self, *args, **kwargs) -> None: return cls -class LazyLoader(types.ModuleType): - """ - LazyLoader module borrowed from Tensorflow - https://github.com/tensorflow/tensorflow/blob/main/tensorflow/python/util/lazy_loader.py - with an addition of "module caching". - - Lazily import a module, mainly to avoid pulling in large dependencies. - Modules such as `xgrammar` might do additional side effects, so we - only want to use this when it is needed, delaying all eager effects - """ - - def __init__( - self, - local_name: str, - parent_module_globals: dict[str, Any], - name: str, - ): - self._local_name = local_name - self._parent_module_globals = parent_module_globals - self._module: types.ModuleType | None = None - - super().__init__(str(name)) - - def _load(self) -> types.ModuleType: - # Import the target module and insert it into the parent's namespace - try: - module = importlib.import_module(self.__name__) - self._parent_module_globals[self._local_name] = module - # The additional add to sys.modules - # ensures library is actually loaded. - sys.modules[self._local_name] = module - except ModuleNotFoundError as err: - raise err from None - - # Update this object's dict so that if someone keeps a - # reference to the LazyLoader, lookups are efficient - # (__getattr__ is only called on lookups that fail). - self.__dict__.update(module.__dict__) - return module - - def __getattr__(self, item: Any) -> Any: - if self._module is None: - self._module = self._load() - return getattr(self._module, item) - - def __dir__(self) -> list[str]: - if self._module is None: - self._module = self._load() - return dir(self._module) - - @contextlib.contextmanager def cprofile_context(save_file: str | None = None): """Run a cprofile diff --git a/vllm/utils/importlib.py b/vllm/utils/importlib.py index f666b3e44cba..40bb999a44df 100644 --- a/vllm/utils/importlib.py +++ b/vllm/utils/importlib.py @@ -277,13 +277,13 @@ def __getattr__(self, key: str) -> Never: class LazyLoader(ModuleType): """ - LazyLoader module borrowed from Tensorflow - https://github.com/tensorflow/tensorflow/blob/main/tensorflow/python/util/lazy_loader.py + `LazyLoader` module borrowed from [Tensorflow] + (https://github.com/tensorflow/tensorflow/blob/main/tensorflow/python/util/lazy_loader.py) with an addition of "module caching". Lazily import a module, mainly to avoid pulling in large dependencies. Modules such as `xgrammar` might do additional side effects, so we - only want to use this when it is needed, delaying all eager effects + only want to use this when it is needed, delaying all eager effects. """ def __init__( From f5738b15bc0ffb4af55b059e50a43517e29b9074 Mon Sep 17 00:00:00 2001 From: DarkLight1337 Date: Thu, 16 Oct 2025 13:07:56 +0000 Subject: [PATCH 3/6] Avoid bad imports Signed-off-by: DarkLight1337 --- vllm/utils/__init__.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vllm/utils/__init__.py b/vllm/utils/__init__.py index 603f76353fcd..c6fc4134d28a 100644 --- a/vllm/utils/__init__.py +++ b/vllm/utils/__init__.py @@ -8,8 +8,6 @@ import getpass import hashlib import importlib -import importlib.metadata -import importlib.util import inspect import ipaddress import json @@ -799,8 +797,6 @@ def find_nccl_include_paths() -> list[str] | None: paths.append(inc) try: - import importlib.util - spec = importlib.util.find_spec("nvidia.nccl") if spec and getattr(spec, "submodule_search_locations", None): for loc in spec.submodule_search_locations: From ba86408b22711dfbc47708e2342a23b17ae560ef Mon Sep 17 00:00:00 2001 From: DarkLight1337 Date: Thu, 16 Oct 2025 13:27:19 +0000 Subject: [PATCH 4/6] Avoid conflict with `importlib` Signed-off-by: DarkLight1337 --- .../model_loader/tensorizer_loader/test_tensorizer.py | 2 +- tests/utils_/test_importlib.py | 2 +- tests/v1/attention/utils.py | 2 +- vllm/assets/audio.py | 2 +- vllm/assets/video.py | 2 +- vllm/attention/backends/registry.py | 2 +- vllm/attention/selector.py | 2 +- vllm/benchmarks/datasets.py | 2 +- vllm/compilation/backends.py | 2 +- vllm/compilation/decorators.py | 2 +- vllm/config/compilation.py | 2 +- vllm/config/model.py | 2 +- vllm/config/speculative.py | 2 +- vllm/distributed/parallel_state.py | 2 +- vllm/entrypoints/openai/protocol.py | 2 +- vllm/entrypoints/openai/speech_to_text.py | 2 +- vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py | 2 +- vllm/lora/punica_wrapper/punica_selector.py | 2 +- vllm/model_executor/layers/pooler.py | 2 +- vllm/model_executor/model_loader/tensorizer.py | 2 +- vllm/model_executor/model_loader/weight_utils.py | 2 +- vllm/multimodal/audio.py | 2 +- vllm/multimodal/inputs.py | 2 +- vllm/multimodal/parse.py | 2 +- vllm/platforms/__init__.py | 2 +- vllm/plugins/io_processors/__init__.py | 2 +- vllm/reasoning/abs_reasoning_parsers.py | 2 +- vllm/transformers_utils/runai_utils.py | 2 +- vllm/transformers_utils/s3_utils.py | 2 +- vllm/utils/{importlib.py => import_utils.py} | 0 vllm/v1/engine/core.py | 2 +- vllm/v1/executor/abstract.py | 2 +- vllm/v1/structured_output/__init__.py | 2 +- vllm/v1/structured_output/backend_guidance.py | 2 +- vllm/v1/structured_output/backend_lm_format_enforcer.py | 2 +- vllm/v1/structured_output/backend_outlines.py | 2 +- vllm/v1/structured_output/backend_xgrammar.py | 2 +- vllm/v1/structured_output/utils.py | 2 +- vllm/v1/worker/worker_base.py | 2 +- 39 files changed, 38 insertions(+), 38 deletions(-) rename vllm/utils/{importlib.py => import_utils.py} (100%) diff --git a/tests/model_executor/model_loader/tensorizer_loader/test_tensorizer.py b/tests/model_executor/model_loader/tensorizer_loader/test_tensorizer.py index c2829e202e6c..ed5129e1c820 100644 --- a/tests/model_executor/model_loader/tensorizer_loader/test_tensorizer.py +++ b/tests/model_executor/model_loader/tensorizer_loader/test_tensorizer.py @@ -27,7 +27,7 @@ from vllm.model_executor.model_loader.tensorizer_loader import ( BLACKLISTED_TENSORIZER_ARGS, ) -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule from .conftest import DummyExecutor, assert_from_collective_rpc diff --git a/tests/utils_/test_importlib.py b/tests/utils_/test_importlib.py index 8d0ca649eca8..d42685b3fc9a 100644 --- a/tests/utils_/test_importlib.py +++ b/tests/utils_/test_importlib.py @@ -2,7 +2,7 @@ # SPDX-FileCopyrightText: Copyright contributors to the vLLM project import pytest -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule def _raises_module_not_found(): diff --git a/tests/v1/attention/utils.py b/tests/v1/attention/utils.py index 23488791ee27..15ed7bdc835b 100644 --- a/tests/v1/attention/utils.py +++ b/tests/v1/attention/utils.py @@ -20,7 +20,7 @@ VllmConfig, ) from vllm.config.model import ModelDType -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from vllm.v1.attention.backends.utils import ( AttentionMetadataBuilder, CommonAttentionMetadata, diff --git a/vllm/assets/audio.py b/vllm/assets/audio.py index 92087f7f5d3c..b527ffcf9b18 100644 --- a/vllm/assets/audio.py +++ b/vllm/assets/audio.py @@ -8,7 +8,7 @@ import numpy.typing as npt -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule from .base import VLLM_S3_BUCKET_URL, get_vllm_public_assets diff --git a/vllm/assets/video.py b/vllm/assets/video.py index 0e960cccfec1..8818b5997004 100644 --- a/vllm/assets/video.py +++ b/vllm/assets/video.py @@ -10,7 +10,7 @@ from huggingface_hub import hf_hub_download from PIL import Image -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule from .base import get_cache_dir diff --git a/vllm/attention/backends/registry.py b/vllm/attention/backends/registry.py index 927935cf55f3..05d0159d0861 100644 --- a/vllm/attention/backends/registry.py +++ b/vllm/attention/backends/registry.py @@ -4,7 +4,7 @@ import enum -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname class _Backend(enum.Enum): diff --git a/vllm/attention/selector.py b/vllm/attention/selector.py index 87d2db0b4dab..9890d8d80cba 100644 --- a/vllm/attention/selector.py +++ b/vllm/attention/selector.py @@ -14,7 +14,7 @@ from vllm.attention.backends.registry import _Backend, backend_name_to_enum from vllm.logger import init_logger from vllm.utils import STR_BACKEND_ENV_VAR -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname logger = init_logger(__name__) diff --git a/vllm/benchmarks/datasets.py b/vllm/benchmarks/datasets.py index 72af30be8aab..652e4b122373 100644 --- a/vllm/benchmarks/datasets.py +++ b/vllm/benchmarks/datasets.py @@ -39,7 +39,7 @@ from vllm.multimodal import MultiModalDataDict from vllm.multimodal.image import convert_image_mode from vllm.transformers_utils.tokenizer import AnyTokenizer -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule try: from datasets import load_dataset diff --git a/vllm/compilation/backends.py b/vllm/compilation/backends.py index c77173209502..9e6053bc3028 100644 --- a/vllm/compilation/backends.py +++ b/vllm/compilation/backends.py @@ -25,7 +25,7 @@ from vllm.logger import init_logger from vllm.platforms import current_platform from vllm.utils import is_torch_equal_or_newer -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from .caching import VllmSerializableFunction from .compiler_interface import ( diff --git a/vllm/compilation/decorators.py b/vllm/compilation/decorators.py index f24c528fcaee..811cbef4afab 100644 --- a/vllm/compilation/decorators.py +++ b/vllm/compilation/decorators.py @@ -22,7 +22,7 @@ from vllm.logger import init_logger from vllm.sequence import IntermediateTensors from vllm.utils import supports_dynamo -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from .monitor import start_monitoring_torch_compile diff --git a/vllm/config/compilation.py b/vllm/config/compilation.py index bd71f4ca477b..ff43e4e826df 100644 --- a/vllm/config/compilation.py +++ b/vllm/config/compilation.py @@ -17,7 +17,7 @@ from vllm.logger import init_logger from vllm.platforms import current_platform from vllm.utils import is_torch_equal_or_newer -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname if TYPE_CHECKING: from vllm.config import VllmConfig diff --git a/vllm/config/model.py b/vllm/config/model.py index 49e4621ef65f..6c723624fbc2 100644 --- a/vllm/config/model.py +++ b/vllm/config/model.py @@ -42,7 +42,7 @@ from vllm.transformers_utils.runai_utils import ObjectStorageModel, is_runai_obj_uri from vllm.transformers_utils.utils import maybe_model_redirect from vllm.utils import LayerBlockType, common_broadcastable_dtype -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader if TYPE_CHECKING: from transformers import PretrainedConfig diff --git a/vllm/config/speculative.py b/vllm/config/speculative.py index 4e9a553cf55e..a5bc4d1fa3c0 100644 --- a/vllm/config/speculative.py +++ b/vllm/config/speculative.py @@ -13,7 +13,7 @@ from vllm.config.parallel import ParallelConfig from vllm.config.utils import config from vllm.logger import init_logger -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader if TYPE_CHECKING: from transformers import PretrainedConfig diff --git a/vllm/distributed/parallel_state.py b/vllm/distributed/parallel_state.py index b5da72146b93..132fb9049163 100644 --- a/vllm/distributed/parallel_state.py +++ b/vllm/distributed/parallel_state.py @@ -54,7 +54,7 @@ get_distributed_init_method, supports_custom_op, ) -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname @dataclass diff --git a/vllm/entrypoints/openai/protocol.py b/vllm/entrypoints/openai/protocol.py index d3f96a8152ee..e73752b9d50b 100644 --- a/vllm/entrypoints/openai/protocol.py +++ b/vllm/entrypoints/openai/protocol.py @@ -82,7 +82,7 @@ StructuredOutputsParams, ) from vllm.utils import random_uuid -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname EMBED_DTYPE_TO_TORCH_DTYPE = { "float32": torch.float32, diff --git a/vllm/entrypoints/openai/speech_to_text.py b/vllm/entrypoints/openai/speech_to_text.py index 0a69e3fb617d..46139642c50c 100644 --- a/vllm/entrypoints/openai/speech_to_text.py +++ b/vllm/entrypoints/openai/speech_to_text.py @@ -32,7 +32,7 @@ from vllm.logger import init_logger from vllm.model_executor.models import SupportsTranscription from vllm.outputs import RequestOutput -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule try: import librosa diff --git a/vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py b/vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py index ebe5bbc1a63b..34ec9f8110e6 100644 --- a/vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py +++ b/vllm/entrypoints/openai/tool_parsers/abstract_tool_parser.py @@ -13,7 +13,7 @@ from vllm.logger import init_logger from vllm.transformers_utils.tokenizer import AnyTokenizer from vllm.utils.collections import is_list_of -from vllm.utils.importlib import import_from_path +from vllm.utils.import_utils import import_from_path logger = init_logger(__name__) diff --git a/vllm/lora/punica_wrapper/punica_selector.py b/vllm/lora/punica_wrapper/punica_selector.py index 929e43310ca7..d8763e913e3a 100644 --- a/vllm/lora/punica_wrapper/punica_selector.py +++ b/vllm/lora/punica_wrapper/punica_selector.py @@ -3,7 +3,7 @@ from vllm.logger import init_logger from vllm.platforms import current_platform -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from .punica_base import PunicaWrapperBase diff --git a/vllm/model_executor/layers/pooler.py b/vllm/model_executor/layers/pooler.py index 06a51daf96a2..a8c66315684e 100644 --- a/vllm/model_executor/layers/pooler.py +++ b/vllm/model_executor/layers/pooler.py @@ -17,7 +17,7 @@ from vllm.model_executor.models.adapters import _load_st_projector from vllm.pooling_params import PoolingParams from vllm.tasks import PoolingTask -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from vllm.v1.outputs import PoolerOutput from vllm.v1.pool.metadata import PoolingCursor, PoolingMetadata diff --git a/vllm/model_executor/model_loader/tensorizer.py b/vllm/model_executor/model_loader/tensorizer.py index 052ad7ea0d28..2890a2c6d702 100644 --- a/vllm/model_executor/model_loader/tensorizer.py +++ b/vllm/model_executor/model_loader/tensorizer.py @@ -27,7 +27,7 @@ from vllm.model_executor.layers.vocab_parallel_embedding import VocabParallelEmbedding from vllm.platforms import current_platform from vllm.utils import FlexibleArgumentParser -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule if TYPE_CHECKING: from vllm.engine.arg_utils import EngineArgs diff --git a/vllm/model_executor/model_loader/weight_utils.py b/vllm/model_executor/model_loader/weight_utils.py index f5dd2a6352fa..a16ce3db3003 100644 --- a/vllm/model_executor/model_loader/weight_utils.py +++ b/vllm/model_executor/model_loader/weight_utils.py @@ -34,7 +34,7 @@ get_quantization_config, ) from vllm.platforms import current_platform -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule try: from runai_model_streamer import SafetensorsStreamer diff --git a/vllm/multimodal/audio.py b/vllm/multimodal/audio.py index 8b6d854e3bcc..53052ddc6343 100644 --- a/vllm/multimodal/audio.py +++ b/vllm/multimodal/audio.py @@ -8,7 +8,7 @@ import numpy as np import numpy.typing as npt -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule from .base import MediaIO diff --git a/vllm/multimodal/inputs.py b/vllm/multimodal/inputs.py index 12d1c7809686..e3a0fa562e79 100644 --- a/vllm/multimodal/inputs.py +++ b/vllm/multimodal/inputs.py @@ -23,7 +23,7 @@ from typing_extensions import NotRequired, TypeVar, deprecated from vllm.utils.collections import full_groupby, is_list_of -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader from vllm.utils.jsontree import json_map_leaves if TYPE_CHECKING: diff --git a/vllm/multimodal/parse.py b/vllm/multimodal/parse.py index 41e3d11e3394..8cb402e951da 100644 --- a/vllm/multimodal/parse.py +++ b/vllm/multimodal/parse.py @@ -20,7 +20,7 @@ from typing_extensions import assert_never from vllm.utils.collections import is_list_of -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader from .audio import AudioResampler from .inputs import ( diff --git a/vllm/platforms/__init__.py b/vllm/platforms/__init__.py index f11b47c17aab..8942a3206e6d 100644 --- a/vllm/platforms/__init__.py +++ b/vllm/platforms/__init__.py @@ -8,7 +8,7 @@ from vllm import envs from vllm.plugins import PLATFORM_PLUGINS_GROUP, load_plugins_by_group from vllm.utils import supports_xccl -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from .interface import CpuArchEnum, Platform, PlatformEnum diff --git a/vllm/plugins/io_processors/__init__.py b/vllm/plugins/io_processors/__init__.py index 3318c6c93906..b3a3b548781e 100644 --- a/vllm/plugins/io_processors/__init__.py +++ b/vllm/plugins/io_processors/__init__.py @@ -6,7 +6,7 @@ from vllm.config import VllmConfig from vllm.plugins import IO_PROCESSOR_PLUGINS_GROUP, load_plugins_by_group from vllm.plugins.io_processors.interface import IOProcessor -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname logger = logging.getLogger(__name__) diff --git a/vllm/reasoning/abs_reasoning_parsers.py b/vllm/reasoning/abs_reasoning_parsers.py index 9325ee1d6227..3a595a3076eb 100644 --- a/vllm/reasoning/abs_reasoning_parsers.py +++ b/vllm/reasoning/abs_reasoning_parsers.py @@ -9,7 +9,7 @@ from vllm.logger import init_logger from vllm.utils.collections import is_list_of -from vllm.utils.importlib import import_from_path +from vllm.utils.import_utils import import_from_path if TYPE_CHECKING: from vllm.entrypoints.openai.protocol import ( diff --git a/vllm/transformers_utils/runai_utils.py b/vllm/transformers_utils/runai_utils.py index ede2980c296d..eac4294bb59c 100644 --- a/vllm/transformers_utils/runai_utils.py +++ b/vllm/transformers_utils/runai_utils.py @@ -9,7 +9,7 @@ from vllm import envs from vllm.assets.base import get_cache_dir from vllm.logger import init_logger -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule logger = init_logger(__name__) diff --git a/vllm/transformers_utils/s3_utils.py b/vllm/transformers_utils/s3_utils.py index f5608b4b9013..a5a3af6538b8 100644 --- a/vllm/transformers_utils/s3_utils.py +++ b/vllm/transformers_utils/s3_utils.py @@ -4,7 +4,7 @@ import fnmatch from typing import TYPE_CHECKING, Optional -from vllm.utils.importlib import PlaceholderModule +from vllm.utils.import_utils import PlaceholderModule if TYPE_CHECKING: from botocore.client import BaseClient diff --git a/vllm/utils/importlib.py b/vllm/utils/import_utils.py similarity index 100% rename from vllm/utils/importlib.py rename to vllm/utils/import_utils.py diff --git a/vllm/v1/engine/core.py b/vllm/v1/engine/core.py index fb3c47c9e0e4..0ca60ce5cf9a 100644 --- a/vllm/v1/engine/core.py +++ b/vllm/v1/engine/core.py @@ -35,7 +35,7 @@ set_process_title, ) from vllm.utils.gc_utils import maybe_attach_gc_debug_callback -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from vllm.v1.core.kv_cache_utils import ( BlockHash, generate_scheduler_kv_cache_config, diff --git a/vllm/v1/executor/abstract.py b/vllm/v1/executor/abstract.py index 167d6ff59659..2a7e052f1329 100644 --- a/vllm/v1/executor/abstract.py +++ b/vllm/v1/executor/abstract.py @@ -14,7 +14,7 @@ ExecutorWithExternalLauncher as ExecutorWithExternalLauncherV0, ) from vllm.executor.uniproc_executor import UniProcExecutor as UniProcExecutorV0 # noqa -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from vllm.v1.core.sched.output import SchedulerOutput from vllm.v1.kv_cache_interface import KVCacheConfig, KVCacheSpec from vllm.v1.outputs import DraftTokenIds, ModelRunnerOutput diff --git a/vllm/v1/structured_output/__init__.py b/vllm/v1/structured_output/__init__.py index b641be008379..4fb26ab1cefa 100644 --- a/vllm/v1/structured_output/__init__.py +++ b/vllm/v1/structured_output/__init__.py @@ -8,7 +8,7 @@ from vllm.logger import init_logger from vllm.reasoning import ReasoningParserManager from vllm.transformers_utils.tokenizer import init_tokenizer_from_configs -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader from vllm.v1.structured_output.backend_guidance import GuidanceBackend from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, diff --git a/vllm/v1/structured_output/backend_guidance.py b/vllm/v1/structured_output/backend_guidance.py index beca182630dd..00a625e103bd 100644 --- a/vllm/v1/structured_output/backend_guidance.py +++ b/vllm/v1/structured_output/backend_guidance.py @@ -11,7 +11,7 @@ from vllm.logger import init_logger from vllm.sampling_params import SamplingParams -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, StructuredOutputGrammar, diff --git a/vllm/v1/structured_output/backend_lm_format_enforcer.py b/vllm/v1/structured_output/backend_lm_format_enforcer.py index 650489c0e0c1..150c57feda0f 100644 --- a/vllm/v1/structured_output/backend_lm_format_enforcer.py +++ b/vllm/v1/structured_output/backend_lm_format_enforcer.py @@ -10,7 +10,7 @@ from transformers import PreTrainedTokenizerBase from vllm.sampling_params import SamplingParams -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, StructuredOutputGrammar, diff --git a/vllm/v1/structured_output/backend_outlines.py b/vllm/v1/structured_output/backend_outlines.py index 01ef9f935d3c..1e01788076d5 100644 --- a/vllm/v1/structured_output/backend_outlines.py +++ b/vllm/v1/structured_output/backend_outlines.py @@ -12,7 +12,7 @@ from regex import escape as regex_escape from vllm.sampling_params import SamplingParams -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, StructuredOutputGrammar, diff --git a/vllm/v1/structured_output/backend_xgrammar.py b/vllm/v1/structured_output/backend_xgrammar.py index 60325fa373e6..074781fb6604 100644 --- a/vllm/v1/structured_output/backend_xgrammar.py +++ b/vllm/v1/structured_output/backend_xgrammar.py @@ -11,7 +11,7 @@ from vllm.logger import init_logger from vllm.sampling_params import SamplingParams from vllm.transformers_utils.tokenizers.mistral import MistralTokenizer -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader from vllm.v1.structured_output.backend_types import ( StructuredOutputBackend, StructuredOutputGrammar, diff --git a/vllm/v1/structured_output/utils.py b/vllm/v1/structured_output/utils.py index 06014e485a0d..e20ad1a6ec31 100644 --- a/vllm/v1/structured_output/utils.py +++ b/vllm/v1/structured_output/utils.py @@ -13,7 +13,7 @@ import vllm.envs as envs from vllm.logger import init_logger -from vllm.utils.importlib import LazyLoader +from vllm.utils.import_utils import LazyLoader if TYPE_CHECKING: import outlines_core as oc diff --git a/vllm/v1/worker/worker_base.py b/vllm/v1/worker/worker_base.py index 4368ddbd8f3e..9319918b84be 100644 --- a/vllm/v1/worker/worker_base.py +++ b/vllm/v1/worker/worker_base.py @@ -19,7 +19,7 @@ update_environment_variables, warn_for_unimplemented_methods, ) -from vllm.utils.importlib import resolve_obj_by_qualname +from vllm.utils.import_utils import resolve_obj_by_qualname from vllm.v1.kv_cache_interface import KVCacheSpec if TYPE_CHECKING: From 5b42ca9ef4898ac92993009e12dcb7c28f03d969 Mon Sep 17 00:00:00 2001 From: DarkLight1337 Date: Thu, 16 Oct 2025 13:36:53 +0000 Subject: [PATCH 5/6] Rename Signed-off-by: DarkLight1337 --- tests/utils_/{test_importlib.py => test_import_utils.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/utils_/{test_importlib.py => test_import_utils.py} (100%) diff --git a/tests/utils_/test_importlib.py b/tests/utils_/test_import_utils.py similarity index 100% rename from tests/utils_/test_importlib.py rename to tests/utils_/test_import_utils.py From cde7b8e683f9576817216475539639d272a77461 Mon Sep 17 00:00:00 2001 From: DarkLight1337 Date: Thu, 16 Oct 2025 14:33:17 +0000 Subject: [PATCH 6/6] Fix doc Signed-off-by: DarkLight1337 --- vllm/utils/import_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vllm/utils/import_utils.py b/vllm/utils/import_utils.py index 40bb999a44df..fdc3d356a7eb 100644 --- a/vllm/utils/import_utils.py +++ b/vllm/utils/import_utils.py @@ -68,7 +68,7 @@ class _PlaceholderBase: Disallows downstream usage of placeholder modules. We need to explicitly override each dunder method because - [`__getattr__`][vllm.utils._PlaceholderBase.__getattr__] + [`__getattr__`][vllm.utils.import_utils._PlaceholderBase.__getattr__] is not called when they are accessed. Info: