1
2
3
4 """
5 Tools for doing dynamic imports.
6
7 @since: 0.3
8 """
9
10 import sys
11
12
13 __all__ = ['when_imported']
14
15
16 post_load_hooks = {}
17
18 loaded_modules = []
19
20
22 """
23 This is a special module finder object that executes a collection of
24 callables when a specific module has been imported. An instance of this
25 is placed in C{sys.meta_path}, which is consulted before C{sys.modules} -
26 allowing us to provide this functionality.
27
28 @see: L{when_imported}
29 @since: 0.5
30 """
31
33 """
34 Called when an import is made. If there are hooks waiting for this
35 module to be imported then we stop the normal import process and
36 manually load the module.
37
38 @param name: The name of the module being imported.
39 @param path The root path of the module (if a package). We ignore this.
40 @return: If we want to hook this module, we return a C{loader}
41 interface (which is this instance again). If not we return C{None}
42 to allow the standard import process to continue.
43 """
44 if name in loaded_modules or name not in post_load_hooks:
45 return None
46
47 return self
48
50 """
51 If we get this far, then there are hooks waiting to be called on
52 import of this module. We manually load the module and then run the
53 hooks.
54
55 @param name: The name of the module to import.
56 """
57 loaded_modules.append(name)
58 parent, child = split_module(name)
59
60 __import__(name, {}, {}, [])
61
62 mod = sys.modules[name]
63
64 run_hooks(name, mod)
65
66 return mod
67
68
70 """
71 Run all hooks for a module.
72 Load an unactivated "lazy" module object.
73 """
74 try:
75 for hook in post_load_hooks[name]:
76 hook(module)
77 finally:
78 del post_load_hooks[name]
79
80
82 """
83 Splits a module name into its parent and child parts.
84
85 >>> split_module('foo.bar.baz')
86 'foo.bar', 'baz'
87 >>> split_module('foo')
88 None, 'foo'
89 """
90 try:
91 splitpos = name.rindex('.') + 1
92
93 return name[:splitpos - 1], name[splitpos:]
94 except ValueError:
95 return None, name
96
97
99 """
100 Call C{hook(module)} when module named C{name} is first used.
101
102 'hook' must accept one argument: the module object named by 'name', which
103 must be a fully qualified (i.e. absolute) module name. The hook should
104 not raise any exceptions, or it will prevent later hooks from running.
105
106 If the module has already been imported normally, 'hook(module)' is
107 called immediately, and the module object is returned from this function.
108 If the module has not been imported, then the hook is called when the
109 module is first imported.
110 """
111 if name in loaded_modules or name in sys.modules:
112 hook(sys.modules[name])
113
114 return
115
116 if name not in post_load_hooks:
117 post_load_hooks[name] = []
118
119 post_load_hooks[name].append(hook)
120
121
122
123 for obj in sys.meta_path:
124 if obj.__class__ is ModuleFinder:
125 break
126 else:
127 sys.meta_path.insert(0, ModuleFinder())
128