diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py index eea81348809..dfd0369627d 100755 --- a/Tools/freeze/freeze.py +++ b/Tools/freeze/freeze.py @@ -57,6 +57,10 @@ Options: (For debugging only -- on a win32 platform, win32 behavior is automatic.) +-r prefix=f: Replace path prefix. + Replace prefix with f in the source path references + contained in the resulting binary. + Arguments: script: The Python script to be executed by the resulting binary. @@ -109,6 +113,7 @@ def main(): debug = 1 odir = '' win = sys.platform[:3] == 'win' + replace_paths = [] # settable with -r option # default the exclude list for each platform if win: exclude = exclude + [ @@ -139,7 +144,7 @@ def main(): # Now parse the command line with the extras inserted. try: - opts, args = getopt.getopt(sys.argv[1:], 'a:de:hmo:p:P:qs:wx:l:') + opts, args = getopt.getopt(sys.argv[1:], 'r:a:de:hmo:p:P:qs:wx:l:') except getopt.error, msg: usage('getopt error: ' + str(msg)) @@ -174,6 +179,9 @@ def main(): addn_link.append(a) if o == '-a': apply(modulefinder.AddPackagePath, tuple(string.split(a,"=", 2))) + if o == '-r': + f,r = string.split(a,"=", 2) + replace_paths.append( (f,r) ) # default prefix and exec_prefix if not exec_prefix: @@ -310,7 +318,7 @@ def main(): # collect all modules of the program dir = os.path.dirname(scriptfile) path[0] = dir - mf = modulefinder.ModuleFinder(path, debug, exclude) + mf = modulefinder.ModuleFinder(path, debug, exclude, replace_paths) if win and subsystem=='service': # If a Windows service, then add the "built-in" module. diff --git a/Tools/freeze/modulefinder.py b/Tools/freeze/modulefinder.py index 8c4b74d442f..42cbbab038b 100644 --- a/Tools/freeze/modulefinder.py +++ b/Tools/freeze/modulefinder.py @@ -7,6 +7,7 @@ import os import re import string import sys +import new IMPORT_NAME = dis.opname.index('IMPORT_NAME') IMPORT_FROM = dis.opname.index('IMPORT_FROM') @@ -49,7 +50,7 @@ class Module: class ModuleFinder: - def __init__(self, path=None, debug=0, excludes = []): + def __init__(self, path=None, debug=0, excludes = [], replace_paths = []): if path is None: path = sys.path self.path = path @@ -58,6 +59,8 @@ class ModuleFinder: self.debug = debug self.indent = 0 self.excludes = excludes + self.replace_paths = replace_paths + self.processed_paths = [] # Used in debugging only def msg(self, level, str, *args): if level <= self.debug: @@ -250,6 +253,8 @@ class ModuleFinder: m = self.add_module(fqname) m.__file__ = pathname if co: + if self.replace_paths: + co = self.replace_paths_in_code(co) m.__code__ = co self.scan_code(co, m) self.msgout(2, "load_module ->", m) @@ -369,6 +374,32 @@ class ModuleFinder: mods.sort() print "?", key, "from", string.join(mods, ', ') + def replace_paths_in_code(self, co): + new_filename = original_filename = os.path.normpath(co.co_filename) + for f,r in self.replace_paths: + if original_filename.startswith(f): + new_filename = r+original_filename[len(f):] + break + + if self.debug and original_filename not in self.processed_paths: + if new_filename!=original_filename: + self.msgout(2, "co_filename %r changed to %r" \ + % (original_filename,new_filename,)) + else: + self.msgout(2, "co_filename %r remains unchanged" \ + % (original_filename,)) + self.processed_paths.append(original_filename) + + consts = list(co.co_consts) + for i in range(len(consts)): + if isinstance(consts[i], type(co)): + consts[i] = self.replace_paths_in_code(consts[i]) + + return new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, + co.co_flags, co.co_code, tuple(consts), co.co_names, + co.co_varnames, new_filename, co.co_name, + co.co_firstlineno, co.co_lnotab) + def test(): # Parse command line