mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
Lawrence Hudson, SF #401702: Modify co_filename in frozen programs
This patch was developed primarily to reduce the size of the
frozen binary. It is particularly useful when freezing for 'small'
platforms, such as Palm OS, where you really want to save that
last miserable byte.
A limitation of this patch is that it does not provide any feedback
about the replacements being made. As the path matching
is case-sensitive this may lead to unexpected behaviour for DOS
and Windows people, eg
> freeze.py -r C:\Python\Lib\=py\ goats.py
should probably be:
> freeze.py -r c:\python\lib\=py\ goats.py
This commit is contained in:
parent
b845cb0946
commit
6b767ac81a
2 changed files with 42 additions and 3 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue