| author | Sandro Knauß <knauss@netzguerilla.net> |
| Fri, 06 Jul 2012 12:22:15 +0200 | |
| branch | devel |
| changeset 282 | 50cc13814bfb |
| child 294 | 0e75bd39767d |
| permissions | -rw-r--r-- |
|
282
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
1 |
from inspect import getargspec, ismethod |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
2 |
import sys |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
3 |
|
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
4 |
#code just copied form python 2.7.3 |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
5 |
|
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
6 |
def getcallargs(func, *positional, **named): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
7 |
"""Get the mapping of arguments to values. |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
8 |
|
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
9 |
A dict is returned, with keys the function argument names (including the |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
10 |
names of the * and ** arguments, if any), and values the respective bound |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
11 |
values from 'positional' and 'named'.""" |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
12 |
args, varargs, varkw, defaults = getargspec(func) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
13 |
f_name = func.__name__ |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
14 |
arg2value = {} |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
15 |
|
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
16 |
# The following closures are basically because of tuple parameter unpacking. |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
17 |
assigned_tuple_params = [] |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
18 |
def assign(arg, value): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
19 |
if isinstance(arg, str): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
20 |
arg2value[arg] = value |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
21 |
else: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
22 |
assigned_tuple_params.append(arg) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
23 |
value = iter(value) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
24 |
for i, subarg in enumerate(arg): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
25 |
try: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
26 |
subvalue = next(value) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
27 |
except StopIteration: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
28 |
raise ValueError('need more than %d %s to unpack' % |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
29 |
(i, 'values' if i > 1 else 'value')) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
30 |
assign(subarg,subvalue) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
31 |
try: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
32 |
next(value) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
33 |
except StopIteration: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
34 |
pass |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
35 |
else: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
36 |
raise ValueError('too many values to unpack') |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
37 |
def is_assigned(arg): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
38 |
if isinstance(arg,str): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
39 |
return arg in arg2value |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
40 |
return arg in assigned_tuple_params |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
41 |
if ismethod(func) and func.im_self is not None: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
42 |
# implicit 'self' (or 'cls' for classmethods) argument |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
43 |
positional = (func.im_self,) + positional |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
44 |
num_pos = len(positional) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
45 |
num_total = num_pos + len(named) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
46 |
num_args = len(args) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
47 |
num_defaults = len(defaults) if defaults else 0 |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
48 |
for arg, value in zip(args, positional): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
49 |
assign(arg, value) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
50 |
if varargs: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
51 |
if num_pos > num_args: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
52 |
assign(varargs, positional[-(num_pos-num_args):]) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
53 |
else: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
54 |
assign(varargs, ()) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
55 |
elif 0 < num_args < num_pos: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
56 |
raise TypeError('%s() takes %s %d %s (%d given)' % ( |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
57 |
f_name, 'at most' if defaults else 'exactly', num_args, |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
58 |
'arguments' if num_args > 1 else 'argument', num_total)) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
59 |
elif num_args == 0 and num_total: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
60 |
if varkw: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
61 |
if num_pos: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
62 |
# XXX: We should use num_pos, but Python also uses num_total: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
63 |
raise TypeError('%s() takes exactly 0 arguments ' |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
64 |
'(%d given)' % (f_name, num_total)) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
65 |
else: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
66 |
raise TypeError('%s() takes no arguments (%d given)' % |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
67 |
(f_name, num_total)) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
68 |
for arg in args: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
69 |
if isinstance(arg, str) and arg in named: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
70 |
if is_assigned(arg): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
71 |
raise TypeError("%s() got multiple values for keyword " |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
72 |
"argument '%s'" % (f_name, arg)) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
73 |
else: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
74 |
assign(arg, named.pop(arg)) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
75 |
if defaults: # fill in any missing values with the defaults |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
76 |
for arg, value in zip(args[-num_defaults:], defaults): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
77 |
if not is_assigned(arg): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
78 |
assign(arg, value) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
79 |
if varkw: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
80 |
assign(varkw, named) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
81 |
elif named: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
82 |
unexpected = next(iter(named)) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
83 |
if isinstance(unexpected, unicode): |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
84 |
unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace') |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
85 |
raise TypeError("%s() got an unexpected keyword argument '%s'" % |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
86 |
(f_name, unexpected)) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
87 |
unassigned = num_args - len([arg for arg in args if is_assigned(arg)]) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
88 |
if unassigned: |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
89 |
num_required = num_args - num_defaults |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
90 |
raise TypeError('%s() takes %s %d %s (%d given)' % ( |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
91 |
f_name, 'at least' if defaults else 'exactly', num_required, |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
92 |
'arguments' if num_required > 1 else 'argument', num_total)) |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
93 |
return arg2value |
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
94 |
|
|
50cc13814bfb
make iro working with python v2.6
Sandro Knauß <knauss@netzguerilla.net>
parents:
diff
changeset
|
95 |