From 70d272968a4373b0fc86c2de62cf76624042f88f 2010-01-31 04:09:04 From: Brian Granger Date: 2010-01-31 04:09:04 Subject: [PATCH] More work to address review comments. * Moved twisted import to top-level of :mod:`IPython.kernel.error` (r1333). * Added docstring about :meth:`InteractiveShell.load_extension` returning whatever the return value of :func:`load_ipython_extension` is. * Renamed the :attr:`user_config_ns` attribute to :attr:`user_ns_hidden` to better reflect what it does. * Moved the ``%HOME`` to the end of home directory options attemped in :func:`IPython.utils.path.get_home_dir` on Windows. --- diff --git a/IPython/core/iplib.py b/IPython/core/iplib.py index 59e6ed6..c75b404 100644 --- a/IPython/core/iplib.py +++ b/IPython/core/iplib.py @@ -833,7 +833,7 @@ class InteractiveShell(Component, Magic): # loaded at startup, so we can list later only variables defined in # actual interactive use. Since it is always a subset of user_ns, it # doesn't need to be separately tracked in the ns_table. - self.user_config_ns = {} + self.user_ns_hidden = {} # A namespace to keep track of internal data structures to prevent # them from cluttering user-visible stuff. Will be updated later @@ -879,7 +879,7 @@ class InteractiveShell(Component, Magic): # Similarly, track all namespaces where references can be held and that # we can safely clear (so it can NOT include builtin). This one can be # a simple list. - self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns, + self.ns_refs_table = [ user_ns, user_global_ns, self.user_ns_hidden, self.internal_ns, self._main_ns_cache ] def make_user_namespaces(self, user_ns=None, user_global_ns=None): @@ -978,7 +978,7 @@ class InteractiveShell(Component, Magic): therm. """ # This function works in two parts: first we put a few things in - # user_ns, and we sync that contents into user_config_ns so that these + # user_ns, and we sync that contents into user_ns_hidden so that these # initial variables aren't shown by %who. After the sync, we add the # rest of what we *do* want the user to see with %who even on a new # session (probably nothing, so theye really only see their own stuff) @@ -1018,9 +1018,9 @@ class InteractiveShell(Component, Magic): # Store myself as the public api!!! ns['get_ipython'] = self.get_ipython - # Sync what we've added so far to user_config_ns so these aren't seen + # Sync what we've added so far to user_ns_hidden so these aren't seen # by %who - self.user_config_ns.update(ns) + self.user_ns_hidden.update(ns) # Anything put into ns now would show up in %who. Think twice before # putting anything here, as we really want %who to show the user their @@ -1093,7 +1093,7 @@ class InteractiveShell(Component, Magic): self.user_ns.update(vdict) # And configure interactive visibility - config_ns = self.user_config_ns + config_ns = self.user_ns_hidden if interactive: for name, val in vdict.iteritems(): config_ns.pop(name, None) @@ -2360,6 +2360,9 @@ class InteractiveShell(Component, Magic): to make it easy to write extensions, you can also put your extensions in ``os.path.join(self.ipython_dir, 'extensions')``. This directory is added to ``sys.path`` automatically. + + If :func:`load_ipython_extension` returns anything, this function + will return that object. """ from IPython.utils.syspathcontext import prepended_to_syspath @@ -2504,11 +2507,11 @@ class InteractiveShell(Component, Magic): # We want to prevent the loading of pylab to pollute the user's # namespace as shown by the %who* magics, so we execute the activation # code in an empty namespace, and we update *both* user_ns and - # user_config_ns with this information. + # user_ns_hidden with this information. ns = {} gui = pylab_activate(ns, gui) self.user_ns.update(ns) - self.user_config_ns.update(ns) + self.user_ns_hidden.update(ns) # Now we must activate the gui pylab wants to use, and fix %run to take # plot updates into account enable_gui(gui) diff --git a/IPython/core/magic.py b/IPython/core/magic.py index 5c581c0..85b5a79 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -886,10 +886,10 @@ Currently the magic system has the following functions:\n""" user_ns = self.shell.user_ns internal_ns = self.shell.internal_ns - user_config_ns = self.shell.user_config_ns + user_ns_hidden = self.shell.user_ns_hidden out = [ i for i in user_ns if not i.startswith('_') \ - and not (i in internal_ns or i in user_config_ns) ] + and not (i in internal_ns or i in user_ns_hidden) ] typelist = parameter_s.split() if typelist: diff --git a/IPython/core/tests/test_iplib.py b/IPython/core/tests/test_iplib.py index f00204b..2fa6633 100644 --- a/IPython/core/tests/test_iplib.py +++ b/IPython/core/tests/test_iplib.py @@ -30,9 +30,9 @@ ip = get_ipython() @dec.parametric def test_reset(): """reset must clear most namespaces.""" - # The number of variables in the private user_config_ns is not zero, but it + # The number of variables in the private user_ns_hidden is not zero, but it # should be constant regardless of what we do - nvars_config_ns = len(ip.user_config_ns) + nvars_config_ns = len(ip.user_ns_hidden) # Check that reset runs without error ip.reset() @@ -51,7 +51,7 @@ def test_reset(): for ns in ip.ns_refs_table: if ns is ip.user_ns: nvars_expected = nvars_user_ns - elif ns is ip.user_config_ns: + elif ns is ip.user_ns_hidden: nvars_expected = nvars_config_ns else: nvars_expected = 0 diff --git a/IPython/kernel/error.py b/IPython/kernel/error.py index 2d0533e..dd1e1c5 100644 --- a/IPython/kernel/error.py +++ b/IPython/kernel/error.py @@ -18,6 +18,8 @@ __test__ = {} # Imports #------------------------------------------------------------------------------- +from twisted.python import failure + from IPython.kernel.core import error #------------------------------------------------------------------------------- @@ -27,6 +29,7 @@ from IPython.kernel.core import error class KernelError(error.IPythonError): pass + class NotDefined(KernelError): def __init__(self, name): self.name = name @@ -37,78 +40,102 @@ class NotDefined(KernelError): __str__ = __repr__ + class QueueCleared(KernelError): pass + class IdInUse(KernelError): pass + class ProtocolError(KernelError): pass + class ConnectionError(KernelError): pass + class InvalidEngineID(KernelError): pass - + + class NoEnginesRegistered(KernelError): pass - + + class InvalidClientID(KernelError): pass - + + class InvalidDeferredID(KernelError): pass - + + class SerializationError(KernelError): pass - + + class MessageSizeError(KernelError): pass - + + class PBMessageSizeError(MessageSizeError): pass - + + class ResultNotCompleted(KernelError): pass - + + class ResultAlreadyRetrieved(KernelError): pass - + class ClientError(KernelError): pass + class TaskAborted(KernelError): pass + class TaskTimeout(KernelError): pass + class NotAPendingResult(KernelError): pass + class UnpickleableException(KernelError): pass + class AbortedPendingDeferredError(KernelError): pass + class InvalidProperty(KernelError): pass + class MissingBlockArgument(KernelError): pass + class StopLocalExecution(KernelError): pass + class SecurityError(KernelError): pass + class FileTimeoutError(KernelError): pass + class TaskRejectError(KernelError): """Exception to raise when a task should be rejected by an engine. @@ -123,6 +150,7 @@ class TaskRejectError(KernelError): properties don't have to be managed or tested by the controller. """ + class CompositeError(KernelError): def __init__(self, message, elist): Exception.__init__(self, *(message, elist)) @@ -177,9 +205,8 @@ class CompositeError(KernelError): else: raise et, ev, etb -def collect_exceptions(rlist, method): - from twisted.python import failure +def collect_exceptions(rlist, method): elist = [] for r in rlist: if isinstance(r, failure.Failure): diff --git a/IPython/utils/path.py b/IPython/utils/path.py index ef05741..3db3472 100644 --- a/IPython/utils/path.py +++ b/IPython/utils/path.py @@ -188,12 +188,7 @@ def get_home_dir(): # is needed when running IPython on cluster where all paths have to # be UNC. try: - # A user with a lot of unix tools in win32 may have defined $HOME, - # honor it if it exists, but otherwise let the more typical - # %HOMESHARE% variable be used. - homedir = env.get('HOME') - if homedir is None: - homedir = env['HOMESHARE'] + homedir = env['HOMESHARE'] except KeyError: pass else: @@ -233,6 +228,16 @@ def get_home_dir(): if isdir(homedir): return homedir.decode(sys.getfilesystemencoding()) + # A user with a lot of unix tools in win32 may have defined $HOME. + # Try this as a last ditch option. + try: + homedir = env['HOME'] + except KeyError: + pass + else: + if isdir(homedir): + return homedir.decode(sys.getfilesystemencoding()) + # If all else fails, raise HomeDirError raise HomeDirError('No valid home directory could be found') elif os.name == 'dos':