Author paul.j3
Recipients n8falke, paul.j3
Date 2019-02-22.21:52:39
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1550872360.36.0.823953544762.issue36078@roundup.psfhosted.org>
In-reply-to
Content
By defining a custom 'type' function:

    def foo(astr):
        if astr is argparse.SUPPRESS:
            raise KeyError
        return astr

I get the full traceback

   1831         def take_action(action, argument_strings, option_string=None):
   1832             seen_actions.add(action)
-> 1833             argument_values = self._get_values(action, argument_strings)

and in '_get_values' the error is produced when it calls '_get_value' (which runs the 'type' function):

        # optional argument produces a default when not present
        if not arg_strings and action.nargs == OPTIONAL:
            if action.option_strings:
                value = action.const
            else:
                value = action.default
            if isinstance(value, str):
 -->            value = self._get_value(action, value)
                self._check_value(action, value)
  
It identifies this as an OPTIONAL action that has received an empty argument list, and assigns it the action.default.

ZERO_OR_MORE * also gets the action.default, but without a _get_value() call.  That default can be SUPPRESSed by the test at the end of take_action.

A couple of fixes come to mind: 

- add a SUPPRESS test at the start of take_action
- add a SUPPRESS test to _get_values block I quote above, maybe bypassing the `_get_value` call

There is a unittest case of a suppressed optional positional; it just doesn't also test for a failed type.

class TestDefaultSuppress(ParserTestCase):
    """Test actions with suppressed defaults"""

    argument_signatures = [
        Sig('foo', nargs='?', default=argparse.SUPPRESS)

I'm inclined go with the second choice, but the alternatives need to be throughly tested.

In the mean time, an 'int' type could be replaced with one that is SUPPRESS knowledgeable:

    def bar(astr):
        if astr is argparse.SUPPRESS:
            return astr
        else:
            return int(astr)

Note that this use of action.default is different from the normal default handling at the start of parse_known_args (and the end of _parse_known_args).  It's specifically for positionals that will always be 'seen' (because an empty argument strings list satisfies their nargs).
History
Date User Action Args
2019-02-22 21:52:40paul.j3setrecipients: + paul.j3, n8falke
2019-02-22 21:52:40paul.j3setmessageid: <1550872360.36.0.823953544762.issue36078@roundup.psfhosted.org>
2019-02-22 21:52:40paul.j3linkissue36078 messages
2019-02-22 21:52:39paul.j3create