Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 75dc496

Browse files
committed
Added support for packages.
We have a whole new module finder that uses the actual Python parser and scans the bytecode for IMPORT_NAME and IMPORT_FROM. This requires some support in import.c (that hasn't been checked in). New command line options for this: -d, -q, -m.
1 parent 3455edc commit 75dc496

4 files changed

Lines changed: 438 additions & 199 deletions

File tree

Tools/freeze/findmodules.py

Lines changed: 0 additions & 127 deletions
This file was deleted.

Tools/freeze/freeze.py

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
2727
-o dir: Directory where the output files are created; default '.'.
2828
29+
-m: Additional arguments are module names instead of filenames.
30+
31+
-d: Debugging mode for the module finder.
32+
33+
-q: Make the module finder totally quiet.
34+
2935
-h: Print this help message.
3036
3137
-w: Toggle Windows (NT or 95) behavior.
@@ -42,7 +48,8 @@
4248
4349
module ...: Additional Python modules (referenced by pathname)
4450
that will be included in the resulting binary. These
45-
may be .py or .pyc files.
51+
may be .py or .pyc files. If -m is specified, these are
52+
module names that are search in the path instead.
4653
4754
NOTES:
4855
@@ -67,7 +74,7 @@
6774
# Import the freeze-private modules
6875

6976
import checkextensions
70-
import findmodules
77+
import modulefinder
7178
import makeconfig
7279
import makefreeze
7380
import makemakefile
@@ -82,6 +89,8 @@ def main():
8289
exec_prefix = None # settable with -P option
8390
extensions = []
8491
path = sys.path
92+
modargs = 0
93+
debug = 1
8594
odir = ''
8695
win = sys.platform[:3] == 'win'
8796

@@ -97,7 +106,7 @@ def main():
97106

98107
# parse command line
99108
try:
100-
opts, args = getopt.getopt(sys.argv[1:], 'he:o:p:P:s:w')
109+
opts, args = getopt.getopt(sys.argv[1:], 'deh:mo:p:P:qs:w')
101110
except getopt.error, msg:
102111
usage('getopt error: ' + str(msg))
103112

@@ -106,14 +115,20 @@ def main():
106115
if o == '-h':
107116
print __doc__
108117
return
118+
if o == '-d':
119+
debug = debug + 1
109120
if o == '-e':
110121
extensions.append(a)
122+
if o == '-m':
123+
modargs = 1
111124
if o == '-o':
112125
odir = a
113126
if o == '-p':
114127
prefix = a
115128
if o == '-P':
116129
exec_prefix = a
130+
if o == '-q':
131+
debug = 0
117132
if o == '-w':
118133
win = not win
119134
if o == '-s':
@@ -220,26 +235,38 @@ def main():
220235
target = os.path.join(odir, target)
221236
makefile = os.path.join(odir, makefile)
222237

223-
for mod in implicits:
224-
modules.append(findmodules.findmodule(mod))
225-
226238
# Actual work starts here...
227239

228-
dict = findmodules.findmodules(scriptfile, modules, path)
229-
names = dict.keys()
230-
names.sort()
231-
print "Modules being frozen:"
232-
for name in names:
233-
print '\t', name
234-
240+
# collect all modules of the program
241+
mf = modulefinder.ModuleFinder(path, debug)
242+
for mod in implicits:
243+
mf.import_hook(mod)
244+
for mod in modules:
245+
if mod == '-m':
246+
modargs = 1
247+
continue
248+
if modargs:
249+
if mod[-2:] == '.*':
250+
mf.import_hook(mod[:-2], None, ["*"])
251+
else:
252+
mf.import_hook(mod)
253+
else:
254+
mf.load_file(mod)
255+
mf.run_script(scriptfile)
256+
if debug > 0:
257+
mf.report()
258+
print
259+
dict = mf.modules
260+
261+
# generate output for frozen modules
235262
backup = frozen_c + '~'
236263
try:
237264
os.rename(frozen_c, backup)
238265
except os.error:
239266
backup = None
240267
outfp = open(frozen_c, 'w')
241268
try:
242-
makefreeze.makefreeze(outfp, dict)
269+
makefreeze.makefreeze(outfp, dict, debug)
243270
if win and subsystem == 'windows':
244271
import winmakemakefile
245272
outfp.write(winmakemakefile.WINMAINTEMPLATE)
@@ -251,6 +278,7 @@ def main():
251278
frozen_c)
252279
os.rename(backup, frozen_c)
253280

