[Python-checkins] python/dist/src/Lib/plat-mac bundlebuilder.py,1.31,1.32

jvr@users.sourceforge.net jvr@users.sourceforge.net
Sun, 29 Jun 2003 14:54:14 -0700


Update of /cvsroot/python/python/dist/src/Lib/plat-mac
In directory sc8-pr-cvs1:/tmp/cvs-serv7851

Modified Files:
	bundlebuilder.py 
Log Message:
- added --semi-standalone option that builds apps that depend on an
  installed Python, yet include any modules not in the std lib
- reworked extension module inclusion code: put all .so files in
  a subdirectory of Contents/Resources/, but more importantly,
  correctly support extensions that are submodules.


Index: bundlebuilder.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/plat-mac/bundlebuilder.py,v
retrieving revision 1.31
retrieving revision 1.32
diff -C2 -d -r1.31 -r1.32
*** bundlebuilder.py	20 Jun 2003 21:43:36 -0000	1.31
--- bundlebuilder.py	29 Jun 2003 21:54:12 -0000	1.32
***************
*** 218,222 ****
  SITE_PY = """\
  import sys
! del sys.path[1:]  # sys.path[0] is Contents/Resources/
  """
  
--- 218,223 ----
  SITE_PY = """\
  import sys
! if not %(semi_standalone)s:
!     del sys.path[1:]  # sys.path[0] is Contents/Resources/
  """
  
***************
*** 230,235 ****
          return path, MAGIC + '\0\0\0\0' + marshal.dumps(code)
  
- SITE_CO = compile(SITE_PY, "<-bundlebuilder.py->", "exec")
- 
  #
  # Extension modules can't be in the modules zip archive, so a placeholder
--- 231,234 ----
***************
*** 313,316 ****
--- 312,319 ----
  
  
+ LIB = os.path.join(sys.prefix, "lib", "python" + sys.version[:3])
+ SITE_PACKAGES = os.path.join(LIB, "site-packages")
+ 
+ 
  class AppBuilder(BundleBuilder):
  
***************
*** 346,349 ****
--- 349,355 ----
      standalone = 0
  
+     # If True, build semi-standalone app (only includes third-party modules).
+     semi_standalone = 0
+ 
      # If set, use this for #! lines in stead of sys.executable
      python = None
***************
*** 375,379 ****
  
      def setup(self):
!         if self.standalone and self.mainprogram is None:
              raise BundleBuilderError, ("must specify 'mainprogram' when "
                      "building a standalone application.")
--- 381,386 ----
  
      def setup(self):
!         if ((self.standalone or self.semi_standalone)
!             and self.mainprogram is None):
              raise BundleBuilderError, ("must specify 'mainprogram' when "
                      "building a standalone application.")
***************
*** 410,414 ****
          self.plist.CFBundleExecutable = self.name
  
!         if self.standalone:
              self.findDependencies()
  
--- 417,421 ----
          self.plist.CFBundleExecutable = self.name
  
!         if self.standalone or self.semi_standalone:
              self.findDependencies()
  
***************
*** 439,443 ****
                  makedirs(resdirpath)
                  open(mainprogrampath, "w").write(ARGV_EMULATOR % locals())
!                 if self.standalone:
                      self.includeModules.append("argvemulator")
                      self.includeModules.append("os")
--- 446,450 ----
                  makedirs(resdirpath)
                  open(mainprogrampath, "w").write(ARGV_EMULATOR % locals())
!                 if self.standalone or self.semi_standalone:
                      self.includeModules.append("argvemulator")
                      self.includeModules.append("os")
***************
*** 454,458 ****
              bootstrappath = pathjoin(execdir, self.name)
              makedirs(execdir)
!             if self.standalone:
                  # XXX we're screwed when the end user has deleted
                  # /usr/bin/python
--- 461,465 ----
              bootstrappath = pathjoin(execdir, self.name)
              makedirs(execdir)
!             if self.standalone or self.semi_standalone:
                  # XXX we're screwed when the end user has deleted
                  # /usr/bin/python
***************
*** 472,476 ****
  
      def postProcess(self):
!         if self.standalone:
              self.addPythonModules()
          if self.strip and not self.symlink:
--- 479,483 ----
  
      def postProcess(self):
!         if self.standalone or self.semi_standalone:
              self.addPythonModules()
          if self.strip and not self.symlink:
***************
*** 508,511 ****
--- 515,522 ----
              self.files.append((src, dst))
  
+     def _getSiteCode(self):
+         return compile(SITE_PY % {"semi_standalone": self.semi_standalone},
+                      "<-bundlebuilder.py->", "exec")
+ 
      def addPythonModules(self):
          self.message("Adding Python modules", 1)
***************
*** 525,529 ****
              sitepath = pathjoin(self.bundlepath, "Contents", "Resources",
                      "site" + PYC_EXT)
!             writePyc(SITE_CO, sitepath)
          else:
              # Create individual .pyc files.
--- 536,540 ----
              sitepath = pathjoin(self.bundlepath, "Contents", "Resources",
                      "site" + PYC_EXT)
