Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-cyclopts for openSUSE:Factory 
checked in at 2026-07-17 18:49:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-cyclopts (Old)
 and      /work/SRC/openSUSE:Factory/.python-cyclopts.new.24530 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-cyclopts"

Fri Jul 17 18:49:07 2026 rev:4 rq:1366324 version:4.21.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-cyclopts/python-cyclopts.changes  
2026-07-10 17:45:00.540800478 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-cyclopts.new.24530/python-cyclopts.changes   
    2026-07-17 18:50:17.730909235 +0200
@@ -1,0 +2,6 @@
+Fri Jul 17 06:58:30 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 4.21.1:
+  * Complete zsh subcommands after meta positionals
+
+-------------------------------------------------------------------

Old:
----
  cyclopts-4.21.0.tar.gz

New:
----
  cyclopts-4.21.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-cyclopts.spec ++++++
--- /var/tmp/diff_new_pack.KdZT9E/_old  2026-07-17 18:50:19.278961615 +0200
+++ /var/tmp/diff_new_pack.KdZT9E/_new  2026-07-17 18:50:19.286961885 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python-cyclopts
-Version:        4.21.0
+Version:        4.21.1
 Release:        0
 Summary:        Intuitive, easy CLIs based on python type hints
 License:        Apache-2.0

++++++ cyclopts-4.21.0.tar.gz -> cyclopts-4.21.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.21.0/PKG-INFO new/cyclopts-4.21.1/PKG-INFO
--- old/cyclopts-4.21.0/PKG-INFO        2020-02-02 01:00:00.000000000 +0100
+++ new/cyclopts-4.21.1/PKG-INFO        2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: cyclopts
-Version: 4.21.0
+Version: 4.21.1
 Summary: Intuitive, easy CLIs based on type hints.
 Project-URL: Homepage, https://github.com/BrianPugh/cyclopts
 Project-URL: Repository, https://github.com/BrianPugh/cyclopts
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.21.0/cyclopts/_version.py 
new/cyclopts-4.21.1/cyclopts/_version.py
--- old/cyclopts-4.21.0/cyclopts/_version.py    2020-02-02 01:00:00.000000000 
+0100
+++ new/cyclopts-4.21.1/cyclopts/_version.py    2020-02-02 01:00:00.000000000 
+0100
@@ -18,7 +18,7 @@
 commit_id: str | None
 __commit_id__: str | None
 
-__version__ = version = '4.21.0'
-__version_tuple__ = version_tuple = (4, 21, 0)
+__version__ = version = '4.21.1'
+__version_tuple__ = version_tuple = (4, 21, 1)
 
 __commit_id__ = commit_id = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.21.0/cyclopts/completion/_base.py 
new/cyclopts-4.21.1/cyclopts/completion/_base.py
--- old/cyclopts-4.21.0/cyclopts/completion/_base.py    2020-02-02 
01:00:00.000000000 +0100
+++ new/cyclopts-4.21.1/cyclopts/completion/_base.py    2020-02-02 
01:00:00.000000000 +0100
@@ -10,6 +10,8 @@
 from pathlib import Path
 from typing import TYPE_CHECKING, Any, get_args, get_origin
 
+from attrs import field
+
 from cyclopts.annotations import ITERABLE_TYPES, is_annotated, is_union
 from cyclopts.argument import ArgumentCollection
 from cyclopts.exceptions import CycloptsError
@@ -30,11 +32,33 @@
 
 @frozen
 class CompletionData:
-    """Completion data for a command path."""
+    """Completion data for a command path.
+
+    Attributes
+    ----------
+    arguments : ArgumentCollection
+        Every argument contributing to this path (inherited meta positionals,
+        this path's meta launcher, and this path's plain default), flattened.
+        Keyword specs and the cyclopts-``run`` path consume the full list.
+    commands : list[RegisteredCommand]
+        Subcommands registered at this path.
+    help_format : str
+        Resolved help format for descriptions.
+    launcher_arguments : ArgumentCollection
+        Arguments contributed by *this path's* meta-app launcher
+        (``app.meta.default``). These are consumed before this path's
+        subcommand dispatch and therefore shift the subcommand's word slot.
+    own_arguments : ArgumentCollection
+        Arguments contributed by *this path's* plain ``@app.default``. These
+        are alternatives to the subcommand at the same word slot and must
+        never shift it.
+    """
 
     arguments: "ArgumentCollection"
     commands: list[RegisteredCommand]
     help_format: str