281+
# windows gets different treatment
254282
if win:
255283
# Taking a shortcut here...
256284
import winmakemakefile
@@ -264,14 +292,17 @@ def main():
264292
outfp.close()
265293
return
266294

295+
# generate config.c and Makefile
267296
builtins = []
268297
unknown = []
269298
mods = dict.keys()
270299
mods.sort()
271300
for mod in mods:
272-
if dict[mod] == '<builtin>':
301+
if dict[mod].__code__:
302+
continue
303+
if not dict[mod].__file__:
273304
builtins.append(mod)
274-
elif dict[mod] == '<unknown>':
305+
else:
275306
unknown.append(mod)
276307

277308
addfiles = []

Tools/freeze/makefreeze.py

Lines changed: 18 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import marshal
2+
import string
23

34

45
# Write a file containing frozen code for the modules in the dictionary.
@@ -23,51 +24,31 @@
2324
2425
"""
2526

26-
def makefreeze(outfp, dict):
27+
def makefreeze(outfp, dict, debug=0):
2728
done = []
2829
mods = dict.keys()
2930
mods.sort()
3031
for mod in mods:
31-
modfn = dict[mod]
32-
try:
33-
str = makecode(modfn)
34-
except IOError, msg:
35-
sys.stderr.write("%s: %s\n" % (modfn, str(msg)))
36-
continue
37-
if str:
38-
done.append(mod, len(str))
39-
writecode(outfp, mod, str)
32+
m = dict[mod]
33+
mangled = string.join(string.split(mod, "."), "__")
34+
if m.__code__:
35+
if debug:
36+
print "freezing", mod, "..."
37+
str = marshal.dumps(m.__code__)
38+
size = len(str)
39+
if m.__path__:
40+
# Indicate package by negative size
41+
size = -size
42+
done.append((mod, mangled, size))
43+
writecode(outfp, mangled, str)
44+
if debug:
45+
print "generating table of frozen modules"
4046
outfp.write(header)
41-
for mod, size in done:
42-
outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mod, size))
47+
for mod, mangled, size in done:
48+
outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size))
4349
outfp.write(trailer)
4450

4551

46-
# Return code string for a given module -- either a .py or a .pyc
47-
# file. Return either a string or None (if it's not Python code).
48-
# May raise IOError.
49-
50-
def makecode(filename):
51-
if filename[-3:] == '.py':
52-
f = open(filename, 'r')
53-
try:
54-
text = f.read()
55-
code = compile(text, filename, 'exec')
56-
finally:
57-
f.close()
58-
return marshal.dumps(code)
59-
if filename[-4:] == '.pyc':
60-
f = open(filename, 'rb')
61-
try:
62-
f.seek(8)
63-
str = f.read()
64-
finally:
65-
f.close()
66-
return str
67-
# Can't generate code for this extension
68-
return None
69-
70-
7152
# Write a C initializer for a module containing the frozen python code.
7253
# The array is called M_<mod>.
7354

@@ -78,22 +59,3 @@ def writecode(outfp, mod, str):
7859
for c in str[i:i+16]:
7960
outfp.write('%d,' % ord(c))
8061
outfp.write('\n};\n')
81-
82-
83-
# Test for the above functions.
84-
85-
def test():
86-
import os
87-
import sys
88-
if not sys.argv[1:]:
89-
print 'usage: python freezepython.py file.py(c) ...'
90-
sys.exit(2)
91-
dict = {}
92-
for arg in sys.argv[1:]:
93-
base = os.path.basename(arg)
94-
mod, ext = os.path.splitext(base)
95-
dict[mod] = arg
96-
makefreeze(sys.stdout, dict)
97-
98-
if __name__ == '__main__':
99-
test()

0 commit comments

Comments
 (0)