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.

classification
Title: signature.bind error messages are sub-optimal
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: yselivanov Nosy List: ethan.furman, martin.panter, python-dev, r.david.murray, yselivanov
Priority: normal Keywords: patch

Created on 2015-05-15 23:48 by r.david.murray, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
sig_exc.patch yselivanov, 2015-05-18 18:55 review
Messages (4)
msg243287 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-05-15 23:48
I have an application where I'm calling a handler function with passed in arguments.  I want to generate an error if the handler is called with the wrong arguments.  I can't just catch TypeError since a TypeError could easily result from some programming error in the handler, rather than an error in the calling args.  So, doing this seems obvious:

    sig = signature(handler)
    try:
        bound = sig.bind(message, payload, *args, **kw)
    except TypeError as exc:
        print("Invalid handler call: {}".format(str(exc))
    handler(*bound.args, **bound.kwargs)

Now, suppose I have a function like:

    def foo(message, payload, anarg, akeyword='bar'):
        pass

If I call it directly with an invalid keyword argument I get:

    >>> foo(1, 2, 3, badword=7)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: foo() got an unexpected keyword argument 'badword'

However, bind gives me:

    >>> sig.bind(1, 2, 3, badword=7)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/rdmurray/python/p35/Lib/inspect.py", line 2818, in bind
        return args[0]._bind(args[1:], kwargs)
      File "/home/rdmurray/python/p35/Lib/inspect.py", line 2809, in _bind
        raise TypeError('too many keyword arguments')
    TypeError: too many keyword arguments

Similarly, for a missing argument I get:

    >>> foo(1, 2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: foo() missing 1 required positional argument: 'anarg'

While bind gives:

    >>> sig.bind(1, 2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/rdmurray/python/p35/Lib/inspect.py", line 2818, in bind
        return args[0]._bind(args[1:], kwargs)
      File "/home/rdmurray/python/p35/Lib/inspect.py", line 2737, in _bind
        raise TypeError(msg) from None
    TypeError: 'anarg' parameter lacking default value

So, using this to replace catching the TypeError from incorrectly calling a function does not work.  Nor are the messages in fact accurate.  Is there any chance we could make bind's error handling work like regular function binding?  That's certainly what I expected would happen!
msg243519 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2015-05-18 18:55
Hi David,
Please see the attached patch. It doesn't make Signature.bind() exceptions look exactly like system messages, but it's now much closer.
msg243548 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-05-18 23:53
I think the patch is okay. Just beware that next(iter(kwargs)) can return different names if there is more than one unexpected argument, so the error message could vary. But it looks like the test cases are only when there is exactly one extra argument, so no problem.
msg243554 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2015-05-19 04:27
New changeset 3cc368d334c5 by Yury Selivanov in branch 'default':
Issue 24205: Improve inspect.Signature.bind() error messages.
https://hg.python.org/cpython/rev/3cc368d334c5
History
Date User Action Args
2022-04-11 14:58:16adminsetgithub: 68393
2015-05-19 04:29:08yselivanovsetstatus: open -> closed
resolution: fixed
stage: resolved
2015-05-19 04:27:57python-devsetnosy: + python-dev
messages: + msg243554
2015-05-18 23:53:15martin.pantersetmessages: + msg243548
2015-05-18 18:55:36yselivanovsetassignee: yselivanov
2015-05-18 18:55:31yselivanovsetfiles: + sig_exc.patch
keywords: + patch
messages: + msg243519
2015-05-16 00:36:39martin.pantersetnosy: + martin.panter
2015-05-16 00:06:41ethan.furmansetnosy: + ethan.furman
2015-05-15 23:48:53r.david.murraycreate