+    launcher_arguments: "ArgumentCollection" = 
field(factory=ArgumentCollection)
+    own_arguments: "ArgumentCollection" = field(factory=ArgumentCollection)
 
 
 def extract_completion_data(app: "App") -> dict[tuple[str, ...], 
CompletionData]:
@@ -67,12 +91,27 @@
             )
             return
 
-        from cyclopts.core import _iter_resolution_argument_collections
+        from cyclopts.core import _iter_resolution_argument_collections, 
_walk_metas
 
+        # Classify each contributing app's arguments by provenance (see
+        # ``CompletionData`` for what ``launcher_arguments``/``own_arguments``
+        # mean to the shell generators):
+        #   * inherited -- an ancestor path's meta launcher; already consumed, 
skip.
+        #   * launcher  -- this path's own meta-app default (``_meta_parent`` 
set).
+        #   * own       -- this path's plain ``@app.default``.
+        current = list(_walk_metas(command_app))
         arguments = ArgumentCollection()
+        launcher_arguments = ArgumentCollection()
+        own_arguments = ArgumentCollection()
         with app.app_stack(execution_path):
-            for _, app_arguments in 
_iter_resolution_argument_collections(execution_path, parse_docstring=True):
+            for subapp, app_arguments in 
_iter_resolution_argument_collections(execution_path, parse_docstring=True):
                 arguments.extend(app_arguments)
+                if not any(subapp is a for a in current):
+                    continue  # inherited (ancestor meta launcher)
+                if subapp._meta_parent is not None:
+                    launcher_arguments.extend(app_arguments)  # this path's 
meta launcher
+                else:
+                    own_arguments.extend(app_arguments)  # plain @app.default
 
         commands = []
         for group, registered_commands in groups_from_app(command_app, 
resolve_lazy=True):
@@ -83,7 +122,13 @@
 
         help_format = command_app.app_stack.resolve("help_format", 
fallback="markdown")
 
-        completion_data[command_path] = CompletionData(arguments=arguments, 
commands=commands, help_format=help_format)
+        completion_data[command_path] = CompletionData(
+            arguments=arguments,
+            commands=commands,
+            help_format=help_format,
+            launcher_arguments=launcher_arguments,
+            own_arguments=own_arguments,
+        )
 
         for registered_command in commands:
             for cmd_name in registered_command.names:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.21.0/cyclopts/completion/bash.py 
new/cyclopts-4.21.1/cyclopts/completion/bash.py
--- old/cyclopts-4.21.0/cyclopts/completion/bash.py     2020-02-02 
01:00:00.000000000 +0100
+++ new/cyclopts-4.21.1/cyclopts/completion/bash.py     2020-02-02 
01:00:00.000000000 +0100
@@ -411,7 +411,11 @@
             if not cmd_name.startswith("-"):
                 commands.append(cmd_name)
 
-    positional_args = [arg for arg in data.arguments if arg.index is not None 
and arg.show]
+    # Exclude inherited (ancestor-meta) positionals: they were consumed before
+    # this path's command name, so they must not claim a slot here. (This PR
+    # does not attempt the full #759-style subcommand shifting for bash.)
+    local_arguments = data.launcher_arguments + data.own_arguments
+    positional_args = [arg for arg in local_arguments if arg.index is not None 
and arg.show]
     positional_args.sort(key=lambda a: a.index if a.index is not None else 0)
 
     lines.append(f"{indent}if [[ ${{cur}} == -* ]]; then")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.21.0/cyclopts/completion/fish.py 
new/cyclopts-4.21.1/cyclopts/completion/fish.py
--- old/cyclopts-4.21.0/cyclopts/completion/fish.py     2020-02-02 
01:00:00.000000000 +0100
+++ new/cyclopts-4.21.1/cyclopts/completion/fish.py     2020-02-02 
01:00:00.000000000 +0100
@@ -402,7 +402,11 @@
     if not command_path:
         return []
 
