From 861a68ef78c6f78691437f79dc9a190c6e836b73 Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Tue, 29 Apr 2025 20:40:16 -0400 Subject: [PATCH 1/7] feat: add deprecated=True and deprecate_reason for argparse Signed-off-by: Aaron Pham --- vllm/utils.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/vllm/utils.py b/vllm/utils.py index f85bbe3a5990..b8a257a4b910 100644 --- a/vllm/utils.py +++ b/vllm/utils.py @@ -1332,6 +1332,22 @@ def __init__(self, *args, **kwargs): kwargs['formatter_class'] = SortedHelpFormatter super().__init__(*args, **kwargs) + def add_argument(self, *args: Any, **kwargs: Any): + # add a deprecated=True with optional deprecated_reason to signify + # reasons for deprecating this args + if kwargs.pop("deprecated", False): + deprecated_message = kwargs.pop("deprecated_reason", None) + if 'help' in kwargs: + kwargs['help'] = ( + f"[DEPRECATED]{(' ' + deprecated_message) or ''}.\n{kwargs['help']}" # noqa: E501 + ) + else: + kwargs['help'] = ( + f"[DEPRECATED]{(' ' + deprecated_message) or ''}" # noqa: E501 + ) + + super().add_argument(*args, **kwargs) + def parse_args(self, args=None, namespace=None): if args is None: args = sys.argv[1:] From 38b8d55d6f8876a2cb2932c6bf192737682e09ff Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Fri, 2 May 2025 17:19:51 -0400 Subject: [PATCH 2/7] chore: match upstream 3.13 Signed-off-by: Aaron Pham --- vllm/utils.py | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/vllm/utils.py b/vllm/utils.py index b8a257a4b910..cff9ab9e4c83 100644 --- a/vllm/utils.py +++ b/vllm/utils.py @@ -41,6 +41,7 @@ from concurrent.futures.process import ProcessPoolExecutor from dataclasses import dataclass, field from functools import cache, lru_cache, partial, wraps +from gettext import gettext as _gettext from types import MappingProxyType from typing import (TYPE_CHECKING, Any, Callable, Generic, Literal, NamedTuple, Optional, Sequence, Tuple, Type, TypeVar, Union, cast, @@ -70,6 +71,8 @@ from vllm.logger import enable_trace_function_call, init_logger if TYPE_CHECKING: + from argparse import Namespace + from vllm.config import ModelConfig, VllmConfig logger = init_logger(__name__) @@ -1331,24 +1334,35 @@ def __init__(self, *args, **kwargs): if 'formatter_class' not in kwargs: kwargs['formatter_class'] = SortedHelpFormatter super().__init__(*args, **kwargs) + self._deprecated = set() def add_argument(self, *args: Any, **kwargs: Any): # add a deprecated=True with optional deprecated_reason to signify # reasons for deprecating this args - if kwargs.pop("deprecated", False): - deprecated_message = kwargs.pop("deprecated_reason", None) - if 'help' in kwargs: - kwargs['help'] = ( - f"[DEPRECATED]{(' ' + deprecated_message) or ''}.\n{kwargs['help']}" # noqa: E501 - ) - else: - kwargs['help'] = ( - f"[DEPRECATED]{(' ' + deprecated_message) or ''}" # noqa: E501 - ) - - super().add_argument(*args, **kwargs) - - def parse_args(self, args=None, namespace=None): + if sys.version_info < (3, 13): + deprecated = kwargs.pop('deprecated', False) + action = super().add_argument(*args, **kwargs) + if deprecated and action.dest not in self._deprecated: + self._warning( + _gettext("argument '%(argument_name)s' is deprecated") % + {'argument_name': action.dest}) + self._deprecated.add(action.dest) + + return action + + # python>3.13 + return super().add_argument(*args, **kwargs) + + def _warning(self, message: str): + args = {'prog': self.prog, 'message': message} + self._print_message( + _gettext('%(prog)s: warning: %(message)s\n') % args, sys.stderr) + + def parse_args( # type: ignore[override] + self, + args: Sequence[str] | None = None, + namespace: Namespace | None = None, + ): if args is None: args = sys.argv[1:] From 2439473d6460df942eb932f68c1e81b2a17d28d6 Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Fri, 2 May 2025 17:36:02 -0400 Subject: [PATCH 3/7] fix: works with subgroup Signed-off-by: Aaron Pham --- vllm/engine/arg_utils.py | 1 + vllm/utils.py | 42 +++++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/vllm/engine/arg_utils.py b/vllm/engine/arg_utils.py index 0ba14c4dee04..603e4345bcfe 100644 --- a/vllm/engine/arg_utils.py +++ b/vllm/engine/arg_utils.py @@ -515,6 +515,7 @@ def add_cli_args(parser: FlexibleArgumentParser) -> FlexibleArgumentParser: description=DecodingConfig.__doc__, ) guided_decoding_group.add_argument("--guided-decoding-backend", + deprecated=True, **guided_decoding_kwargs["backend"]) guided_decoding_group.add_argument( "--guided-decoding-disable-fallback", diff --git a/vllm/utils.py b/vllm/utils.py index cff9ab9e4c83..4c1aaef3f3cd 100644 --- a/vllm/utils.py +++ b/vllm/utils.py @@ -33,7 +33,7 @@ import warnings import weakref from argparse import (Action, ArgumentDefaultsHelpFormatter, ArgumentParser, - ArgumentTypeError) + ArgumentTypeError, _ArgumentGroup) from asyncio import FIRST_COMPLETED, AbstractEventLoop, Task from collections import UserDict, defaultdict from collections.abc import (AsyncGenerator, Awaitable, Generator, Hashable, @@ -1326,15 +1326,39 @@ def add_arguments(self, actions): super().add_arguments(actions) +class _FlexibleArgumentGroup(_ArgumentGroup): + + def __init__(self, parser: FlexibleArgumentParser, *args, **kwargs): + self._parser = parser + super().__init__(*args, **kwargs) + + def add_argument(self, *args: Any, **kwargs: Any): + if sys.version_info < (3, 13): + deprecated = kwargs.pop('deprecated', False) + action = super().add_argument(*args, **kwargs) + object.__setattr__(action, 'deprecated', deprecated) + if deprecated and action.dest not in \ + self._parser.__class__._deprecated: + self._parser._warning( + _gettext("argument '%(argument_name)s' is deprecated") % + {'argument_name': action.dest}) + self._parser._deprecated.add(action.dest) + return action + + # python>3.13 + return super().add_argument(*args, **kwargs) + + class FlexibleArgumentParser(ArgumentParser): """ArgumentParser that allows both underscore and dash in names.""" + _deprecated: set[str] = set() + def __init__(self, *args, **kwargs): # Set the default 'formatter_class' to SortedHelpFormatter if 'formatter_class' not in kwargs: kwargs['formatter_class'] = SortedHelpFormatter super().__init__(*args, **kwargs) - self._deprecated = set() def add_argument(self, *args: Any, **kwargs: Any): # add a deprecated=True with optional deprecated_reason to signify @@ -1342,7 +1366,9 @@ def add_argument(self, *args: Any, **kwargs: Any): if sys.version_info < (3, 13): deprecated = kwargs.pop('deprecated', False) action = super().add_argument(*args, **kwargs) - if deprecated and action.dest not in self._deprecated: + object.__setattr__(action, 'deprecated', deprecated) + if deprecated and \ + action.dest not in FlexibleArgumentParser._deprecated: self._warning( _gettext("argument '%(argument_name)s' is deprecated") % {'argument_name': action.dest}) @@ -1354,9 +1380,9 @@ def add_argument(self, *args: Any, **kwargs: Any): return super().add_argument(*args, **kwargs) def _warning(self, message: str): - args = {'prog': self.prog, 'message': message} self._print_message( - _gettext('%(prog)s: warning: %(message)s\n') % args, sys.stderr) + _gettext('warning: %(message)s\n') % {'message': message}, + sys.stderr) def parse_args( # type: ignore[override] self, @@ -1533,6 +1559,12 @@ def _load_config_file(self, file_path: str) -> list[str]: return processed_args + def add_argument_group(self, *args: Any, + **kwargs: Any) -> _FlexibleArgumentGroup: + group = _FlexibleArgumentGroup(self, self, *args, **kwargs) + self._action_groups.append(group) + return group + async def _run_task_with_lock(task: Callable, lock: asyncio.Lock, *args, **kwargs): From fa47e7b572964d163cd3f8251d08e206eb11ca64 Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Fri, 2 May 2025 17:54:53 -0400 Subject: [PATCH 4/7] --wip-- Signed-off-by: Aaron Pham --- vllm/utils.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/vllm/utils.py b/vllm/utils.py index 4c1aaef3f3cd..28770f43fde7 100644 --- a/vllm/utils.py +++ b/vllm/utils.py @@ -1384,6 +1384,15 @@ def _warning(self, message: str): _gettext('warning: %(message)s\n') % {'message': message}, sys.stderr) + def parse_known_args( + self, + args: list[str], + namespace: Namespace, + ) -> tuple[Namespace, list[str]]: + namespace, args = super().parse_known_args(args, namespace) + print(namespace) + return namespace, args + def parse_args( # type: ignore[override] self, args: Sequence[str] | None = None, From d49e4ee29f3ee32befc1d9cbe4dd2b7f66611ad4 Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Fri, 2 May 2025 22:30:35 +0000 Subject: [PATCH 5/7] chore: update backport Signed-off-by: Aaron Pham --- vllm/utils.py | 57 ++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/vllm/utils.py b/vllm/utils.py index 28770f43fde7..be30c821c283 100644 --- a/vllm/utils.py +++ b/vllm/utils.py @@ -1339,10 +1339,7 @@ def add_argument(self, *args: Any, **kwargs: Any): object.__setattr__(action, 'deprecated', deprecated) if deprecated and action.dest not in \ self._parser.__class__._deprecated: - self._parser._warning( - _gettext("argument '%(argument_name)s' is deprecated") % - {'argument_name': action.dest}) - self._parser._deprecated.add(action.dest) + self._parser._deprecated.add(action) return action # python>3.13 @@ -1352,7 +1349,8 @@ def add_argument(self, *args: Any, **kwargs: Any): class FlexibleArgumentParser(ArgumentParser): """ArgumentParser that allows both underscore and dash in names.""" - _deprecated: set[str] = set() + _deprecated: set[Action] = set() + _seen: set[str] = set() def __init__(self, *args, **kwargs): # Set the default 'formatter_class' to SortedHelpFormatter @@ -1360,38 +1358,37 @@ def __init__(self, *args, **kwargs): kwargs['formatter_class'] = SortedHelpFormatter super().__init__(*args, **kwargs) - def add_argument(self, *args: Any, **kwargs: Any): - # add a deprecated=True with optional deprecated_reason to signify - # reasons for deprecating this args - if sys.version_info < (3, 13): + if sys.version_info < (3, 13): + def parse_known_args( # type: ignore[override] + self, + args: Sequence[str] | None = None, + namespace: Namespace | None = None, + ) -> tuple[Namespace | None, list[str]]: + namespace, args = super().parse_known_args(args, namespace) + for action in FlexibleArgumentParser._deprecated: + if action.dest not in FlexibleArgumentParser._seen and getattr(namespace, action.dest, None) != action.default: + self._warning( + _gettext("argument '%(argument_name)s' is deprecated") % + {'argument_name': action.dest}) + FlexibleArgumentParser._seen.add(action.dest) + return namespace, args + + def add_argument(self, *args: Any, **kwargs: Any): + # add a deprecated=True compatibility + # for python < 3.13 deprecated = kwargs.pop('deprecated', False) action = super().add_argument(*args, **kwargs) object.__setattr__(action, 'deprecated', deprecated) if deprecated and \ - action.dest not in FlexibleArgumentParser._deprecated: - self._warning( - _gettext("argument '%(argument_name)s' is deprecated") % - {'argument_name': action.dest}) - self._deprecated.add(action.dest) + action not in FlexibleArgumentParser._deprecated: + self._deprecated.add(action) return action - # python>3.13 - return super().add_argument(*args, **kwargs) - - def _warning(self, message: str): - self._print_message( - _gettext('warning: %(message)s\n') % {'message': message}, - sys.stderr) - - def parse_known_args( - self, - args: list[str], - namespace: Namespace, - ) -> tuple[Namespace, list[str]]: - namespace, args = super().parse_known_args(args, namespace) - print(namespace) - return namespace, args + def _warning(self, message: str): + self._print_message( + _gettext('warning: %(message)s\n') % {'message': message}, + sys.stderr) def parse_args( # type: ignore[override] self, From 6260b246e444cd263d5aac16132f6dd72aa69cb3 Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Sat, 3 May 2025 20:50:54 -0400 Subject: [PATCH 6/7] chore: cleanup deprecated for '--enable-reasoning' instead Signed-off-by: Aaron Pham --- vllm/engine/arg_utils.py | 2 +- vllm/utils.py | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/vllm/engine/arg_utils.py b/vllm/engine/arg_utils.py index 603e4345bcfe..b75090ee495b 100644 --- a/vllm/engine/arg_utils.py +++ b/vllm/engine/arg_utils.py @@ -515,7 +515,6 @@ def add_cli_args(parser: FlexibleArgumentParser) -> FlexibleArgumentParser: description=DecodingConfig.__doc__, ) guided_decoding_group.add_argument("--guided-decoding-backend", - deprecated=True, **guided_decoding_kwargs["backend"]) guided_decoding_group.add_argument( "--guided-decoding-disable-fallback", @@ -529,6 +528,7 @@ def add_cli_args(parser: FlexibleArgumentParser) -> FlexibleArgumentParser: guided_decoding_group.add_argument( "--enable-reasoning", action=argparse.BooleanOptionalAction, + deprecated=True, help="[DEPRECATED] The `--enable-reasoning` flag is deprecated as " "of v0.8.6. Use `--reasoning-parser` to specify the reasoning " "parser backend insteadThis flag (`--enable-reasoning`) will be " diff --git a/vllm/utils.py b/vllm/utils.py index be30c821c283..3324c149a078 100644 --- a/vllm/utils.py +++ b/vllm/utils.py @@ -1392,7 +1392,7 @@ def _warning(self, message: str): def parse_args( # type: ignore[override] self, - args: Sequence[str] | None = None, + args: list[str] | None = None, namespace: Namespace | None = None, ): if args is None: @@ -1565,8 +1565,11 @@ def _load_config_file(self, file_path: str) -> list[str]: return processed_args - def add_argument_group(self, *args: Any, - **kwargs: Any) -> _FlexibleArgumentGroup: + def add_argument_group( + self, + *args: Any, + **kwargs: Any, + ) -> _FlexibleArgumentGroup: group = _FlexibleArgumentGroup(self, self, *args, **kwargs) self._action_groups.append(group) return group From 60ce9b87b12007f8c4a3a5825f3c0e1d00725376 Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Sat, 3 May 2025 20:54:45 -0400 Subject: [PATCH 7/7] chore: cleanup format and waren signs Signed-off-by: Aaron Pham --- vllm/utils.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vllm/utils.py b/vllm/utils.py index 3324c149a078..8ab5bb2a9adc 100644 --- a/vllm/utils.py +++ b/vllm/utils.py @@ -1359,6 +1359,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if sys.version_info < (3, 13): + def parse_known_args( # type: ignore[override] self, args: Sequence[str] | None = None, @@ -1366,10 +1367,12 @@ def parse_known_args( # type: ignore[override] ) -> tuple[Namespace | None, list[str]]: namespace, args = super().parse_known_args(args, namespace) for action in FlexibleArgumentParser._deprecated: - if action.dest not in FlexibleArgumentParser._seen and getattr(namespace, action.dest, None) != action.default: + if action.dest not in FlexibleArgumentParser._seen and getattr( + namespace, action.dest, + None) != action.default: # noqa: E501 self._warning( - _gettext("argument '%(argument_name)s' is deprecated") % - {'argument_name': action.dest}) + _gettext("argument '%(argument_name)s' is deprecated") + % {'argument_name': action.dest}) FlexibleArgumentParser._seen.add(action.dest) return namespace, args