argh icon indicating copy to clipboard operation
argh copied to clipboard

conflict when short option does not match first letter of long option

Open sswam opened this issue 5 months ago • 0 comments

Summary

The bug happens when:

  1. An option has a short name (-n) that doesn't match its long name (--user-name).
  2. Another option is added with a long name (--note) starting with the same letter as the first option's short name.
  3. Even if the second option has its own short name (-N), argh tries to create another short name (-n) based on its long name.
  4. This causes a conflict with the first option's short name (-n), resulting in an exception.

The issue stems from argh attempting to automatically generate short names for long options, even when explicit short names are provided.

The error message is:

argh.exceptions.AssemblingError: query: cannot add 'note' as -n/--note/-N: argument -n/--note/-N: conflicting option string: -n

To Reproduce

Python script:

import argh

@argh.arg("-n", "--user-name")
@argh.arg("-N", "--note")
def hello(user_name="world", note=""):
    return f"hello, {name}! {note}"

if __name__ == "__main__":
    argh.dispatch_command(hello)

Command line input/output:

$ python bug.py
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/argh/assembling.py", line 454, in set_default_command
    action = parser.add_argument(
             ^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/argparse.py", line 1507, in add_argument
    return self._add_action(action)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/argparse.py", line 1889, in _add_action
    self._optionals._add_action(action)
  File "/usr/lib/python3.12/argparse.py", line 1709, in _add_action
    action = super(_ArgumentGroup, self)._add_action(action)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/argparse.py", line 1521, in _add_action
    self._check_conflict(action)
  File "/usr/lib/python3.12/argparse.py", line 1658, in _check_conflict
    conflict_handler(action, confl_optionals)
  File "/usr/lib/python3.12/argparse.py", line 1667, in _handle_conflict_error
    raise ArgumentError(action, message % conflict_string)
argparse.ArgumentError: argument -n/--note/-N: conflicting option string: -n

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/tmp/bug.py", line 30, in <module>
    argh.dispatch_command(hello)
  File "/usr/lib/python3/dist-packages/argh/dispatching.py", line 470, in dispatch_command
    set_default_command(parser, function, name_mapping_policy=name_mapping_policy)
  File "/usr/lib/python3/dist-packages/argh/assembling.py", line 460, in set_default_command
    raise AssemblingError(
argh.exceptions.AssemblingError: hello: cannot add 'note' as -n/--note/-N: argument -n/--note/-N: conflicting option string: -n

Expected behavior

Not raise an exception.

Environment

  • OS: Linux
  • Python version: Python 3.12.5
  • Argh version: 0.31.3

Additional context

I'm using argh for a lot of AI-related tools. This problem has occured a few times.

I asked OpenAI o1-preview to fix it, and it didn't quite manage it, but I figured it out eventually, see PR #234

sswam avatar Sep 19 '24 12:09 sswam