-    positional_args = [arg for arg in data.arguments if arg.index is not None 
and arg.show]
+    # Exclude inherited (ancestor-meta) positionals: they were consumed before
+    # this path's command name, so they must not claim a slot here. (This PR
+    # does not attempt the full #759-style subcommand shifting for fish.)
+    local_arguments = data.launcher_arguments + data.own_arguments
+    positional_args = [arg for arg in local_arguments if arg.index is not None 
and arg.show]
     if not positional_args:
         return []
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.21.0/cyclopts/completion/zsh.py 
new/cyclopts-4.21.1/cyclopts/completion/zsh.py
--- old/cyclopts-4.21.0/cyclopts/completion/zsh.py      2020-02-02 
01:00:00.000000000 +0100
+++ new/cyclopts-4.21.1/cyclopts/completion/zsh.py      2020-02-02 
01:00:00.000000000 +0100
@@ -27,6 +27,44 @@
     from cyclopts.command_spec import CommandSpec
 
 
+def _is_variadic(arg: "Argument") -> bool:
+    """Whether ``arg`` consumes an unbounded number of words positionally.
+
+    Covers both ``*args`` var-positionals and collection-typed positionals
+    (``list[X]``, ``set[X]``, ``tuple[X, ...]``, ...), which zsh must model 
with
+    a single rest-arg (``*:``) spec rather than a numbered position.
+
+    Parameters
+    ----------
+    arg : Argument
+        Argument to inspect.
+
+    Returns
+    -------
+    bool
+        True if the argument is variadic/iterable.
+    """
+    return arg.is_var_positional() or is_iterable_type(arg.hint)
+
+
+def _choose_rest_arg(positional_args: list["Argument"]) -> "Argument | None":
+    """Pick the single positional that becomes zsh's rest-arg (``*:``) spec.
+
+    zsh's ``_arguments`` errors with "doubled rest argument definition" if more
+    than one ``*:`` spec is present, so multiple variadic positionals (e.g.
+    several ``list[X]`` defaults) must collapse to one. A true var-positional
+    (``*args``) is preferred; otherwise the first iterable wins. The others
+    remain reachable via their ``--name`` keyword specs emitted elsewhere.
+
+    Returns ``None`` when there is no variadic positional.
+    """
+    variadic_args = [arg for arg in positional_args if _is_variadic(arg)]
+    var_positional = next((a for a in variadic_args if a.is_var_positional()), 
None)
+    if var_positional is not None:
+        return var_positional
+    return variadic_args[0] if variadic_args else None
+
+
 def generate_completion_script(app: "App", prog_name: str) -> str:
     """Generate zsh completion script.
 
@@ -149,6 +187,7 @@
 def _generate_nested_positional_specs(
     positional_args: list["Argument"],
     help_format: str,
+    offset: int = 0,
 ) -> list[str]:
     """Generate positional argument specs for nested command context.
 
@@ -163,53 +202,24 @@
         Positional arguments to generate specs for.
     help_format : str
         Help text format.
