summaryrefslogtreecommitdiff
path: root/lab/show_pyc.py
blob: e272ef8e1222d783ad017bb09ee66e08f74761a0 (plain)
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
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt

import binascii
import dis
import marshal
import struct
import sys
import time
import types


def show_pyc_file(fname):
    f = open(fname, "rb")
    magic = f.read(4)
    moddate = f.read(4)
    modtime = time.asctime(time.localtime(struct.unpack('<L', moddate)[0]))
    print("magic %s" % (binascii.hexlify(magic)))
    print("moddate %s (%s)" % (binascii.hexlify(moddate), modtime))
    code = marshal.load(f)
    show_code(code)

def show_py_file(fname):
    text = open(fname).read().replace('\r\n', '\n')
    show_py_text(text, fname=fname)

def show_py_text(text, fname="<string>"):
    code = compile(text, fname, "exec")
    show_code(code)

def show_code(code, indent=''):
    print("%scode" % indent)
    indent += '   '
    print("%sargcount %d" % (indent, code.co_argcount))
    print("%snlocals %d" % (indent, code.co_nlocals))
    print("%sstacksize %d" % (indent, code.co_stacksize))
    print("%sflags %04x" % (indent, code.co_flags))
    show_hex("code", code.co_code, indent=indent)
    dis.disassemble(code)
    print("%sconsts" % indent)
    for const in code.co_consts:
        if type(const) == types.CodeType:
            show_code(const, indent+'   ')
        else:
            print("   %s%r" % (indent, const))
    print("%snames %r" % (indent, code.co_names))
    print("%svarnames %r" % (indent, code.co_varnames))
    print("%sfreevars %r" % (indent, code.co_freevars))
    print("%scellvars %r" % (indent, code.co_cellvars))
    print("%sfilename %r" % (indent, code.co_filename))
    print("%sname %r" % (indent, code.co_name))
    print("%sfirstlineno %d" % (indent, code.co_firstlineno))
    show_hex("lnotab", code.co_lnotab, indent=indent)

def show_hex(label, h, indent):
    h = binascii.hexlify(h)
    if len(h) < 60:
        print("%s%s %s" % (indent, label, h))
    else:
        print("%s%s" % (indent, label))
        for i in range(0, len(h), 60):
            print("%s   %s" % (indent, h[i:i+60]))

def show_file(fname):
    if fname.endswith('pyc'):
        show_pyc_file(fname)
    elif fname.endswith('py'):
        show_py_file(fname)
    else:
        print("Odd file:", fname)

def main(args):
    if args[0] == '-c':
        show_py_text(" ".join(args[1:]).replace(";", "\n"))
    else:
        for a in args:
            show_file(a)

if __name__ == '__main__':
    main(sys.argv[1:])