File: jastlib2.py

package info (click to toggle)
jython 2.5.3-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 43,304 kB
  • sloc: python: 351,314; java: 216,338; xml: 1,547; sh: 330; perl: 124; ansic: 102; makefile: 101
file content (152 lines) | stat: -rw-r--r-- 4,287 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env python
"""lispify_ast - returns a tuple representation of the AST

Uses 2.5's _ast, not other AST implementations in CPython, since these
are not used by the compilation phase. And that's what we're
interested in.

Since this is a tuple, we can directly compare, and this is going to
be handy when comparing Jython's implementation vs CPython.

"""
import array
import os
import globwalk

import org.python.antlr.PythonTree as AST
import org.python.antlr.Main as parser

def lispify_ast(node):
    return tuple(lispify_ast2(node))

def lispify_ast2(node):
    s = node.__class__.__name__
    name = s.split(".")[-1]
    if name.endswith("Type"):
        name = name[:-4]
    yield name
    try:
        for field in node._fields:
            yield tuple(lispify_field(field, getattr(node, field)))
    except:
        pass

def lispify_field(field, child):
    fname = field
    yield field
    if not isinstance(child, array.ArrayType):
        children = [child]
    else:
        children = child

    for node in children:
        if isinstance(node, AST):
            yield lispify_ast(node)
        else:
            if fname in ("ctx", "ops", "op"):
                yield tuple([str(node)])
            elif fname == "n":
                try:
                    if isinstance(node, float):
                        yield str(node)
                    else:
                        yield node
                except Exception, why:
                    print "crap: %s" % why
                    
            else:
                yield node

def main(code_path, jy_exe="jython", print_diff=True, print_fail=False, print_success=False, print_diff_lines=False):
    from pprint import pprint
    from popen2 import popen2
    from StringIO import StringIO
    from difflib import Differ

    if os.path.isdir(code_path):
        pyfiles = globwalk.GlobDirectoryWalker(code_path, "*.py")
    else:
        pyfiles = [code_path]

    for pyfile in pyfiles:
        ast = parser().parse([pyfile])
        lispified = lispify_ast(ast)
        sio = StringIO()
        pprint(lispified, stream=sio)

        fin, fout = popen2("python astlib2.py %s" % pyfile)

        sio.seek(0)
        jstr = sio.readlines()
        pstr = fin.readlines()

        differs = False
        diffstr = []
        difflines = 0
        diff = Differ()
        results = diff.compare(pstr, jstr)
        for d in results:
            diffstr.append(d)
            if d[0] in ['+', '-']:
                differs = True
                difflines += 1

        if print_success and not differs:
            print "SUCCESS: %s" % pyfile

        if print_fail and differs:
            print "FAIL: %s" % pyfile

        if print_diff_lines:
            print "%s diff lines in %s" % (difflines, pyfile)

        if print_diff and differs:
            print "---------- ouput -------------"
            print "py: %s" % sio.getvalue()
            print "jy: %s" % "".join(jstr)
            print "---------- DIFF -------------"
            print "".join(diffstr)

if __name__ == '__main__':
    import sys
    import getopt

    usage = """\
Usage: python %s [-j jython_exe_name] [-s -f -d -n] code_path
       where -s = print success messages
             -f = print failure messages
             -n = print number of diff lines
             -d = don't print diffs on failure
       if codepath is a file test it, if codepath is a directory
             test all .py files in and below that directory.
""" % sys.argv[0]

    jy_exe = 'jython'
    print_diff = True
    print_diff_lines = False
    print_fail = False
    print_success = False
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'j:sfdhn')
    except:
        print usage
        sys.exit(1)
    for o, v in opts:
        if o == '-h':
            print usage
            sys.exit(0)
        if o == '-j' and v != '':
            jy_exe = v
        if o == '-s':
            print_success = True
        if o == '-f':
            print_fail = True
        if o == '-d':
            print_diff = False
        if o == '-n':
            print_diff_lines = True
    if len(args) < 1 or len(args) > 7:
        print usage
        sys.exit(1)

    main(args[0], jy_exe, print_diff, print_fail, print_success, print_diff_lines)