blob: 231a33dcea445f701bee8c60cf7fdfede87eb1ef [file] [log] [blame]
Guido van Rossum52325901995-04-07 09:03:10 +00001"""Prototype of 'import' functionality enhanced to implement packages.
2
3Why packages? Packages enable module nesting and sibling module
4imports. 'Til now, the python module namespace was flat, which
5means every module had to have a unique name, in order to not
6conflict with names of other modules on the load path. Furthermore,
7suites of modules could not be structurally affiliated with one
8another.
9
10With packages, a suite of, eg, email-oriented modules can include a
11module named 'mailbox', without conflicting with the, eg, 'mailbox'
12module of a shared-memory suite - 'email.mailbox' vs
13'shmem.mailbox'. Packages also enable modules within a suite to
14load other modules within their package without having the package
15name hard-coded. Similarly, package suites of modules can be loaded
16as a unit, by loading the package that contains them.
17
18Usage: once installed (newimp.install(); newimp.revert() to revert to
19the prior __import__ routine), 'import ...' and 'from ... import ...'
20can be used to:
21
22 - import modules from the search path, as before.
23
24 - import modules from within other directory "packages" on the search
25 path using a '.' dot-delimited nesting syntax. The nesting is fully
26 recursive.
27
Guido van Rossum96044da1995-04-07 09:06:50 +000028 For example, 'import test.test_types' will import the test_types
29 module within the 'test' package. The calling environment would
30 then access the module as 'test.test_types', which is the name of
31 the fully-loaded 'test_types' module. It is found contained within
32 the stub (ie, only partially loaded) 'test' module, hence accessed as
33 'test.test_types'.
Guido van Rossum52325901995-04-07 09:03:10 +000034
35 - import siblings from modules within a package, using '__.' as a shorthand
36 prefix to refer to the parent package. This enables referential
37 transparency - package modules need not know their package name.
38
Guido van Rossum96044da1995-04-07 09:06:50 +000039 The '__' package references are actually names assigned within
Guido van Rossum52325901995-04-07 09:03:10 +000040 modules, to refer to their containing package. This means that
Guido van Rossum96044da1995-04-07 09:06:50 +000041 variable references can be made to imported modules, or to variables
42 defined via 'import ... from', also using the '__.var' shorthand
43 notation. This establishes a proper equivalence between the import
44 reference '__.sibling' and the var reference '__.sibling'.
Guido van Rossum52325901995-04-07 09:03:10 +000045
Guido van Rossum96044da1995-04-07 09:06:50 +000046 - import an entire package as a unit, by importing the package directory.
Guido van Rossumb89ab8c1995-07-12 02:17:51 +000047 If there is a module named '__init__.py' in the package, it controls the
Guido van Rossum96044da1995-04-07 09:06:50 +000048 load. Otherwise, all the modules in the dir, including packages, are
49 inherently loaded into the package module's namespace.
50
51 For example, 'import test' will load the modules of the entire 'test'
52 package, at least until a test failure is encountered.
53
Guido van Rossumb89ab8c1995-07-12 02:17:51 +000054 In a package, a module with the name '__init__' has a special role.
Guido van Rossum96044da1995-04-07 09:06:50 +000055 If present in a package directory, then it is loaded into the package
56 module, instead of loading the contents of the directory. This
Guido van Rossumb89ab8c1995-07-12 02:17:51 +000057 enables the __init__ module to control the load, possibly loading
Guido van Rossum96044da1995-04-07 09:06:50 +000058 the entire directory deliberately (using 'import __', or even
59 'from __ import *', to load all the module contents directly into the
60 package module).
61
62 - perform any combination of the above - have a package that contains
63 packages, etc.
64
65Modules have a few new attributes in support of packages. As mentioned
66above, '__' is a shorthand attribute denoting the modules' parent package,
67also denoted in the module by '__package__'. Additionally, modules have
68associated with them a '__pkgpath__', a path by which sibling modules are
69found."""
Guido van Rossum52325901995-04-07 09:03:10 +000070
Guido van Rossumb89ab8c1995-07-12 02:17:51 +000071__version__ = "$Revision$"
Guido van Rossum52325901995-04-07 09:03:10 +000072
Guido van Rossumb89ab8c1995-07-12 02:17:51 +000073# $Id$ First release:
74# Ken.Manheimer@nist.gov, 5-Apr-1995, for python 1.2
75
76# Issues (scattered in code - search for three asterisks)
77# *** Despite my efforts, 'reload(newimp)' will foul things up.
78# *** Normalize_pathname will only work for Unix - which we need to detect.
79# *** when a module with the name of the platform (as indicated by
80# to-be-created var sys.platform), the package path gets '.' and the
81# platform dir.
82# *** use sys.impadmin for things like an import load-hooks var
83# *** Import-load-hook keying module name versus package path, which dictates
84# additions to the default ('.' and os-specific dir) path
85# *** Document that the __init__.py can set __.__pkgpath__, in which case that
86# will be used for the package-relative loads.
87# *** Add a 'recursive' option to reload, for reload of package constituent
88# modules (including subpackages), as well. Or maybe that should be the
89# default, and eg stub-completion should override that default. ???
Guido van Rossum52325901995-04-07 09:03:10 +000090
91# Developers Notes:
92#
93# - 'sys.stub_modules' registers "incidental" (partially loaded) modules.
94# A stub module is promoted to the fully-loaded 'sys.modules' list when it is
95# explicitly loaded as a unit.
Guido van Rossumb89ab8c1995-07-12 02:17:51 +000096# - One load nuance - the actual load of most module types goes into the
97# already-generated stub module. HOWEVER, eg dynamically loaded modules
98# generate a new module object, which must supplant the existing stub. One
99# consequence is that the import process must use indirection through
100# sys.stub_modules or sys.modules to track the actual modules across some of
101# the phases.
Guido van Rossum52325901995-04-07 09:03:10 +0000102# - The test routines are cool, including a transient directory
103# hierarchy facility, and a means of skipping to later tests by giving
104# the test routine a numeric arg.
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000105# - There may still be some loose ends, not to mention bugs. But the full
106# functionality should be there.
107# - The ImportStack object is necessary to carry the list of in-process imports
108# across very open-ended recursions, where the state cannot be passed
109# explicitly via the import_module calls; for a primary example, via exec of
110# an 'import' statement within a module.
111# - Python's (current) handling of extension modules, via imp.load_dynamic,
112# does too much, some of which needs to be undone. See comments in
113# load_module. Among other things, we actually change the __name__ of the
114# module, which conceivably may break something.
Guido van Rossum52325901995-04-07 09:03:10 +0000115
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000116try:
117 VERBOSE
118except NameError:
119 VERBOSE = 0 # Will be reset by init(1), also.
Guido van Rossum52325901995-04-07 09:03:10 +0000120
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000121import sys, string, regex, types, os, marshal, traceback
122import __main__, __builtin__
123
124newimp_globals = vars()
125
Guido van Rossum52325901995-04-07 09:03:10 +0000126try:
127 import imp # Build on this recent addition
128except ImportError:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000129 raise ImportError, 'Pkg import module depends on optional "imp" module'#==X
Guido van Rossum52325901995-04-07 09:03:10 +0000130
131from imp import SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION
Guido van Rossum52325901995-04-07 09:03:10 +0000132
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000133def defvar(varNm, envDict, val, override=0):
134 """If VARNAME does not have value in DICT, assign VAL to it. Optional arg
135 OVERRIDE means force the assignment in any case."""
136 if (not envDict.has_key(varNm)) or override:
137 envDict[varNm] = val
138
139def init(full_reset=0):
140 """Do environment initialization, including retrofitting sys.modules with
141 module attributes."""
142 # Retrofit all existing modules with package attributes, under auspices of
143 # __root__:
Guido van Rossum52325901995-04-07 09:03:10 +0000144
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000145 locals, globals = vars(), newimp_globals
Guido van Rossum52325901995-04-07 09:03:10 +0000146
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000147 if full_reset:
148 global VERBOSE
149 VERBOSE = 0
Guido van Rossum52325901995-04-07 09:03:10 +0000150
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000151 # sys.stub_modules tracks modules partially loaded modules, ie loaded only
152 # incidental to load of nested components. Together with sys.modules and
153 # the import stack, it serves as part of the module registration mechanism.
154 defvar('stub_modules', sys.__dict__, {}, full_reset)
Guido van Rossum52325901995-04-07 09:03:10 +0000155
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000156 # Environment setup - "root" module, '__root__'
157 # Establish root package '__root__' in __main__ and newimp envs.
Guido van Rossum52325901995-04-07 09:03:10 +0000158
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000159 # Longhand for name of variable identifying module's containing package:
160 defvar('PKG_NM', globals, "__package__", full_reset)
161 # Shorthand for module's container:
162 defvar('PKG_SHORT_NM', globals, "__", full_reset)
163 defvar('PKG_SHORT_NM_LEN', globals, len(PKG_SHORT_NM), full_reset)
Guido van Rossum52325901995-04-07 09:03:10 +0000164
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000165 # Name of controlling module for a package, if any:
166 defvar('INIT_MOD_NM', globals, "__init__", full_reset)
167
168 # Paths eventually will be extended to accomodate non-filesystem media -
169 # eg, URLs, composite objects, who knows.
170
171 # Name assigned in sys for general import administration:
172 defvar('IMP_SYS_NM', globals, "imp_admin", full_reset)
173 defvar('MOD_LOAD_HOOKS', globals, "mod_load_hooks", full_reset)
174 if full_reset:
175 defvar(IMP_SYS_NM, sys.__dict__, {MOD_LOAD_HOOKS: {}}, full_reset)
176
177
178 # Name assigned in each module to tuple describing module import attrs:
179 defvar('IMP_ADMIN', globals, "__impadmin__", full_reset)
180 # The load-path obtaining for this package. Not defined for non-packages.
181 # If not set, package directory is used. If no package directory
182 # registered, sys.path is used.
183 defvar('PKG_PATH', globals, 0, full_reset)
184 # File from which module was loaded - may be None, eg, for __root__:
185 defvar('MOD_TYPE', globals, 1, full_reset)
186 # Exact path from which the module was loaded:
187 defvar('MOD_PATHNAME', globals, 2, full_reset)
188 # Package within which the module was found:
189 defvar('MOD_PACKAGE', globals, 3, full_reset)
190 defvar('USE_PATH', globals, 'either PKG_PATH or my dir', full_reset)
191
192 # We're aliasing the top-level __main__ module as '__root__':
193 defvar('__root__', globals, __main__, full_reset)
194 defvar('ROOT_MOD_NM', globals, "__root__", full_reset)
195 if not sys.modules.has_key('__root__') or full_reset:
196 # and register it as an imported module:
197 sys.modules[ROOT_MOD_NM] = __root__
198
199 # Register package information in all existing top-level modules - they'll
200 # the None's mean, among other things, that their USE_PATH's all defer to
201 # sys.path.
202 for aMod in sys.modules.values():
203 if (not aMod.__dict__.has_key(PKG_NM)) or full_reset:
204 set_mod_attrs(aMod, None, __root__, None, None)
205
206 try:
207 __builtin__.__import__
208 defvar('origImportFunc', globals, __builtin__.__import__)
209 defvar('origReloadFunc', globals, __builtin__.reload)
210 except AttributeError:
211 pass
212
213 defvar('PY_PACKAGE', globals, 4, full_reset)
214 defvar('PY_FROZEN', globals, 5, full_reset)
215 defvar('PY_BUILTIN', globals, 6, full_reset)
216
217 # Establish lookup table from mod-type "constants" to names:
218 defvar('mod_types', globals,
219 {SEARCH_ERROR: 'SEARCH_ERROR',
220 PY_SOURCE: 'PY_SOURCE',
221 PY_COMPILED: 'PY_COMPILED',
222 C_EXTENSION: 'C_EXTENSION',
223 PY_PACKAGE: 'PY_PACKAGE',
224 PY_FROZEN: 'PY_FROZEN',
225 PY_BUILTIN: 'PY_BUILTIN'},
226 full_reset)
227
228 defvar('stack', globals, ImportStack(), full_reset)
229
Guido van Rossum52325901995-04-07 09:03:10 +0000230def install():
231 """Install newimp import_module() routine, for package support.
232
233 newimp.revert() reverts to __import__ routine that was superceded."""
Guido van Rossum52325901995-04-07 09:03:10 +0000234 __builtin__.__import__ = import_module
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000235 __builtin__.reload = reload
236 __builtin__.unload = unload
237 __builtin__.bypass = bypass
238 return 'Enhanced import functionality in place.'
Guido van Rossum52325901995-04-07 09:03:10 +0000239def revert():
240 """Revert to original __builtin__.__import__ func, if newimp.install() has
241 been executed."""
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000242 if not (origImportFunc and origReloadFunc):
243 raise SystemError, "Can't find original import and reload funcs." # ==X
244 __builtin__.__import__ = origImportFunc
245 __builtin__.reload = origReloadFunc
246 del __builtin__.unload, __builtin__.bypass
247 return 'Original import routines back in place.'
Guido van Rossum52325901995-04-07 09:03:10 +0000248
249def import_module(name,
250 envLocals=None, envGlobals=None,
251 froms=None,
252 inPkg=None):
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000253 """Primary service routine implementing 'import' with package nesting.
Guido van Rossum52325901995-04-07 09:03:10 +0000254
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000255 NAME: name as specified to 'import NAME' or 'from NAME...'
256 LOCALS, GLOBALS: local and global dicts obtaining for import
257 FROMS: list of strings of "..." in 'import blat from ...'
258 INPKG: package to which the name search is restricted, for use
259 by recursive package loads (from import_module()).
Guido van Rossum52325901995-04-07 09:03:10 +0000260
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000261 A subtle difference from the old import - modules that do fail
262 initialization will not be registered in sys.modules, ie will not, in
263 effect, be registered as being loaded. Note further that packages which
264 fail their overall load, but have successfully loaded constituent modules,
265 will be accessible in the importing namespace as stub modules.
266
267 A new routine, 'newimp.bypass()', provides the means to circumvent
268 constituent modules that fail their load, in order to enable load of the
269 remainder of a package."""
270
271 rootMod = sys.modules[ROOT_MOD_NM]
272
273 note("import_module: seeking '%s'" % name, 1)
Guido van Rossum52325901995-04-07 09:03:10 +0000274
275 # We need callers environment dict for local path and resulting module
276 # binding.
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000277 if not envGlobals:
278 # This should not happen, but does for imports called from within
279 # functions.
Guido van Rossum52325901995-04-07 09:03:10 +0000280 envLocals, envGlobals = exterior()
281
Guido van Rossum52325901995-04-07 09:03:10 +0000282 if inPkg:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000283 pkg = inPkg
284 elif envGlobals.has_key(PKG_NM):
285 pkg = envGlobals[PKG_NM]
Guido van Rossum52325901995-04-07 09:03:10 +0000286 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000287 # ** KLUDGE - cover for modules that lack package attributes:
288 pkg = rootMod
Guido van Rossum52325901995-04-07 09:03:10 +0000289
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000290 if pkg != rootMod:
291 note(' - relative to package %s' % pkg)
Guido van Rossum52325901995-04-07 09:03:10 +0000292
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000293 modList = theMod = absNm = nesting = None
294
295 # Normalize
296 # - absNm is absolute w.r.t. __root__
297 # - relNm is relative w.r.t. pkg.
298 if inPkg:
299 absNm, relNm = pkg.__name__ + '.' + name, name
Guido van Rossum52325901995-04-07 09:03:10 +0000300 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000301 absNm, relNm, pkg = normalize_import_ref(name, pkg)
302 note("Normalized: %s%s" % (absNm, (((relNm != absNm)
303 and (" ('%s' in %s)" % (relNm, pkg)))
304 or '')), 3)
305
306 pkgPath = get_mod_attrs(pkg, USE_PATH)
307
308 try: # try...finally guards import stack integrity.
309
310 if stack.push(absNm):
311 # We're nested inside a containing import of this module, perhaps
312 # indirectly. Avoid infinite recursion at this point by using the
313 # existing stub module, for now. Load of it will be completed by
314 # the superior import.
315 note('recursion on in-process module %s, punting with stub' %
316 absNm)
317 theMod = stack.mod(absNm)
318
Guido van Rossum52325901995-04-07 09:03:10 +0000319 else:
Guido van Rossum52325901995-04-07 09:03:10 +0000320
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000321 # Try to find already-imported:
322 if sys.modules.has_key(absNm):
323 note('found ' + absNm + ' already imported')
324 theMod = sys.modules[absNm]
325 stack.mod(absNm, theMod)
Guido van Rossum52325901995-04-07 09:03:10 +0000326
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000327 else: # Actually do load, of one sort or another:
Guido van Rossum52325901995-04-07 09:03:10 +0000328
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000329 # Seek builtin or frozen first:
330 theMod = imp.init_builtin(absNm)
331 if theMod:
332 set_mod_attrs(theMod, None, pkg, None, PY_BUILTIN)
333 stack.mod(absNm, theMod)
334 note('found builtin ' + absNm)
335 else:
336 theMod = imp.init_frozen(absNm)
337 if theMod:
338 set_mod_attrs(theMod, None, pkg, None, PY_FROZEN)
339 stack.mod(absNm, theMod)
340 note('found frozen ' + absNm)
Guido van Rossum52325901995-04-07 09:03:10 +0000341
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000342 if not theMod:
343 # Not already-loaded, in-process, builtin, or frozen -
344 # we're seeking in the outside world (filesystem):
345
346 if sys.stub_modules.has_key(absNm):
347
348 # A package for which we have a stub:
349 theMod = reload(sys.stub_modules[absNm], inPkg)
350
351 else:
352
353 # Now we actually search the fs.
354
355 if type(pkgPath) == types.StringType:
356 pkgPath = [pkgPath]
357
358 # Find a path leading to the module:
359 modList = find_module(relNm, pkgPath, absNm)
360 if not modList:
361 raise ImportError, ("module '%s' not found" % #==X
362 absNm)
363
364 # We have a list of successively nested dirs leading
365 # to the module, register with import admin, as stubs:
366 nesting = register_mod_nesting(modList, pkg)
367
368 # Load from file if necessary and possible:
369 modNm, modf, path, ty = modList[-1]
370 note('found type %s - %s' % (mod_types[ty[2]], absNm))
371
372 # Establish the module object in question:
373 theMod = procure_module(absNm)
374 stack.mod(absNm, theMod)
375
376 # Do the load:
377 theMod = load_module(theMod, ty[2], modf, inPkg)
378
379 commit_mod_containment(absNm)
380
381 # Successful load - promote to fully-imported status:
382 register_module(theMod, theMod.__name__)
383
384
385 # We have a loaded module (perhaps stub): situate specified components,
386 # and return appropriate thing. According to guido:
387 #
388 # "Note that for "from spam.ham import bacon" your function should
389 # return the object denoted by 'spam.ham', while for "import
390 # spam.ham" it should return the object denoted by 'spam' -- the
391 # STORE instructions following the import statement expect it this
392 # way."
393 # *** The above rationale should probably be reexamined, since newimp
394 # actually takes care of populating the caller's namespace.
395
396 if not froms:
397
398 # Return the outermost container, possibly stub:
399 if nesting:
400 return find_mod_registration(nesting[0][0])
Guido van Rossumb1c13151995-05-05 15:50:56 +0000401 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000402 return find_mod_registration(string.splitfields(absNm,'.')[0])
403 else:
Guido van Rossum52325901995-04-07 09:03:10 +0000404
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000405 return theMod
406
407 finally: # Decrement stack registration:
408 stack.pop(absNm)
409
410
411def reload(module, inPkg = None):
412 """Re-parse and re-initialize an already (or partially) imported MODULE.
413
414 The argument can be an already loaded module object or a string name of a
415 loaded module or a "stub" module that was partially loaded package module
416 incidental to the full load of a contained module.
417
418 This is useful if you have edited the module source file using an external
419 editor and want to try out the new version without leaving the Python
420 interpreter. The return value is the resulting module object.
421
422 Contrary to the old 'reload', the load is sought from the same location
423 where the module was originally found. If you wish to do a fresh load from
424 a different module on the path, do an 'unload()' and then an import.
425
426 When a module is reloaded, its dictionary (containing the module's
427 global variables) is retained. Redefinitions of names will
428 override the old definitions, so this is generally not a problem.
429 If the new version of a module does not define a name that was
430 defined by the old version, the old definition remains. This
431 feature can be used to the module's advantage if it maintains a
432 global table or cache of objects -- with a `try' statement it can
433 test for the table's presence and skip its initialization if
434 desired.
435
436 It is legal though generally not very useful to reload built-in or
437 dynamically loaded modules, except for `sys', `__main__' and
438 `__builtin__'. In certain cases, however, extension modules are
439 not designed to be initialized more than once, and may fail in
440 arbitrary ways when reloaded.
441
442 If a module imports objects from another module using `from' ...
443 `import' ..., calling `reload()' for the other module does not
444 redefine the objects imported from it -- one way around this is to
445 re-execute the `from' statement, another is to use `import' and
446 qualified names (MODULE.NAME) instead.
447
448 If a module instantiates instances of a class, reloading the module
449 that defines the class does not affect the method definitions of
450 the instances, unless they are reinstantiated -- they continue to use the
451 old class definition. The same is true for derived classes."""
452
453 if type(module) == types.StringType:
454 theMod = find_mod_registration(module)
455 elif type(module) == types.ModuleType:
456 theMod = module
457 else:
458 raise ImportError, '%s not already imported' # ==X
459
460 if theMod in [sys.modules[ROOT_MOD_NM], sys.modules['__builtin__']]:
461 raise ImportError, 'cannot re-init internal module' # ==X
462
463 try:
464 thePath = get_mod_attrs(theMod, MOD_PATHNAME)
465 except KeyError:
466 thePath = None
467
468 if not thePath:
469 # If we have no path for the module, we can only reload it from
470 # scratch:
471 note('no pathname registered for %s, doing full reload' % theMod)
472 unload(theMod)
473 envGlobals, envLocals = exterior()
474 return import_module(theMod.__name__,
475 envGlobals, envLocals, None, inPkg)
476 else:
477
478 stack.mod(theMod.__name__, theMod)
479 ty = get_mod_attrs(theMod, MOD_TYPE)
480 if ty in [PY_SOURCE, PY_COMPILED]:
481 note('reload invoked for %s %s' % (mod_types[ty], theMod))
482 thePath, ty, openFile = prefer_compiled(thePath, ty)
483 else:
484 openFile = open(thePath, get_suffixes(ty)[1])
485 return load_module(theMod, # ==>
486 ty,
487 openFile,
488 inPkg)
Guido van Rossum52325901995-04-07 09:03:10 +0000489def unload(module):
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000490 """Remove registration for a module, so import will do a fresh load.
491
492 Returns the module registries (sys.modules and/or sys.stub_modules) where
493 it was found."""
Guido van Rossum52325901995-04-07 09:03:10 +0000494 if type(module) == types.ModuleType:
495 module = module.__name__
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000496 gotit = []
497 for which in ['sys.modules', 'sys.stub_modules']:
498 m = eval(which)
Guido van Rossum52325901995-04-07 09:03:10 +0000499 try:
500 del m[module]
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000501 gotit.append(which)
Guido van Rossum52325901995-04-07 09:03:10 +0000502 except KeyError:
503 pass
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000504 if not gotit:
505 raise ValueError, '%s not a module or a stub' % module # ==X
506 else: return gotit
507def bypass(modNm):
508 """Register MODULE-NAME so module will be skipped, eg in package load."""
509 if sys.modules.has_key(modNm):
510 raise ImportError("'%s' already imported, cannot be bypassed." % modNm)
511 else:
512 sys.modules[modNm] = imp.new_module('bypass()ed module %s' % modNm)
513 commit_mod_containment(modNm)
514
515
516def normalize_import_ref(name, pkg):
517 """Produce absolute and relative nm and relative pkg given MODNM and origin
518 PACKAGE, reducing out all '__'s in the process."""
519
520 # First reduce out all the '__' container-refs we can:
521 outwards, inwards = 0, []
522 for nm in string.splitfields(name, '.'):
523 if nm == PKG_SHORT_NM:
524 if inwards:
525 # Pop a containing inwards:
526 del inwards[-1]
527 else:
528 # (Effectively) leading '__' - notch outwards:
529 outwards = outwards + 1
530 else:
531 inwards.append(nm)
532 inwards = string.joinfields(inwards, '.')
533
534 # Now identify the components:
535
536 if not outwards:
537 pkg = sys.modules[ROOT_MOD_NM]
538 else:
539 while outwards > 1:
540 pkg = pkg.__dict__[PKG_NM] # We'll just loop at top
541 if pkg == __root__:
542 break # ==v
543 outwards = outwards - 1
544
545 if not inwards: # Entire package:
546 return pkg.__name__, pkg.__name__, pkg # ==>
547 else: # Name relative to package:
548 if pkg == __root__:
549 return inwards, inwards, pkg # ==>
550 else:
551 return pkg.__name__ + '.' + inwards, inwards, pkg # ==>
552
553class ImportStack:
554 """Provide judicious support for mutually recursive import loops.
555
556 Mutually recursive imports, eg a module that imports the package that
557 contains it, which in turn imports the module, are not uncommon, and must
558 be supported judiciously. This class is used to track cycles, so a module
559 already in the process of being imported (via 'stack.push(module)', and
560 concluded via 'stack.release(module)') is not redundantly pursued; *except*
561 when a module master '__init__.py' loads the module, in which case it is
562 'stack.relax(module)'ed, so the full import is pursued."""
563
564 def __init__(self):
565 self._cycles = {}
566 self._mods = {}
567 self._looped = []
568 def in_process(self, modNm):
569 """1 if modNm load already in process, 0 otherwise."""
570 return self._cycles.has_key(modNm) # ==>
571 def looped(self, modNm):
572 """1 if modNm load has looped once or more, 0 otherwise."""
573 return modNm in self._looped
574 def push(self, modNm):
575 """1 if modNm already in process and not 'relax'ed, 0 otherwise.
576 (Note that the 'looped' status remains even when the cycle count
577 returns to 1. This is so error messages can indicate that it was, at
578 some point, looped during the import process.)"""
579 if self.in_process(modNm):
580 self._looped.append(modNm)
581 self._cycles[modNm] = self._cycles[modNm] + 1
582 return 1 # ==>
583 else:
584 self._cycles[modNm] = 1
585 return 0 # ==>
586 def mod(self, modNm, mod=None):
587 """Associate MOD-NAME with MODULE, for easy reference."""
588 if mod:
589 self._mods[modNm] = mod
590 else:
591 try:
592 return self._mods[modNm] # ==>
593 except KeyError:
594 return None
595 def pop(self, modNm):
596 """Decrement stack count of MODNM"""
597 if self.in_process(modNm):
598 amt = self._cycles[modNm] = self._cycles[modNm] - 1
599 if amt < 1:
600 del self._cycles[modNm]
601 if modNm in self._looped:
602 self._looped.remove(modNm)
603 if self._mods.has_key(modNm):
604 del self._mods[modNm]
605 def relax(self, modNm):
606 """Enable modNm load despite being registered as already in-process."""
607 if self._cycles.has_key(modNm):
608 del self._cycles[modNm]
Guido van Rossum52325901995-04-07 09:03:10 +0000609
610def find_module(name, path, absNm=''):
611 """Locate module NAME on PATH. PATH is pathname string or a list of them.
612
613 Note that up-to-date compiled versions of a module are preferred to plain
614 source, and compilation is automatically performed when necessary and
615 possible.
616
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000617 Returns a list of the tuples returned by 'find_mod_file()', one for
Guido van Rossum52325901995-04-07 09:03:10 +0000618 each nested level, deepest last."""
619
620 checked = [] # For avoiding redundant dir lists.
621
622 if not absNm: absNm = name
623
624 # Parse name into list of nested components,
625 expNm = string.splitfields(name, '.')
626
627 for curPath in path:
628
629 if (type(curPath) != types.StringType) or (curPath in checked):
630 # Disregard bogus or already investigated path elements:
631 continue # ==^
632 else:
633 # Register it for subsequent disregard.
634 checked.append(curPath)
635
636 if len(expNm) == 1:
637
638 # Non-nested module name:
639
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000640 got = find_mod_file(curPath, absNm)
Guido van Rossum52325901995-04-07 09:03:10 +0000641 if got:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000642 note('using %s' % got[2], 3)
643 return [got] # ==>
Guido van Rossum52325901995-04-07 09:03:10 +0000644
645 else:
646
647 # Composite name specifying nested module:
648
649 gotList = []; nameAccume = expNm[0]
650
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000651 got = find_mod_file(curPath, nameAccume)
Guido van Rossum52325901995-04-07 09:03:10 +0000652 if not got: # Continue to next prospective path.
653 continue # ==^
654 else:
655 gotList.append(got)
656 nm, file, fullPath, ty = got
657
658 # Work on successively nested components:
659 for component in expNm[1:]:
660 # 'ty'pe of containing component must be package:
661 if ty[2] != PY_PACKAGE:
662 gotList, got = [], None
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000663 break # ==v
Guido van Rossum52325901995-04-07 09:03:10 +0000664 if nameAccume:
665 nameAccume = nameAccume + '.' + component
666 else:
667 nameAccume = component
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000668 got = find_mod_file(fullPath, nameAccume)
Guido van Rossum52325901995-04-07 09:03:10 +0000669 if got:
670 gotList.append(got)
Guido van Rossum52325901995-04-07 09:03:10 +0000671 nm, file, fullPath, ty = got
672 else:
673 # Clear state vars:
674 gotList, got, nameAccume = [], None, ''
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000675 break # ==v
Guido van Rossum52325901995-04-07 09:03:10 +0000676 # Found nesting all the way to the specified tip:
677 if got:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000678 return gotList # ==>
Guido van Rossum52325901995-04-07 09:03:10 +0000679
680 # Failed.
681 return None
682
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000683def find_mod_file(pathNm, modname):
684 """Find right module file given DIR and module NAME, compiling if needed.
Guido van Rossum52325901995-04-07 09:03:10 +0000685
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000686 If successful, returns quadruple consisting of:
687 - mod name,
688 - file object,
689 - full pathname for the found file,
690 - a description triple as contained in the list returned by get_suffixes.
Guido van Rossum52325901995-04-07 09:03:10 +0000691
692 Otherwise, returns None.
693
694 Note that up-to-date compiled versions of a module are preferred to plain
695 source, and compilation is automatically performed, when necessary and
696 possible."""
697
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000698 relNm = modname[1 + string.rfind(modname, '.'):]
Guido van Rossum52325901995-04-07 09:03:10 +0000699
700 for suff, mode, ty in get_suffixes():
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000701 fullPath = os.path.join(pathNm, relNm + suff)
702 note('trying ' + fullPath + '...', 4)
Guido van Rossum52325901995-04-07 09:03:10 +0000703 try:
704 modf = open(fullPath, mode)
705 except IOError:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000706 # ** ?? Skip unreadable ones:
Guido van Rossum52325901995-04-07 09:03:10 +0000707 continue # ==^
708
709 if ty == PY_PACKAGE:
710 # Enforce directory characteristic:
711 if not os.path.isdir(fullPath):
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000712 note('Skipping non-dir match ' + fullPath, 3)
Guido van Rossum52325901995-04-07 09:03:10 +0000713 continue # ==^
714 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000715 return (modname, modf, fullPath, (suff, mode, ty)) # ==>
Guido van Rossum52325901995-04-07 09:03:10 +0000716
717
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000718 elif ty in [PY_SOURCE, PY_COMPILED]:
719 usePath, useTy, openFile = prefer_compiled(fullPath, ty)
720 return (modname, # ==>
721 openFile,
722 usePath,
723 get_suffixes(useTy))
Guido van Rossum52325901995-04-07 09:03:10 +0000724
725 elif ty == C_EXTENSION:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000726 note('found C_EXTENSION ' + fullPath, 3)
727 return (modname, modf, fullPath, (suff, mode, ty)) # ==>
Guido van Rossum52325901995-04-07 09:03:10 +0000728
729 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000730 raise SystemError, 'Unanticipated module type encountered' # ==X
Guido van Rossum52325901995-04-07 09:03:10 +0000731
732 return None
733
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000734def prefer_compiled(path, ty, modf=None):
735 """Given a path to a .py or .pyc file, attempt to return a path to a
736 current pyc file, compiling the .py in the process if necessary. Returns
737 the path to the most current version we can get."""
Guido van Rossum52325901995-04-07 09:03:10 +0000738
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000739 if ty == PY_SOURCE:
740 if not modf:
741 try:
742 modf = open(path, 'r')
743 except IOError:
744 pass
745 note('working from PY_SOURCE', 3)
746 # Try for a compiled version:
747 pyc = path + 'c' # Sadly, we're presuming '.py' suff.
748 if (not os.path.exists(pyc) or
749 (os.stat(path)[8] > os.stat(pyc)[8])):
750 # Try to compile:
751 pyc = compile_source(path, modf)
752 if pyc and not (os.stat(path)[8] > os.stat(pyc)[8]):
753 # Either pyc was already newer or we just made it so; in either
754 # case it's what we crave:
755 note('but got newer compiled, ' + pyc, 3)
756 try:
757 return (pyc, PY_COMPILED, open(pyc, 'rb')) # ==>
758 except IOError:
759 if modf:
760 return (path, PY_SOURCE, modf) # ==>
761 else:
762 raise ImportError, 'Failed acces to .py and .pyc' # ==X
763 else:
764 note("couldn't get newer compiled, using PY_SOURCE", 3)
765 if modf:
766 return (path, PY_SOURCE, modf) # ==>
767 else:
768 raise ImportError, 'Failed acces to .py and .pyc' # ==X
Guido van Rossum52325901995-04-07 09:03:10 +0000769
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000770 elif ty == PY_COMPILED:
771 note('working from PY_COMPILED', 3)
772 if not modf:
773 try:
774 modf = open(path, 'rb')
775 except IOError:
776 return prefer_compiled(path[:-1], PY_SOURCE)
777 # Make sure it is current, trying to compile if necessary, and
778 # prefer source failing that:
779 note('found compiled ' + path, 3)
780 py = path[:-1] # ** Presuming '.pyc' suffix
781 if not os.path.exists(py):
782 note('pyc SANS py: ' + path, 3)
783 return (path, PY_COMPILED, open(py, 'r')) # ==>
784 elif (os.stat(py)[8] > os.stat(path)[8]):
785 note('Forced to compile: ' + py, 3)
786 pyc = compile_source(py, open(py, 'r'))
787 if pyc:
788 return (pyc, PY_COMPILED, modf) # ==>
789 else:
790 note('failed compile - must use more recent .py', 3)
791 return (py, PY_SOURCE, open(py, 'r')) # ==>
792 else:
793 return (path, PY_COMPILED, modf) # ==>
794
795def load_module(theMod, ty, theFile, fromMod):
796 """Load module NAME, of TYPE, from FILE, within MODULE.
797
798 Optional arg fromMod indicates the module from which the load is being done
799 - necessary for detecting import of __ from a package's __init__ module.
Guido van Rossum52325901995-04-07 09:03:10 +0000800
801 Return the populated module object."""
802
803 # Note: we mint and register intermediate package directories, as necessary
804
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000805 name = theMod.__name__
806 nameTail = name[1 + string.rfind(name, '.'):]
Guido van Rossum52325901995-04-07 09:03:10 +0000807 thePath = theFile.name
808
809 if ty == PY_SOURCE:
810 exec_into(theFile, theMod, theFile.name)
811
812 elif ty == PY_COMPILED:
813 pyc = open(theFile.name, 'rb').read()
814 if pyc[0:4] != imp.get_magic():
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000815 raise ImportError, 'bad magic number: ' + theFile.name # ==X
Guido van Rossum52325901995-04-07 09:03:10 +0000816 code = marshal.loads(pyc[8:])
817 exec_into(code, theMod, theFile.name)
818
819 elif ty == C_EXTENSION:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000820 # Dynamically loaded C_EXTENSION modules do too much import admin,
821 # themselves, which we need to *undo* in order to integrate them with
822 # the new import scheme.
823 # 1 They register themselves in sys.modules, registering themselves
824 # under their top-level names. Have to rectify that.
825 # 2 The produce their own module objects, *unless* they find an
826 # existing module already registered a la 1, above. We employ this
827 # quirk to make it use the already generated module.
Guido van Rossum52325901995-04-07 09:03:10 +0000828 try:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000829 # Stash a ref to any module that is already registered under the
830 # dyamic module's simple name (nameTail), so we can reestablish it
831 # after the dynamic takes over its' slot:
832 protMod = None
833 if nameTail != name:
834 if sys.modules.has_key(nameTail):
835 protMod = sys.modules[nameTail]
836 # Trick the dynamic load, by registering the module we generated
837 # under the nameTail of the module we're loading, so the one we're
838 # loading will use that established module, rather than producing a
839 # new one:
840 sys.modules[nameTail] = theMod
Guido van Rossum52325901995-04-07 09:03:10 +0000841 theMod = imp.load_dynamic(nameTail, thePath, theFile)
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000842 theMod.__name__ = name
843 # Cleanup dynamic mod's bogus self-registration, if necessary:
844 if nameTail != name:
845 if protMod:
846 # ... reinstating the one that was already there...
847 sys.modules[nameTail] = protMod
848 else:
849 if sys.modules.has_key(nameTail):
850 # Certain, as long os dynamics continue to misbehave.
851 del sys.modules[nameTail]
852 stack.mod(name, theMod)
853 if sys.stub_modules.has_key(name):
854 sys.stub_modules[name] = theMod
855 elif sys.modules.has_key(name):
856 sys.modules[name] = theMod
Guido van Rossum52325901995-04-07 09:03:10 +0000857 except:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000858 # Provide import-nesting info, including signs of circularity:
Guido van Rossum7f64e241995-07-12 15:34:34 +0000859 raise sys.exc_type, import_trail_msg(str(sys.exc_value),# ==X
860 sys.exc_traceback,
861 name)
Guido van Rossum52325901995-04-07 09:03:10 +0000862 elif ty == PY_PACKAGE:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000863 # Load package constituents, doing the controlling module *if* it
864 # exists *and* it isn't already in process:
865
866 init_mod_f = init_mod = None
867 if not stack.in_process(name + '.' + INIT_MOD_NM):
868 # Not already doing __init__ - check for it:
869 init_mod_f = find_mod_file(thePath, INIT_MOD_NM)
Guido van Rossum52325901995-04-07 09:03:10 +0000870 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000871 note('skipping already-in-process %s.%s' % (theMod.__name__,
872 INIT_MOD_NM))
873 got = {}
874 if init_mod_f:
875 note("Found package's __init__: " + init_mod_f[2])
876 # Enable full continuance of containing-package-load from __init__:
877 if stack.in_process(theMod.__name__):
878 stack.relax(theMod.__name__)
879 init_mod = import_module(INIT_MOD_NM,
880 theMod.__dict__, theMod.__dict__,
881 None,
882 theMod)
883 else:
884 # ... or else recursively load all constituent modules, except
885 # __init__:
886 for prospect in mod_prospects(thePath):
887 if prospect != INIT_MOD_NM:
888 import_module(prospect,
889 theMod.__dict__, theMod.__dict__,
890 None,
891 theMod)
892
Guido van Rossum52325901995-04-07 09:03:10 +0000893 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000894 raise ImportError, 'Unimplemented import type: %s' % ty # ==X
895
Guido van Rossum52325901995-04-07 09:03:10 +0000896 return theMod
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000897
Guido van Rossum52325901995-04-07 09:03:10 +0000898def exec_into(obj, module, path):
899 """Helper for load_module, execfile/exec path or code OBJ within MODULE."""
900
901 # This depends on ability of exec and execfile to mutilate, erhm, mutate
902 # the __dict__ of a module. It will not work if/when this becomes
903 # disallowed, as it is for normal assignments.
904
905 try:
906 if type(obj) == types.FileType:
907 execfile(path, module.__dict__, module.__dict__)
908 elif type(obj) in [types.CodeType, types.StringType]:
909 exec obj in module.__dict__, module.__dict__
910 except:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000911 # Make the error message nicer?
912 raise sys.exc_type, import_trail_msg(str(sys.exc_value), # ==X
913 sys.exc_traceback,
914 module.__name__)
Guido van Rossum52325901995-04-07 09:03:10 +0000915
916
917def mod_prospects(path):
918 """Return a list of prospective modules within directory PATH.
919
920 We actually return the distinct names resulting from stripping the dir
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000921 entries (excluding os.curdir and os.pardir) of their suffixes (as
922 represented by 'get_suffixes').
Guido van Rossum52325901995-04-07 09:03:10 +0000923
924 (Note that matches for the PY_PACKAGE type with null suffix are
925 implicitly constrained to be directories.)"""
926
927 # We actually strip the longest matching suffixes, so eg 'dbmmodule.so'
928 # mates with 'module.so' rather than '.so'.
929
930 dirList = os.listdir(path)
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000931 excludes = [os.curdir, os.pardir]
Guido van Rossum52325901995-04-07 09:03:10 +0000932 sortedSuffs = sorted_suffixes()
933 entries = []
934 for item in dirList:
935 if item in excludes: continue # ==^
936 for suff in sortedSuffs:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000937 # *** ?? maybe platform-specific:
Guido van Rossum52325901995-04-07 09:03:10 +0000938 sub = -1 * len(suff)
939 if sub == 0:
940 if os.path.isdir(os.path.join(path, item)):
941 entries.append(item)
942 elif item[sub:] == suff:
943 it = item[:sub]
944 if not it in entries:
945 entries.append(it)
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000946 break # ==v
Guido van Rossum52325901995-04-07 09:03:10 +0000947 return entries
948
949
950
951def procure_module(name):
952 """Return an established or else new module object having NAME.
953
954 First checks sys.modules, then sys.stub_modules."""
955
956 if sys.modules.has_key(name):
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000957 return sys.modules[name] # ==>
Guido van Rossum52325901995-04-07 09:03:10 +0000958 elif sys.stub_modules.has_key(name):
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000959 return sys.stub_modules[name] # ==>
Guido van Rossum52325901995-04-07 09:03:10 +0000960 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000961 return (stack.mod(name) or imp.new_module(name)) # ==>
Guido van Rossum52325901995-04-07 09:03:10 +0000962
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000963def commit_mod_containment(name):
964 """Bind a module object and its containers within their respective
965 containers."""
966 cume, pkg = '', find_mod_registration(ROOT_MOD_NM)
967 for next in string.splitfields(name, '.'):
968 if cume:
969 cume = cume + '.' + next
Guido van Rossum52325901995-04-07 09:03:10 +0000970 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000971 cume = next
972 cumeMod = find_mod_registration(cume)
973 pkg.__dict__[next] = cumeMod
974 pkg = cumeMod
Guido van Rossum52325901995-04-07 09:03:10 +0000975
Guido van Rossumb89ab8c1995-07-12 02:17:51 +0000976def register_mod_nesting(modList, pkg):
977 """Given find_module()-style NEST-LIST and parent PACKAGE, register new
978 package components as stub modules, and return list of nested
979 module/relative-name pairs.
980
981 Note that the modules objects are not situated in their containing packages
982 here - that is left 'til after a successful load, and done by
983 commit_mod_nesting()."""
984 nesting = []
985
986 for modNm, modF, path, ty in modList:
987
988 relNm = modNm[1 + string.rfind(modNm, '.'):]
989
990 if sys.modules.has_key(modNm):
991 theMod = sys.modules[modNm] # Nestle in containing package
992 pkg = theMod # Set as parent for next in sequence.
993 elif sys.stub_modules.has_key(modNm):
994 # Similar to above...
995 theMod = sys.stub_modules[modNm]
996 pkg = theMod
997 else:
998 theMod = procure_module(modNm)
999 stack.mod(modNm, theMod)
1000 # *** ??? Should we be using 'path' instead of modF.name? If not,
1001 # should we get rid of the 'path' return val?
1002 set_mod_attrs(theMod, normalize_pathname(modF.name),
1003 pkg, None, ty[2])
1004 if ty[2] == PY_PACKAGE:
1005 # Register as a stub:
1006 register_module(theMod, modNm, 1)
1007 pkg = theMod
1008 nesting.append((theMod.__name__,relNm))
1009
1010 return nesting
1011
1012def register_module(theMod, name, stub=0):
1013 """Properly register MODULE, NAME, and optional STUB qualification."""
Guido van Rossum52325901995-04-07 09:03:10 +00001014
1015 if stub:
1016 sys.stub_modules[name] = theMod
1017 else:
1018 sys.modules[name] = theMod
1019 if sys.stub_modules.has_key(name):
1020 del sys.stub_modules[name]
Guido van Rossum52325901995-04-07 09:03:10 +00001021
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001022def find_mod_registration(name):
1023 """Find module named NAME sys.modules, .stub_modules, or on the stack."""
1024 if sys.stub_modules.has_key(name):
1025 return sys.stub_modules[name] # ==>
1026 elif sys.modules.has_key(name):
1027 return sys.modules[name] # ==>
1028 else:
1029 if stack.in_process(name):
1030 it = stack.mod(name)
1031 if it:
1032 return it # ==>
1033 else:
1034 raise ValueError, '%s %s in %s or %s' % (name, # ==X
1035 'not registered',
1036 'sys.modules',
1037 'sys.stub_modules')
1038
1039def get_mod_attrs(theMod, which = None):
1040 """Get MODULE object's path, containing-package, and designated path.
1041
1042 Virtual attribute USE_PATH is derived from PKG_PATH, MOD_PATHNAME,
1043 and/or sys.path, depending on the module type and settings."""
1044 it = theMod.__dict__[IMP_ADMIN]
1045 if which:
1046 # Load path is either the explicitly designated load path for the
1047 # package, or else the directory in which it resides:
1048 if which == USE_PATH:
1049 if it[PKG_PATH]:
1050 # Return explicitly designated path:
1051 return it[PKG_PATH] # ==>
1052 if it[MOD_PATHNAME]:
1053 if it[MOD_TYPE] == PY_PACKAGE:
1054 # Return the package's directory path:
1055 return [it[MOD_PATHNAME]] # ==>
1056 else:
1057 # Return the directory where the module resides:
1058 return [os.path.split(it[MOD_PATHNAME])[0]] # ==>
1059 # No explicitly designated path - use sys.path, eg for system
1060 # modules, etc:
1061 return sys.path
1062 return it[which] # ==>
1063 else:
1064 return it # ==>
1065
1066def set_mod_attrs(theMod, path, pkg, pkgPath, ty):
1067 """Register MOD import attrs PATH, PKG container, and PKGPATH, linking
1068 the package container into the module along the way."""
1069 theDict = theMod.__dict__
1070 try:
1071 # Get existing one, if any:
1072 it = theDict[IMP_ADMIN]
1073 except KeyError:
1074 # None existing, gen a new one:
1075 it = [None] * 4
1076 for fld, val in ((MOD_PATHNAME, path), (MOD_PACKAGE, pkg),
1077 (PKG_PATH, pkgPath), (MOD_TYPE, ty)):
1078 if val:
1079 it[fld] = val
1080
1081 theDict[IMP_ADMIN] = it
1082 if pkg:
1083 theDict[PKG_NM] = theDict[PKG_SHORT_NM] = pkg
1084 return it # ==>
1085
1086def format_tb_msg(tb, recursive):
1087 """This should be in traceback.py, and traceback.print_tb() should use it
1088 and traceback.extract_tb(), instead of print_tb() and extract_tb() having
1089 so much redundant code!"""
1090 tb_lines, formed = traceback.extract_tb(tb), ''
1091 for line in tb_lines:
1092 f, lno, nm, ln = line
1093 if f[-1 * (len(__name__) + 3):] == __name__ + '.py':
1094 # Skip newimp notices - agregious hack, justified only by the fact
1095 # that this functionality will be properly doable in new impending
1096 # exception mechanism:
1097 continue
1098 formed = formed + ('\n%s File "%s", line %d, in %s%s' %
1099 (((recursive and '*') or ' '),
1100 f, lno, nm,
1101 ((ln and '\n ' + string.strip(ln)) or '')))
1102 return formed
1103
1104def import_trail_msg(msg, tb, modNm):
1105 """Doctor an error message to include the path of the current import, and
1106 a sign that it is a circular import, if so."""
1107 return (msg +
1108 format_tb_msg(tb,
1109 (stack.looped(modNm) and stack.in_process(modNm))))
Guido van Rossum52325901995-04-07 09:03:10 +00001110
1111def compile_source(sourcePath, sourceFile):
1112 """Given python code source path and file obj, Create a compiled version.
1113
1114 Return path of compiled version, or None if file creation is not
1115 successful. (Compilation errors themselves are passed without restraint.)
1116
1117 This is an import-private interface, and not well-behaved for general use.
1118
1119 In particular, we presume the validity of the sourcePath, and that it
1120 includes a '.py' extension."""
1121
1122 compiledPath = sourcePath[:-3] + '.pyc'
1123 try:
1124 compiledFile = open(compiledPath, 'wb')
1125 except IOError:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001126 note("write permission denied to " + compiledPath, 3)
Guido van Rossum52325901995-04-07 09:03:10 +00001127 return None
1128 mtime = os.stat(sourcePath)[8]
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001129
Guido van Rossum52325901995-04-07 09:03:10 +00001130 try:
Guido van Rossumf4ef7e61995-06-22 18:50:15 +00001131 compiled = compile(sourceFile.read(), sourcePath, 'exec')
1132 except SyntaxError:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001133 # Doctor the exception a bit, to include the source file name in
1134 # the report, and then reraise the doctored version.
1135 os.unlink(compiledFile.name)
1136 sys.exc_value = ((sys.exc_value[0] + ' in ' + sourceFile.name,)
1137 + sys.exc_value[1:])
1138 raise sys.exc_type, sys.exc_value # ==X
1139
1140 # Ok, we have a valid compilation.
Guido van Rossumf4ef7e61995-06-22 18:50:15 +00001141 try:
Guido van Rossum52325901995-04-07 09:03:10 +00001142 compiledFile.write(imp.get_magic()) # compiled magic number
1143 compiledFile.seek(8, 0) # mtime space holder
Guido van Rossum52325901995-04-07 09:03:10 +00001144 marshal.dump(compiled, compiledFile) # write the code obj
1145 compiledFile.seek(4, 0) # position for mtime
1146 compiledFile.write(marshal.dumps(mtime)[1:]) # register mtime
1147 compiledFile.flush()
1148 compiledFile.close()
1149 return compiledPath
1150 except IOError:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001151 return None # ==>
Guido van Rossum52325901995-04-07 09:03:10 +00001152
1153
Guido van Rossum52325901995-04-07 09:03:10 +00001154got_suffixes = None
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001155got_suffixes_dict = {}
1156def get_suffixes(ty=None):
Guido van Rossum52325901995-04-07 09:03:10 +00001157 """Produce a list of triples, each describing a type of import file.
1158
1159 Triples have the form '(SUFFIX, MODE, TYPE)', where:
1160
1161 SUFFIX is a string found appended to a module name to make a filename for
1162 that type of import file.
1163
1164 MODE is the mode string to be passed to the built-in 'open' function - "r"
1165 for text files, "rb" for binary.
1166
1167 TYPE is the file type:
1168
1169 PY_SOURCE: python source code,
1170 PY_COMPILED: byte-compiled python source,
1171 C_EXTENSION: compiled-code object file,
1172 PY_PACKAGE: python library directory, or
1173 SEARCH_ERROR: no module found. """
1174
1175 # Note: sorted_suffixes() depends on this function's value being invariant.
1176 # sorted_suffixes() must be revised if this becomes untrue.
1177
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001178 global got_suffixes, got_suffixes_dict
Guido van Rossum52325901995-04-07 09:03:10 +00001179
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001180 if not got_suffixes:
Guido van Rossum52325901995-04-07 09:03:10 +00001181 # Ensure that the .pyc suffix precedes the .py:
1182 got_suffixes = [('', 'r', PY_PACKAGE)]
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001183 got_suffixes_dict[PY_PACKAGE] = ('', 'r', PY_PACKAGE)
Guido van Rossum52325901995-04-07 09:03:10 +00001184 py = pyc = None
1185 for suff in imp.get_suffixes():
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001186 got_suffixes_dict[suff[2]] = suff
Guido van Rossum52325901995-04-07 09:03:10 +00001187 if suff[0] == '.py':
1188 py = suff
1189 elif suff[0] == '.pyc':
1190 pyc = suff
1191 else:
1192 got_suffixes.append(suff)
1193 got_suffixes.append(pyc)
1194 got_suffixes.append(py)
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001195 if ty:
1196 return got_suffixes_dict[ty] # ==>
1197 else:
1198 return got_suffixes # ==>
Guido van Rossum52325901995-04-07 09:03:10 +00001199
1200
1201sortedSuffs = [] # State vars for sorted_suffixes(). Go
1202def sorted_suffixes():
1203 """Helper function ~efficiently~ tracks sorted list of module suffixes."""
1204
1205 # Produce sortedSuffs once - this presumes that get_suffixes does not
1206 # change from call to call during a python session. Needs to be
1207 # corrected if that becomes no longer true.
1208
1209 global sortedsuffs
1210 if not sortedSuffs: # do compute only the "first" time
1211 for item in get_suffixes():
1212 sortedSuffs.append(item[0])
1213 # Sort them in descending order:
1214 sortedSuffs.sort(lambda x, y: (((len(x) > len(y)) and 1) or
1215 ((len(x) < len(y)) and -1)))
1216 sortedSuffs.reverse()
1217 return sortedSuffs
1218
1219
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001220def normalize_pathname(path):
1221 """Given PATHNAME, return an absolute pathname relative to cwd, reducing
1222 unnecessary components where convenient (eg, on Unix)."""
1223
1224 # We do a lot more when we have posix-style paths, eg os.sep == '/'.
1225
1226 if os.sep != '/':
Guido van Rossum7f64e241995-07-12 15:34:34 +00001227 return os.path.join(os.getcwd, path) # ==>
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001228
1229 outwards, inwards = 0, []
1230 for nm in string.splitfields(path, os.sep):
1231 if nm != os.curdir:
1232 if nm == os.pardir:
1233 # Translate parent-dir entries to outward notches:
1234 if inwards:
1235 # Pop a containing inwards:
1236 del inwards[-1]
1237 else:
1238 # Register leading outward notches:
1239 outwards = outwards + 1
1240 else:
1241 inwards.append(nm)
1242 inwards = string.joinfields(inwards, os.sep)
1243
1244 if (not inwards) or (inwards[0] != os.sep):
1245 # Relative path - join with current working directory, (ascending
1246 # outwards to account for leading parent-dir components):
1247 cwd = os.getcwd()
1248 if outwards:
1249 cwd = string.splitfields(cwd, os.sep)
1250 cwd = string.joinfields(cwd[:len(cwd) - outwards], os.sep)
1251 if inwards:
1252 return os.path.join(cwd, inwards) # ==>
1253 else:
1254 return cwd # ==>
1255 else:
1256 return inwards # ==>
1257
1258
Guido van Rossum52325901995-04-07 09:03:10 +00001259# exterior(): Utility routine, obtain local and global dicts of environment
1260# containing/outside the callers environment, ie that of the
1261# caller's caller. Routines can use exterior() to determine the
1262# environment from which they were called.
1263
1264def exterior():
1265 """Return dyad containing locals and globals of caller's caller.
1266
1267 Locals will be None if same as globals, ie env is global env."""
1268
1269 bogus = 'bogus' # A locally usable exception
1270 try: raise bogus # Force an exception object
1271 except bogus:
1272 at = sys.exc_traceback.tb_frame.f_back # The external frame.
1273 if at.f_back: at = at.f_back # And further, if any.
1274 globals, locals = at.f_globals, at.f_locals
1275 if locals == globals: # Exterior is global?
1276 locals = None
1277 return (locals, globals)
1278
1279#########################################################################
1280# TESTING FACILITIES #
1281
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001282def note(msg, threshold=2):
Guido van Rossum96044da1995-04-07 09:06:50 +00001283 if VERBOSE >= threshold: sys.stderr.write('(import: ' + msg + ')\n')
Guido van Rossum52325901995-04-07 09:03:10 +00001284
1285class TestDirHier:
1286 """Populate a transient directory hierarchy according to a definition
1287 template - so we can create package/module hierarchies with which to
1288 exercise the new import facilities..."""
1289
1290 def __init__(self, template, where='/var/tmp'):
1291 """Establish a dir hierarchy, according to TEMPLATE, that will be
1292 deleted upon deletion of this object (or deliberate invocation of the
1293 __del__ method)."""
1294 self.PKG_NM = 'tdh_'
1295 rev = 0
1296 while os.path.exists(os.path.join(where, self.PKG_NM+str(rev))):
1297 rev = rev + 1
1298 sys.exc_traceback = None # Ensure Discard of try/except obj ref
1299 self.PKG_NM = self.PKG_NM + str(rev)
1300 self.root = os.path.join(where, self.PKG_NM)
1301 self.createDir(self.root)
1302 self.add(template)
1303
1304 def __del__(self):
1305 """Cleanup the test hierarchy."""
1306 self.remove()
1307 def add(self, template, root=None):
1308 """Populate directory according to template dictionary.
1309
1310 Keys indicate file names, possibly directories themselves.
1311
1312 String values dictate contents of flat files.
1313
1314 Dictionary values dictate recursively embedded dictionary templates."""
1315 if root == None: root = self.root
1316 for key, val in template.items():
1317 name = os.path.join(root, key)
1318 if type(val) == types.StringType: # flat file
1319 self.createFile(name, val)
1320 elif type(val) == types.DictionaryType: # embedded dir
1321 self.createDir(name)
1322 self.add(val, name)
1323 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001324 raise ValueError, ('invalid file-value type, %s' % # ==X
1325 type(val))
Guido van Rossum52325901995-04-07 09:03:10 +00001326 def remove(self, name=''):
1327 """Dispose of the NAME (or keys in dictionary), using 'rm -r'."""
1328 name = os.path.join(self.root, name)
1329 sys.exc_traceback = None # Ensure Discard of try/except obj ref
1330 if os.path.exists(name):
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001331 print '(TestDirHier: eradicating %s)' % name
Guido van Rossum52325901995-04-07 09:03:10 +00001332 os.system('rm -r ' + name)
1333 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001334 raise IOError, "can't remove non-existent " + name # ==X
Guido van Rossum52325901995-04-07 09:03:10 +00001335 def createFile(self, name, contents=None):
1336 """Establish file NAME with CONTENTS.
1337
1338 If no contents specfied, contents will be 'print NAME'."""
1339 f = open(name, 'w')
1340 if not contents:
1341 f.write("print '" + name + "'\n")
1342 else:
1343 f.write(contents)
1344 f.close
1345 def createDir(self, name):
1346 """Create dir with NAME."""
1347 return os.mkdir(name, 0755)
1348
1349skipToTest = 0
1350atTest = 1
1351def testExec(msg, execList, locals, globals):
1352 global skipToTest, atTest
1353 print 'Import Test:', '(' + str(atTest) + ')', msg, '...'
1354 atTest = atTest + 1
1355 if skipToTest > (atTest - 1):
1356 print ' ... skipping til test', skipToTest
1357 return
1358 else:
1359 print ''
1360 for stmt in execList:
1361 exec stmt in locals, globals
1362
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001363def test(number=0, leaveHiers=0):
Guido van Rossum52325901995-04-07 09:03:10 +00001364 """Exercise import functionality, creating a transient dir hierarchy for
1365 the purpose.
1366
1367 We actually install the new import functionality, temporarily, resuming the
1368 existing function on cleanup."""
1369
1370 import __builtin__
1371
1372 global skipToTest, atTest
1373 skipToTest = number
1374 hier = None
1375
Guido van Rossum52325901995-04-07 09:03:10 +00001376 def unloadFull(mod):
1377 """Unload module and offspring submodules, if any."""
1378 modMod = ''
1379 if type(mod) == types.StringType:
1380 modNm = mod
1381 elif type(mod) == types.ModuleType:
1382 modNm = modMod.__name__
1383 for subj in sys.modules.keys() + sys.stub_modules.keys():
1384 if subj[0:len(modNm)] == modNm:
1385 unload(subj)
1386
Guido van Rossum52325901995-04-07 09:03:10 +00001387 try:
1388 __main__.testMods
1389 except AttributeError:
1390 __main__.testMods = []
1391 testMods = __main__.testMods
1392
1393
1394 # Install the newimp routines, within a try/finally:
1395 try:
1396 sys.exc_traceback = None
1397 wasImport = __builtin__.__import__ # Stash default
1398 wasPath = sys.path
1399 except AttributeError:
1400 wasImport = None
1401 try:
1402 hiers = []; modules = []
1403 global VERBOSE
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001404 wasVerbose, VERBOSE = VERBOSE, 1
Guido van Rossum52325901995-04-07 09:03:10 +00001405 __builtin__.__import__ = import_module # Install new version
1406
1407 if testMods: # Clear out imports from previous tests
1408 for m in testMods[:]:
1409 unloadFull(m)
1410 testMods.remove(m)
1411
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001412 # ------
1413 # Test 1
Guido van Rossum52325901995-04-07 09:03:10 +00001414 testExec("already imported module: %s" % sys.modules.keys()[0],
1415 ['import ' + sys.modules.keys()[0]],
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001416 vars(), newimp_globals)
1417 no_sirree = 'no_sirree_does_not_exist'
1418 # ------
1419 # Test 2
1420 testExec("non-existent module: %s" % no_sirree,
1421 ['try: import ' + no_sirree +
1422 '\nexcept ImportError: pass'],
1423 vars(), newimp_globals)
Guido van Rossum52325901995-04-07 09:03:10 +00001424 got = None
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001425
1426 # ------
1427 # Test 3
1428 # Find a module that's not yet loaded, from a list of prospects:
Guido van Rossum52325901995-04-07 09:03:10 +00001429 for mod in ['Complex', 'UserDict', 'UserList', 'calendar',
1430 'cmd', 'dis', 'mailbox', 'profile', 'random', 'rfc822']:
1431 if not (mod in sys.modules.keys()):
1432 got = mod
1433 break # ==v
1434 if got:
1435 testExec("not-yet loaded module: %s" % mod,
1436 ['import ' + mod, 'modules.append(got)'],
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001437 vars(), newimp_globals)
Guido van Rossum52325901995-04-07 09:03:10 +00001438 else:
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001439 testExec("not-yet loaded module: list exhausted, never mind",
1440 [], vars(), newimp_globals)
Guido van Rossum52325901995-04-07 09:03:10 +00001441
1442 # Now some package stuff.
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001443
1444 # ------
1445 # Test 4
Guido van Rossum52325901995-04-07 09:03:10 +00001446 # First change the path to include our temp dir, copying so the
1447 # addition can be revoked on cleanup in the finally, below:
1448 sys.path = ['/var/tmp'] + sys.path[:]
1449 # Now create a trivial package:
1450 stmts = ["hier1 = TestDirHier({'a.py': 'print \"a.py executing\"'})",
1451 "hiers.append(hier1)",
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001452 "base = hier1.PKG_NM",
1453 "exec 'import ' + base",
1454 "testMods.append(base)"]
Guido van Rossum52325901995-04-07 09:03:10 +00001455 testExec("trivial package, with one module, a.py",
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001456 stmts, vars(), newimp_globals)
1457
1458 # ------
1459 # Test 5
Guido van Rossum52325901995-04-07 09:03:10 +00001460 # Slightly less trivial package - reference to '__':
1461 stmts = [("hier2 = TestDirHier({'ref.py': 'print \"Pkg __:\", __'})"),
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001462 "base = hier2.PKG_NM",
Guido van Rossum52325901995-04-07 09:03:10 +00001463 "hiers.append(hier2)",
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001464 "exec 'import ' + base",
1465 "testMods.append(base)"]
Guido van Rossum52325901995-04-07 09:03:10 +00001466 testExec("trivial package, with module that has pkg shorthand ref",
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001467 stmts, vars(), newimp_globals)
1468
1469 # ------
1470 # Test 6
Guido van Rossum52325901995-04-07 09:03:10 +00001471 # Nested package, plus '__' references:
1472
1473 complexTemplate = {'ref.py': 'print "ref.py loading..."',
1474 'suite': {'s1.py': 'print "s1.py, in pkg:", __',
1475 'subsuite': {'sub1.py':
1476 'print "sub1.py"'}}}
1477 stmts = [('print """%s\n%s\n%s\n%s\n%s\n%s"""' %
1478 ('.../',
1479 ' ref.py\t\t\t"ref.py loading..."',
1480 ' suite/',
1481 ' s1.py \t\t"s1.py, in pkg: xxxx.suite"',
1482 ' subsuite/',
1483 ' sub1.py "sub1.py" ')),
1484 "hier3 = TestDirHier(complexTemplate)",
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001485 "base = hier3.PKG_NM",
Guido van Rossum52325901995-04-07 09:03:10 +00001486 "hiers.append(hier3)",
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001487 "exec 'import ' + base",
1488 "testMods.append(base)"]
Guido van Rossum52325901995-04-07 09:03:10 +00001489 testExec("Significantly nestled package:",
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001490 stmts, vars(), newimp_globals)
Guido van Rossum52325901995-04-07 09:03:10 +00001491
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001492 # ------
1493 # Test 7
1494 # Try an elaborate hierarchy which includes an __init__ master in one
1495 # one portion, a ref across packages within the hierarchies, and an
1496 # indirect recursive import which cannot be satisfied (and hence,
1497 # prevents load of part of the hierarchy).
1498 complexTemplate = {'mid':
1499 {'prime':
1500 {'__init__.py': 'import __.easy, __.nother',
1501 'easy.py': 'print "easy.py:", __name__',
1502 'nother.py': ('%s\n%s\n%s\n' %
1503 ('import __.easy',
1504 'print "nother got __.easy"',
1505 # __.__.awry should be found but
1506 # should not load successfully,
1507 # disrupting nother, but not easy
1508 'import __.__.awry'))},
1509 # continuing dict 'mid':
1510 'awry':
1511 {'__init__.py':
1512 ('%s\n%s' %
1513 ('print "got " + __name__',
1514 'from __ import *')),
1515 # This mutual recursion (b->a, a->d->b) should be
1516 # ok, since a.py sets ax before recursing.
1517 'a.py': 'ax = 1; from __.b import bx',
1518 'b.py': 'bx = 1; from __.a import ax'}}}
1519 stmts = ["hier5 = TestDirHier(complexTemplate)",
1520 "base = hier5.PKG_NM",
1521 "testMods.append(base)",
1522 "hiers.append(hier5)",
1523 "exec 'import %s.mid.prime' % base",
1524 "print eval(base)", # Verify the base was bound
1525 "testMods.append(base)"]
1526 testExec("Elaborate, clean hierarchy",
1527 stmts, vars(), newimp_globals)
1528
1529 # ------
1530 # test 8
1531 # Here we disrupt the mutual recursion in the mid.awry package, so the
1532 # import should now fail.
1533 complexTemplate['mid']['awry']['a.py'] = 'from __.b import bx; ax = 1'
1534 complexTemplate['mid']['awry']['b.py'] = 'from __.a import ax; bx = 1'
1535 stmts = ["hier6 = TestDirHier(complexTemplate)",
1536 "base = hier6.PKG_NM",
1537 "testMods.append(base)",
1538 "hiers.append(hier6)",
1539 "work = ('import %s.mid.prime' % base)",
1540 ("try: exec work" +
1541 "\nexcept ImportError: print ' -- import failed, as ought'" +
1542 "\nelse: raise SystemError, sys.exc_value"),
1543 "testMods.append(base)"]
1544 testExec("Elaborate hier w/ deliberately flawed import recursion",
1545 stmts, vars(), newimp_globals)
Guido van Rossum52325901995-04-07 09:03:10 +00001546
1547 sys.exc_traceback = None # Signify clean conclusion.
1548
1549 finally:
Guido van Rossum52325901995-04-07 09:03:10 +00001550 skipToTest = 0
1551 atTest = 1
1552 sys.path = wasPath
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001553 VERBOSE = wasVerbose
1554 if wasImport: # Resurrect prior routine
Guido van Rossum52325901995-04-07 09:03:10 +00001555 __builtin__.__import__ = wasImport
1556 else:
1557 del __builtin__.__import__
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001558 if leaveHiers:
1559 print 'Cleanup inhibited'
1560 else:
1561 if sys.exc_traceback:
1562 print ' ** Import test FAILURE... cleanup.'
1563 else:
1564 print ' Import test SUCCESS... cleanup'
1565 for h in hiers: h.remove(); del h # Dispose of test directories
1566
1567init()
Guido van Rossumfa486a21995-04-07 09:04:01 +00001568
1569if __name__ == '__main__':
Guido van Rossumb89ab8c1995-07-12 02:17:51 +00001570 test()