Commit 2db29e89 authored by Just van Rossum's avatar Just van Rossum

added Thomas H's LOADER code for importing extension (sub)modules; little tweaks

parent cb6c2669
...@@ -141,6 +141,7 @@ class BundleBuilder(Defaults): ...@@ -141,6 +141,7 @@ class BundleBuilder(Defaults):
self._copyFiles() self._copyFiles()
self._addMetaFiles() self._addMetaFiles()
self.postProcess() self.postProcess()
self.message("Done.", 1)
def preProcess(self): def preProcess(self):
"""Hook for subclasses.""" """Hook for subclasses."""
...@@ -200,7 +201,6 @@ class BundleBuilder(Defaults): ...@@ -200,7 +201,6 @@ class BundleBuilder(Defaults):
pass pass
if __debug__: if __debug__:
PYC_EXT = ".pyc" PYC_EXT = ".pyc"
else: else:
...@@ -228,6 +228,13 @@ f.close() ...@@ -228,6 +228,13 @@ f.close()
SITE_CO = compile(SITE_PY, "<-bundlebuilder.py->", "exec") SITE_CO = compile(SITE_PY, "<-bundlebuilder.py->", "exec")
EXT_LOADER = """\
import imp, sys, os
path = os.path.join(sys.path[0], "%(filename)s")
mod = imp.load_dynamic("%(name)s", path)
sys.modules["%(name)s"] = mod
"""
MAYMISS_MODULES = ['mac', 'os2', 'nt', 'ntpath', 'dos', 'dospath', MAYMISS_MODULES = ['mac', 'os2', 'nt', 'ntpath', 'dos', 'dospath',
'win32api', 'ce', '_winreg', 'nturl2path', 'sitecustomize', 'win32api', 'ce', '_winreg', 'nturl2path', 'sitecustomize',
'org.python.core', 'riscos', 'riscosenviron', 'riscospath' 'org.python.core', 'riscos', 'riscosenviron', 'riscospath'
...@@ -285,9 +292,6 @@ class AppBuilder(BundleBuilder): ...@@ -285,9 +292,6 @@ class AppBuilder(BundleBuilder):
# Strip binaries. # Strip binaries.
strip = 0 strip = 0
# Found C extension modules: [(name, path), ...]
extensions = []
# Found Python modules: [(name, codeobject, ispkg), ...] # Found Python modules: [(name, codeobject, ispkg), ...]
pymodules = [] pymodules = []
...@@ -355,7 +359,7 @@ class AppBuilder(BundleBuilder): ...@@ -355,7 +359,7 @@ class AppBuilder(BundleBuilder):
mainwrapperpath = pathjoin(execdir, self.name) mainwrapperpath = pathjoin(execdir, self.name)
makedirs(execdir) makedirs(execdir)
open(mainwrapperpath, "w").write(BOOTSTRAP_SCRIPT % locals()) open(mainwrapperpath, "w").write(BOOTSTRAP_SCRIPT % locals())
os.chmod(mainwrapperpath, 0777) os.chmod(mainwrapperpath, 0775)
def postProcess(self): def postProcess(self):
self.addPythonModules() self.addPythonModules()
...@@ -374,35 +378,35 @@ class AppBuilder(BundleBuilder): ...@@ -374,35 +378,35 @@ class AppBuilder(BundleBuilder):
def addPythonModules(self): def addPythonModules(self):
self.message("Adding Python modules", 1) self.message("Adding Python modules", 1)
pymodules = self.pymodules
if USE_FROZEN: if USE_FROZEN:
# This anticipates the acceptance of this patch: # This anticipates the acceptance of this patch:
# http://www.python.org/sf/642578 # http://www.python.org/sf/642578
# Create a file containing all modules, frozen. # Create a file containing all modules, frozen.
frozenmodules = [] frozenmodules = []
for name, code, ispkg in pymodules: for name, code, ispkg in self.pymodules:
if ispkg: if ispkg:
self.message("Adding Python package %s" % name, 2) self.message("Adding Python package %s" % name, 2)
else: else:
self.message("Adding Python module %s" % name, 2) self.message("Adding Python module %s" % name, 2)
frozenmodules.append((name, marshal.dumps(code), ispkg)) frozenmodules.append((name, marshal.dumps(code), ispkg))
frozenmodules = tuple(frozenmodules) frozenmodules = tuple(frozenmodules)
relpath = "Contents/Resources/" + FROZEN_ARCHIVE relpath = pathjoin("Contents", "Resources", FROZEN_ARCHIVE)
abspath = pathjoin(self.bundlepath, relpath) abspath = pathjoin(self.bundlepath, relpath)
f = open(abspath, "wb") f = open(abspath, "wb")
marshal.dump(frozenmodules, f) marshal.dump(frozenmodules, f)
f.close() f.close()
# add site.pyc # add site.pyc
sitepath = pathjoin(self.bundlepath, "Contents/Resources/site" + PYC_EXT) sitepath = pathjoin(self.bundlepath, "Contents", "Resources",
"site" + PYC_EXT)
writePyc(SITE_CO, sitepath) writePyc(SITE_CO, sitepath)
else: else:
# Create individual .pyc files. # Create individual .pyc files.
for name, code, ispkg in pymodules: for name, code, ispkg in self.pymodules:
if ispkg: if ispkg:
name += ".__init__" name += ".__init__"
path = name.split(".") path = name.split(".")
path = pathjoin("Contents/Resources/", *path) + PYC_EXT path = pathjoin("Contents", "Resources", *path) + PYC_EXT
if ispkg: if ispkg:
self.message("Adding Python package %s" % path, 2) self.message("Adding Python package %s" % path, 2)
...@@ -443,7 +447,6 @@ class AppBuilder(BundleBuilder): ...@@ -443,7 +447,6 @@ class AppBuilder(BundleBuilder):
except ImportError: except ImportError:
self.missingModules.append(name) self.missingModules.append(name)
mf.run_script(self.mainprogram) mf.run_script(self.mainprogram)
modules = mf.modules.items() modules = mf.modules.items()
modules.sort() modules.sort()
...@@ -451,18 +454,21 @@ class AppBuilder(BundleBuilder): ...@@ -451,18 +454,21 @@ class AppBuilder(BundleBuilder):
if mod.__file__ and mod.__code__ is None: if mod.__file__ and mod.__code__ is None:
# C extension # C extension
path = mod.__file__ path = mod.__file__
ext = os.path.splitext(path)[1] filename = os.path.basename(path)
if USE_FROZEN: # "proper" freezing if USE_FROZEN:
# rename extensions that are submodules of packages to # "proper" freezing, put extensions in Contents/Resources/,
# <packagename>.<modulename>.<ext> # freeze a tiny "loader" program. Due to Thomas Heller.
dstpath = "Contents/Resources/" + name + ext dstpath = pathjoin("Contents", "Resources", filename)
source = EXT_LOADER % {"name": name, "filename": filename}
code = compile(source, "<dynloader for %s>" % name, "exec")
mod.__code__ = code
else: else:
dstpath = name.split(".") # just copy the file
dstpath = pathjoin("Contents/Resources/", *dstpath) + ext dstpath = name.split(".")[:-1] + [filename]
dstpath = pathjoin("Contents", "Resources", *dstpath)
self.files.append((path, dstpath)) self.files.append((path, dstpath))
self.extensions.append((name, path, dstpath))
self.binaries.append(dstpath) self.binaries.append(dstpath)
elif mod.__code__ is not None: if mod.__code__ is not None:
ispkg = mod.__path__ is not None ispkg = mod.__path__ is not None
if not USE_FROZEN or name != "site": if not USE_FROZEN or name != "site":
# Our site.py is doing the bootstrapping, so we must # Our site.py is doing the bootstrapping, so we must
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment