Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 # -*- coding: iso-8859-1 -*- | 1 # -*- coding: iso-8859-1 -*- |
2 """Get useful information from live Python objects. | 2 """Get useful information from live Python objects. |
3 | 3 |
4 This module encapsulates the interface provided by the internal special | 4 This module encapsulates the interface provided by the internal special |
5 attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion. | 5 attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion. |
6 It also provides some help for examining source code and class layout. | 6 It also provides some help for examining source code and class layout. |
7 | 7 |
8 Here are some of the useful functions provided by this module: | 8 Here are some of the useful functions provided by this module: |
9 | 9 |
10 ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), | 10 ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), |
(...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
888 """Get the mapping of arguments to values when calling func(*positional, **n amed). | 888 """Get the mapping of arguments to values when calling func(*positional, **n amed). |
889 | 889 |
890 A dict is returned, with keys the function argument names (including the | 890 A dict is returned, with keys the function argument names (including the |
891 names of the * and ** arguments, if any), and values the respective bound | 891 names of the * and ** arguments, if any), and values the respective bound |
892 values from 'positional' and 'named'.""" | 892 values from 'positional' and 'named'.""" |
893 args, varargs, varkw, defaults = getargspec(func) | 893 args, varargs, varkw, defaults = getargspec(func) |
894 f_name = func.__name__ | 894 f_name = func.__name__ |
895 arg2value = {} | 895 arg2value = {} |
896 | 896 |
897 # the following closures are basically because of tuple parameter unpacking | 897 # the following closures are basically because of tuple parameter unpacking |
898 assigned_tuple_params = [] | 898 assigned_tuple_params = [] |
Benjamin
2010/03/20 03:14:31
How about simply keeping all assigned names in a s
George Sakkis
2010/03/20 13:26:34
getargspec() returns the tuple parameter names as
| |
899 def assign(arg, value): | 899 def assign(arg, value): |
900 if isinstance(arg, str): | 900 if isinstance(arg, str): |
901 arg2value[arg] = value | 901 arg2value[arg] = value |
902 else: | 902 else: |
903 assigned_tuple_params.append(arg) | 903 assigned_tuple_params.append(arg) |
904 value = iter(value) | 904 value = iter(value) |
905 for i,subarg in enumerate(arg): | 905 for i, subarg in enumerate(arg): |
906 try: subvalue = next(value) | 906 try: |
Benjamin
2010/03/20 03:14:31
Please keep these on separate lines.
George Sakkis
2010/03/20 13:26:34
Done.
| |
907 subvalue = next(value) | |
907 except StopIteration: | 908 except StopIteration: |
908 raise ValueError('need more than %d %s to unpack' % | 909 raise ValueError('need more than %d %s to unpack' % |
909 (i, 'values' if i>1 else 'value')) | 910 (i, 'values' if i>1 else 'value')) |
910 assign(subarg,subvalue) | 911 assign(subarg,subvalue) |
911 try: next(value) | 912 try: next(value) |
912 except StopIteration: pass | 913 except StopIteration: pass |
913 else: raise ValueError('too many values to unpack') | 914 else: raise ValueError('too many values to unpack') |
914 def is_assigned(arg): | 915 def is_assigned(arg): |
915 if isinstance(arg,str): | 916 if isinstance(arg,str): |
916 return arg in arg2value | 917 return arg in arg2value |
917 return arg in assigned_tuple_params | 918 return arg in assigned_tuple_params |
918 #------- handle methods (bound and unbound) -------------------------------- | |
Benjamin
2010/03/20 03:14:31
Remove all the "-" and all similar following comme
George Sakkis
2010/03/20 13:26:34
Done.
| |
919 if ismethod(func): | 919 if ismethod(func): |
920 # implicit 'self' (or 'cls' for classmethods) argument | 920 # implicit 'self' (or 'cls' for classmethods) argument |
921 if func.im_self is not None: | 921 if func.im_self is not None: |
922 positional = (func.im_self,) + positional | 922 positional = (func.im_self,) + positional |
923 elif not positional or not isinstance(positional[0], func.im_class): | 923 elif not positional or not isinstance(positional[0], func.im_class): |
Benjamin
2010/03/20 03:14:31
Why are you typechecking this here? Why not just l
George Sakkis
2010/03/20 13:26:34
Which function call ? We never call func() in getc
Benjamin
2010/03/20 16:32:15
I mean why should this be typechecked here?
| |
924 got = ('%s instance' % type(positional[0]).__name__ if positional | 924 got = ('%s instance' % type(positional[0]).__name__ if positional |
925 else 'nothing') | 925 else 'nothing') |
926 raise TypeError('unbound method %s() must be called with %s ' | 926 raise TypeError('unbound method %s() must be called with %s ' |
927 'instance as first argument (got %s instead)' % | 927 'instance as first argument (got %s instead)' % |
928 (f_name, func.im_class.__name__, got)) | 928 (f_name, func.im_class.__name__, got)) |
929 num_pos = len(positional) | 929 num_pos = len(positional) |
930 has_named = bool(named) | 930 num_total = num_pos + len(named) |
931 num_args = len(args) | 931 num_args = len(args) |
932 num_defaults = len(defaults or ()) | 932 num_defaults = len(defaults) if defaults else 0 |
Benjamin
2010/03/20 03:14:31
Conditional "len(default) if default else 0" is mo
George Sakkis
2010/03/20 13:26:34
Done.
| |
933 #------- assign the positional arguments ----------------------------------- | 933 for arg, value in zip(args, positional): |
934 for arg,value in zip(args,positional): | |
Benjamin
2010/03/20 03:14:31
Needs a space.
George Sakkis
2010/03/20 13:26:34
Done.
| |
935 assign(arg, value) | 934 assign(arg, value) |
936 if varargs: | 935 if varargs: |
937 if num_pos > num_args: | 936 if num_pos > num_args: |
Benjamin
2010/03/20 03:14:31
I don't think this conditional is needed.
George Sakkis
2010/03/20 13:26:34
It is, otherwise positional[-(num_pos-num_args):]
| |
938 assign(varargs, positional[-(num_pos-num_args):]) | 937 assign(varargs, positional[-(num_pos-num_args):]) |
939 else: | 938 else: |
940 assign(varargs, ()) | 939 assign(varargs, ()) |
941 elif 0 < num_args < num_pos: | 940 elif 0 < num_args < num_pos: |
942 raise TypeError('%s() takes %s %d %s%s (%d given)' % ( | 941 raise TypeError('%s() takes %s %d %s (%d given)' % ( |
943 f_name, 'at most' if defaults else 'exactly', num_args, | 942 f_name, 'at most' if defaults else 'exactly', num_args, |
944 'non-keyword ' if has_named else '', | 943 'arguments' if num_args>1 else 'argument', num_total)) |
945 'arguments' if num_args>1 else 'argument', num_pos)) | 944 elif num_args == 0 and num_total: |
946 elif num_args==0 and (num_pos or has_named): | 945 raise TypeError('%s() takes no arguments (%d given)' % (f_name, num_tota l)) |
Benjamin
2010/03/20 03:14:31
Space between the == and operands.
George Sakkis
2010/03/20 13:26:34
Done.
| |
947 raise TypeError('%s() takes no arguments (%d given)' % | |
948 (f_name, num_pos+len(named))) | |
949 #------- assign the named arguments ---------------------------------------- | |
950 for arg in args: | 946 for arg in args: |
951 if isinstance(arg,str) and arg in named: | 947 if isinstance(arg, str) and arg in named: |
Benjamin
2010/03/20 03:14:31
Space in function call.
George Sakkis
2010/03/20 13:26:34
Done.
| |
952 if is_assigned(arg): | 948 if is_assigned(arg): |
953 raise TypeError("%s() got multiple values for keyword " | 949 raise TypeError("%s() got multiple values for keyword " |
954 "argument '%s'" % (f_name,arg)) | 950 "argument '%s'" % (f_name, arg)) |
Benjamin
2010/03/20 03:14:31
Space in tuple.
George Sakkis
2010/03/20 13:26:34
Done.
| |
955 else: | 951 else: |
956 assign(arg, named.pop(arg)) | 952 assign(arg, named.pop(arg)) |
957 if defaults: # fill in any missing values with the defaults | 953 if defaults: # fill in any missing values with the defaults |
958 for arg,value in zip(args[-num_defaults:],defaults): | 954 for arg, value in zip(args[-num_defaults:], defaults): |
Benjamin
2010/03/20 03:14:31
Space in zip() call.
George Sakkis
2010/03/20 13:26:34
Done.
| |
959 if not is_assigned(arg): | 955 if not is_assigned(arg): |
960 assign(arg, value) | 956 assign(arg, value) |
961 if varkw: | 957 if varkw: |
962 assign(varkw, named) | 958 assign(varkw, named) |
963 elif named: | 959 elif named: |
964 unexpected = next(iter(named)) | 960 unexpected = next(iter(named)) |
965 if isinstance(unexpected, unicode): | 961 if isinstance(unexpected, unicode): |
966 unexpected = unexpected.encode('ascii','replace') | 962 unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace') |
Benjamin
2010/03/20 03:14:31
You should actually encode it with sys.getdefaulte
George Sakkis
2010/03/20 13:26:34
Changed 'ascii' to sys.getdefaultencoding() but th
| |
967 raise TypeError("%s() got an unexpected keyword argument '%s'" % | 963 raise TypeError("%s() got an unexpected keyword argument '%s'" % |
968 (f_name, unexpected)) | 964 (f_name, unexpected)) |
969 #------- ensure that all required args have a value ------------------------ | 965 unassigned = num_args - len([arg for arg in args if is_assigned(arg)]) |
970 unassigned = sum(1 for arg in args if not is_assigned(arg)) | |
Benjamin
2010/03/20 03:14:31
Just use len on a listcomp.
George Sakkis
2010/03/20 13:26:34
I think "len(args) - len(filter(is_assigned, args)
| |
971 if unassigned: | 966 if unassigned: |
972 num_required = num_args - num_defaults | 967 num_required = num_args - num_defaults |
973 raise TypeError('%s() takes %s %d %s%s (%d given)' % ( | 968 raise TypeError('%s() takes %s %d %s (%d given)' % ( |
974 f_name, 'at least' if defaults else 'exactly', num_required, | 969 f_name, 'at least' if defaults else 'exactly', num_required, |
975 'non-keyword ' if has_named else '', | 970 'arguments' if num_required>1 else 'argument', num_total)) |
976 'arguments' if num_required>1 else 'argument', num_required-unassign ed)) | |
977 return arg2value | 971 return arg2value |
978 | 972 |
979 # -------------------------------------------------- stack frame extraction | 973 # -------------------------------------------------- stack frame extraction |
980 | 974 |
981 Traceback = namedtuple('Traceback', 'filename lineno function code_context index ') | 975 Traceback = namedtuple('Traceback', 'filename lineno function code_context index ') |
982 | 976 |
983 def getframeinfo(frame, context=1): | 977 def getframeinfo(frame, context=1): |
984 """Get information about a frame or traceback object. | 978 """Get information about a frame or traceback object. |
985 | 979 |
986 A tuple of five things is returned: the filename, the line number of | 980 A tuple of five things is returned: the filename, the line number of |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1045 else: | 1039 else: |
1046 currentframe = lambda _=None: None | 1040 currentframe = lambda _=None: None |
1047 | 1041 |
1048 def stack(context=1): | 1042 def stack(context=1): |
1049 """Return a list of records for the stack above the caller's frame.""" | 1043 """Return a list of records for the stack above the caller's frame.""" |
1050 return getouterframes(sys._getframe(1), context) | 1044 return getouterframes(sys._getframe(1), context) |
1051 | 1045 |
1052 def trace(context=1): | 1046 def trace(context=1): |
1053 """Return a list of records for the stack below the current exception.""" | 1047 """Return a list of records for the stack below the current exception.""" |
1054 return getinnerframes(sys.exc_info()[2], context) | 1048 return getinnerframes(sys.exc_info()[2], context) |
LEFT | RIGHT |