Show More
@@ -73,14 +73,26 b' class _demandmod(object):' | |||
|
73 | 73 | head = name |
|
74 | 74 | after = [] |
|
75 | 75 | object.__setattr__(self, "_data", |
|
76 | (head, globals, locals, after, level)) | |
|
76 | (head, globals, locals, after, level, set())) | |
|
77 | 77 | object.__setattr__(self, "_module", None) |
|
78 | 78 | def _extend(self, name): |
|
79 | 79 | """add to the list of submodules to load""" |
|
80 | 80 | self._data[3].append(name) |
|
81 | ||
|
82 | def _addref(self, name): | |
|
83 | """Record that the named module ``name`` imports this module. | |
|
84 | ||
|
85 | References to this proxy class having the name of this module will be | |
|
86 | replaced at module load time. We assume the symbol inside the importing | |
|
87 | module is identical to the "head" name of this module. We don't | |
|
88 | actually know if "as X" syntax is being used to change the symbol name | |
|
89 | because this information isn't exposed to __import__. | |
|
90 | """ | |
|
91 | self._data[5].add(name) | |
|
92 | ||
|
81 | 93 | def _load(self): |
|
82 | 94 | if not self._module: |
|
83 | head, globals, locals, after, level = self._data | |
|
95 | head, globals, locals, after, level, modrefs = self._data | |
|
84 | 96 | mod = _hgextimport(_import, head, globals, locals, None, level) |
|
85 | 97 | # load submodules |
|
86 | 98 | def subload(mod, p): |
@@ -95,9 +107,15 b' class _demandmod(object):' | |||
|
95 | 107 | for x in after: |
|
96 | 108 | subload(mod, x) |
|
97 | 109 | |
|
98 | # are we in the locals dictionary still? | |
|
110 | # Replace references to this proxy instance with the actual module. | |
|
99 | 111 | if locals and locals.get(head) == self: |
|
100 | 112 | locals[head] = mod |
|
113 | ||
|
114 | for modname in modrefs: | |
|
115 | modref = sys.modules.get(modname, None) | |
|
116 | if modref and getattr(modref, head, None) == self: | |
|
117 | setattr(modref, head, mod) | |
|
118 | ||
|
101 | 119 | object.__setattr__(self, "_module", mod) |
|
102 | 120 | |
|
103 | 121 | def __repr__(self): |
@@ -107,7 +125,7 b' class _demandmod(object):' | |||
|
107 | 125 | def __call__(self, *args, **kwargs): |
|
108 | 126 | raise TypeError("%s object is not callable" % repr(self)) |
|
109 | 127 | def __getattribute__(self, attr): |
|
110 | if attr in ('_data', '_extend', '_load', '_module'): | |
|
128 | if attr in ('_data', '_extend', '_load', '_module', '_addref'): | |
|
111 | 129 | return object.__getattribute__(self, attr) |
|
112 | 130 | self._load() |
|
113 | 131 | return getattr(self._module, attr) |
@@ -143,6 +161,9 b' def _demandimport(name, globals=None, lo' | |||
|
143 | 161 | # The modern Mercurial convention is to use absolute_import everywhere, |
|
144 | 162 | # so modern Mercurial code will have level >= 0. |
|
145 | 163 | |
|
164 | # The name of the module the import statement is located in. | |
|
165 | globalname = globals.get('__name__') | |
|
166 | ||
|
146 | 167 | def processfromitem(mod, attr, **kwargs): |
|
147 | 168 | """Process an imported symbol in the import statement. |
|
148 | 169 | |
@@ -154,6 +175,12 b' def _demandimport(name, globals=None, lo' | |||
|
154 | 175 | symbol = _demandmod(attr, mod.__dict__, locals, **kwargs) |
|
155 | 176 | setattr(mod, attr, symbol) |
|
156 | 177 | |
|
178 | # Record the importing module references this symbol so we can | |
|
179 | # replace the symbol with the actual module instance at load | |
|
180 | # time. | |
|
181 | if globalname and isinstance(symbol, _demandmod): | |
|
182 | symbol._addref(globalname) | |
|
183 | ||
|
157 | 184 | if level >= 0: |
|
158 | 185 | # Mercurial's enforced import style does not use |
|
159 | 186 | # "from a import b,c,d" or "from .a import b,c,d" syntax. In |
General Comments 0
You need to be logged in to leave comments.
Login now