diff mercurial/packagescan.py @ 1283:f5faab34f32e

Support for the distutils extention 'py2exe' added. Description: - If the py2exe distutils extention is installed this patch allows building standalone exe for windows - example: > python setup.py build --compiler=mingw32 py2exe - The 'out of the box' py2exe is not able to resolve the dependencies due to 'demandload'. A new helper module of scanning the mercurial package has been added. Changed: - setup.py: importing py2exe and sub classing its command class to fetch the build directory and insert the needed includes - packagescan.py: new helper module added, that scans the distutil build directory for modules to be included.
author Volker.Kleinfeld@gmx.de
date Tue, 20 Sep 2005 19:25:14 -0700
parents
children 2073e5a71008
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/mercurial/packagescan.py
@@ -0,0 +1,74 @@
+# packagescan.py - Helper module for identifing used modules. 
+# Used for the py2exe distutil.
+#
+# Copyright 2005 Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+import glob
+import os
+import sys
+import demandload
+import ihooks
+
+requiredmodules = {} # Will contain the modules imported by demandload
+def demandload(scope, modules):
+    """ fake demandload function that collects the required modules """
+    for m in modules.split():
+        mod = None
+        mod = __import__(m,scope,scope)
+        scope[m] = mod
+        requiredmodules[mod.__name__] = 1
+
+def getmodules(libpath,packagename):
+    """ helper for finding all required modules of package <packagename> """
+    # Use the package in the build directory
+    libpath = os.path.abspath(libpath)
+    sys.path.insert(0,libpath)
+    packdir = os.path.join(libpath,packagename)
+    # A normal import would not find the package in 
+    # the build directory. ihook is used to force the import.
+    # After the package is imported the import scope for 
+    # the following imports is settled.
+    p = importfrom(packdir)
+    globals()[packagename] = p
+    sys.modules[packagename] = p
+    # Fetch the python modules in the package
+    cwd = os.getcwd()
+    os.chdir(packdir)
+    pymodulefiles = glob.glob('*.py')
+    extmodulefiles = glob.glob('*.pyd')
+    os.chdir(cwd)
+    # Install a fake demandload module
+    sys.modules['mercurial.demandload'] = sys.modules['mercurial.packagescan']
+    # Import all python modules and by that run the fake demandload
+    for m in pymodulefiles:
+        if m == '__init__.py': continue
+        tmp = {}
+        mname,ext = os.path.splitext(m)
+        fullname = packagename+'.'+mname 
+        __import__(fullname,tmp,tmp)
+        requiredmodules[fullname] = 1
+    # Import all extension modules and by that run the fake demandload
+    for m in extmodulefiles:
+        tmp = {}
+        mname,ext = os.path.splitext(m)
+        fullname = packagename+'.'+mname
+        __import__(fullname,tmp,tmp)
+        requiredmodules[fullname] = 1
+    includes = requiredmodules.keys()
+    return includes
+
+def importfrom(filename):
+    """
+    import module/package from a named file and returns the module.
+    It does not check on sys.modules or includes the module in the scope.
+    """
+    loader = ihooks.BasicModuleLoader()
+    path, file = os.path.split(filename)
+    name, ext  = os.path.splitext(file)
+    m = loader.find_module_in_dir(name, path)
+    if not m:
+        raise ImportError, name
+    m = loader.load_module(name, m)
+    return m