root/lang/python/coda/trunk/coda/find_name_error.py @ 209

Revision 209, 3.4 kB (checked in by nishio, 6 years ago)

/lang/python/coda: initial import.

Line 
1import types
2
3import __builtin__
4_default_stored = set(__builtin__.__dict__.keys())
5
6_default_stored.update("""
7""".split())
8
9_default_stored.add(None) # special value for class definition
10
11def _default_printer(line_no, argstr):
12    print "line %d: %s" % (line_no, argstr)
13
14def find_name_error(o, stored=_default_stored, printer=_default_printer):
15    """Find possibility of NameError
16
17    unsupported issue:
18    "from foo import *"
19    LOAD_ATTR(foo.bar)
20    """
21    from co2insts import co2insts
22    from get_co import get_co
23
24    co = get_co(o)
25    stored = set(stored)
26    stored.update(co.co_varnames)
27
28    children = set()
29    for ins in co2insts(co):
30        if ins.opname.startswith("LOAD_"):
31            if ins.opname == "LOAD_CONST":
32                const = co.co_consts[ins.arg]
33                if type(const) == types.CodeType:
34                    children.add(const)
35                continue
36            if ins.opname == "LOAD_ATTR":
37                continue
38           
39            if ins.argstr not in stored:
40                #print o
41                #from _dis import dis
42                #dis(o)
43                printer(ins.line_no, ins.argstr)
44
45        if ins.opname.startswith("STORE_"):
46            stored.add(ins.argstr)
47
48    for c in children:
49        find_name_error(c, stored, printer)
50
51def recursive(dirname):
52    import os
53    printed_filenames = []
54    def printer(line_no, argstr):
55        if filename not in printed_filenames:
56            print "***", path
57            printed_filenames.append(filename)
58        print "line %d: %s" % (line_no, argstr)
59
60   
61    for (dp, dn, fns) in os.walk(dirname):
62        for filename in fns:
63            if filename.endswith(".py"):
64                path = os.path.join(dp, filename)
65                find_name_error(
66                    file(path),
67                    printer=printer)
68
69
70def watch(targets):
71    import os, time
72    def get_mtime(filename):
73        return os.stat(filename).st_mtime
74
75    old_mtime = {}
76    while 1:
77        time.sleep(0.3)
78        for filename in targets:
79            mtime = get_mtime(filename)
80            if old_mtime.get(filename) < mtime:
81                print "***", filename, "modified"
82                old_mtime[filename] = mtime
83                find_name_error(file(filename))
84
85def main():
86    import sys
87    import optparse
88    parser = optparse.OptionParser()
89    parser.add_option("-r", "--recursive", dest="dirname",
90                      help="find *.py under the directory", metavar="DIR")
91    parser.add_option("-w", "--watch",
92                      action="store_true", dest="watch", default=False,
93                      help="watching target continuously(not implemented yet)")
94
95    (options, args) = parser.parse_args()
96
97    if options.watch:
98        import os
99        print "watch mode"
100        if options.dirname:
101            targets = []
102            for (dp, dn, fns) in os.walk(options.dirname):
103                for filename in fns:
104                    if filename.endswith(".py"):
105                        path = os.path.join(dp, filename)
106                        targets.append(path)
107        else:
108            targets = sys.argv[1:]
109
110        watch(targets)
111
112    if options.dirname:
113        recursive(options.dirname)
114    else:
115        for filename in sys.argv[1:]:
116            find_name_error(file(filename))
117   
118if __name__ == "__main__":
119    main()
Note: See TracBrowser for help on using the browser.