| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | """Prototype of 'import' functionality enhanced to implement packages.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Why packages?  Packages enable module nesting and sibling module | 
					
						
							|  |  |  | imports.  'Til now, the python module namespace was flat, which | 
					
						
							|  |  |  | means every module had to have a unique name, in order to not | 
					
						
							|  |  |  | conflict with names of other modules on the load path.  Furthermore, | 
					
						
							|  |  |  | suites of modules could not be structurally affiliated with one | 
					
						
							|  |  |  | another. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | With packages, a suite of, eg, email-oriented modules can include a | 
					
						
							|  |  |  | module named 'mailbox', without conflicting with the, eg, 'mailbox' | 
					
						
							|  |  |  | module of a shared-memory suite - 'email.mailbox' vs | 
					
						
							|  |  |  | 'shmem.mailbox'.  Packages also enable modules within a suite to | 
					
						
							|  |  |  | load other modules within their package without having the package | 
					
						
							|  |  |  | name hard-coded.  Similarly, package suites of modules can be loaded | 
					
						
							|  |  |  | as a unit, by loading the package that contains them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Usage: once installed (newimp.install(); newimp.revert() to revert to | 
					
						
							|  |  |  | the prior __import__ routine), 'import ...' and 'from ... import ...' | 
					
						
							|  |  |  | can be used to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   - import modules from the search path, as before. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   - import modules from within other directory "packages" on the search | 
					
						
							|  |  |  |     path using a '.' dot-delimited nesting syntax.  The nesting is fully | 
					
						
							|  |  |  |     recursive. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:06:50 +00:00
										 |  |  |     For example, 'import test.test_types' will import the test_types | 
					
						
							|  |  |  |     module within the 'test' package.  The calling environment would | 
					
						
							|  |  |  |     then access the module as 'test.test_types', which is the name of | 
					
						
							|  |  |  |     the fully-loaded 'test_types' module.  It is found contained within | 
					
						
							|  |  |  |     the stub (ie, only partially loaded) 'test' module, hence accessed as | 
					
						
							|  |  |  |     'test.test_types'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   - import siblings from modules within a package, using '__.' as a shorthand | 
					
						
							|  |  |  |     prefix to refer to the parent package.  This enables referential | 
					
						
							|  |  |  |     transparency - package modules need not know their package name. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The '__' package references are actually names assigned within | 
					
						
							|  |  |  |     modules, to refer to their containing package.  This means that | 
					
						
							|  |  |  |     variable references can be made to imported modules, or to variables | 
					
						
							|  |  |  |     defined via 'import ... from', also using the '__.var' shorthand | 
					
						
							|  |  |  |     notation.  This establishes a proper equivalence between the import | 
					
						
							|  |  |  |     reference '__.sibling' and the var reference '__.sibling'.   | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |   - import an entire package as a unit, by importing the package directory. | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     If there is a module named '__init__.py' in the package, it controls the | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     load.  Otherwise, all the modules in the dir, including packages, are | 
					
						
							|  |  |  |     inherently loaded into the package module's namespace. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:06:50 +00:00
										 |  |  |     For example, 'import test' will load the modules of the entire 'test' | 
					
						
							|  |  |  |     package, at least until a test failure is encountered. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     In a package, a module with the name '__init__' has a special role. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:06:50 +00:00
										 |  |  |     If present in a package directory, then it is loaded into the package | 
					
						
							|  |  |  |     module, instead of loading the contents of the directory.  This | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     enables the __init__ module to control the load, possibly loading | 
					
						
							| 
									
										
										
										
											1995-04-07 09:06:50 +00:00
										 |  |  |     the entire directory deliberately (using 'import __', or even | 
					
						
							|  |  |  |     'from __ import *', to load all the module contents directly into the | 
					
						
							|  |  |  |     package module). | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:06:50 +00:00
										 |  |  |   - perform any combination of the above - have a package that contains | 
					
						
							|  |  |  |     packages, etc. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:06:50 +00:00
										 |  |  | Modules have a few new attributes in support of packages.  As mentioned | 
					
						
							|  |  |  | above, '__' is a shorthand attribute denoting the modules' parent package, | 
					
						
							|  |  |  | also denoted in the module by '__package__'.  Additionally, modules have | 
					
						
							|  |  |  | associated with them a '__pkgpath__', a path by which sibling modules are | 
					
						
							|  |  |  | found."""
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | __version__ = "$Revision$" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # $Id$ First release: | 
					
						
							|  |  |  | # Ken.Manheimer@nist.gov, 5-Apr-1995, for python 1.2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Issues (scattered in code - search for three asterisks) | 
					
						
							|  |  |  | # *** Despite my efforts, 'reload(newimp)' will foul things up. | 
					
						
							|  |  |  | # *** Normalize_pathname will only work for Unix - which we need to detect. | 
					
						
							|  |  |  | # *** when a module with the name of the platform (as indicated by | 
					
						
							|  |  |  | #     to-be-created var sys.platform), the package path gets '.' and the | 
					
						
							|  |  |  | #     platform dir. | 
					
						
							|  |  |  | # *** use sys.impadmin for things like an import load-hooks var | 
					
						
							|  |  |  | # *** Import-load-hook keying module name versus package path, which dictates | 
					
						
							|  |  |  | #     additions to the default ('.' and os-specific dir) path | 
					
						
							|  |  |  | # *** Document that the __init__.py can set __.__pkgpath__, in which case that | 
					
						
							|  |  |  | #     will be used for the package-relative loads. | 
					
						
							|  |  |  | # *** Add a 'recursive' option to reload, for reload of package constituent | 
					
						
							|  |  |  | #     modules (including subpackages), as well.  Or maybe that should be the | 
					
						
							|  |  |  | #     default, and eg stub-completion should override that default.  ??? | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Developers Notes: | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # - 'sys.stub_modules' registers "incidental" (partially loaded) modules. | 
					
						
							|  |  |  | #   A stub module is promoted to the fully-loaded 'sys.modules' list when it is | 
					
						
							|  |  |  | #   explicitly loaded as a unit. | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | # - One load nuance - the actual load of most module types goes into the | 
					
						
							|  |  |  | #   already-generated stub module.  HOWEVER, eg dynamically loaded modules | 
					
						
							|  |  |  | #   generate a new module object, which must supplant the existing stub.  One | 
					
						
							|  |  |  | #   consequence is that the import process must use indirection through | 
					
						
							|  |  |  | #   sys.stub_modules or sys.modules to track the actual modules across some of | 
					
						
							|  |  |  | #   the phases. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | # - The test routines are cool, including a transient directory | 
					
						
							|  |  |  | #   hierarchy facility, and a means of skipping to later tests by giving | 
					
						
							|  |  |  | #   the test routine a numeric arg. | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | # - There may still be some loose ends, not to mention bugs.  But the full | 
					
						
							|  |  |  | #   functionality should be there. | 
					
						
							|  |  |  | # - The ImportStack object is necessary to carry the list of in-process imports | 
					
						
							|  |  |  | #   across very open-ended recursions, where the state cannot be passed | 
					
						
							|  |  |  | #   explicitly via the import_module calls; for a primary example, via exec of | 
					
						
							|  |  |  | #   an 'import' statement within a module. | 
					
						
							|  |  |  | # - Python's (current) handling of extension modules, via imp.load_dynamic, | 
					
						
							|  |  |  | #   does too much, some of which needs to be undone.  See comments in | 
					
						
							|  |  |  | #   load_module.  Among other things, we actually change the __name__ of the | 
					
						
							|  |  |  | #   module, which conceivably may break something. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     VERBOSE | 
					
						
							|  |  |  | except NameError: | 
					
						
							|  |  |  |     VERBOSE = 0				# Will be reset by init(1), also. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | import sys, string, regex, types, os, marshal, traceback | 
					
						
							|  |  |  | import __main__, __builtin__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | newimp_globals = vars() | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     import imp				# Build on this recent addition | 
					
						
							|  |  |  | except ImportError: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     raise ImportError, 'Pkg import module depends on optional "imp" module'#==X | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | from imp import SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | def defvar(varNm, envDict, val, override=0): | 
					
						
							|  |  |  |     """If VARNAME does not have value in DICT, assign VAL to it.  Optional arg
 | 
					
						
							|  |  |  |     OVERRIDE means force the assignment in any case."""
 | 
					
						
							|  |  |  |     if (not envDict.has_key(varNm)) or override: | 
					
						
							|  |  |  | 	envDict[varNm] = val | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | def init(full_reset=0): | 
					
						
							|  |  |  |     """Do environment initialization, including retrofitting sys.modules with
 | 
					
						
							|  |  |  |     module attributes."""
 | 
					
						
							|  |  |  |     # Retrofit all existing modules with package attributes, under auspices of | 
					
						
							|  |  |  |     # __root__: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     locals, globals = vars(), newimp_globals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if full_reset: | 
					
						
							|  |  |  | 	global VERBOSE | 
					
						
							|  |  |  | 	VERBOSE = 0 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     # sys.stub_modules tracks modules partially loaded modules, ie loaded only | 
					
						
							|  |  |  |     # incidental to load of nested components.  Together with sys.modules and | 
					
						
							|  |  |  |     # the import stack, it serves as part of the module registration mechanism. | 
					
						
							|  |  |  |     defvar('stub_modules', sys.__dict__, {}, full_reset) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     # Environment setup - "root" module, '__root__' | 
					
						
							|  |  |  |     # Establish root package '__root__' in __main__ and newimp envs. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     # Longhand for name of variable identifying module's containing package: | 
					
						
							|  |  |  |     defvar('PKG_NM', globals, "__package__", full_reset) | 
					
						
							|  |  |  |     # Shorthand for module's container: | 
					
						
							|  |  |  |     defvar('PKG_SHORT_NM', globals, "__", full_reset) | 
					
						
							|  |  |  |     defvar('PKG_SHORT_NM_LEN', globals, len(PKG_SHORT_NM), full_reset) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     # Name of controlling module for a package, if any: | 
					
						
							|  |  |  |     defvar('INIT_MOD_NM', globals, "__init__", full_reset) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     # Paths eventually will be extended to accomodate non-filesystem media - | 
					
						
							|  |  |  |     # eg, URLs, composite objects, who knows. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Name assigned in sys for general import administration: | 
					
						
							|  |  |  |     defvar('IMP_SYS_NM', globals, "imp_admin", full_reset) | 
					
						
							|  |  |  |     defvar('MOD_LOAD_HOOKS', globals, "mod_load_hooks", full_reset) | 
					
						
							|  |  |  |     if full_reset: | 
					
						
							|  |  |  | 	defvar(IMP_SYS_NM, sys.__dict__, {MOD_LOAD_HOOKS: {}}, full_reset) | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Name assigned in each module to tuple describing module import attrs: | 
					
						
							|  |  |  |     defvar('IMP_ADMIN', globals, "__impadmin__", full_reset) | 
					
						
							|  |  |  |     # The load-path obtaining for this package.  Not defined for non-packages. | 
					
						
							|  |  |  |     # If not set, package directory is used.  If no package directory | 
					
						
							|  |  |  |     # registered, sys.path is used. | 
					
						
							|  |  |  |     defvar('PKG_PATH', globals, 0, full_reset) | 
					
						
							|  |  |  |     # File from which module was loaded - may be None, eg, for __root__: | 
					
						
							|  |  |  |     defvar('MOD_TYPE', globals, 1, full_reset) | 
					
						
							|  |  |  |     # Exact path from which the module was loaded: | 
					
						
							|  |  |  |     defvar('MOD_PATHNAME', globals, 2, full_reset) | 
					
						
							|  |  |  |     # Package within which the module was found: | 
					
						
							|  |  |  |     defvar('MOD_PACKAGE', globals, 3, full_reset) | 
					
						
							|  |  |  |     defvar('USE_PATH', globals, 'either PKG_PATH or my dir', full_reset) | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     # We're aliasing the top-level __main__ module as '__root__': | 
					
						
							|  |  |  |     defvar('__root__', globals, __main__, full_reset) | 
					
						
							|  |  |  |     defvar('ROOT_MOD_NM', globals, "__root__", full_reset) | 
					
						
							|  |  |  |     if not sys.modules.has_key('__root__') or full_reset: | 
					
						
							|  |  |  | 	# and register it as an imported module: | 
					
						
							|  |  |  | 	sys.modules[ROOT_MOD_NM] = __root__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Register package information in all existing top-level modules - they'll | 
					
						
							|  |  |  |     # the None's mean, among other things, that their USE_PATH's all defer to | 
					
						
							|  |  |  |     # sys.path. | 
					
						
							|  |  |  |     for aMod in sys.modules.values(): | 
					
						
							|  |  |  | 	if (not aMod.__dict__.has_key(PKG_NM)) or full_reset: | 
					
						
							|  |  |  | 	    set_mod_attrs(aMod, None, __root__, None, None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  | 	__builtin__.__import__ | 
					
						
							|  |  |  | 	defvar('origImportFunc', globals, __builtin__.__import__) | 
					
						
							|  |  |  | 	defvar('origReloadFunc', globals, __builtin__.reload) | 
					
						
							|  |  |  |     except AttributeError: | 
					
						
							|  |  |  | 	pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     defvar('PY_PACKAGE', globals, 4, full_reset) | 
					
						
							|  |  |  |     defvar('PY_FROZEN', globals, 5, full_reset) | 
					
						
							|  |  |  |     defvar('PY_BUILTIN', globals, 6, full_reset) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Establish lookup table from mod-type "constants" to names: | 
					
						
							|  |  |  |     defvar('mod_types', globals, | 
					
						
							|  |  |  | 	   {SEARCH_ERROR: 'SEARCH_ERROR', | 
					
						
							|  |  |  | 	    PY_SOURCE: 'PY_SOURCE', | 
					
						
							|  |  |  | 	    PY_COMPILED: 'PY_COMPILED', | 
					
						
							|  |  |  | 	    C_EXTENSION: 'C_EXTENSION', | 
					
						
							|  |  |  | 	    PY_PACKAGE: 'PY_PACKAGE', | 
					
						
							|  |  |  | 	    PY_FROZEN: 'PY_FROZEN', | 
					
						
							|  |  |  | 	    PY_BUILTIN: 'PY_BUILTIN'}, | 
					
						
							|  |  |  | 	   full_reset) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     defvar('stack', globals, ImportStack(), full_reset) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def install(): | 
					
						
							|  |  |  |     """Install newimp import_module() routine, for package support.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     newimp.revert() reverts to __import__ routine that was superceded."""
 | 
					
						
							|  |  |  |     __builtin__.__import__ = import_module | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     __builtin__.reload = reload | 
					
						
							|  |  |  |     __builtin__.unload = unload | 
					
						
							|  |  |  |     __builtin__.bypass = bypass | 
					
						
							|  |  |  |     return 'Enhanced import functionality in place.' | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | def revert(): | 
					
						
							|  |  |  |     """Revert to original __builtin__.__import__ func, if newimp.install() has
 | 
					
						
							|  |  |  |     been executed."""
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     if not (origImportFunc and origReloadFunc): | 
					
						
							|  |  |  | 	raise SystemError, "Can't find original import and reload funcs." # ==X | 
					
						
							|  |  |  |     __builtin__.__import__ = origImportFunc | 
					
						
							|  |  |  |     __builtin__.reload = origReloadFunc | 
					
						
							|  |  |  |     del __builtin__.unload, __builtin__.bypass | 
					
						
							|  |  |  |     return 'Original import routines back in place.' | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def import_module(name, | 
					
						
							|  |  |  | 		  envLocals=None, envGlobals=None, | 
					
						
							|  |  |  | 		  froms=None, | 
					
						
							|  |  |  | 		  inPkg=None): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     """Primary service routine implementing 'import' with package nesting.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NAME:		name as specified to 'import NAME' or 'from NAME...' | 
					
						
							|  |  |  |     LOCALS, GLOBALS:	local and global dicts obtaining for import | 
					
						
							|  |  |  |     FROMS:		list of strings of "..." in 'import blat from ...' | 
					
						
							|  |  |  |     INPKG:		package to which the name search is restricted, for use | 
					
						
							|  |  |  |     			by recursive package loads (from import_module()). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     A subtle difference from the old import - modules that do fail | 
					
						
							|  |  |  |     initialization will not be registered in sys.modules, ie will not, in | 
					
						
							|  |  |  |     effect, be registered as being loaded.  Note further that packages which | 
					
						
							|  |  |  |     fail their overall load, but have successfully loaded constituent modules, | 
					
						
							|  |  |  |     will be accessible in the importing namespace as stub modules. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     A new routine, 'newimp.bypass()', provides the means to circumvent | 
					
						
							|  |  |  |     constituent modules that fail their load, in order to enable load of the | 
					
						
							|  |  |  |     remainder of a package."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rootMod = sys.modules[ROOT_MOD_NM] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     note("import_module: seeking '%s'" % name, 1) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # We need callers environment dict for local path and resulting module | 
					
						
							|  |  |  |     # binding. | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     if not envGlobals: | 
					
						
							|  |  |  | 	# This should not happen, but does for imports called from within | 
					
						
							|  |  |  | 	# functions. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	envLocals, envGlobals = exterior() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     if inPkg: | 
					
						
							|  |  |  | 	pkg = inPkg | 
					
						
							|  |  |  |     elif envGlobals.has_key(PKG_NM): | 
					
						
							|  |  |  | 	pkg = envGlobals[PKG_NM] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	# ** KLUDGE - cover for modules that lack package attributes: | 
					
						
							|  |  |  | 	pkg = rootMod | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if pkg != rootMod: | 
					
						
							|  |  |  | 	note(' - relative to package %s' % pkg) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     modList = theMod = absNm = nesting = None | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     # Normalize | 
					
						
							|  |  |  |     #  - absNm is absolute w.r.t. __root__ | 
					
						
							|  |  |  |     #  - relNm is relative w.r.t. pkg. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     if inPkg: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	absNm, relNm = pkg.__name__ + '.' + name, name | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	absNm, relNm, pkg = normalize_import_ref(name, pkg) | 
					
						
							|  |  |  |     note("Normalized: %s%s" % (absNm, (((relNm != absNm) | 
					
						
							|  |  |  | 					and (" ('%s' in %s)" % (relNm, pkg))) | 
					
						
							|  |  |  | 				       or '')), 3) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     pkgPath = get_mod_attrs(pkg, USE_PATH) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try:			# try...finally guards import stack integrity. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if stack.push(absNm): | 
					
						
							|  |  |  | 	    # We're nested inside a containing import of this module, perhaps | 
					
						
							|  |  |  | 	    # indirectly.  Avoid infinite recursion at this point by using the | 
					
						
							|  |  |  | 	    # existing stub module, for now.  Load of it will be completed by | 
					
						
							|  |  |  | 	    # the superior import. | 
					
						
							|  |  |  | 	    note('recursion on in-process module %s, punting with stub' % | 
					
						
							|  |  |  | 		 absNm) | 
					
						
							|  |  |  | 	    theMod = stack.mod(absNm) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    # Try to find already-imported: | 
					
						
							|  |  |  | 	    if sys.modules.has_key(absNm): | 
					
						
							|  |  |  | 		note('found ' + absNm + ' already imported') | 
					
						
							|  |  |  | 		theMod = sys.modules[absNm] | 
					
						
							|  |  |  | 		stack.mod(absNm, theMod) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    else:		# Actually do load, of one sort or another: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		# Seek builtin or frozen first: | 
					
						
							|  |  |  | 		theMod = imp.init_builtin(absNm) | 
					
						
							|  |  |  | 		if theMod: | 
					
						
							|  |  |  | 		    set_mod_attrs(theMod, None, pkg, None, PY_BUILTIN) | 
					
						
							|  |  |  | 		    stack.mod(absNm, theMod) | 
					
						
							|  |  |  | 		    note('found builtin ' + absNm) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 		    theMod = imp.init_frozen(absNm) | 
					
						
							|  |  |  | 		    if theMod: | 
					
						
							|  |  |  | 			set_mod_attrs(theMod, None, pkg, None, PY_FROZEN) | 
					
						
							|  |  |  | 			stack.mod(absNm, theMod) | 
					
						
							|  |  |  | 			note('found frozen ' + absNm) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if not theMod: | 
					
						
							|  |  |  | 		    # Not already-loaded, in-process, builtin, or frozen - | 
					
						
							|  |  |  | 		    # we're seeking in the outside world (filesystem): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		    if sys.stub_modules.has_key(absNm): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			# A package for which we have a stub: | 
					
						
							|  |  |  | 			theMod = reload(sys.stub_modules[absNm], inPkg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		    else: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			# Now we actually search the fs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if type(pkgPath) == types.StringType: | 
					
						
							|  |  |  | 			    pkgPath = [pkgPath] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			# Find a path leading to the module: | 
					
						
							|  |  |  | 			modList = find_module(relNm, pkgPath, absNm) | 
					
						
							|  |  |  | 			if not modList: | 
					
						
							|  |  |  | 			    raise ImportError, ("module '%s' not found" % #==X | 
					
						
							|  |  |  | 						absNm) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			# We have a list of successively nested dirs leading | 
					
						
							|  |  |  | 			# to the module, register with import admin, as stubs: | 
					
						
							|  |  |  | 			nesting = register_mod_nesting(modList, pkg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			# Load from file if necessary and possible: | 
					
						
							|  |  |  | 			modNm, modf, path, ty = modList[-1] | 
					
						
							|  |  |  | 			note('found type %s - %s' % (mod_types[ty[2]], absNm)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			# Establish the module object in question: | 
					
						
							|  |  |  | 			theMod = procure_module(absNm) | 
					
						
							|  |  |  | 			stack.mod(absNm, theMod) | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			# Do the load: | 
					
						
							|  |  |  | 			theMod = load_module(theMod, ty[2], modf, inPkg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			commit_mod_containment(absNm) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		    # Successful load - promote to fully-imported status: | 
					
						
							|  |  |  | 		    register_module(theMod, theMod.__name__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# We have a loaded module (perhaps stub): situate specified components, | 
					
						
							|  |  |  | 	# and return appropriate thing.  According to guido: | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	# "Note that for "from spam.ham import bacon" your function should | 
					
						
							|  |  |  | 	#  return the object denoted by 'spam.ham', while for "import | 
					
						
							|  |  |  | 	#  spam.ham" it should return the object denoted by 'spam' -- the | 
					
						
							|  |  |  | 	#  STORE instructions following the import statement expect it this | 
					
						
							|  |  |  | 	#  way." | 
					
						
							|  |  |  | 	# *** The above rationale should probably be reexamined, since newimp | 
					
						
							|  |  |  | 	#     actually takes care of populating the caller's namespace. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if not froms: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    # Return the outermost container, possibly stub: | 
					
						
							|  |  |  | 	    if nesting: | 
					
						
							|  |  |  | 		return find_mod_registration(nesting[0][0]) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		return find_mod_registration(string.splitfields(absNm,'.')[0]) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	    return theMod | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     finally:				# Decrement stack registration: | 
					
						
							|  |  |  | 	stack.pop(absNm) | 
					
						
							|  |  |  | 	     | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def reload(module, inPkg = None): | 
					
						
							|  |  |  |     """Re-parse and re-initialize an already (or partially) imported MODULE.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The argument can be an already loaded module object or a string name of a | 
					
						
							|  |  |  |     loaded module or a "stub" module that was partially loaded package module | 
					
						
							|  |  |  |     incidental to the full load of a contained module. | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     This is useful if you have edited the module source file using an external | 
					
						
							|  |  |  |     editor and want to try out the new version without leaving the Python | 
					
						
							|  |  |  |     interpreter.  The return value is the resulting module object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Contrary to the old 'reload', the load is sought from the same location | 
					
						
							|  |  |  |     where the module was originally found.  If you wish to do a fresh load from | 
					
						
							|  |  |  |     a different module on the path, do an 'unload()' and then an import. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     When a module is reloaded, its dictionary (containing the module's | 
					
						
							|  |  |  |     global variables) is retained.  Redefinitions of names will | 
					
						
							|  |  |  |     override the old definitions, so this is generally not a problem. | 
					
						
							|  |  |  |     If the new version of a module does not define a name that was | 
					
						
							|  |  |  |     defined by the old version, the old definition remains.  This | 
					
						
							|  |  |  |     feature can be used to the module's advantage if it maintains a | 
					
						
							|  |  |  |     global table or cache of objects -- with a `try' statement it can | 
					
						
							|  |  |  |     test for the table's presence and skip its initialization if | 
					
						
							|  |  |  |     desired. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     It is legal though generally not very useful to reload built-in or | 
					
						
							|  |  |  |     dynamically loaded modules, except for `sys', `__main__' and | 
					
						
							|  |  |  |     `__builtin__'.  In certain cases, however, extension modules are | 
					
						
							|  |  |  |     not designed to be initialized more than once, and may fail in | 
					
						
							|  |  |  |     arbitrary ways when reloaded. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If a module imports objects from another module using `from' ... | 
					
						
							|  |  |  |     `import' ..., calling `reload()' for the other module does not | 
					
						
							|  |  |  |     redefine the objects imported from it -- one way around this is to | 
					
						
							|  |  |  |     re-execute the `from' statement, another is to use `import' and | 
					
						
							|  |  |  |     qualified names (MODULE.NAME) instead. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If a module instantiates instances of a class, reloading the module | 
					
						
							|  |  |  |     that defines the class does not affect the method definitions of | 
					
						
							|  |  |  |     the instances, unless they are reinstantiated -- they continue to use the | 
					
						
							|  |  |  |     old class definition.  The same is true for derived classes."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if type(module) == types.StringType: | 
					
						
							|  |  |  | 	theMod = find_mod_registration(module) | 
					
						
							|  |  |  |     elif type(module) == types.ModuleType: | 
					
						
							|  |  |  | 	theMod = module | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	raise ImportError, '%s not already imported'			# ==X | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if theMod in [sys.modules[ROOT_MOD_NM], sys.modules['__builtin__']]: | 
					
						
							|  |  |  | 	raise ImportError, 'cannot re-init internal module'		# ==X | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  | 	thePath = get_mod_attrs(theMod, MOD_PATHNAME) | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  | 	thePath = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not thePath: | 
					
						
							|  |  |  | 	# If we have no path for the module, we can only reload it from | 
					
						
							|  |  |  | 	# scratch: | 
					
						
							|  |  |  | 	note('no pathname registered for %s, doing full reload' % theMod) | 
					
						
							|  |  |  | 	unload(theMod) | 
					
						
							|  |  |  | 	envGlobals, envLocals = exterior() | 
					
						
							|  |  |  | 	return import_module(theMod.__name__, | 
					
						
							|  |  |  | 			     envGlobals, envLocals, None, inPkg) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	stack.mod(theMod.__name__, theMod) | 
					
						
							|  |  |  | 	ty = get_mod_attrs(theMod, MOD_TYPE) | 
					
						
							|  |  |  | 	if ty in [PY_SOURCE, PY_COMPILED]: | 
					
						
							|  |  |  | 	    note('reload invoked for %s %s' % (mod_types[ty], theMod)) | 
					
						
							|  |  |  | 	    thePath, ty, openFile = prefer_compiled(thePath, ty) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    openFile = open(thePath, get_suffixes(ty)[1]) | 
					
						
							|  |  |  | 	return load_module(theMod,					# ==> | 
					
						
							|  |  |  | 			   ty, | 
					
						
							|  |  |  | 			   openFile, | 
					
						
							|  |  |  | 			   inPkg) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | def unload(module): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     """Remove registration for a module, so import will do a fresh load.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Returns the module registries (sys.modules and/or sys.stub_modules) where | 
					
						
							|  |  |  |     it was found."""
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     if type(module) == types.ModuleType: | 
					
						
							|  |  |  | 	module = module.__name__ | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     gotit = [] | 
					
						
							|  |  |  |     for which in ['sys.modules', 'sys.stub_modules']: | 
					
						
							|  |  |  | 	m = eval(which) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	try: | 
					
						
							|  |  |  | 	    del m[module] | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    gotit.append(which) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	except KeyError: | 
					
						
							|  |  |  | 	    pass | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     if not gotit: | 
					
						
							|  |  |  | 	raise ValueError, '%s not a module or a stub' % module		# ==X | 
					
						
							|  |  |  |     else: return gotit | 
					
						
							|  |  |  | def bypass(modNm): | 
					
						
							|  |  |  |     """Register MODULE-NAME so module will be skipped, eg in package load.""" | 
					
						
							|  |  |  |     if sys.modules.has_key(modNm): | 
					
						
							|  |  |  | 	raise ImportError("'%s' already imported, cannot be bypassed." % modNm) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	sys.modules[modNm] = imp.new_module('bypass()ed module %s' % modNm) | 
					
						
							|  |  |  | 	commit_mod_containment(modNm) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def normalize_import_ref(name, pkg): | 
					
						
							|  |  |  |     """Produce absolute and relative nm and relative pkg given MODNM and origin
 | 
					
						
							|  |  |  |     PACKAGE, reducing out all '__'s in the process."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # First reduce out all the '__' container-refs we can: | 
					
						
							|  |  |  |     outwards, inwards = 0, [] | 
					
						
							|  |  |  |     for nm in string.splitfields(name, '.'): | 
					
						
							|  |  |  | 	if nm == PKG_SHORT_NM: | 
					
						
							|  |  |  | 	    if inwards: | 
					
						
							|  |  |  | 		# Pop a containing inwards: | 
					
						
							|  |  |  | 		del inwards[-1] | 
					
						
							|  |  |  | 	    else: | 
					
						
							|  |  |  | 		# (Effectively) leading '__' - notch outwards: | 
					
						
							|  |  |  | 		outwards = outwards + 1 | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    inwards.append(nm) | 
					
						
							|  |  |  |     inwards = string.joinfields(inwards, '.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Now identify the components: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not outwards: | 
					
						
							|  |  |  | 	pkg = sys.modules[ROOT_MOD_NM] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	while outwards > 1: | 
					
						
							|  |  |  | 	    pkg = pkg.__dict__[PKG_NM]	# We'll just loop at top | 
					
						
							|  |  |  | 	    if pkg == __root__: | 
					
						
							|  |  |  | 		break							# ==v | 
					
						
							|  |  |  | 	    outwards = outwards - 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not inwards:			# Entire package: | 
					
						
							|  |  |  | 	return pkg.__name__, pkg.__name__, pkg				# ==> | 
					
						
							|  |  |  |     else:				# Name relative to package: | 
					
						
							|  |  |  | 	if pkg == __root__: | 
					
						
							|  |  |  | 	    return inwards, inwards, pkg				# ==> | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    return pkg.__name__ + '.' + inwards, inwards, pkg		# ==> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ImportStack: | 
					
						
							|  |  |  |     """Provide judicious support for mutually recursive import loops.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Mutually recursive imports, eg a module that imports the package that | 
					
						
							|  |  |  |     contains it, which in turn imports the module, are not uncommon, and must | 
					
						
							|  |  |  |     be supported judiciously.  This class is used to track cycles, so a module | 
					
						
							|  |  |  |     already in the process of being imported (via 'stack.push(module)', and | 
					
						
							|  |  |  |     concluded via 'stack.release(module)') is not redundantly pursued; *except* | 
					
						
							|  |  |  |     when a module master '__init__.py' loads the module, in which case it is | 
					
						
							|  |  |  |     'stack.relax(module)'ed, so the full import is pursued."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  | 	self._cycles = {} | 
					
						
							|  |  |  | 	self._mods = {} | 
					
						
							|  |  |  | 	self._looped = [] | 
					
						
							|  |  |  |     def in_process(self, modNm): | 
					
						
							|  |  |  | 	"""1 if modNm load already in process, 0 otherwise.""" | 
					
						
							|  |  |  | 	return self._cycles.has_key(modNm)				# ==> | 
					
						
							|  |  |  |     def looped(self, modNm): | 
					
						
							|  |  |  | 	"""1 if modNm load has looped once or more, 0 otherwise.""" | 
					
						
							|  |  |  | 	return modNm in self._looped | 
					
						
							|  |  |  |     def push(self, modNm): | 
					
						
							|  |  |  | 	"""1 if modNm already in process and not 'relax'ed, 0 otherwise.
 | 
					
						
							|  |  |  | 	(Note that the 'looped' status remains even when the cycle count | 
					
						
							|  |  |  | 	returns to 1.  This is so error messages can indicate that it was, at | 
					
						
							|  |  |  | 	some point, looped during the import process.)"""
 | 
					
						
							|  |  |  | 	if self.in_process(modNm): | 
					
						
							|  |  |  | 	    self._looped.append(modNm) | 
					
						
							|  |  |  | 	    self._cycles[modNm] = self._cycles[modNm] + 1 | 
					
						
							|  |  |  | 	    return 1							# ==> | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    self._cycles[modNm] = 1 | 
					
						
							|  |  |  | 	    return 0							# ==> | 
					
						
							|  |  |  |     def mod(self, modNm, mod=None): | 
					
						
							|  |  |  | 	"""Associate MOD-NAME with MODULE, for easy reference.""" | 
					
						
							|  |  |  | 	if mod: | 
					
						
							|  |  |  | 	    self._mods[modNm] = mod | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    try: | 
					
						
							|  |  |  | 		return self._mods[modNm]				# ==> | 
					
						
							|  |  |  | 	    except KeyError: | 
					
						
							|  |  |  | 		return None | 
					
						
							|  |  |  |     def pop(self, modNm): | 
					
						
							|  |  |  | 	"""Decrement stack count of MODNM""" | 
					
						
							|  |  |  | 	if self.in_process(modNm): | 
					
						
							|  |  |  | 	    amt = self._cycles[modNm] = self._cycles[modNm] - 1 | 
					
						
							|  |  |  | 	    if amt < 1: | 
					
						
							|  |  |  | 		del self._cycles[modNm] | 
					
						
							|  |  |  | 		if modNm in self._looped: | 
					
						
							|  |  |  | 		    self._looped.remove(modNm) | 
					
						
							|  |  |  | 		if self._mods.has_key(modNm): | 
					
						
							|  |  |  | 		    del self._mods[modNm] | 
					
						
							|  |  |  |     def relax(self, modNm): | 
					
						
							|  |  |  | 	"""Enable modNm load despite being registered as already in-process.""" | 
					
						
							|  |  |  | 	if self._cycles.has_key(modNm): | 
					
						
							|  |  |  | 	    del self._cycles[modNm] | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def find_module(name, path, absNm=''): | 
					
						
							|  |  |  |     """Locate module NAME on PATH.  PATH is pathname string or a list of them.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Note that up-to-date compiled versions of a module are preferred to plain | 
					
						
							|  |  |  |     source, and compilation is automatically performed when necessary and | 
					
						
							|  |  |  |     possible. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     Returns a list of the tuples returned by 'find_mod_file()', one for | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     each nested level, deepest last."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     checked = []			# For avoiding redundant dir lists. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not absNm: absNm = name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Parse name into list of nested components,  | 
					
						
							|  |  |  |     expNm = string.splitfields(name, '.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for curPath in path: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (type(curPath) != types.StringType) or (curPath in checked): | 
					
						
							|  |  |  | 	    # Disregard bogus or already investigated path elements: | 
					
						
							|  |  |  | 	    continue							# ==^ | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    # Register it for subsequent disregard. | 
					
						
							|  |  |  | 	    checked.append(curPath) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(expNm) == 1: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    # Non-nested module name: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    got = find_mod_file(curPath, absNm) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    if got: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		note('using %s' % got[2], 3) | 
					
						
							|  |  |  | 		return [got]						# ==> | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    # Composite name specifying nested module: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    gotList = []; nameAccume = expNm[0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    got = find_mod_file(curPath, nameAccume) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    if not got:			# Continue to next prospective path. | 
					
						
							|  |  |  | 		continue						# ==^ | 
					
						
							|  |  |  | 	    else: | 
					
						
							|  |  |  | 		gotList.append(got) | 
					
						
							|  |  |  | 		nm, file, fullPath, ty = got | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    # Work on successively nested components: | 
					
						
							|  |  |  | 	    for component in expNm[1:]: | 
					
						
							|  |  |  | 		# 'ty'pe of containing component must be package: | 
					
						
							|  |  |  | 		if ty[2] != PY_PACKAGE: | 
					
						
							|  |  |  | 		    gotList, got = [], None | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		    break						# ==v | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 		if nameAccume: | 
					
						
							|  |  |  | 		    nameAccume = nameAccume + '.' + component | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 		    nameAccume = component | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		got = find_mod_file(fullPath, nameAccume) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 		if got: | 
					
						
							|  |  |  | 		    gotList.append(got) | 
					
						
							|  |  |  | 		    nm, file, fullPath, ty = got | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 		    # Clear state vars: | 
					
						
							|  |  |  | 		    gotList, got, nameAccume = [], None, '' | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		    break						# ==v | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    # Found nesting all the way to the specified tip: | 
					
						
							|  |  |  | 	    if got: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		return gotList						# ==> | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Failed. | 
					
						
							|  |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | def find_mod_file(pathNm, modname): | 
					
						
							|  |  |  |     """Find right module file given DIR and module NAME, compiling if needed.
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     If successful, returns quadruple consisting of: | 
					
						
							|  |  |  |      - mod name, | 
					
						
							|  |  |  |      - file object, | 
					
						
							|  |  |  |      - full pathname for the found file, | 
					
						
							|  |  |  |      - a description triple as contained in the list returned by get_suffixes. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Otherwise, returns None. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Note that up-to-date compiled versions of a module are preferred to plain | 
					
						
							|  |  |  |     source, and compilation is automatically performed, when necessary and | 
					
						
							|  |  |  |     possible."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     relNm = modname[1 + string.rfind(modname, '.'):] | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for suff, mode, ty in get_suffixes(): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	fullPath = os.path.join(pathNm, relNm + suff) | 
					
						
							|  |  |  | 	note('trying ' + fullPath + '...', 4) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	try: | 
					
						
							|  |  |  | 	    modf = open(fullPath, mode) | 
					
						
							|  |  |  | 	except IOError: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    # ** ?? Skip unreadable ones: | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    continue							# ==^ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ty == PY_PACKAGE: | 
					
						
							|  |  |  | 	    # Enforce directory characteristic: | 
					
						
							|  |  |  | 	    if not os.path.isdir(fullPath): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		note('Skipping non-dir match ' + fullPath, 3) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 		continue						# ==^ | 
					
						
							|  |  |  | 	    else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		return (modname, modf, fullPath, (suff, mode, ty))	# ==> | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	     | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	elif ty in [PY_SOURCE, PY_COMPILED]: | 
					
						
							|  |  |  | 	    usePath, useTy, openFile = prefer_compiled(fullPath, ty) | 
					
						
							|  |  |  | 	    return (modname,						# ==> | 
					
						
							|  |  |  | 		    openFile, | 
					
						
							|  |  |  | 		    usePath, | 
					
						
							|  |  |  | 		    get_suffixes(useTy)) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	elif ty == C_EXTENSION: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    note('found C_EXTENSION ' + fullPath, 3) | 
					
						
							|  |  |  | 	    return (modname, modf, fullPath, (suff, mode, ty))		# ==> | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    raise SystemError, 'Unanticipated module type encountered'	# ==X | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | def prefer_compiled(path, ty, modf=None): | 
					
						
							|  |  |  |     """Given a path to a .py or .pyc file, attempt to return a path to a
 | 
					
						
							|  |  |  |     current pyc file, compiling the .py in the process if necessary.  Returns | 
					
						
							|  |  |  |     the path to the most current version we can get."""
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     if ty == PY_SOURCE: | 
					
						
							|  |  |  | 	if not modf: | 
					
						
							|  |  |  | 	    try: | 
					
						
							|  |  |  | 		modf = open(path, 'r') | 
					
						
							|  |  |  | 	    except IOError: | 
					
						
							|  |  |  | 		pass | 
					
						
							|  |  |  | 	note('working from PY_SOURCE', 3) | 
					
						
							|  |  |  | 	# Try for a compiled version: | 
					
						
							|  |  |  | 	pyc = path + 'c'	# Sadly, we're presuming '.py' suff. | 
					
						
							|  |  |  | 	if (not os.path.exists(pyc) or | 
					
						
							|  |  |  | 	    (os.stat(path)[8] > os.stat(pyc)[8])): | 
					
						
							|  |  |  | 	    # Try to compile: | 
					
						
							|  |  |  | 	    pyc = compile_source(path, modf) | 
					
						
							|  |  |  | 	if pyc and not (os.stat(path)[8] > os.stat(pyc)[8]): | 
					
						
							|  |  |  | 	    # Either pyc was already newer or we just made it so; in either | 
					
						
							|  |  |  | 	    # case it's what we crave: | 
					
						
							|  |  |  | 	    note('but got newer compiled, ' + pyc, 3) | 
					
						
							|  |  |  | 	    try: | 
					
						
							|  |  |  | 		return (pyc, PY_COMPILED, open(pyc, 'rb'))		# ==> | 
					
						
							|  |  |  | 	    except IOError: | 
					
						
							|  |  |  | 		if modf: | 
					
						
							|  |  |  | 		    return (path, PY_SOURCE, modf)			# ==> | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 		    raise ImportError, 'Failed acces to .py and .pyc'	# ==X | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    note("couldn't get newer compiled, using PY_SOURCE", 3) | 
					
						
							|  |  |  | 	    if modf: | 
					
						
							|  |  |  | 		return (path, PY_SOURCE, modf)				# ==> | 
					
						
							|  |  |  | 	    else: | 
					
						
							|  |  |  | 		raise ImportError, 'Failed acces to .py and .pyc'	# ==X | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     elif ty == PY_COMPILED: | 
					
						
							|  |  |  | 	note('working from PY_COMPILED', 3) | 
					
						
							|  |  |  | 	if not modf: | 
					
						
							|  |  |  | 	    try: | 
					
						
							|  |  |  | 		modf = open(path, 'rb') | 
					
						
							|  |  |  | 	    except IOError: | 
					
						
							|  |  |  | 		return prefer_compiled(path[:-1], PY_SOURCE) | 
					
						
							|  |  |  | 	# Make sure it is current, trying to compile if necessary, and | 
					
						
							|  |  |  | 	# prefer source failing that: | 
					
						
							|  |  |  | 	note('found compiled ' + path, 3) | 
					
						
							|  |  |  | 	py = path[:-1]			# ** Presuming '.pyc' suffix | 
					
						
							|  |  |  | 	if not os.path.exists(py): | 
					
						
							|  |  |  | 	    note('pyc SANS py: ' + path, 3) | 
					
						
							|  |  |  | 	    return (path, PY_COMPILED, open(py, 'r'))			# ==> | 
					
						
							|  |  |  | 	elif (os.stat(py)[8] > os.stat(path)[8]): | 
					
						
							|  |  |  | 	    note('Forced to compile: ' + py, 3) | 
					
						
							|  |  |  | 	    pyc = compile_source(py, open(py, 'r')) | 
					
						
							|  |  |  | 	    if pyc: | 
					
						
							|  |  |  | 		return (pyc, PY_COMPILED, modf)				# ==> | 
					
						
							|  |  |  | 	    else: | 
					
						
							|  |  |  | 		note('failed compile - must use more recent .py', 3) | 
					
						
							|  |  |  | 		return (py, PY_SOURCE, open(py, 'r'))			# ==> | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    return (path, PY_COMPILED, modf)				# ==> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def load_module(theMod, ty, theFile, fromMod): | 
					
						
							|  |  |  |     """Load module NAME, of TYPE, from FILE, within MODULE.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Optional arg fromMod indicates the module from which the load is being done | 
					
						
							|  |  |  |     - necessary for detecting import of __ from a package's __init__ module. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Return the populated module object."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Note: we mint and register intermediate package directories, as necessary | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     name = theMod.__name__ | 
					
						
							|  |  |  |     nameTail = name[1 + string.rfind(name, '.'):] | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     thePath = theFile.name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ty == PY_SOURCE: | 
					
						
							|  |  |  | 	exec_into(theFile, theMod, theFile.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     elif ty == PY_COMPILED: | 
					
						
							|  |  |  | 	pyc = open(theFile.name, 'rb').read() | 
					
						
							|  |  |  | 	if pyc[0:4] != imp.get_magic(): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    raise ImportError, 'bad magic number: ' + theFile.name	# ==X | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	code = marshal.loads(pyc[8:]) | 
					
						
							|  |  |  | 	exec_into(code, theMod, theFile.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     elif ty == C_EXTENSION: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	# Dynamically loaded C_EXTENSION modules do too much import admin, | 
					
						
							|  |  |  | 	# themselves, which we need to *undo* in order to integrate them with | 
					
						
							|  |  |  | 	# the new import scheme. | 
					
						
							|  |  |  | 	# 1 They register themselves in sys.modules, registering themselves | 
					
						
							|  |  |  | 	#   under their top-level names.  Have to rectify that. | 
					
						
							|  |  |  | 	# 2 The produce their own module objects, *unless* they find an | 
					
						
							|  |  |  | 	#   existing module already registered a la 1, above.  We employ this | 
					
						
							|  |  |  | 	#   quirk to make it use the already generated module. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	try: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    # Stash a ref to any module that is already registered under the | 
					
						
							|  |  |  | 	    # dyamic module's simple name (nameTail), so we can reestablish it | 
					
						
							|  |  |  | 	    # after the dynamic takes over its' slot: | 
					
						
							|  |  |  | 	    protMod = None | 
					
						
							|  |  |  | 	    if nameTail != name: | 
					
						
							|  |  |  | 		if sys.modules.has_key(nameTail): | 
					
						
							|  |  |  | 		    protMod = sys.modules[nameTail] | 
					
						
							|  |  |  | 	    # Trick the dynamic load, by registering the module we generated | 
					
						
							|  |  |  | 	    # under the nameTail of the module we're loading, so the one we're | 
					
						
							|  |  |  | 	    # loading will use that established module, rather than producing a | 
					
						
							|  |  |  | 	    # new one: | 
					
						
							|  |  |  | 	    sys.modules[nameTail] = theMod | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    theMod = imp.load_dynamic(nameTail, thePath, theFile) | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    theMod.__name__ = name | 
					
						
							|  |  |  | 	    # Cleanup dynamic mod's bogus self-registration, if necessary: | 
					
						
							|  |  |  | 	    if nameTail != name: | 
					
						
							|  |  |  | 		if protMod: | 
					
						
							|  |  |  | 		    # ... reinstating the one that was already there... | 
					
						
							|  |  |  | 		    sys.modules[nameTail] = protMod | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 		    if sys.modules.has_key(nameTail): | 
					
						
							|  |  |  | 			# Certain, as long os dynamics continue to misbehave. | 
					
						
							|  |  |  | 			del sys.modules[nameTail] | 
					
						
							|  |  |  | 	    stack.mod(name, theMod) | 
					
						
							|  |  |  | 	    if sys.stub_modules.has_key(name): | 
					
						
							|  |  |  | 		sys.stub_modules[name] = theMod | 
					
						
							|  |  |  | 	    elif sys.modules.has_key(name): | 
					
						
							|  |  |  | 		sys.modules[name] = theMod | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	except: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    # Provide import-nesting info, including signs of circularity: | 
					
						
							| 
									
										
										
										
											1995-07-12 15:34:34 +00:00
										 |  |  | 		raise sys.exc_type, import_trail_msg(str(sys.exc_value),# ==X | 
					
						
							|  |  |  | 						     sys.exc_traceback, | 
					
						
							|  |  |  | 						     name) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     elif ty == PY_PACKAGE: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	# Load package constituents, doing the controlling module *if* it | 
					
						
							|  |  |  | 	# exists *and* it isn't already in process: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init_mod_f = init_mod = None | 
					
						
							|  |  |  | 	if not stack.in_process(name + '.' + INIT_MOD_NM): | 
					
						
							|  |  |  | 	    # Not already doing __init__ - check for it: | 
					
						
							|  |  |  | 	    init_mod_f = find_mod_file(thePath, INIT_MOD_NM) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    note('skipping already-in-process %s.%s' % (theMod.__name__, | 
					
						
							|  |  |  | 							INIT_MOD_NM)) | 
					
						
							|  |  |  | 	got = {} | 
					
						
							|  |  |  | 	if init_mod_f: | 
					
						
							|  |  |  | 	    note("Found package's __init__: " + init_mod_f[2]) | 
					
						
							|  |  |  | 	    # Enable full continuance of containing-package-load from __init__: | 
					
						
							|  |  |  | 	    if stack.in_process(theMod.__name__): | 
					
						
							|  |  |  | 		stack.relax(theMod.__name__) | 
					
						
							|  |  |  | 	    init_mod = import_module(INIT_MOD_NM, | 
					
						
							|  |  |  | 				     theMod.__dict__, theMod.__dict__, | 
					
						
							|  |  |  | 				     None, | 
					
						
							|  |  |  | 				     theMod) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    # ... or else recursively load all constituent modules, except | 
					
						
							|  |  |  | 	    # __init__: | 
					
						
							|  |  |  | 	    for prospect in mod_prospects(thePath): | 
					
						
							|  |  |  | 		if prospect != INIT_MOD_NM: | 
					
						
							|  |  |  | 		    import_module(prospect, | 
					
						
							|  |  |  | 				  theMod.__dict__, theMod.__dict__, | 
					
						
							|  |  |  | 				  None, | 
					
						
							|  |  |  | 				  theMod) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	raise ImportError, 'Unimplemented import type: %s' % ty		# ==X | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     return theMod | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | def exec_into(obj, module, path): | 
					
						
							|  |  |  |     """Helper for load_module, execfile/exec path or code OBJ within MODULE.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # This depends on ability of exec and execfile to mutilate, erhm, mutate | 
					
						
							|  |  |  |     # the __dict__ of a module.  It will not work if/when this becomes | 
					
						
							|  |  |  |     # disallowed, as it is for normal assignments. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  | 	if type(obj) == types.FileType: | 
					
						
							|  |  |  | 	    execfile(path, module.__dict__, module.__dict__) | 
					
						
							|  |  |  | 	elif type(obj) in [types.CodeType, types.StringType]: | 
					
						
							|  |  |  | 	    exec obj in module.__dict__, module.__dict__ | 
					
						
							|  |  |  |     except: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    # Make the error message nicer? | 
					
						
							|  |  |  | 	    raise sys.exc_type, import_trail_msg(str(sys.exc_value),	# ==X | 
					
						
							|  |  |  | 						 sys.exc_traceback, | 
					
						
							|  |  |  | 						 module.__name__) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def mod_prospects(path): | 
					
						
							|  |  |  |     """Return a list of prospective modules within directory PATH.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     We actually return the distinct names resulting from stripping the dir | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     entries (excluding os.curdir and os.pardir) of their suffixes (as | 
					
						
							|  |  |  |     represented by 'get_suffixes'). | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     (Note that matches for the PY_PACKAGE type with null suffix are | 
					
						
							|  |  |  |     implicitly constrained to be directories.)"""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # We actually strip the longest matching suffixes, so eg 'dbmmodule.so' | 
					
						
							|  |  |  |     # mates with 'module.so' rather than '.so'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dirList = os.listdir(path) | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     excludes = [os.curdir, os.pardir] | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     sortedSuffs = sorted_suffixes() | 
					
						
							|  |  |  |     entries = [] | 
					
						
							|  |  |  |     for item in dirList: | 
					
						
							|  |  |  | 	if item in excludes: continue					# ==^ | 
					
						
							|  |  |  | 	for suff in sortedSuffs: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    # *** ?? maybe platform-specific: | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    sub = -1 * len(suff) | 
					
						
							|  |  |  | 	    if sub == 0: | 
					
						
							|  |  |  | 		if os.path.isdir(os.path.join(path, item)): | 
					
						
							|  |  |  | 		    entries.append(item) | 
					
						
							|  |  |  | 	    elif item[sub:] == suff: | 
					
						
							|  |  |  | 		it = item[:sub] | 
					
						
							|  |  |  | 		if not it in entries: | 
					
						
							|  |  |  | 		    entries.append(it) | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		break							# ==v | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     return entries | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def procure_module(name): | 
					
						
							|  |  |  |     """Return an established or else new module object having NAME.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     First checks sys.modules, then sys.stub_modules."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if sys.modules.has_key(name): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	return sys.modules[name]					# ==> | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     elif sys.stub_modules.has_key(name): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	return sys.stub_modules[name]					# ==> | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	return (stack.mod(name) or imp.new_module(name))		# ==> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def commit_mod_containment(name): | 
					
						
							|  |  |  |     """Bind a module object and its containers within their respective
 | 
					
						
							|  |  |  |     containers."""
 | 
					
						
							|  |  |  |     cume, pkg = '', find_mod_registration(ROOT_MOD_NM) | 
					
						
							|  |  |  |     for next in string.splitfields(name, '.'): | 
					
						
							|  |  |  | 	if cume: | 
					
						
							|  |  |  | 	    cume = cume + '.' + next | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    cume = next | 
					
						
							|  |  |  | 	cumeMod = find_mod_registration(cume) | 
					
						
							|  |  |  | 	pkg.__dict__[next] = cumeMod | 
					
						
							|  |  |  | 	pkg = cumeMod | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def register_mod_nesting(modList, pkg): | 
					
						
							|  |  |  |     """Given find_module()-style NEST-LIST and parent PACKAGE, register new
 | 
					
						
							|  |  |  |     package components as stub modules, and return list of nested | 
					
						
							|  |  |  |     module/relative-name pairs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Note that the modules objects are not situated in their containing packages | 
					
						
							|  |  |  |     here - that is left 'til after a successful load, and done by | 
					
						
							|  |  |  |     commit_mod_nesting()."""
 | 
					
						
							|  |  |  |     nesting = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for modNm, modF, path, ty in modList: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	relNm = modNm[1 + string.rfind(modNm, '.'):] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if sys.modules.has_key(modNm): | 
					
						
							|  |  |  | 	    theMod = sys.modules[modNm]	# Nestle in containing package | 
					
						
							|  |  |  | 	    pkg = theMod		# Set as parent for next in sequence. | 
					
						
							|  |  |  | 	elif sys.stub_modules.has_key(modNm): | 
					
						
							|  |  |  | 	    # Similar to above... | 
					
						
							|  |  |  | 	    theMod = sys.stub_modules[modNm] | 
					
						
							|  |  |  | 	    pkg = theMod | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    theMod = procure_module(modNm) | 
					
						
							|  |  |  | 	    stack.mod(modNm, theMod) | 
					
						
							|  |  |  | 	    # *** ??? Should we be using 'path' instead of modF.name?  If not, | 
					
						
							|  |  |  | 	    # should we get rid of the 'path' return val? | 
					
						
							|  |  |  | 	    set_mod_attrs(theMod, normalize_pathname(modF.name), | 
					
						
							|  |  |  | 			  pkg, None, ty[2]) | 
					
						
							|  |  |  | 	    if ty[2] == PY_PACKAGE: | 
					
						
							|  |  |  | 		# Register as a stub: | 
					
						
							|  |  |  | 		register_module(theMod, modNm, 1) | 
					
						
							|  |  |  | 	    pkg = theMod | 
					
						
							|  |  |  | 	nesting.append((theMod.__name__,relNm)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return nesting | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def register_module(theMod, name, stub=0): | 
					
						
							|  |  |  |     """Properly register MODULE, NAME, and optional STUB qualification.""" | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |      | 
					
						
							|  |  |  |     if stub: | 
					
						
							|  |  |  | 	sys.stub_modules[name] = theMod | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	sys.modules[name] = theMod | 
					
						
							|  |  |  | 	if sys.stub_modules.has_key(name): | 
					
						
							|  |  |  | 	    del sys.stub_modules[name] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | def find_mod_registration(name): | 
					
						
							|  |  |  |     """Find module named NAME sys.modules, .stub_modules, or on the stack.""" | 
					
						
							|  |  |  |     if sys.stub_modules.has_key(name): | 
					
						
							|  |  |  | 	return sys.stub_modules[name]					# ==> | 
					
						
							|  |  |  |     elif sys.modules.has_key(name): | 
					
						
							|  |  |  | 	return sys.modules[name]					# ==> | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	if stack.in_process(name): | 
					
						
							|  |  |  | 	    it = stack.mod(name) | 
					
						
							|  |  |  | 	    if it: | 
					
						
							|  |  |  | 		return it						# ==> | 
					
						
							|  |  |  | 	    else: | 
					
						
							|  |  |  | 		raise ValueError, '%s %s in %s or %s' % (name,		# ==X | 
					
						
							|  |  |  | 							 'not registered', | 
					
						
							|  |  |  | 							 'sys.modules', | 
					
						
							|  |  |  | 							 'sys.stub_modules') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_mod_attrs(theMod, which = None): | 
					
						
							|  |  |  |     """Get MODULE object's path, containing-package, and designated path.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Virtual attribute USE_PATH is derived from PKG_PATH, MOD_PATHNAME, | 
					
						
							|  |  |  |     and/or sys.path, depending on the module type and settings."""
 | 
					
						
							|  |  |  |     it = theMod.__dict__[IMP_ADMIN] | 
					
						
							|  |  |  |     if which: | 
					
						
							|  |  |  | 	# Load path is either the explicitly designated load path for the | 
					
						
							|  |  |  | 	# package, or else the directory in which it resides: | 
					
						
							|  |  |  | 	if which == USE_PATH: | 
					
						
							|  |  |  | 	    if it[PKG_PATH]: | 
					
						
							|  |  |  | 		# Return explicitly designated path: | 
					
						
							|  |  |  | 		return it[PKG_PATH]					# ==> | 
					
						
							|  |  |  | 	    if it[MOD_PATHNAME]:  | 
					
						
							|  |  |  | 		if it[MOD_TYPE] == PY_PACKAGE: | 
					
						
							|  |  |  | 		    # Return the package's directory path: | 
					
						
							|  |  |  | 		    return [it[MOD_PATHNAME]]				# ==> | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 		    # Return the directory where the module resides: | 
					
						
							|  |  |  | 		    return [os.path.split(it[MOD_PATHNAME])[0]]		# ==> | 
					
						
							|  |  |  | 	    # No explicitly designated path - use sys.path, eg for system | 
					
						
							|  |  |  | 	    # modules, etc: | 
					
						
							|  |  |  | 	    return sys.path | 
					
						
							|  |  |  | 	return it[which]						# ==> | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	return it							# ==> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_mod_attrs(theMod, path, pkg, pkgPath, ty): | 
					
						
							|  |  |  |     """Register MOD import attrs PATH, PKG container, and PKGPATH, linking
 | 
					
						
							|  |  |  |     the package container into the module along the way."""
 | 
					
						
							|  |  |  |     theDict = theMod.__dict__ | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  | 	# Get existing one, if any: | 
					
						
							|  |  |  | 	it = theDict[IMP_ADMIN] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  | 	# None existing, gen a new one: | 
					
						
							|  |  |  | 	it = [None] * 4 | 
					
						
							|  |  |  |     for fld, val in ((MOD_PATHNAME, path), (MOD_PACKAGE, pkg), | 
					
						
							|  |  |  | 		     (PKG_PATH, pkgPath), (MOD_TYPE, ty)): | 
					
						
							|  |  |  | 	if val: | 
					
						
							|  |  |  | 	    it[fld] = val | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     theDict[IMP_ADMIN] = it | 
					
						
							|  |  |  |     if pkg: | 
					
						
							|  |  |  | 	theDict[PKG_NM] = theDict[PKG_SHORT_NM] = pkg | 
					
						
							|  |  |  |     return it								# ==> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def format_tb_msg(tb, recursive): | 
					
						
							|  |  |  |     """This should be in traceback.py, and traceback.print_tb() should use it
 | 
					
						
							|  |  |  |     and traceback.extract_tb(), instead of print_tb() and extract_tb() having | 
					
						
							|  |  |  |     so much redundant code!"""
 | 
					
						
							|  |  |  |     tb_lines, formed = traceback.extract_tb(tb), '' | 
					
						
							|  |  |  |     for line in tb_lines: | 
					
						
							|  |  |  | 	f, lno, nm, ln = line | 
					
						
							|  |  |  | 	if f[-1 * (len(__name__) + 3):] == __name__ + '.py': | 
					
						
							|  |  |  | 	    # Skip newimp notices - agregious hack, justified only by the fact | 
					
						
							|  |  |  | 	    # that this functionality will be properly doable in new impending | 
					
						
							|  |  |  | 	    # exception mechanism: | 
					
						
							|  |  |  | 	    continue | 
					
						
							|  |  |  | 	formed = formed + ('\n%s File "%s", line %d, in %s%s' % | 
					
						
							|  |  |  | 			   (((recursive and '*') or ' '), | 
					
						
							|  |  |  | 			    f, lno, nm, | 
					
						
							|  |  |  | 			    ((ln and '\n    ' + string.strip(ln)) or ''))) | 
					
						
							|  |  |  |     return formed | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def import_trail_msg(msg, tb, modNm): | 
					
						
							|  |  |  |     """Doctor an error message to include the path of the current import, and
 | 
					
						
							|  |  |  |     a sign that it is a circular import, if so."""
 | 
					
						
							|  |  |  |     return (msg + | 
					
						
							|  |  |  | 	    format_tb_msg(tb, | 
					
						
							|  |  |  | 			  (stack.looped(modNm) and stack.in_process(modNm)))) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def compile_source(sourcePath, sourceFile): | 
					
						
							|  |  |  |     """Given python code source path and file obj, Create a compiled version.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Return path of compiled version, or None if file creation is not | 
					
						
							|  |  |  |     successful.  (Compilation errors themselves are passed without restraint.) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This is an import-private interface, and not well-behaved for general use. | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     In particular, we presume the validity of the sourcePath, and that it | 
					
						
							|  |  |  |     includes a '.py' extension."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     compiledPath = sourcePath[:-3] + '.pyc' | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  | 	compiledFile = open(compiledPath, 'wb') | 
					
						
							|  |  |  |     except IOError: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	note("write permission denied to " + compiledPath, 3) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	return None | 
					
						
							|  |  |  |     mtime = os.stat(sourcePath)[8] | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-06-22 18:50:15 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  | 	compiled = compile(sourceFile.read(), sourcePath, 'exec') | 
					
						
							|  |  |  |     except SyntaxError: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    # Doctor the exception a bit, to include the source file name in | 
					
						
							|  |  |  | 	    # the report, and then reraise the doctored version. | 
					
						
							|  |  |  | 	    os.unlink(compiledFile.name) | 
					
						
							|  |  |  | 	    sys.exc_value = ((sys.exc_value[0] + ' in ' + sourceFile.name,) | 
					
						
							|  |  |  | 			     + sys.exc_value[1:]) | 
					
						
							|  |  |  | 	    raise sys.exc_type, sys.exc_value				# ==X | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Ok, we have a valid compilation. | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  | 	compiledFile.write(imp.get_magic())		# compiled magic number | 
					
						
							|  |  |  | 	compiledFile.seek(8, 0)				# mtime space holder | 
					
						
							|  |  |  | 	marshal.dump(compiled, compiledFile)		# write the code obj | 
					
						
							|  |  |  | 	compiledFile.seek(4, 0)				# position for mtime | 
					
						
							|  |  |  | 	compiledFile.write(marshal.dumps(mtime)[1:])	# register mtime | 
					
						
							|  |  |  | 	compiledFile.flush() | 
					
						
							|  |  |  | 	compiledFile.close() | 
					
						
							|  |  |  | 	return compiledPath | 
					
						
							|  |  |  |     except IOError: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	return None							# ==> | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | got_suffixes = None | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | got_suffixes_dict = {} | 
					
						
							|  |  |  | def get_suffixes(ty=None): | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     """Produce a list of triples, each describing a type of import file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Triples have the form '(SUFFIX, MODE, TYPE)', where: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SUFFIX is a string found appended to a module name to make a filename for | 
					
						
							|  |  |  |     that type of import file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     MODE is the mode string to be passed to the built-in 'open' function - "r" | 
					
						
							|  |  |  |     for text files, "rb" for binary. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     TYPE is the file type: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      PY_SOURCE:		python source code, | 
					
						
							|  |  |  |      PY_COMPILED:	byte-compiled python source, | 
					
						
							|  |  |  |      C_EXTENSION:	compiled-code object file, | 
					
						
							|  |  |  |      PY_PACKAGE:	python library directory, or | 
					
						
							|  |  |  |      SEARCH_ERROR:	no module found. """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Note: sorted_suffixes() depends on this function's value being invariant. | 
					
						
							|  |  |  |     # sorted_suffixes() must be revised if this becomes untrue. | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     global got_suffixes, got_suffixes_dict | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     if not got_suffixes: | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	# Ensure that the .pyc suffix precedes the .py: | 
					
						
							|  |  |  | 	got_suffixes = [('', 'r', PY_PACKAGE)] | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	got_suffixes_dict[PY_PACKAGE] = ('', 'r', PY_PACKAGE) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	py = pyc = None | 
					
						
							|  |  |  | 	for suff in imp.get_suffixes(): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    got_suffixes_dict[suff[2]] = suff | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    if suff[0] == '.py': | 
					
						
							|  |  |  | 		py = suff | 
					
						
							|  |  |  | 	    elif suff[0] == '.pyc': | 
					
						
							|  |  |  | 		pyc = suff | 
					
						
							|  |  |  | 	    else: | 
					
						
							|  |  |  | 		got_suffixes.append(suff) | 
					
						
							|  |  |  | 	got_suffixes.append(pyc) | 
					
						
							|  |  |  | 	got_suffixes.append(py) | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     if ty: | 
					
						
							|  |  |  | 	return got_suffixes_dict[ty]					# ==> | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	return got_suffixes						# ==> | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sortedSuffs = []			# State vars for sorted_suffixes().  Go | 
					
						
							|  |  |  | def sorted_suffixes(): | 
					
						
							|  |  |  |     """Helper function ~efficiently~ tracks sorted list of module suffixes.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Produce sortedSuffs once - this presumes that get_suffixes does not | 
					
						
							|  |  |  |     # change from call to call during a python session.  Needs to be | 
					
						
							|  |  |  |     # corrected if that becomes no longer true. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     global sortedsuffs | 
					
						
							|  |  |  |     if not sortedSuffs:			# do compute only the "first" time | 
					
						
							|  |  |  | 	for item in get_suffixes(): | 
					
						
							|  |  |  | 	    sortedSuffs.append(item[0]) | 
					
						
							|  |  |  | 	# Sort them in descending order: | 
					
						
							|  |  |  | 	sortedSuffs.sort(lambda x, y: (((len(x) > len(y)) and 1) or | 
					
						
							|  |  |  | 				       ((len(x) < len(y)) and -1))) | 
					
						
							|  |  |  | 	sortedSuffs.reverse() | 
					
						
							|  |  |  |     return sortedSuffs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | def normalize_pathname(path): | 
					
						
							|  |  |  |     """Given PATHNAME, return an absolute pathname relative to cwd, reducing
 | 
					
						
							|  |  |  |     unnecessary components where convenient (eg, on Unix)."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # We do a lot more when we have posix-style paths, eg os.sep == '/'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if os.sep != '/': | 
					
						
							| 
									
										
										
										
											1995-07-12 15:34:34 +00:00
										 |  |  | 	return os.path.join(os.getcwd, path)				# ==> | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     outwards, inwards = 0, [] | 
					
						
							|  |  |  |     for nm in string.splitfields(path, os.sep): | 
					
						
							|  |  |  | 	if nm != os.curdir: | 
					
						
							|  |  |  | 	    if nm == os.pardir: | 
					
						
							|  |  |  | 		# Translate parent-dir entries to outward notches: | 
					
						
							|  |  |  | 		if inwards: | 
					
						
							|  |  |  | 		    # Pop a containing inwards: | 
					
						
							|  |  |  | 		    del inwards[-1] | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 		    # Register leading outward notches: | 
					
						
							|  |  |  | 		    outwards = outwards + 1 | 
					
						
							|  |  |  | 	    else: | 
					
						
							|  |  |  | 		inwards.append(nm) | 
					
						
							|  |  |  |     inwards = string.joinfields(inwards, os.sep) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (not inwards) or (inwards[0] != os.sep): | 
					
						
							|  |  |  | 	# Relative path - join with current working directory, (ascending | 
					
						
							|  |  |  | 	# outwards to account for leading parent-dir components): | 
					
						
							|  |  |  | 	cwd = os.getcwd() | 
					
						
							|  |  |  | 	if outwards: | 
					
						
							|  |  |  | 	    cwd = string.splitfields(cwd, os.sep) | 
					
						
							|  |  |  | 	    cwd = string.joinfields(cwd[:len(cwd) - outwards], os.sep) | 
					
						
							|  |  |  | 	if inwards: | 
					
						
							|  |  |  | 	    return os.path.join(cwd, inwards)				# ==> | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    return cwd							# ==> | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	return inwards							# ==> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | # exterior(): Utility routine, obtain local and global dicts of environment | 
					
						
							|  |  |  | #	      containing/outside the callers environment, ie that of the | 
					
						
							|  |  |  | #	      caller's caller.  Routines can use exterior() to determine the | 
					
						
							|  |  |  | #	      environment from which they were called.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def exterior(): | 
					
						
							|  |  |  |     """Return dyad containing locals and globals of caller's caller.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Locals will be None if same as globals, ie env is global env."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bogus = 'bogus'			# A locally usable exception | 
					
						
							|  |  |  |     try: raise bogus			# Force an exception object | 
					
						
							|  |  |  |     except bogus: | 
					
						
							|  |  |  | 	at = sys.exc_traceback.tb_frame.f_back		# The external frame. | 
					
						
							|  |  |  | 	if at.f_back: at = at.f_back			# And further, if any. | 
					
						
							|  |  |  | 	globals, locals = at.f_globals, at.f_locals | 
					
						
							|  |  |  | 	if locals == globals:				# Exterior is global? | 
					
						
							|  |  |  | 	    locals = None | 
					
						
							|  |  |  | 	return (locals, globals) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ######################################################################### | 
					
						
							|  |  |  | #			      TESTING FACILITIES			# | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | def note(msg, threshold=2): | 
					
						
							| 
									
										
										
										
											1995-04-07 09:06:50 +00:00
										 |  |  |     if VERBOSE >= threshold: sys.stderr.write('(import: ' + msg + ')\n') | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TestDirHier: | 
					
						
							|  |  |  |     """Populate a transient directory hierarchy according to a definition
 | 
					
						
							|  |  |  |     template - so we can create package/module hierarchies with which to | 
					
						
							|  |  |  |     exercise the new import facilities..."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, template, where='/var/tmp'): | 
					
						
							|  |  |  | 	"""Establish a dir hierarchy, according to TEMPLATE, that will be
 | 
					
						
							|  |  |  | 	deleted upon deletion of this object (or deliberate invocation of the | 
					
						
							|  |  |  | 	__del__ method)."""
 | 
					
						
							|  |  |  | 	self.PKG_NM = 'tdh_' | 
					
						
							|  |  |  | 	rev = 0 | 
					
						
							|  |  |  | 	while os.path.exists(os.path.join(where, self.PKG_NM+str(rev))): | 
					
						
							|  |  |  | 	    rev = rev + 1 | 
					
						
							|  |  |  | 	sys.exc_traceback = None	# Ensure Discard of try/except obj ref | 
					
						
							|  |  |  | 	self.PKG_NM = self.PKG_NM + str(rev) | 
					
						
							|  |  |  | 	self.root = os.path.join(where, self.PKG_NM) | 
					
						
							|  |  |  | 	self.createDir(self.root) | 
					
						
							|  |  |  | 	self.add(template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __del__(self): | 
					
						
							|  |  |  | 	"""Cleanup the test hierarchy.""" | 
					
						
							|  |  |  | 	self.remove() | 
					
						
							|  |  |  |     def add(self, template, root=None): | 
					
						
							|  |  |  | 	"""Populate directory according to template dictionary.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Keys indicate file names, possibly directories themselves. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String values dictate contents of flat files. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Dictionary values dictate recursively embedded dictionary templates."""
 | 
					
						
							|  |  |  | 	if root == None: root = self.root | 
					
						
							|  |  |  | 	for key, val in template.items(): | 
					
						
							|  |  |  | 	    name = os.path.join(root, key) | 
					
						
							|  |  |  | 	    if type(val) == types.StringType:	# flat file | 
					
						
							|  |  |  | 		self.createFile(name, val) | 
					
						
							|  |  |  | 	    elif type(val) == types.DictionaryType:	# embedded dir | 
					
						
							|  |  |  | 		self.createDir(name) | 
					
						
							|  |  |  | 		self.add(val, name) | 
					
						
							|  |  |  | 	    else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		raise ValueError, ('invalid file-value type, %s' %	# ==X | 
					
						
							|  |  |  | 				   type(val)) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     def remove(self, name=''): | 
					
						
							|  |  |  | 	"""Dispose of the NAME (or keys in dictionary), using 'rm -r'.""" | 
					
						
							|  |  |  | 	name = os.path.join(self.root, name) | 
					
						
							|  |  |  | 	sys.exc_traceback = None	# Ensure Discard of try/except obj ref | 
					
						
							|  |  |  | 	if os.path.exists(name): | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    print '(TestDirHier: eradicating %s)' % name | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    os.system('rm -r ' + name) | 
					
						
							|  |  |  | 	else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    raise IOError, "can't remove non-existent " + name		# ==X | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     def createFile(self, name, contents=None): | 
					
						
							|  |  |  | 	"""Establish file NAME with CONTENTS.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	If no contents specfied, contents will be 'print NAME'."""
 | 
					
						
							|  |  |  | 	f = open(name, 'w') | 
					
						
							|  |  |  | 	if not contents: | 
					
						
							|  |  |  | 	    f.write("print '" + name + "'\n") | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    f.write(contents) | 
					
						
							|  |  |  | 	f.close | 
					
						
							|  |  |  |     def createDir(self, name): | 
					
						
							|  |  |  | 	"""Create dir with NAME.""" | 
					
						
							|  |  |  | 	return os.mkdir(name, 0755) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | skipToTest = 0 | 
					
						
							|  |  |  | atTest = 1 | 
					
						
							|  |  |  | def testExec(msg, execList, locals, globals): | 
					
						
							|  |  |  |     global skipToTest, atTest | 
					
						
							|  |  |  |     print 'Import Test:', '(' + str(atTest) + ')', msg, '...' | 
					
						
							|  |  |  |     atTest = atTest + 1 | 
					
						
							|  |  |  |     if skipToTest > (atTest - 1): | 
					
						
							|  |  |  | 	print ' ... skipping til test', skipToTest | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  | 	print '' | 
					
						
							|  |  |  |     for stmt in execList: | 
					
						
							|  |  |  | 	exec stmt in locals, globals | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | def test(number=0, leaveHiers=0): | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  |     """Exercise import functionality, creating a transient dir hierarchy for
 | 
					
						
							|  |  |  |     the purpose. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     We actually install the new import functionality, temporarily, resuming the | 
					
						
							|  |  |  |     existing function on cleanup."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     import __builtin__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     global skipToTest, atTest | 
					
						
							|  |  |  |     skipToTest = number | 
					
						
							|  |  |  |     hier = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def unloadFull(mod): | 
					
						
							|  |  |  | 	"""Unload module and offspring submodules, if any.""" | 
					
						
							|  |  |  | 	modMod = '' | 
					
						
							|  |  |  | 	if type(mod) == types.StringType: | 
					
						
							|  |  |  | 	    modNm = mod | 
					
						
							|  |  |  | 	elif type(mod) == types.ModuleType: | 
					
						
							|  |  |  | 	    modNm = modMod.__name__ | 
					
						
							|  |  |  | 	for subj in sys.modules.keys() + sys.stub_modules.keys(): | 
					
						
							|  |  |  | 	    if subj[0:len(modNm)] == modNm: | 
					
						
							|  |  |  | 		unload(subj) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  | 	__main__.testMods | 
					
						
							|  |  |  |     except AttributeError: | 
					
						
							|  |  |  | 	__main__.testMods = [] | 
					
						
							|  |  |  |     testMods = __main__.testMods | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Install the newimp routines, within a try/finally: | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  | 	sys.exc_traceback = None | 
					
						
							|  |  |  | 	wasImport = __builtin__.__import__	# Stash default | 
					
						
							|  |  |  | 	wasPath = sys.path | 
					
						
							|  |  |  |     except AttributeError: | 
					
						
							|  |  |  | 	wasImport = None | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  | 	hiers = []; modules = [] | 
					
						
							|  |  |  | 	global VERBOSE | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	wasVerbose, VERBOSE = VERBOSE, 1 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	__builtin__.__import__ = import_module	# Install new version | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if testMods:		# Clear out imports from previous tests | 
					
						
							|  |  |  | 	    for m in testMods[:]: | 
					
						
							|  |  |  | 		unloadFull(m) | 
					
						
							|  |  |  | 		testMods.remove(m) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	# ------ | 
					
						
							|  |  |  | 	# Test 1 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	testExec("already imported module: %s" % sys.modules.keys()[0], | 
					
						
							|  |  |  | 		 ['import ' + sys.modules.keys()[0]], | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 vars(), newimp_globals) | 
					
						
							|  |  |  | 	no_sirree = 'no_sirree_does_not_exist' | 
					
						
							|  |  |  | 	# ------ | 
					
						
							|  |  |  | 	# Test 2 | 
					
						
							|  |  |  | 	testExec("non-existent module: %s" % no_sirree, | 
					
						
							|  |  |  | 		 ['try: import ' + no_sirree + | 
					
						
							|  |  |  | 		  '\nexcept ImportError: pass'], | 
					
						
							|  |  |  | 		  vars(), newimp_globals) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	got = None | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	# ------ | 
					
						
							|  |  |  | 	# Test 3 | 
					
						
							|  |  |  | 	# Find a module that's not yet loaded, from a list of prospects: | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	for mod in ['Complex', 'UserDict', 'UserList', 'calendar', | 
					
						
							|  |  |  | 		    'cmd', 'dis', 'mailbox', 'profile', 'random', 'rfc822']: | 
					
						
							|  |  |  | 	    if not (mod in sys.modules.keys()): | 
					
						
							|  |  |  | 		got = mod | 
					
						
							|  |  |  | 		break							# ==v | 
					
						
							|  |  |  | 	if got: | 
					
						
							|  |  |  | 	    testExec("not-yet loaded module: %s" % mod, | 
					
						
							|  |  |  | 		     ['import ' + mod, 'modules.append(got)'], | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		     vars(), newimp_globals) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	else: | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	    testExec("not-yet loaded module: list exhausted, never mind", | 
					
						
							|  |  |  | 		     [], vars(), newimp_globals) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	# Now some package stuff. | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	# ------ | 
					
						
							|  |  |  | 	# Test 4 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	# First change the path to include our temp dir, copying so the | 
					
						
							|  |  |  | 	# addition can be revoked on cleanup in the finally, below: | 
					
						
							|  |  |  | 	sys.path = ['/var/tmp'] + sys.path[:] | 
					
						
							|  |  |  | 	# Now create a trivial package: | 
					
						
							|  |  |  | 	stmts = ["hier1 = TestDirHier({'a.py': 'print \"a.py executing\"'})", | 
					
						
							|  |  |  | 		 "hiers.append(hier1)", | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 "base = hier1.PKG_NM", | 
					
						
							|  |  |  | 		 "exec 'import ' + base", | 
					
						
							|  |  |  | 		 "testMods.append(base)"] | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	testExec("trivial package, with one module, a.py", | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 stmts, vars(), newimp_globals) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# ------ | 
					
						
							|  |  |  | 	# Test 5 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	# Slightly less trivial package - reference to '__': | 
					
						
							|  |  |  | 	stmts = [("hier2 = TestDirHier({'ref.py': 'print \"Pkg __:\", __'})"), | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 "base = hier2.PKG_NM", | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 		 "hiers.append(hier2)", | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 "exec 'import ' + base", | 
					
						
							|  |  |  | 		 "testMods.append(base)"] | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	testExec("trivial package, with module that has pkg shorthand ref", | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 stmts, vars(), newimp_globals) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# ------ | 
					
						
							|  |  |  | 	# Test 6 | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	# Nested package, plus '__' references: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	complexTemplate = {'ref.py': 'print "ref.py loading..."', | 
					
						
							|  |  |  | 			    'suite': {'s1.py': 'print "s1.py, in pkg:", __', | 
					
						
							|  |  |  | 				      'subsuite': {'sub1.py': | 
					
						
							|  |  |  | 						   'print "sub1.py"'}}} | 
					
						
							|  |  |  | 	stmts = [('print """%s\n%s\n%s\n%s\n%s\n%s"""' % | 
					
						
							|  |  |  | 		  ('.../', | 
					
						
							|  |  |  | 		   '    ref.py\t\t\t"ref.py loading..."', | 
					
						
							|  |  |  | 		   '    suite/', | 
					
						
							|  |  |  | 		   '	    s1.py \t\t"s1.py, in pkg: xxxx.suite"', | 
					
						
							|  |  |  | 		   '	    subsuite/', | 
					
						
							|  |  |  | 		   '		sub1.py		"sub1.py" ')), | 
					
						
							|  |  |  | 		 "hier3 = TestDirHier(complexTemplate)", | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 "base = hier3.PKG_NM", | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 		 "hiers.append(hier3)", | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 "exec 'import ' + base", | 
					
						
							|  |  |  | 		 "testMods.append(base)"] | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	testExec("Significantly nestled package:", | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 		 stmts, vars(), newimp_globals) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# ------ | 
					
						
							|  |  |  | 	# Test 7 | 
					
						
							|  |  |  | 	# Try an elaborate hierarchy which includes an __init__ master in one | 
					
						
							|  |  |  | 	# one portion, a ref across packages within the hierarchies, and an | 
					
						
							|  |  |  | 	# indirect recursive import which cannot be satisfied (and hence, | 
					
						
							|  |  |  | 	# prevents load of part of the hierarchy). | 
					
						
							|  |  |  | 	complexTemplate = {'mid': | 
					
						
							|  |  |  | 			   {'prime': | 
					
						
							|  |  |  | 			    {'__init__.py': 'import __.easy, __.nother', | 
					
						
							|  |  |  | 			     'easy.py': 'print "easy.py:", __name__', | 
					
						
							|  |  |  | 			     'nother.py': ('%s\n%s\n%s\n' % | 
					
						
							|  |  |  | 					   ('import __.easy', | 
					
						
							|  |  |  | 					    'print "nother got __.easy"', | 
					
						
							|  |  |  | 					    # __.__.awry should be found but | 
					
						
							|  |  |  | 					    # should not load successfully, | 
					
						
							|  |  |  | 					    # disrupting nother, but not easy | 
					
						
							|  |  |  | 					    'import __.__.awry'))}, | 
					
						
							|  |  |  | 			    # continuing dict 'mid': | 
					
						
							|  |  |  | 			    'awry': | 
					
						
							|  |  |  | 			    {'__init__.py': | 
					
						
							|  |  |  | 			     ('%s\n%s' % | 
					
						
							|  |  |  | 			      ('print "got " + __name__', | 
					
						
							|  |  |  | 			       'from __ import *')), | 
					
						
							|  |  |  | 			     # This mutual recursion (b->a, a->d->b) should be | 
					
						
							|  |  |  | 			     # ok, since a.py sets ax before recursing. | 
					
						
							|  |  |  | 			     'a.py':	'ax = 1; from __.b import bx', | 
					
						
							|  |  |  | 			     'b.py':	'bx = 1; from __.a import ax'}}} | 
					
						
							|  |  |  | 	stmts = ["hier5 = TestDirHier(complexTemplate)", | 
					
						
							|  |  |  | 		 "base = hier5.PKG_NM", | 
					
						
							|  |  |  | 		 "testMods.append(base)", | 
					
						
							|  |  |  | 		 "hiers.append(hier5)", | 
					
						
							|  |  |  | 		 "exec 'import %s.mid.prime' % base", | 
					
						
							|  |  |  | 		 "print eval(base)",		# Verify the base was bound | 
					
						
							|  |  |  | 		 "testMods.append(base)"] | 
					
						
							|  |  |  | 	testExec("Elaborate, clean hierarchy", | 
					
						
							|  |  |  | 		 stmts, vars(), newimp_globals) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# ------ | 
					
						
							|  |  |  | 	# test 8 | 
					
						
							|  |  |  | 	# Here we disrupt the mutual recursion in the mid.awry package, so the | 
					
						
							|  |  |  | 	# import should now fail. | 
					
						
							|  |  |  | 	complexTemplate['mid']['awry']['a.py'] = 'from __.b import bx; ax = 1' | 
					
						
							|  |  |  | 	complexTemplate['mid']['awry']['b.py'] = 'from __.a import ax; bx = 1' | 
					
						
							|  |  |  | 	stmts = ["hier6 = TestDirHier(complexTemplate)", | 
					
						
							|  |  |  | 		 "base = hier6.PKG_NM", | 
					
						
							|  |  |  | 		 "testMods.append(base)", | 
					
						
							|  |  |  | 		 "hiers.append(hier6)", | 
					
						
							|  |  |  | 		 "work = ('import %s.mid.prime' % base)", | 
					
						
							|  |  |  | 		 ("try: exec work" + | 
					
						
							|  |  |  | 		  "\nexcept ImportError: print ' -- import failed, as ought'" + | 
					
						
							|  |  |  | 		  "\nelse: raise SystemError, sys.exc_value"), | 
					
						
							|  |  |  | 		 "testMods.append(base)"] | 
					
						
							|  |  |  | 	testExec("Elaborate hier w/ deliberately flawed import recursion", | 
					
						
							|  |  |  | 		 stmts, vars(), newimp_globals) | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sys.exc_traceback = None	# Signify clean conclusion. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  | 	skipToTest = 0 | 
					
						
							|  |  |  | 	atTest = 1 | 
					
						
							|  |  |  | 	sys.path = wasPath | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	VERBOSE = wasVerbose | 
					
						
							|  |  |  | 	if wasImport:			# Resurrect prior routine | 
					
						
							| 
									
										
										
										
											1995-04-07 09:03:10 +00:00
										 |  |  | 	    __builtin__.__import__ = wasImport | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    del __builtin__.__import__ | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  | 	if leaveHiers: | 
					
						
							|  |  |  | 	    print 'Cleanup inhibited' | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    if sys.exc_traceback: | 
					
						
							|  |  |  | 		print ' ** Import test FAILURE... cleanup.' | 
					
						
							|  |  |  | 	    else: | 
					
						
							|  |  |  | 		print ' Import test SUCCESS... cleanup' | 
					
						
							|  |  |  | 	    for h in hiers: h.remove(); del h	# Dispose of test directories | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | init() | 
					
						
							| 
									
										
										
										
											1995-04-07 09:04:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											1995-07-12 02:17:51 +00:00
										 |  |  |     test() |