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