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
|
#!/usr/bin/pypy
import argparse
import itertools
import os
import re
import py_compile
import subprocess
import sys
def abort(message):
print >> sys.stderr, message
sys.exit(1)
def package_modules(package):
'''Iterate through all python modules in an installed Debian package'''
p = subprocess.Popen(('dpkg', '-L', package), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
files, stderr = p.communicate()
if p.returncode != 0:
abort('Unable to list files in %s. Is it installed?' % package)
for fn in files.splitlines():
if fn.endswith('.py'):
if fn.startswith('/usr/share/doc/'):
continue
yield fn
def find_modules(root):
'''Iterate through all python modules in directory tree root'''
if os.path.isfile(root):
yield root
return
for dirpath, dirnames, filenames in os.walk(root):
for fn in filenames:
if fn.endswith('.py'):
yield os.path.join(dirpath, fn)
def generate_namespace_init(package, verbose):
'''Iterate through a package's ns file.
Create all necessary__init__.pys, and yield them.
'''
ns_file = os.path.join('/usr/share/pypy/ns', package)
if not os.path.exists(ns_file):
return
with open(ns_file) as f:
contents = f.read().decode('utf-8').strip()
namespaces = [line.strip() for line in contents.splitlines()]
for namespace in namespaces:
init = os.path.join('/usr/lib/pypy/dist-packages',
namespace.replace('.', '/'),
'__init__.py')
if verbose:
print 'Ensuring %s exists' % init
with open(init, 'w') as f:
pass
yield init
def main():
parser = argparse.ArgumentParser(
description='Byte-compile Python source files in a package, for PyPy')
parser.add_argument('-p', '--package', metavar='PACKAGE',
action='append', default=[],
help='Debian package to byte-compile '
'(may be specified multiple times)')
parser.add_argument('directory', nargs='*',
help='Directory tree (or file) to byte-compile')
parser.add_argument('-X', '--exclude', metavar='REGEXPR',
action='append', default=[], type=re.compile,
help='Exclude items that match given REGEXPR '
'(may be specified multiple times)')
parser.add_argument('-v', '--verbose', action='store_true',
help='Be more verbose')
parser.add_argument('-q', '--quiet', action='store_true',
help='Be quiet')
parser.add_argument('-V', metavar='VRANGE', dest='vrange',
help=argparse.SUPPRESS)
parser.add_argument('-O', action='store_true', dest='pyo',
help=argparse.SUPPRESS)
args = parser.parse_args()
if not (args.package or args.directory):
parser.error('Either a package or a directory must be specified')
if args.quiet and args.verbose:
parser.error('--quiet and --verbose cannot both be specified')
if args.vrange:
print >> sys.stderr, '-V is ignored in pypycompile'
if args.pyo:
print >> sys.stderr, '-O is ignored in pypycompile'
modules_p = set(itertools.chain(*(
package_modules(package) for package in args.package)))
modules_d = set(itertools.chain(*(
find_modules(dir_) for dir_ in args.directory)))
if args.package and args.directory:
modules = modules_d & modules_p
else:
modules = modules_d | modules_p
for package in args.package:
modules |= set(generate_namespace_init(package, verbose=args.verbose))
modules = filter(lambda module: not any(pattern.match(module)
for pattern in args.exclude),
modules)
for module in modules:
if args.verbose:
print 'Byte-compiling %s' % module
try:
py_compile.compile(module, doraise=True)
except py_compile.PyCompileError as e:
if not args.quiet:
print >> sys.stderr, ('Failed to byte-compile %s: %s'
% (module, e.msg))
if __name__ == '__main__':
main()
# vim: ft=python
|