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@python components: Documentation, Library (Lib), Tests messages: 226862 nosy: docs@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 <rep...@bugs.python.org> <http://bugs.python.org/issue22401> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com