[Bugfix] Let an optional Literal flag accept the None it advertises (#52370)
Signed-off-by: Vineeth Sai <vineethsai4444@gmail.com> Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Vineeth Sai Varikuntla committed
Sep 16, 2026 at 05:14 UTC
903285fbcc4e51332d562499bd90ec9a1513c813
2 files changed
+25
-6
tests/engine/test_arg_utils.py
+23
-4
@@ -254,10 +254,13 @@ def test_get_type_hints(type_hint, expected):
254
assert get_type_hints(type_hint) == expected
255
256
257
-def test_get_kwargs():
258
- kwargs = get_kwargs(DummyConfig)
259
- print(kwargs)
257
+@pytest.fixture
258
+def dummy_config_kwargs():
259
+ return get_kwargs(DummyConfig)
260
261
+
262
+def test_get_kwargs(dummy_config_kwargs):
263
+ kwargs = dummy_config_kwargs
264
# bools should not have their type set
265
assert kwargs["regular_bool"].get("type") is None
266
assert kwargs["optional_bool"].get("type") is None
@@ -267,7 +270,7 @@ def test_get_kwargs():
270
assert kwargs["optional_bool_or_str"]["const"] is True
271
assert "action" not in kwargs["optional_bool_or_str"]
272
# optional literals should have None as a choice
270
- assert kwargs["optional_literal"]["choices"] == ["x", "y", "None"]
273
+ assert kwargs["optional_literal"]["choices"] == ["x", "y", None]
274
# tuples should have the correct nargs
275
assert kwargs["tuple_n"]["nargs"] == "+"
276
assert kwargs["tuple_2"]["nargs"] == 2
@@ -293,6 +296,22 @@ def test_get_kwargs():
296
assert kwargs["nested_config"]["type"]('{"field": 2}') == NestedConfig(2) # type: ignore[call-arg]
297
298
299
+@pytest.mark.parametrize(
300
+ ("args", "expected"),
301
+ [
302
+ (["--optional-literal", "None"], None),
303
+ (["--optional-literal", ""], None),
304
+ (["--optional-literal", "x"], "x"),
305
+ ],
306
+)
307
+def test_optional_handling(args, expected, dummy_config_kwargs):
308
+ parser = FlexibleArgumentParser()
309
+ parser.add_argument("--optional-literal", **dummy_config_kwargs["optional_literal"])
310
+
311
+ assert parser.parse_args(args).optional_literal is expected
312
+ assert "None" in parser.format_help()
313
+
314
+
315
def test_jit_monitor_verbose_arg():
316
parser = EngineArgs.add_cli_args(FlexibleArgumentParser())
317
args = parser.parse_args(["--jit-monitor-verbose"])
vllm/engine/arg_utils.py
+2
-2
@@ -411,7 +411,7 @@ def _compute_kwargs(cls: ConfigType) -> dict[str, dict[str, Any]]:
411
if type(None) in type_hints and not contains_type(type_hints, bool):
412
kwargs[name]["type"] = optional_type(kwargs[name]["type"])
413
if kwargs[name].get("choices"):
414
- kwargs[name]["choices"].append("None")
414
+ kwargs[name]["choices"].append(None)
415
return kwargs
416
417
@@ -1526,7 +1526,7 @@ class EngineArgs:
1526
)
1527
# TODO: generalise this special case
1528
choices = observability_kwargs["collect_detailed_traces"]["choices"]
1529
- metavar = f"{{{','.join(choices)}}}"
1529
+ metavar = f"{{{','.join(str(c) for c in choices)}}}"
1530
observability_kwargs["collect_detailed_traces"]["metavar"] = metavar
1531
observability_kwargs["collect_detailed_traces"]["choices"] += [
1532
",".join(p) for p in permutations(get_args(DetailedTraceModules), r=2)