1""" 2The UserModuleDeleter and runfile methods are copied from 3Spyder and carry their own license agreement. 4http://code.google.com/p/spyderlib/source/browse/spyderlib/widgets/externalshell/sitecustomize.py 5 6Spyder License Agreement (MIT License) 7-------------------------------------- 8 9Copyright (c) 2009-2012 Pierre Raybaut 10 11Permission is hereby granted, free of charge, to any person 12obtaining a copy of this software and associated documentation 13files (the "Software"), to deal in the Software without 14restriction, including without limitation the rights to use, 15copy, modify, merge, publish, distribute, sublicense, and/or sell 16copies of the Software, and to permit persons to whom the 17Software is furnished to do so, subject to the following 18conditions: 19 20The above copyright notice and this permission notice shall be 21included in all copies or substantial portions of the Software. 22 23THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 25OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 27HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 30OTHER DEALINGS IN THE SOFTWARE. 31""" 32 33import sys 34import os 35 36# The following classes and functions are mainly intended to be used from 37# an interactive Python session 38class UserModuleDeleter: 39 """ 40 User Module Deleter (UMD) aims at deleting user modules 41 to force Python to deeply reload them during import 42 43 pathlist [list]: ignore list in terms of module path 44 namelist [list]: ignore list in terms of module name 45 """ 46 def __init__(self, namelist=None, pathlist=None): 47 if namelist is None: 48 namelist = [] 49 self.namelist = namelist 50 if pathlist is None: 51 pathlist = [] 52 self.pathlist = pathlist 53 try: 54 # ignore all files in org.python.pydev/pysrc 55 import pydev_pysrc, inspect 56 self.pathlist.append(os.path.dirname(pydev_pysrc.__file__)) 57 except: 58 pass 59 self.previous_modules = list(sys.modules.keys()) 60 61 def is_module_ignored(self, modname, modpath): 62 for path in [sys.prefix] + self.pathlist: 63 if modpath.startswith(path): 64 return True 65 else: 66 return set(modname.split('.')) & set(self.namelist) 67 68 def run(self, verbose=False): 69 """ 70 Del user modules to force Python to deeply reload them 71 72 Do not del modules which are considered as system modules, i.e. 73 modules installed in subdirectories of Python interpreter's binary 74 Do not del C modules 75 """ 76 log = [] 77 modules_copy = dict(sys.modules) 78 for modname, module in modules_copy.items(): 79 if modname == 'aaaaa': 80 print(modname, module) 81 print(self.previous_modules) 82 if modname not in self.previous_modules: 83 modpath = getattr(module, '__file__', None) 84 if modpath is None: 85 # *module* is a C module that is statically linked into the 86 # interpreter. There is no way to know its path, so we 87 # choose to ignore it. 88 continue 89 if not self.is_module_ignored(modname, modpath): 90 log.append(modname) 91 del sys.modules[modname] 92 if verbose and log: 93 print("\x1b[4;33m%s\x1b[24m%s\x1b[0m" % ("UMD has deleted", 94 ": " + ", ".join(log))) 95 96__umd__ = None 97 98_get_globals_callback = None 99def _set_globals_function(get_globals): 100 global _get_globals_callback 101 _get_globals_callback = get_globals 102def _get_globals(): 103 """Return current Python interpreter globals namespace""" 104 if _get_globals_callback is not None: 105 return _get_globals_callback() 106 else: 107 try: 108 from __main__ import __dict__ as namespace 109 except ImportError: 110 try: 111 # The import fails on IronPython 112 import __main__ 113 namespace = __main__.__dict__ 114 except: 115 namespace 116 shell = namespace.get('__ipythonshell__') 117 if shell is not None and hasattr(shell, 'user_ns'): 118 # IPython 0.12+ kernel 119 return shell.user_ns 120 else: 121 # Python interpreter 122 return namespace 123 return namespace 124 125 126def runfile(filename, args=None, wdir=None, namespace=None): 127 """ 128 Run filename 129 args: command line arguments (string) 130 wdir: working directory 131 """ 132 try: 133 if hasattr(filename, 'decode'): 134 filename = filename.decode('utf-8') 135 except (UnicodeError, TypeError): 136 pass 137 global __umd__ 138 if os.environ.get("PYDEV_UMD_ENABLED", "").lower() == "true": 139 if __umd__ is None: 140 namelist = os.environ.get("PYDEV_UMD_NAMELIST", None) 141 if namelist is not None: 142 namelist = namelist.split(',') 143 __umd__ = UserModuleDeleter(namelist=namelist) 144 else: 145 verbose = os.environ.get("PYDEV_UMD_VERBOSE", "").lower() == "true" 146 __umd__.run(verbose=verbose) 147 if args is not None and not isinstance(args, basestring): 148 raise TypeError("expected a character buffer object") 149 if namespace is None: 150 namespace = _get_globals() 151 if '__file__' in namespace: 152 old_file = namespace['__file__'] 153 else: 154 old_file = None 155 namespace['__file__'] = filename 156 sys.argv = [filename] 157 if args is not None: 158 for arg in args.split(): 159 sys.argv.append(arg) 160 if wdir is not None: 161 try: 162 if hasattr(wdir, 'decode'): 163 wdir = wdir.decode('utf-8') 164 except (UnicodeError, TypeError): 165 pass 166 os.chdir(wdir) 167 execfile(filename, namespace) 168 sys.argv = [''] 169 if old_file is None: 170 del namespace['__file__'] 171 else: 172 namespace['__file__'] = old_file 173