##// END OF EJS Templates
Merge with main
Brendan Cully -
r3898:316cd5b0 merge default
parent child Browse files
Show More
@@ -1,104 +1,104 b''
1 # demandimport.py - global demand-loading of modules for Mercurial
1 # demandimport.py - global demand-loading of modules for Mercurial
2 #
2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 '''
8 '''
9 demandimport - automatic demandloading of modules
9 demandimport - automatic demandloading of modules
10
10
11 To enable this module, do:
11 To enable this module, do:
12
12
13 import demandimport; demandimport.enable()
13 import demandimport; demandimport.enable()
14
14
15 Imports of the following forms will be demand-loaded:
15 Imports of the following forms will be demand-loaded:
16
16
17 import a, b.c
17 import a, b.c
18 import a.b as c
18 import a.b as c
19 from a import b,c # a will be loaded immediately
19 from a import b,c # a will be loaded immediately
20
20
21 These imports will not be delayed:
21 These imports will not be delayed:
22
22
23 from a import *
23 from a import *
24 b = __import__(a)
24 b = __import__(a)
25 '''
25 '''
26
26
27 _origimport = __import__
27 _origimport = __import__
28
28
29 class _demandmod(object):
29 class _demandmod(object):
30 """module demand-loader and proxy"""
30 """module demand-loader and proxy"""
31 def __init__(self, name, globals, locals):
31 def __init__(self, name, globals, locals):
32 if '.' in name:
32 if '.' in name:
33 head, rest = name.split('.', 1)
33 head, rest = name.split('.', 1)
34 after = [rest]
34 after = [rest]
35 else:
35 else:
36 head = name
36 head = name
37 after = []
37 after = []
38 object.__setattr__(self, "_data", (head, globals, locals, after))
38 object.__setattr__(self, "_data", (head, globals, locals, after))
39 object.__setattr__(self, "_module", None)
39 object.__setattr__(self, "_module", None)
40 def _extend(self, name):
40 def _extend(self, name):
41 """add to the list of submodules to load"""
41 """add to the list of submodules to load"""
42 self._data[3].append(name)
42 self._data[3].append(name)
43 def _load(self):
43 def _load(self):
44 if not self._module:
44 if not self._module:
45 head, globals, locals, after = self._data
45 head, globals, locals, after = self._data
46 mod = _origimport(head, globals, locals)
46 mod = _origimport(head, globals, locals)
47 # load submodules
47 # load submodules
48 for x in after:
48 for x in after:
49 hx = x
49 hx = x
50 if '.' in x:
50 if '.' in x:
51 hx = x.split('.')[0]
51 hx = x.split('.')[0]
52 if not hasattr(mod, hx):
52 if not hasattr(mod, hx):
53 setattr(mod, hx, _demandmod(x, mod.__dict__, mod.__dict__))
53 setattr(mod, hx, _demandmod(x, mod.__dict__, mod.__dict__))
54 # are we in the locals dictionary still?
54 # are we in the locals dictionary still?
55 if locals and locals.get(head) == self:
55 if locals and locals.get(head) == self:
56 locals[head] = mod
56 locals[head] = mod
57 object.__setattr__(self, "_module", mod)
57 object.__setattr__(self, "_module", mod)
58 def __repr__(self):
58 def __repr__(self):
59 return "<unloaded module '%s'>" % self._data[0]
59 return "<unloaded module '%s'>" % self._data[0]
60 def __call__(self, *args, **kwargs):
60 def __call__(self, *args, **kwargs):
61 raise TypeError("'unloaded module' object is not callable")
61 raise TypeError("'unloaded module' object is not callable")
62 def __getattr__(self, attr):
62 def __getattr__(self, attr):
63 self._load()
63 self._load()
64 return getattr(self._module, attr)
64 return getattr(self._module, attr)
65 def __setattr__(self, attr, val):
65 def __setattr__(self, attr, val):
66 self._load()
66 self._load()
67 setattr(self._module, attr, val)
67 setattr(self._module, attr, val)
68
68
69 def _demandimport(name, globals=None, locals=None, fromlist=None):
69 def _demandimport(name, globals=None, locals=None, fromlist=None):
70 if not locals or name in ignore or fromlist == ('*',):
70 if not locals or name in ignore or fromlist == ('*',):
71 # these cases we can't really delay
71 # these cases we can't really delay
72 return _origimport(name, globals, locals, fromlist)
72 return _origimport(name, globals, locals, fromlist)
73 elif not fromlist:
73 elif not fromlist:
74 # import a [as b]
74 # import a [as b]
75 if '.' in name: # a.b
75 if '.' in name: # a.b
76 base, rest = name.split('.', 1)
76 base, rest = name.split('.', 1)
77 # if a is already demand-loaded, add b to its submodule list
77 # if a is already demand-loaded, add b to its submodule list
78 if base in locals:
78 if base in locals:
79 if isinstance(locals[base], _demandmod):
79 if isinstance(locals[base], _demandmod):
80 locals[base]._extend(rest)
80 locals[base]._extend(rest)
81 return locals[base]
81 return locals[base]
82 return _demandmod(name, globals, locals)
82 return _demandmod(name, globals, locals)
83 else:
83 else:
84 # from a import b,c,d
84 # from a import b,c,d
85 mod = _origimport(name, globals, locals)
85 mod = _origimport(name, globals, locals)
86 # recurse down the module chain
86 # recurse down the module chain
87 for comp in name.split('.')[1:]:
87 for comp in name.split('.')[1:]:
88 mod = getattr(mod, comp)
88 mod = getattr(mod, comp)
89 for x in fromlist:
89 for x in fromlist:
90 # set requested submodules for demand load
90 # set requested submodules for demand load
91 if not(hasattr(mod, x)):
91 if not(hasattr(mod, x)):
92 setattr(mod, x, _demandmod(x, mod.__dict__, mod.__dict__))
92 setattr(mod, x, _demandmod(x, mod.__dict__, mod.__dict__))
93 return mod
93 return mod
94
94
95 ignore = []
95 ignore = ['_hashlib', 'email.mime']
96
96
97 def enable():
97 def enable():
98 "enable global demand-loading of modules"
98 "enable global demand-loading of modules"
99 __builtins__["__import__"] = _demandimport
99 __builtins__["__import__"] = _demandimport
100
100
101 def disable():
101 def disable():
102 "disable global demand-loading of modules"
102 "disable global demand-loading of modules"
103 __builtins__["__import__"] = _origimport
103 __builtins__["__import__"] = _origimport
104
104
@@ -1,73 +1,77 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, 0, 'final'):
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3, 0, 'final'):
10 raise SystemExit, "Mercurial requires python 2.3 or later."
10 raise SystemExit, "Mercurial requires python 2.3 or later."
11
11
12 import os
12 import os
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 import mercurial.version
16 import mercurial.version
17 import mercurial.demandimport
17 import mercurial.demandimport
18 mercurial.demandimport.enable = lambda: None
18 mercurial.demandimport.enable = lambda: None
19
19
20 extra = {}
21
20 # py2exe needs to be installed to work
22 # py2exe needs to be installed to work
21 try:
23 try:
22 import py2exe
24 import py2exe
23
25
24 # Help py2exe to find win32com.shell
26 # Help py2exe to find win32com.shell
25 try:
27 try:
26 import modulefinder
28 import modulefinder
27 import win32com
29 import win32com
28 for p in win32com.__path__[1:]: # Take the path to win32comext
30 for p in win32com.__path__[1:]: # Take the path to win32comext
29 modulefinder.AddPackagePath("win32com", p)
31 modulefinder.AddPackagePath("win32com", p)
30 pn = "win32com.shell"
32 pn = "win32com.shell"
31 __import__(pn)
33 __import__(pn)
32 m = sys.modules[pn]
34 m = sys.modules[pn]
33 for p in m.__path__[1:]:
35 for p in m.__path__[1:]:
34 modulefinder.AddPackagePath(pn, p)
36 modulefinder.AddPackagePath(pn, p)
35 except ImportError:
37 except ImportError:
36 pass
38 pass
37
39
40 extra['console'] = ['hg']
41
38 except ImportError:
42 except ImportError:
39 pass
43 pass
40
44
41 # specify version string, otherwise 'hg identify' will be used:
45 # specify version string, otherwise 'hg identify' will be used:
42 version = ''
46 version = ''
43
47
44 class install_package_data(install_data):
48 class install_package_data(install_data):
45 def finalize_options(self):
49 def finalize_options(self):
46 self.set_undefined_options('install',
50 self.set_undefined_options('install',
47 ('install_lib', 'install_dir'))
51 ('install_lib', 'install_dir'))
48 install_data.finalize_options(self)
52 install_data.finalize_options(self)
49
53
50 mercurial.version.remember_version(version)
54 mercurial.version.remember_version(version)
51 cmdclass = {'install_data': install_package_data}
55 cmdclass = {'install_data': install_package_data}
52
56
53 setup(name='mercurial',
57 setup(name='mercurial',
54 version=mercurial.version.get_version(),
58 version=mercurial.version.get_version(),
55 author='Matt Mackall',
59 author='Matt Mackall',
56 author_email='mpm@selenic.com',
60 author_email='mpm@selenic.com',
57 url='http://selenic.com/mercurial',
61 url='http://selenic.com/mercurial',
58 description='Scalable distributed SCM',
62 description='Scalable distributed SCM',
59 license='GNU GPL',
63 license='GNU GPL',
60 packages=['mercurial', 'mercurial.hgweb', 'hgext'],
64 packages=['mercurial', 'mercurial.hgweb', 'hgext'],
61 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
65 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
62 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
66 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
63 Extension('mercurial.base85', ['mercurial/base85.c'])],
67 Extension('mercurial.base85', ['mercurial/base85.c'])],
64 data_files=[(os.path.join('mercurial', root),
68 data_files=[(os.path.join('mercurial', root),
65 [os.path.join(root, file_) for file_ in files])
69 [os.path.join(root, file_) for file_ in files])
66 for root, dirs, files in os.walk('templates')],
70 for root, dirs, files in os.walk('templates')],
67 cmdclass=cmdclass,
71 cmdclass=cmdclass,
68 scripts=['hg', 'hgmerge'],
72 scripts=['hg', 'hgmerge'],
69 options=dict(bdist_mpkg=dict(zipdist=True,
73 options=dict(bdist_mpkg=dict(zipdist=True,
70 license='COPYING',
74 license='COPYING',
71 readme='contrib/macosx/Readme.html',
75 readme='contrib/macosx/Readme.html',
72 welcome='contrib/macosx/Welcome.html')),
76 welcome='contrib/macosx/Welcome.html')),
73 console=['hg'])
77 **extra)
General Comments 0
You need to be logged in to leave comments. Login now