[New-bugs-announce] [issue22401] argparse: 'resolve' conflict handler damages the actions of the parent parser

paul j3 report at bugs.python.org
Sun Sep 14 07:46:38 CEST 2014


New submission from paul j3:

When there's a conflict involving an argument that was added via 'parents', and the conflict handler is 'resolve', the action in the parent parser may be damaged, rendering that parent unsuitable for further use.

In this example, 2 parents have the same '--config' argument:
  
    parent1 = argparse.ArgumentParser(add_help=False) 
    parent1.add_argument('--config')

    parent2 = argparse.ArgumentParser(add_help=False)
    parent2.add_argument('--config')

    parser = argparse.ArgumentParser(parents=[parent1,parent2],
        conflict_handler='resolve')

The actions of the 3 parsers are (from the ._actions list):

               (id,          dest,    option_strings)
    parent1:  [(3077384012L, 'config', [])]    # empty option_strings

    parent2:  [(3076863628L, 'config', ['--config'])]

    parser:   [(3076864428L, 'help', ['-h', '--help']),
               (3076863628L, 'config', ['--config'])]  # same id

The 'config' Action from 'parent1' is first copied to 'parser' by reference (this is important).  When 'config' from 'parent2' is copied, there's a conflict.  '_handle_conflict_resolve()' attempts to remove the first Action, so it can add the second.  But in the process it ends up deleting the 'option_strings' values from the original action.

So now 'parent1' has an action in its 'optionals' argument group with an empty option_strings list.  It would display as an 'optionals' but parse as a 'positionals'.  'parent1' can no longer be safely used as a parent for another (sub)parser, nor used as a parser itself.

The same sort of thing would happen, if, as suggested in the documentation:

    "Sometimes (e.g. when using parents_) it may be useful to simply
     override any older arguments with the same option string." 

In test_argparse.py, 'resolve' is only tested once, with a simple case of two 'add_argument' statements.  The 'parents' class tests a couple of cases of conflicting actions (for positionals and optionals), but does nothing with the 'resolve' handler.

------------------------------

Possible fixes:

- change the documentation to warn against reusing such a parent parser

- test the 'resolve' conflict handler more thoroughly

- rewrite this conflict handler so it does not modify the action in the parent

- possibly change the 'parents' mechanism so it does a deep copy of actions.

References:

http://stackoverflow.com/questions/25818651/argparse-conflict-resolver-for-options-in-subcommands-turns-keyword-argument-int

http://bugs.python.org/issue15271 
argparse: repeatedly specifying the same argument ignores the previous ones

http://bugs.python.org/issue19462
Add remove_argument() method to argparse.ArgumentParser

http://bugs.python.org/issue15428
add "Name Collision" section to argparse docs

----------
assignee: docs at python
components: Documentation, Library (Lib), Tests
messages: 226862
nosy: docs at python, paul.j3
priority: normal
severity: normal
status: open
title: argparse: 'resolve' conflict handler damages the actions of the parent parser
type: behavior
versions: Python 3.5

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue22401>
_______________________________________


More information about the New-bugs-announce mailing list