This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author paul.j3
Recipients A. Skrobov, docs@python, paul.j3, r.david.murray
Date 2015-10-03.04:53:44
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1443848025.64.0.420161293456.issue25299@psf.upfronthosting.co.za>
In-reply-to
Content
A fix that I am exploring would wrap the Action instantiation call in add_argument with a try/except block

That is replace:

    def add_argument(...)
        ....
        action = action_class(**kwargs)
        ...

with

        ....
        try:
            action = action_class(**kwargs)
        except TypeError:
            msg = str(_sys.exc_info()[1])
            msg = msg.replace('__init__','add_argument')
            msg = [msg]
            msg.append('Wrong argument(s) for Action subclass: %s'%action_class.__name__)
            # action_class is now a class, rather than the input string
            msg.append('kwargs: %s'%kwargs)
            sig = getattr(action_class, 'action_sig',None)
            if sig is not None:
                msg = sig(msg)
            raise ValueError(msg)
       ....

This collects information on the error, the action class and arguments, and passes them to a class method of the Action.  That customizes the message, and returns it for reraising.

In 'class Action' I define:

    @classmethod
    def action_sig(cls, msg=[]):
        # return the signature
        # subclasses may return custom version
        import inspect
        try:
            name = cls.__name__
            sig = inspect.signature(cls.__init__)
            sig = str(sig)
        except AttributeError:
            spec = inspect.getfullargspec(cls.__init__)
            sig = inspect.formatargspec(*spec)
        # remove self, option_strings, dest
        dstr='dest,'
        ind = sig.find(dstr)
        if ind>=0:
            sig = '(...'+sig[(ind+len(dstr)+1):]
        sig = 'class args: %s'%sig
        msg.append(sig)
        return '\n'.join(msg)

This adds inspect.signature information from the subclass __init__ method to the message from add_argument.  Subclasses (including the user defined ones) could customize this.

So a missing 'const' error would display as:

ValueError: add_argument() missing 1 required positional argument: 'const'
Wrong argument(s) for Action subclass: _StoreConstAction
kwargs: {'option_strings': ['--bar'], 'dest': 'bar'}
class args: (...const, default=None, required=False, help=None, metavar=None)

This may be overkill, but it gives an idea of the information that we can add to the original TypeError.

Done right this action_sig() could also serve as a usage function for an Action class.
History
Date User Action Args
2015-10-03 04:53:45paul.j3setrecipients: + paul.j3, r.david.murray, docs@python, A. Skrobov
2015-10-03 04:53:45paul.j3setmessageid: <1443848025.64.0.420161293456.issue25299@psf.upfronthosting.co.za>
2015-10-03 04:53:45paul.j3linkissue25299 messages
2015-10-03 04:53:44paul.j3create