!             writePyc(self._getSiteCode(), sitepath)
          else:
              # Create individual .pyc files.
***************
*** 582,587 ****
          # manually add our own site.py
          site = mf.add_module("site")
!         site.__code__ = SITE_CO
!         mf.scan_code(SITE_CO, site)
  
          # warnings.py gets imported implicitly from C
--- 593,598 ----
          # manually add our own site.py
          site = mf.add_module("site")
!         site.__code__ = self._getSiteCode()
!         mf.scan_code(site.__code__, site)
  
          # warnings.py gets imported implicitly from C
***************
*** 601,621 ****
          modules.sort()
          for name, mod in modules:
!             if mod.__file__ and mod.__code__ is None:
                  # C extension
-                 path = mod.__file__
                  filename = os.path.basename(path)
                  if USE_ZIPIMPORT:
                      # Python modules are stored in a Zip archive, but put
!                     # extensions in Contents/Resources/.a and add a tiny "loader"
                      # program in the Zip archive. Due to Thomas Heller.
!                     dstpath = pathjoin("Contents", "Resources", filename)
!                     source = EXT_LOADER % {"name": name, "filename": filename}
                      code = compile(source, "<dynloader for %s>" % name, "exec")
                      mod.__code__ = code
!                 else:
!                     # just copy the file
!                     dstpath = name.split(".")[:-1] + [filename]
!                     dstpath = pathjoin("Contents", "Resources", *dstpath)
!                 self.files.append((path, dstpath))
              if mod.__code__ is not None:
                  ispkg = mod.__path__ is not None
--- 612,640 ----
          modules.sort()
          for name, mod in modules:
!             path = mod.__file__
!             if path and self.semi_standalone:
!                 # skip the standard library
!                 if path.startswith(LIB) and not path.startswith(SITE_PACKAGES):
!                     continue
!             if path and mod.__code__ is None:
                  # C extension
                  filename = os.path.basename(path)
+                 dstpath = name.split(".")[:-1] + [filename]
+                 if name != "zlib":
+                     # put all extension module in a separate folder
+                     # inside Contents/Resources/
+                     dstpath = pathjoin("ExtensionModules", *dstpath)
+                 else:
+                     # zlib is neccesary for bootstrapping, so don't
+                     # hide it in "ExtensionModules"
+                     dstpath = pathjoin(*dstpath)
                  if USE_ZIPIMPORT:
                      # Python modules are stored in a Zip archive, but put
!                     # extensions in Contents/Resources/. Add a tiny "loader"
                      # program in the Zip archive. Due to Thomas Heller.
!                     source = EXT_LOADER % {"name": name, "filename": dstpath}
                      code = compile(source, "<dynloader for %s>" % name, "exec")
                      mod.__code__ = code
!                 self.files.append((path, pathjoin("Contents", "Resources", dstpath)))
              if mod.__code__ is not None:
                  ispkg = mod.__path__ is not None
***************
*** 661,665 ****
          import pprint
          pprint.pprint(self.__dict__)
!         if self.standalone:
              self.reportMissing()
  
--- 680,684 ----
          import pprint
          pprint.pprint(self.__dict__)
!         if self.standalone or self.semi_standalone:
              self.reportMissing()
  
***************
*** 762,771 ****
        --standalone       build a standalone application, which is fully
                           independent of a Python installation
        --python=FILE      Python to use in #! line in stead of current Python
        --lib=FILE         shared library or framework to be copied into
                           the bundle
!   -x, --exclude=MODULE   exclude module (with --standalone)
!   -i, --include=MODULE   include module (with --standalone)
!       --package=PACKAGE  include a whole package (with --standalone)
        --strip            strip binaries (remove debug info)
    -v, --verbose          increase verbosity level
--- 781,793 ----
        --standalone       build a standalone application, which is fully
                           independent of a Python installation
+       --semi-standalone  build a standalone application, which depends on
+                          an installed Python, yet includes all third-party
+                          modules.
        --python=FILE      Python to use in #! line in stead of current Python
        --lib=FILE         shared library or framework to be copied into
                           the bundle
!   -x, --exclude=MODULE   exclude module (with --(semi-)standalone)
!   -i, --include=MODULE   include module (with --(semi-)standalone)
!       --package=PACKAGE  include a whole package (with --(semi-)standalone)
        --strip            strip binaries (remove debug info)
    -v, --verbose          increase verbosity level
***************
*** 789,793 ****
          "link-exec", "help", "verbose", "quiet", "argv", "standalone",
          "exclude=", "include=", "package=", "strip", "iconfile=",
!         "lib=", "python=")
  
      try:
--- 811,815 ----
          "link-exec", "help", "verbose", "quiet", "argv", "standalone",
          "exclude=", "include=", "package=", "strip", "iconfile=",
!         "lib=", "python=", "semi-standalone")
  
      try:
***************
*** 837,840 ****
--- 859,864 ----
          elif opt == '--standalone':
              builder.standalone = 1
+         elif opt == '--semi-standalone':
+             builder.semi_standalone = 1
          elif opt == '--python':
              builder.python = arg