Skip to content

Commit 7e53d92

Browse files
v68 Improved help for variadic
1 parent 2856f02 commit 7e53d92

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

pydantic_argparse_next/parser/classes.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,12 +270,13 @@ def variadic_min_args(self) -> int:
270270
args_count = len(self.type_args)
271271
if args_count != 0:
272272
return args_count
273-
return self.extra_info.min_args
273+
return self.extra_info.min_args if self.extra_info.min_args >= 1 else 1
274274
else:
275275
raise PydanticArgparserError("variadic_min_args is only supported for variadic action")
276276

277277
@property
278278
def help_text(self) -> list[str]:
279+
# Name
279280
if isinstance(self, Argument):
280281
name = self.attribute_name
281282
alias = "" if self.alias is None else f"({self.alias})"
@@ -288,6 +289,7 @@ def help_text(self) -> list[str]:
288289
else:
289290
raise IOError(f"Type {type(self)} not recognized")
290291

292+
# Default
291293
if self.action == "choice" and isinstance(self.default, Enum):
292294
default = "" if self.required else f"[Default: {str(self.default.name)}]"
293295
else:
@@ -296,20 +298,72 @@ def help_text(self) -> list[str]:
296298
else:
297299
default = "" if self.required else f"[Default: {str(self.default)}]"
298300

301+
# Description
299302
description = self.description
300303

304+
# Value
301305
match self.action:
302306
case "choice":
303307
input_ = "{" + f"{'|'.join(self.choices)}" + "}"
304308
case "store_false" | "store_true":
305309
input_ = "STORE"
310+
case "variadic":
311+
if not self.type_args:
312+
input_ = str(self.type.__name__).upper()
313+
input_ = f"{input_}[STR]"
314+
315+
i = 1
316+
req_args = []
317+
for _ in range(self.variadic_min_args):
318+
req_args.append(f"arg{i}")
319+
i += 1
320+
req_args = ", ".join(req_args)
321+
322+
if i < self.variadic_max_args:
323+
req_args += ", {" f"arg{i}, ..."
324+
325+
if self.variadic_max_args < float("inf"):
326+
req_args += f", arg{self.variadic_max_args}" + "}"
327+
else:
328+
req_args += "}"
329+
330+
input_ = f"{input_} ({req_args})"
331+
elif self.type is tuple:
332+
vals_help = [x.__name__.upper() for x in self.type_args]
333+
vals_help = [f"arg{x+1} {vals_help[x]}" for x in range(len(vals_help))]
334+
vals_help = f"{', '.join(vals_help)}"
335+
input_ = str(self.type.__name__).upper()
336+
input_ = f"{input_} ({vals_help})"
337+
else:
338+
vals_help = self.type_args[0].__name__.upper()
339+
input_ = str(self.type.__name__).upper()
340+
input_ = f"{input_}[{vals_help}]"
341+
342+
i = 1
343+
req_args = []
344+
for _ in range(self.variadic_min_args):
345+
req_args.append(f"arg{i}")
346+
i += 1
347+
req_args = ", ".join(req_args)
348+
349+
if i < self.variadic_max_args:
350+
req_args += ", {" f"arg{i}, ..."
351+
352+
if self.variadic_max_args < float("inf"):
353+
req_args += f", arg{self.variadic_max_args}" + "}"
354+
else:
355+
req_args += "}"
356+
357+
input_ = f"{input_} ({req_args})"
358+
306359
case _:
307360
input_ = str(self.type.__name__).upper()
308361

309362
if isinstance(self, Subcommand):
310363
input_ = ""
311364
default = ""
312365

366+
# ###
313367
result = [
314368
name,
315369
alias,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[project]
66
name = "pydantic-argparse-next"
7-
version = "1.0.5"
7+
version = "1.0.6"
88
description = "Pydantic 2 argparse."
99
readme = "README.md"
1010
requires-python = ">=3.11"

tests/help/test_help.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,18 @@ class Test(BaseModel):
197197
assert "S1-D" in output
198198
assert "S1-E" in output
199199

200+
201+
def test_help_variadic(capsys):
202+
class Test(BaseModel):
203+
a: list[str]
204+
b: tuple[str, int, float]
205+
c: tuple
206+
d: list[int] = pa.KwArg(n_args="2...6")
207+
208+
output = read_output(Test, ["--help"], capsys).out
209+
210+
assert "LIST[STR] (arg1, {arg2, ...})" in output
211+
assert "TUPLE (arg1 STR, arg2 INT, arg3 FLOAT)" in output
212+
assert "TUPLE[STR] (arg1, {arg2, ...})" in output
213+
assert "LIST[INT] (arg1, arg2, {arg3, ..., arg6})" in output
214+

0 commit comments

Comments
 (0)