Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | # A subroutine for extracting a function name from a code object |
2 | # (with cache) | |
3 | ||
4 | import sys | |
5 | from stat import * | |
6 | import string | |
7 | import os | |
8 | import linecache | |
9 | ||
10 | # XXX The functions getcodename() and getfuncname() are now obsolete | |
11 | # XXX as code and function objects now have a name attribute -- | |
12 | # XXX co.co_name and f.func_name. | |
13 | # XXX getlineno() is now also obsolete because of the new attribute | |
14 | # XXX of code objects, co.co_firstlineno. | |
15 | ||
16 | # Extract the function or class name from a code object. | |
17 | # This is a bit of a hack, since a code object doesn't contain | |
18 | # the name directly. So what do we do: | |
19 | # - get the filename (which *is* in the code object) | |
20 | # - look in the code string to find the first SET_LINENO instruction | |
21 | # (this must be the first instruction) | |
22 | # - get the line from the file | |
23 | # - if the line starts with 'class' or 'def' (after possible whitespace), | |
24 | # extract the following identifier | |
25 | # | |
26 | # This breaks apart when the function was read from <stdin> | |
27 | # or constructed by exec(), when the file is not accessible, | |
28 | # and also when the file has been modified or when a line is | |
29 | # continued with a backslash before the function or class name. | |
30 | # | |
31 | # Because this is a pretty expensive hack, a cache is kept. | |
32 | ||
33 | SET_LINENO = 127 # The opcode (see "opcode.h" in the Python source) | |
34 | identchars = string.ascii_letters + string.digits + '_' # Identifier characters | |
35 | ||
36 | _namecache = {} # The cache | |
37 | ||
38 | def getcodename(co): | |
39 | try: | |
40 | return co.co_name | |
41 | except AttributeError: | |
42 | pass | |
43 | key = `co` # arbitrary but uniquely identifying string | |
44 | if _namecache.has_key(key): return _namecache[key] | |
45 | filename = co.co_filename | |
46 | code = co.co_code | |
47 | name = '' | |
48 | if ord(code[0]) == SET_LINENO: | |
49 | lineno = ord(code[1]) | ord(code[2]) << 8 | |
50 | line = linecache.getline(filename, lineno) | |
51 | words = line.split() | |
52 | if len(words) >= 2 and words[0] in ('def', 'class'): | |
53 | name = words[1] | |
54 | for i in range(len(name)): | |
55 | if name[i] not in identchars: | |
56 | name = name[:i] | |
57 | break | |
58 | _namecache[key] = name | |
59 | return name | |
60 | ||
61 | # Use the above routine to find a function's name. | |
62 | ||
63 | def getfuncname(func): | |
64 | try: | |
65 | return func.func_name | |
66 | except AttributeError: | |
67 | pass | |
68 | return getcodename(func.func_code) | |
69 | ||
70 | # A part of the above code to extract just the line number from a code object. | |
71 | ||
72 | def getlineno(co): | |
73 | try: | |
74 | return co.co_firstlineno | |
75 | except AttributeError: | |
76 | pass | |
77 | code = co.co_code | |
78 | if ord(code[0]) == SET_LINENO: | |
79 | return ord(code[1]) | ord(code[2]) << 8 | |
80 | else: | |
81 | return -1 |