Issue 22998: inspect.Signature and default arguments (original) (raw)

Created on 2014-12-04 20:14 by doerwalter, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
signature-bind.diff doerwalter,2014-12-04 20:14 review
Messages (10)
msg232150 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2014-12-04 20:14
inspect.Signature.bind() doesn't add values for parameters that are unspecified but have a default value. The documentation at https://docs.python.org/3/library/inspect.html#inspect.BoundArguments.arguments includes an example how to add default values, but that example doesn't work for the * and ** parameters. This patch adds a new method Signature.bind_with_defaults() that works like Signature.bind(), but includes parameters with a default value (and can handle values for the * and ** parameters).
msg232151 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-12-04 20:20
Can you give an example of what you say doesn't work? IIRC the reason this method isn't part of the API is because normally it isn't needed (the defaults are filled in when you do the actual call). What is your use case for needing the defaults to be pre-bound?
msg232152 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2014-12-04 20:43
The following doesn't work:: import inspect def foo(*args, **kwargs): return (args, kwargs) # Code from https://docs.python.org/3/library/inspect.html#inspect.BoundArguments.arguments to fill in the defaults sig = inspect.signature(foo) ba = sig.bind() for param in sig.parameters.values(): if param.name not in ba.arguments: ba.arguments[param.name] = param.default print(foo(*ba.args, **ba.kwargs)) instead it gives the following traceback:: Traceback (most recent call last): File "sig_test.py", line 16, in print(foo(*ba.args, **ba.kwargs)) File "/Users/walter/.local/lib/python3.4/inspect.py", line 2246, in args args.extend(arg) TypeError: 'type' object is not iterable In my use case there isn't a call to a function implemented in Python. Instead I'm implementing a templating languages that supports defining a signature for a template. Calling the template binds the arguments and inside the template the variables simply are a dictionary. I.e. define the template like this: t = Template("", signature="a, b=23") Then you can call it like this: t(17) and inside the template the variables will be {"a": 17, "b": 23}. The signature argument in the Template constructor will be parsed into an inspect.Signature object and I'd like to use Signature.bind() to get the final variables dictionary.
msg232153 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-12-04 21:28
This is indeed a bit tricky. Your use case is pretty specialized (it doesn't involve any actual python functions), so I don't think by itself it argues for the inclusion of a _with_defaults method. The example fill-in in the docs fails because args and kwargs don't check for _empty as a possible value for the VAR_POSITIONAL (resp VAR_KEYWORD). So I think either we add that check to args and kwargs, or we add a _with_defaults method because filling in the defaults would no longer be a simple loop (and thus easy to get wrong). Let's see what Yury thinks.
msg232154 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2014-12-04 22:05
I think we should just fix the documentation, and update the code in example with a proper check: for param in sig.parameters.values(): if (param.name not in ba.arguments and param.default is not param.empty): ba.arguments[param.name] = param.default I'm -1 on adding '_with_defaults' method, because usually you don't need this (at least in my experience).
msg232175 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2014-12-05 03:49
New changeset 71c38c233e5c by Yury Selivanov in branch '3.4': docs.inspect: Fix BoundArguments example. Issue #22998. https://hg.python.org/cpython/rev/71c38c233e5c New changeset 697adefaba6b by Yury Selivanov in branch 'default': docs.inspect: Fix BoundArguments example. Issue #22998. https://hg.python.org/cpython/rev/697adefaba6b
msg232227 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-12-05 23:57
Should this be closed now?
msg232228 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2014-12-06 00:05
> Should this be closed now? Yes, let's close it. David and Walter, you're welcome to re-open the issue if you want to discuss it in more detail.
msg232234 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-12-06 01:32
I'm good with your solution, but I'm going to adjust the resolution by changing the component :)
msg232375 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2014-12-09 13:33
The updated code in the documentation still doesn't set the * and ** parameters. I would have preferred the following code: for param in sig.parameters.values(): if param.name not in ba.arguments: if param.kind is inspect.Parameter.VAR_POSITIONAL: default = () elif param.kind is inspect.Parameter.VAR_KEYWORD: default = {} else: default = param.default ba.arguments[param.name] = default
History
Date User Action Args
2022-04-11 14:58:10 admin set github: 67187
2014-12-09 13:33:49 doerwalter set messages: +
2014-12-06 01:32:18 r.david.murray set assignee: docs@pythoncomponents: + Documentation, - Library (Lib)nosy: + docs@pythonmessages: + resolution: wont fix -> fixedstage: resolved
2014-12-06 00:05:53 yselivanov set status: open -> closedresolution: wont fixmessages: +
2014-12-05 23:57:30 terry.reedy set nosy: + terry.reedymessages: +
2014-12-05 03:49:03 python-dev set nosy: + python-devmessages: +
2014-12-04 22:05:21 yselivanov set messages: +
2014-12-04 21:28:34 r.david.murray set nosy: + yselivanovmessages: + versions: + Python 3.4, Python 3.5
2014-12-04 20:43:18 doerwalter set messages: +
2014-12-04 20:20:38 r.david.murray set nosy: + r.david.murraymessages: +
2014-12-04 20:14:01 doerwalter create