Closed bitdancer closed 9 years ago
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!
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.
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.
New changeset 3cc368d334c5 by Yury Selivanov in branch 'default': bpo-24205: Improve inspect.Signature.bind() error messages. https://hg.python.org/cpython/rev/3cc368d334c5
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields: ```python assignee = 'https://github.com/1st1' closed_at =
created_at =
labels = ['type-bug', 'library']
title = 'signature.bind error messages are sub-optimal'
updated_at =
user = 'https://github.com/bitdancer'
```
bugs.python.org fields:
```python
activity =
actor = 'yselivanov'
assignee = 'yselivanov'
closed = True
closed_date =
closer = 'yselivanov'
components = ['Library (Lib)']
creation =
creator = 'r.david.murray'
dependencies = []
files = ['39422']
hgrepos = []
issue_num = 24205
keywords = ['patch']
message_count = 4.0
messages = ['243287', '243519', '243548', '243554']
nosy_count = 5.0
nosy_names = ['r.david.murray', 'ethan.furman', 'python-dev', 'martin.panter', 'yselivanov']
pr_nums = []
priority = 'normal'
resolution = 'fixed'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue24205'
versions = ['Python 3.5']
```