diff options
author | Benjamin Peterson <benjamin@python.org> | 2010-03-30 18:42:32 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2010-03-30 18:42:32 (GMT) |
commit | 25cd7eb9a14cb646e58e315ebfafe867862a705b (patch) | |
tree | 79a7b79ca21a2f2e8e3012163745f9d513edbeaf /Lib/inspect.py | |
parent | e6c9d24562adf4eddfcbeb6cc1873b3e6795e2eb (diff) | |
download | cpython-25cd7eb9a14cb646e58e315ebfafe867862a705b.zip cpython-25cd7eb9a14cb646e58e315ebfafe867862a705b.tar.gz cpython-25cd7eb9a14cb646e58e315ebfafe867862a705b.tar.bz2 |
Merged revisions 79500 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r79500 | benjamin.peterson | 2010-03-30 12:58:13 -0500 (Tue, 30 Mar 2010) | 4 lines
add inspect.getcallargs, which binds function arguments like a normal call #3135
Patch by George Sakkis
........
Diffstat (limited to 'Lib/inspect.py')
-rw-r--r-- | Lib/inspect.py | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index c489502..b9fcd74 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -17,7 +17,7 @@ Here are some of the useful functions provided by this module: getmodule() - determine the module that an object came from getclasstree() - arrange classes so as to represent their hierarchy - getargspec(), getargvalues() - get info about function arguments + getargspec(), getargvalues(), getcallargs() - get info about function arguments getfullargspec() - same, with support for Python-3000 features formatargspec(), formatargvalues() - format an argument spec getouterframes(), getinnerframes() - get info about frames @@ -33,6 +33,7 @@ __date__ = '1 Jan 2001' import sys import os import types +import itertools import string import re import dis @@ -926,6 +927,71 @@ def formatargvalues(args, varargs, varkw, locals, specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) return '(' + ', '.join(specs) + ')' +def getcallargs(func, *positional, **named): + """Get the mapping of arguments to values. + + A dict is returned, with keys the function argument names (including the + names of the * and ** arguments, if any), and values the respective bound + values from 'positional' and 'named'.""" + spec = getfullargspec(func) + args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = spec + f_name = func.__name__ + arg2value = {} + + if ismethod(func) and func.__self__ is not None: + # implicit 'self' (or 'cls' for classmethods) argument + positional = (func.__self__,) + positional + num_pos = len(positional) + num_total = num_pos + len(named) + num_args = len(args) + num_defaults = len(defaults) if defaults else 0 + for arg, value in zip(args, positional): + arg2value[arg] = value + if varargs: + if num_pos > num_args: + arg2value[varargs] = positional[-(num_pos-num_args):] + else: + arg2value[varargs] = () + elif 0 < num_args < num_pos: + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at most' if defaults else 'exactly', num_args, + 'arguments' if num_args > 1 else 'argument', num_total)) + elif num_args == 0 and num_total: + raise TypeError('%s() takes no arguments (%d given)' % + (f_name, num_total)) + + for arg in itertools.chain(args, kwonlyargs): + if arg in named: + if arg in arg2value: + raise TypeError("%s() got multiple values for keyword " + "argument '%s'" % (f_name, arg)) + else: + arg2value[arg] = named.pop(arg) + for kwonlyarg in kwonlyargs: + if kwonlyarg not in arg2value: + try: + arg2value[kwonlyarg] = kwonlydefaults[kwonlyarg] + except KeyError: + raise TypeError("%s() needs keyword-only argument %s" % + (f_name, kwonlyarg)) + if defaults: # fill in any missing values with the defaults + for arg, value in zip(args[-num_defaults:], defaults): + if arg not in arg2value: + arg2value[arg] = value + if varkw: + arg2value[varkw] = named + elif named: + unexpected = next(iter(named)) + raise TypeError("%s() got an unexpected keyword argument '%s'" % + (f_name, unexpected)) + unassigned = num_args - len([arg for arg in args if arg in arg2value]) + if unassigned: + num_required = num_args - num_defaults + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at least' if defaults else 'exactly', num_required, + 'arguments' if num_required > 1 else 'argument', num_total)) + return arg2value + # -------------------------------------------------- stack frame extraction Traceback = namedtuple('Traceback', 'filename lineno function code_context index') |