+    offset : int
+        Number of preceding positional slots to skip (e.g. fixed launcher
+        positionals that come before these arguments on the command line).
 
     Returns
     -------
     list[str]
         List of zsh positional argument specs.
     """
-    specs = []
-
-    # Check if we have variadic positionals (including collection types like 
list[X])
-    variadic_args = [arg for arg in positional_args if arg.is_var_positional() 
or is_iterable_type(arg.hint)]
-    non_variadic_args = [
-        arg for arg in positional_args if not arg.is_var_positional() and not 
is_iterable_type(arg.hint)
-    ]
+    # Emit fixed positionals first (each at ``arg.index + 1 + offset``), then 
at
+    # most one rest-arg (``*:``) spec -- ``_generate_positional_spec`` computes
+    # both forms from the argument itself.
+    non_variadic_args = [arg for arg in positional_args if not 
_is_variadic(arg)]
+    specs = [_generate_positional_spec(arg, help_format, offset=offset) for 
arg in non_variadic_args]
 
-    def _build(arg, position: str) -> str:
-        choices = arg.get_choices(force=True)
-        if choices:
-            escaped_choices = 
[_escape_choice_for_dq_spec(clean_choice_text(c)) for c in choices]
-            choices_str = " ".join(escaped_choices)
-            action = f"({choices_str})"
-            desc = _escape_zsh_description_dq(_description_text(arg, 
help_format))
-            quote = '"'
-        else:
-            action = 
_map_completion_action_to_zsh(get_completion_action(arg.hint))
-            desc = _get_description_from_argument(arg, help_format)
-            quote = "'"
-        return f"{quote}{position}:{desc}:{action}{quote}" if action else 
f"{quote}{position}:{desc}{quote}"
-
-    # Generate specs for non-variadic positionals
-    for arg in non_variadic_args:
-        # Position in nested context: After *::arg:->args, $words[1] is the 
subcommand
-        # So positionals start at position 1 (not 2)
-        # Use 1-based indexing: first positional is '1:', second is '2:', etc.
-        pos = 1 + (arg.index or 0)
-        specs.append(_build(arg, str(pos)))
-
-    # Emit at most one rest-arg (``*:``) spec. zsh's ``_arguments`` errors
-    # with "doubled rest argument definition" if more than one is present.
-    # When a function has multiple iterable positional-or-keyword params
-    # (e.g. several ``list[X]`` defaults), only the first can realistically
-    # be filled positionally — the others remain available via their
-    # ``--name`` keyword forms emitted elsewhere.
-    chosen = next((a for a in variadic_args if a.is_var_positional()), None)
-    if chosen is None and variadic_args:
-        chosen = variadic_args[0]
+    chosen = _choose_rest_arg(positional_args)
     if chosen is not None:
-        specs.append(_build(chosen, "*"))
+        specs.append(_generate_positional_spec(chosen, help_format, 
offset=offset))
 
     return specs
 
@@ -261,6 +271,77 @@
     return lines
 
 
+def _generate_root_positional_specs(
+    positional_args: list["Argument"],
+    help_format: str,
+    offset: int = 0,
+) -> list[str]:
+    """Generate positional specs for the root (non-nested) command context.
+
+    Unlike the nested helper, at the root ``_arguments`` sees the real
+    command line, so positions are ``arg.index + 1`` (plus ``offset``). Only
+    one rest-arg (``*:``) spec is allowed, so multiple iterable positionals
+    collapse to the first (var-positional preferred); the others remain
+    reachable via their ``--name`` keyword specs.
+
+    Parameters
+    ----------
+    positional_args : list[Argument]
+        Positional arguments to generate specs for.
+    help_format : str
+        Help text format.
+    offset : int
+        Number of preceding positional slots to skip.
+
+    Returns
+    -------
+    list[str]
+        List of zsh positional argument specs.
+    """
+    specs: list[str] = []
+    chosen_rest = _choose_rest_arg(positional_args)
+    for argument in positional_args:
+        # Keep only the one chosen rest-arg; drop every other variadic 
positional.
+        if _is_variadic(argument) and argument is not chosen_rest:
+            continue
+        specs.append(_generate_positional_spec(argument, help_format, 
offset=offset))
+    return specs
+
+
+def _generate_positional_specs(
+    positional_args: list["Argument"],
+    command_path: tuple[str, ...],
+    help_format: str,
+    offset: int = 0,
+) -> list[str]:
+    """Dispatch positional-spec generation to the root or nested helper."""
+    if not positional_args:
+        return []
+    if command_path:
+        return _generate_nested_positional_specs(positional_args, help_format, 
offset=offset)
+    return _generate_root_positional_specs(positional_args, help_format, 
offset=offset)
+
+
+def _cap_rest_specs(specs: list[str]) -> list[str]:
+    """Drop every rest-arg (``*:``) spec after the first.
+
+    zsh's ``_arguments`` errors with "doubled rest argument definition" if more
+    than one ``*:`` spec is present. When positional specs from two provenance
+    groups (launcher + own) are concatenated, each group may contribute a rest
+    spec; keep only the first.
+    """
+    result: list[str] = []
+    seen_rest = False
+    for spec in specs:
+        # Specs are quoted (``'...'`` or ``"..."``); a rest spec's body is 
``*:``.
+        if spec[1:].startswith("*:"):
+            if seen_rest:
+                continue
+            seen_rest = True
+        result.append(spec)
+    return result
+
+
 def _generate_completion_for_path(
     completion_data: dict[tuple[str, ...], CompletionData],
     command_path: tuple[str, ...],
@@ -304,13 +385,24 @@
     args_specs = []
     positional_specs = []
 
-    # Separate positional from keyword arguments
-    # Include all arguments with an index (both positional-only and 
positional-or-keyword)
-    positional_args = [arg for arg in arguments if arg.index is not None and 
arg.show]
-    keyword_args = [arg for arg in arguments if not arg.is_positional_only() 
and arg.show]
+    # Positional arguments, split by provenance (see ``CompletionData`` for 
what
+    # each group means): launcher positionals shift the subcommand's word slot,
+    # own positionals never do. Inherited (ancestor-meta) positionals are in
+    # neither group -- consumed before this path's command name, so no slot 
here.
+    launcher_positionals = sorted(
+        (arg for arg in data.launcher_arguments if arg.index is not None),
+        key=lambda a: a.index or 0,
+    )
+    own_positionals = sorted(
+        (arg for arg in data.own_arguments if arg.index is not None and 
arg.show),
+        key=lambda a: a.index or 0,
+    )
+    # Fixed (non-variadic) launcher positionals each consume exactly one word.
+    # Count them regardless of ``show`` -- a hidden fixed positional still
+    # occupies a slot on the command line (so it still shifts the subcommand).
+    fixed_launcher = [arg for arg in launcher_positionals if not 
_is_variadic(arg)]
 
-    # Sort positionals by index (should never be None for positional-only args)
-    positional_args.sort(key=lambda a: a.index or 0)
+    keyword_args = [arg for arg in arguments if not arg.is_positional_only() 
and arg.show]
 
     # Generate keyword argument specs
     for argument in keyword_args:
@@ -342,37 +434,48 @@
         not cmd_name.startswith("-") for registered_command in commands for 
cmd_name in registered_command.names
     )
 
-    # Generate positional argument specs
-    # Only add positionals if there are no subcommands (they conflict in zsh)
-    if positional_args and not has_non_flag_commands:
-        if command_path:
-            # Nested context: use shifted positional indexing (words[1] is 
subcommand)
-            positional_specs = 
_generate_nested_positional_specs(positional_args, data.help_format)
-        else:
-            # Root context: standard _arguments works fine. As in the
-            # nested helper, only one rest-arg (``*:``) spec is allowed —
-            # collapse multiple iterable positionals to the first one
-            # (var-positional preferred). The other iterables remain
-            # available via their ``--name`` keyword specs.
-            seen_rest = False
-            iterable_args = [a for a in positional_args if 
a.is_var_positional() or is_iterable_type(a.hint)]
-            chosen_rest = next((a for a in iterable_args if 
a.is_var_positional()), None)
-            if chosen_rest is None and iterable_args:
-                chosen_rest = iterable_args[0]
-            for argument in positional_args:
-                is_rest = argument.is_var_positional() or 
is_iterable_type(argument.hint)
-                if is_rest:
-                    if argument is not chosen_rest or seen_rest:
-                        continue
-                    seen_rest = True
-                spec = _generate_positional_spec(argument, data.help_format)
-                positional_specs.append(spec)
+    # Positional specs and the subcommand's word slot.
+    command_position = 1
+    if has_non_flag_commands:
+        # The subcommand slot shifts past the fixed launcher positionals only
+        # when every one of them is required (occupies a definite word) and
+        # they form a contiguous prefix (indices 0..k-1) -- a variadic
+        # positional interleaved among them would consume an unbounded number
+        # of words, making every later slot non-deterministic.
+        # Required positional-or-keyword args count the same as positional-only
+        # here: the dominant launcher usage is positional (``prog 5 sub``); the
+        # ``--opt value`` form would offset the slot -- an accepted trade-off.
+        contiguous_prefix = [arg.index for arg in fixed_launcher] == 
list(range(len(fixed_launcher)))
+        shift_deterministic = contiguous_prefix and all(arg.required for arg 
in fixed_launcher)
+        if shift_deterministic and fixed_launcher:
+            # ``contiguous_prefix`` guarantees indices are exactly ``0..k-1``, 
so
+            # the subcommand sits one slot past the last launcher positional.
+            command_position = len(fixed_launcher) + 1
+            # Emit specs for the *shown* fixed launcher positionals only.
+            shown_launcher = [arg for arg in fixed_launcher if arg.show]
+            positional_specs = _generate_positional_specs(shown_launcher, 
command_path, data.help_format)
+        # Non-deterministic shift (some fixed launcher positional is optional)
+        # or no launcher positionals: ``command_position`` stays 1 and own
+        # positionals get no specs -- they are alternatives to the subcommand
+        # at the same slot (pre-PR rule).
+    else:
+        # No subcommands: launcher and own positionals both complete. Own
+        # indices are offset past the fixed launcher positionals that precede
+        # them on the command line. A single rest-arg (``*:``) cap holds across
+        # both groups combined.
+        launcher_shown = [arg for arg in launcher_positionals if arg.show]
+        positional_specs = _generate_positional_specs(launcher_shown, 
command_path, data.help_format)
+        positional_specs += _generate_positional_specs(
+            own_positionals, command_path, data.help_format, 
offset=len(fixed_launcher)
+        )
+        positional_specs = _cap_rest_specs(positional_specs)
 
+    if positional_specs:
         # Add positionals BEFORE options to prioritize them in completion
         args_specs = positional_specs + args_specs
 
     if has_non_flag_commands:
-        args_specs.append("'1: :->cmds'")
+        args_specs.append(f"'{command_position}: :->cmds'")
         args_specs.append("'*::arg:->args'")
 
     # Eq-form pre-pass: zsh's ``_arguments`` only handles ``--opt=value``
@@ -416,6 +519,16 @@
         lines.append(f"{indent_str}    ;;")
 
         lines.append(f"{indent_str}  args)")
+        # Normalize the ``$words`` frame so the subcommand sits at 
``$words[1]``.
+        # When ``command_position > 1`` the fixed launcher positionals occupy
+        # ``$words[1..k]`` here (standard zsh precommand idiom); dropping them
+        # lets the recursively-inlined child code use its own command name at
+        # ``$words[1]`` and its own ``pos = 1 + arg.index`` slots, unchanged at
+        # any nesting depth.
+        k = command_position - 1
+        if k >= 1:
+            lines.append(f"{indent_str}    shift {k} words")
+            lines.append(f"{indent_str}    (( CURRENT -= {k} ))")
         lines.append(f"{indent_str}    case $words[1] in")
 
         for registered_command in commands:
@@ -754,7 +867,7 @@
     return specs
 
 
-def _generate_positional_spec(argument: "Argument", help_format: str) -> str:
+def _generate_positional_spec(argument: "Argument", help_format: str, offset: 
int = 0) -> str:
     """Generate zsh _arguments spec for a positional argument.
 
     Parameters
@@ -763,6 +876,8 @@
         Positional argument object.
     help_format : str
         Help text format.
+    offset : int
+        Number of preceding positional slots to skip.
 
     Returns
     -------
@@ -783,14 +898,14 @@
         desc = _get_description_from_argument(argument, help_format)
         quote = "'"
 
-    if argument.is_var_positional() or is_iterable_type(argument.hint):
+    if _is_variadic(argument):
         # Variadic positional (*args) or collection type (list[X], set[X], 
etc.)
         return f"{quote}*:{desc}:{action}{quote}" if action else 
f"{quote}*:{desc}{quote}"
 
     # Regular positional - zsh uses 1-based indexing
     if argument.index is None:
         raise ValueError(f"Positional-only argument {argument.names} missing 
index")
-    pos = argument.index + 1
+    pos = argument.index + 1 + offset
     return f"{quote}{pos}:{desc}:{action}{quote}" if action else 
f"{quote}{pos}:{desc}{quote}"
 
 

Reply via email to