##// END OF EJS Templates
packagescan can't scan nested packages
Eung-Ju PARK -
r2402:82cef38f default
parent child Browse files
Show More
@@ -1,113 +1,113 b''
1 1 # packagescan.py - Helper module for identifing used modules.
2 2 # Used for the py2exe distutil.
3 3 # This module must be the first mercurial module imported in setup.py
4 4 #
5 5 # Copyright 2005 Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
6 6 #
7 7 # This software may be used and distributed according to the terms
8 8 # of the GNU General Public License, incorporated herein by reference.
9 9 import glob
10 10 import os
11 11 import sys
12 12 import ihooks
13 13 import types
14 14 import string
15 15
16 16 # Install this module as fake demandload module
17 17 sys.modules['mercurial.demandload'] = sys.modules[__name__]
18 18
19 19 # Requiredmodules contains the modules imported by demandload.
20 20 # Please note that demandload can be invoked before the
21 21 # mercurial.packagescan.scan method is invoked in case a mercurial
22 22 # module is imported.
23 23 requiredmodules = {}
24 24 def demandload(scope, modules):
25 25 """ fake demandload function that collects the required modules
26 26 foo import foo
27 27 foo bar import foo, bar
28 28 foo.bar import foo.bar
29 29 foo:bar from foo import bar
30 30 foo:bar,quux from foo import bar, quux
31 31 foo.bar:quux from foo.bar import quux"""
32 32
33 33 for m in modules.split():
34 34 mod = None
35 35 try:
36 36 module, fromlist = m.split(':')
37 37 fromlist = fromlist.split(',')
38 38 except:
39 39 module = m
40 40 fromlist = []
41 41 mod = __import__(module, scope, scope, fromlist)
42 42 if fromlist == []:
43 43 # mod is only the top package, but we need all packages
44 44 comp = module.split('.')
45 45 i = 1
46 46 mn = comp[0]
47 47 while True:
48 48 # mn and mod.__name__ might not be the same
49 49 scope[mn] = mod
50 50 requiredmodules[mod.__name__] = 1
51 51 if len(comp) == i: break
52 52 mod = getattr(mod,comp[i])
53 53 mn = string.join(comp[:i+1],'.')
54 54 i += 1
55 55 else:
56 56 # mod is the last package in the component list
57 57 requiredmodules[mod.__name__] = 1
58 58 for f in fromlist:
59 59 scope[f] = getattr(mod,f)
60 60 if type(scope[f]) == types.ModuleType:
61 61 requiredmodules[scope[f].__name__] = 1
62 62
63 63 def scan(libpath,packagename):
64 64 """ helper for finding all required modules of package <packagename> """
65 65 # Use the package in the build directory
66 66 libpath = os.path.abspath(libpath)
67 67 sys.path.insert(0,libpath)
68 packdir = os.path.join(libpath,packagename)
68 packdir = os.path.join(libpath,packagename.replace('.', '/'))
69 69 # A normal import would not find the package in
70 70 # the build directory. ihook is used to force the import.
71 71 # After the package is imported the import scope for
72 72 # the following imports is settled.
73 73 p = importfrom(packdir)
74 74 globals()[packagename] = p
75 75 sys.modules[packagename] = p
76 76 # Fetch the python modules in the package
77 77 cwd = os.getcwd()
78 78 os.chdir(packdir)
79 79 pymodulefiles = glob.glob('*.py')
80 80 extmodulefiles = glob.glob('*.pyd')
81 81 os.chdir(cwd)
82 82 # Import all python modules and by that run the fake demandload
83 83 for m in pymodulefiles:
84 84 if m == '__init__.py': continue
85 85 tmp = {}
86 86 mname,ext = os.path.splitext(m)
87 87 fullname = packagename+'.'+mname
88 88 __import__(fullname,tmp,tmp)
89 89 requiredmodules[fullname] = 1
90 90 # Import all extension modules and by that run the fake demandload
91 91 for m in extmodulefiles:
92 92 tmp = {}
93 93 mname,ext = os.path.splitext(m)
94 94 fullname = packagename+'.'+mname
95 95 __import__(fullname,tmp,tmp)
96 96 requiredmodules[fullname] = 1
97 97
98 98 def getmodules():
99 99 return requiredmodules.keys()
100 100
101 101 def importfrom(filename):
102 102 """
103 103 import module/package from a named file and returns the module.
104 104 It does not check on sys.modules or includes the module in the scope.
105 105 """
106 106 loader = ihooks.BasicModuleLoader()
107 107 path, file = os.path.split(filename)
108 108 name, ext = os.path.splitext(file)
109 109 m = loader.find_module_in_dir(name, path)
110 110 if not m:
111 111 raise ImportError, name
112 112 m = loader.load_module(name, m)
113 113 return m
@@ -1,104 +1,104 b''
1 1 #!/usr/bin/env python
2 2 #
3 3 # This is the mercurial setup script.
4 4 #
5 5 # './setup.py install', or
6 6 # './setup.py --help' for more options
7 7
8 8 import sys
9 9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3):
10 10 raise SystemExit, "Mercurial requires python 2.3 or later."
11 11
12 12 import glob
13 13 from distutils.core import setup, Extension
14 14 from distutils.command.install_data import install_data
15 15
16 16 # mercurial.packagescan must be the first mercurial module imported
17 17 import mercurial.packagescan
18 18 import mercurial.version
19 19
20 20 # py2exe needs to be installed to work
21 21 try:
22 22 import py2exe
23 23
24 24 # Help py2exe to find win32com.shell
25 25 try:
26 26 import modulefinder
27 27 import win32com
28 28 for p in win32com.__path__[1:]: # Take the path to win32comext
29 29 modulefinder.AddPackagePath("win32com", p)
30 30 pn = "win32com.shell"
31 31 __import__(pn)
32 32 m = sys.modules[pn]
33 33 for p in m.__path__[1:]:
34 34 modulefinder.AddPackagePath(pn, p)
35 35 except ImportError:
36 36 pass
37 37
38 38 # Due to the use of demandload py2exe is not finding the modules.
39 39 # packagescan.getmodules creates a list of modules included in
40 40 # the mercurial package plus depdent modules.
41 41 from py2exe.build_exe import py2exe as build_exe
42 42
43 43 class py2exe_for_demandload(build_exe):
44 44 """ overwrites the py2exe command class for getting the build
45 45 directory and for setting the 'includes' option."""
46 46 def initialize_options(self):
47 47 self.build_lib = None
48 48 build_exe.initialize_options(self)
49 49 def finalize_options(self):
50 50 # Get the build directory, ie. where to search for modules.
51 51 self.set_undefined_options('build',
52 52 ('build_lib', 'build_lib'))
53 53 # Sets the 'includes' option with the list of needed modules
54 54 if not self.includes:
55 55 self.includes = []
56 56 else:
57 57 self.includes = self.includes.split(',')
58 58 mercurial.packagescan.scan(self.build_lib,'mercurial')
59 mercurial.packagescan.scan(self.build_lib,'mercurial/hgweb')
59 mercurial.packagescan.scan(self.build_lib,'mercurial.hgweb')
60 60 mercurial.packagescan.scan(self.build_lib,'hgext')
61 61 self.includes += mercurial.packagescan.getmodules()
62 62 build_exe.finalize_options(self)
63 63 except ImportError:
64 64 py2exe_for_demandload = None
65 65
66 66
67 67 # specify version string, otherwise 'hg identify' will be used:
68 68 version = ''
69 69
70 70 class install_package_data(install_data):
71 71 def finalize_options(self):
72 72 self.set_undefined_options('install',
73 73 ('install_lib', 'install_dir'))
74 74 install_data.finalize_options(self)
75 75
76 76 mercurial.version.remember_version(version)
77 77 cmdclass = {'install_data': install_package_data}
78 78 py2exe_opts = {}
79 79 if py2exe_for_demandload is not None:
80 80 cmdclass['py2exe'] = py2exe_for_demandload
81 81 py2exe_opts['console'] = ['hg']
82 82 setup(name='mercurial',
83 83 version=mercurial.version.get_version(),
84 84 author='Matt Mackall',
85 85 author_email='mpm@selenic.com',
86 86 url='http://selenic.com/mercurial',
87 87 description='Scalable distributed SCM',
88 88 license='GNU GPL',
89 89 packages=['mercurial', 'mercurial.hgweb', 'hgext'],
90 90 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
91 91 Extension('mercurial.bdiff', ['mercurial/bdiff.c'])],
92 92 data_files=[('mercurial/templates',
93 93 ['templates/map'] +
94 94 glob.glob('templates/map-*') +
95 95 glob.glob('templates/*.tmpl')),
96 96 ('mercurial/templates/static',
97 97 glob.glob('templates/static/*'))],
98 98 cmdclass=cmdclass,
99 99 scripts=['hg', 'hgmerge'],
100 100 options=dict(bdist_mpkg=dict(zipdist=True,
101 101 license='COPYING',
102 102 readme='contrib/macosx/Readme.html',
103 103 welcome='contrib/macosx/Welcome.html')),
104 104 **py2exe_opts)
General Comments 0
You need to be logged in to leave comments. Login now