summaryrefslogtreecommitdiff
path: root/python/helpers/pydev/pydev_umd.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/helpers/pydev/pydev_umd.py')
-rw-r--r--python/helpers/pydev/pydev_umd.py172
1 files changed, 172 insertions, 0 deletions
diff --git a/python/helpers/pydev/pydev_umd.py b/python/helpers/pydev/pydev_umd.py
new file mode 100644
index 000000000000..0bfeda74a1a6
--- /dev/null
+++ b/python/helpers/pydev/pydev_umd.py
@@ -0,0 +1,172 @@
+"""
+The UserModuleDeleter and runfile methods are copied from
+Spyder and carry their own license agreement.
+http://code.google.com/p/spyderlib/source/browse/spyderlib/widgets/externalshell/sitecustomize.py
+
+Spyder License Agreement (MIT License)
+--------------------------------------
+
+Copyright (c) 2009-2012 Pierre Raybaut
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+"""
+
+import sys
+import os
+
+# The following classes and functions are mainly intended to be used from
+# an interactive Python session
+class UserModuleDeleter:
+ """
+ User Module Deleter (UMD) aims at deleting user modules
+ to force Python to deeply reload them during import
+
+ pathlist [list]: blacklist in terms of module path
+ namelist [list]: blacklist in terms of module name
+ """
+ def __init__(self, namelist=None, pathlist=None):
+ if namelist is None:
+ namelist = []
+ self.namelist = namelist
+ if pathlist is None:
+ pathlist = []
+ self.pathlist = pathlist
+ try:
+ # blacklist all files in org.python.pydev/pysrc
+ import pydev_pysrc, inspect
+ self.pathlist.append(os.path.dirname(pydev_pysrc.__file__))
+ except:
+ pass
+ self.previous_modules = list(sys.modules.keys())
+
+ def is_module_blacklisted(self, modname, modpath):
+ for path in [sys.prefix] + self.pathlist:
+ if modpath.startswith(path):
+ return True
+ else:
+ return set(modname.split('.')) & set(self.namelist)
+
+ def run(self, verbose=False):
+ """
+ Del user modules to force Python to deeply reload them
+
+ Do not del modules which are considered as system modules, i.e.
+ modules installed in subdirectories of Python interpreter's binary
+ Do not del C modules
+ """
+ log = []
+ modules_copy = dict(sys.modules)
+ for modname, module in modules_copy.items():
+ if modname == 'aaaaa':
+ print(modname, module)
+ print(self.previous_modules)
+ if modname not in self.previous_modules:
+ modpath = getattr(module, '__file__', None)
+ if modpath is None:
+ # *module* is a C module that is statically linked into the
+ # interpreter. There is no way to know its path, so we
+ # choose to ignore it.
+ continue
+ if not self.is_module_blacklisted(modname, modpath):
+ log.append(modname)
+ del sys.modules[modname]
+ if verbose and log:
+ print("\x1b[4;33m%s\x1b[24m%s\x1b[0m" % ("UMD has deleted",
+ ": " + ", ".join(log)))
+
+__umd__ = None
+
+_get_globals_callback = None
+def _set_globals_function(get_globals):
+ global _get_globals_callback
+ _get_globals_callback = get_globals
+def _get_globals():
+ """Return current Python interpreter globals namespace"""
+ if _get_globals_callback is not None:
+ return _get_globals_callback()
+ else:
+ try:
+ from __main__ import __dict__ as namespace
+ except ImportError:
+ try:
+ # The import fails on IronPython
+ import __main__
+ namespace = __main__.__dict__
+ except:
+ namespace
+ shell = namespace.get('__ipythonshell__')
+ if shell is not None and hasattr(shell, 'user_ns'):
+ # IPython 0.12+ kernel
+ return shell.user_ns
+ else:
+ # Python interpreter
+ return namespace
+ return namespace
+
+
+def runfile(filename, args=None, wdir=None, namespace=None):
+ """
+ Run filename
+ args: command line arguments (string)
+ wdir: working directory
+ """
+ try:
+ if hasattr(filename, 'decode'):
+ filename = filename.decode('utf-8')
+ except (UnicodeError, TypeError):
+ pass
+ global __umd__
+ if os.environ.get("PYDEV_UMD_ENABLED", "").lower() == "true":
+ if __umd__ is None:
+ namelist = os.environ.get("PYDEV_UMD_NAMELIST", None)
+ if namelist is not None:
+ namelist = namelist.split(',')
+ __umd__ = UserModuleDeleter(namelist=namelist)
+ else:
+ verbose = os.environ.get("PYDEV_UMD_VERBOSE", "").lower() == "true"
+ __umd__.run(verbose=verbose)
+ if args is not None and not isinstance(args, basestring):
+ raise TypeError("expected a character buffer object")
+ if namespace is None:
+ namespace = _get_globals()
+ if '__file__' in namespace:
+ old_file = namespace['__file__']
+ else:
+ old_file = None
+ namespace['__file__'] = filename
+ sys.argv = [filename]
+ if args is not None:
+ for arg in args.split():
+ sys.argv.append(arg)
+ if wdir is not None:
+ try:
+ if hasattr(wdir, 'decode'):
+ wdir = wdir.decode('utf-8')
+ except (UnicodeError, TypeError):
+ pass
+ os.chdir(wdir)
+ execfile(filename, namespace)
+ sys.argv = ['']
+ if old_file is None:
+ del namespace['__file__']
+ else:
+ namespace['__file__'] = old_file