From 487b6b96e5d72a641ea66701210f17b7f895c966 2011-12-06 00:24:24 From: Fernando Perez Date: 2011-12-06 00:24:24 Subject: [PATCH] Merge pull request #1059 from fperez/__IPYTHON__ Switch to simple `__IPYTHON__` global to indicate an IPython Shell object has been created. Note that this does *not* try to track whether user code is being executed by ipython via %run, nor whether the Shell object itself is running an interactive event loop or not. So the answer for how people should query whether IPython objects are active is now simply ``` try: __IPYTHON__ except NameError: print 'not in IPython' ``` We do not attempt to track activity levels anymore, as we realized that logic was ultimately to brittle and error prone to be of any real use. --- diff --git a/IPython/core/builtin_trap.py b/IPython/core/builtin_trap.py index 7551334..ad0eb2d 100644 --- a/IPython/core/builtin_trap.py +++ b/IPython/core/builtin_trap.py @@ -88,17 +88,12 @@ class BuiltinTrap(Configurable): self._orig_builtins[key] = orig bdict[key] = value - def remove_builtin(self, key): + def remove_builtin(self, key, orig): """Remove an added builtin and re-set the original.""" - try: - orig = self._orig_builtins.pop(key) - except KeyError: - pass + if orig is BuiltinUndefined: + del __builtin__.__dict__[key] else: - if orig is BuiltinUndefined: - del __builtin__.__dict__[key] - else: - __builtin__.__dict__[key] = orig + __builtin__.__dict__[key] = orig def activate(self): """Store ipython references in the __builtin__ namespace.""" @@ -107,22 +102,11 @@ class BuiltinTrap(Configurable): for name, func in self.auto_builtins.iteritems(): add_builtin(name, func) - # Keep in the builtins a flag for when IPython is active. We set it - # with setdefault so that multiple nested IPythons don't clobber one - # another. - __builtin__.__dict__.setdefault('__IPYTHON__active', 0) - def deactivate(self): """Remove any builtins which might have been added by add_builtins, or restore overwritten ones to their previous values.""" - # Note: must iterate over a static keys() list because we'll be - # mutating the dict itself remove_builtin = self.remove_builtin - for key in self._orig_builtins.keys(): - remove_builtin(key) + for key, val in self._orig_builtins.iteritems(): + remove_builtin(key, val) self._orig_builtins.clear() self._builtins_added = False - try: - del __builtin__.__dict__['__IPYTHON__active'] - except KeyError: - pass diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index bb3ffc1..a40a422 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -605,6 +605,20 @@ class InteractiveShell(SingletonConfigurable, Magic): self.magic_logstart() def init_builtins(self): + # A single, static flag that we set to True. Its presence indicates + # that an IPython shell has been created, and we make no attempts at + # removing on exit or representing the existence of more than one + # IPython at a time. + builtin_mod.__dict__['__IPYTHON__'] = True + + # In 0.11 we introduced '__IPYTHON__active' as an integer we'd try to + # manage on enter/exit, but with all our shells it's virtually + # impossible to get all the cases right. We're leaving the name in for + # those who adapted their codes to check for this flag, but will + # eventually remove it after a few more releases. + builtin_mod.__dict__['__IPYTHON__active'] = \ + 'Deprecated, check for __IPYTHON__' + self.builtin_trap = BuiltinTrap(shell=self) def init_inspector(self): diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py index a5d3c9f..d57cd51 100644 --- a/IPython/core/tests/test_interactiveshell.py +++ b/IPython/core/tests/test_interactiveshell.py @@ -271,3 +271,8 @@ class TestSystemRaw(unittest.TestCase): """ cmd = ur'''python -c "'åäö'" ''' _ip.shell.system_raw(cmd) + + +def test__IPYTHON__(): + # This shouldn't raise a NameError, that's all + __IPYTHON__ diff --git a/IPython/frontend/terminal/interactiveshell.py b/IPython/frontend/terminal/interactiveshell.py index a8d2038..37ad352 100644 --- a/IPython/frontend/terminal/interactiveshell.py +++ b/IPython/frontend/terminal/interactiveshell.py @@ -341,9 +341,6 @@ class TerminalInteractiveShell(InteractiveShell): more = False - # Mark activity in the builtins - __builtin__.__dict__['__IPYTHON__active'] += 1 - if self.has_readline: self.readline_startup_hook(self.pre_readline) hlen_b4_cell = self.readline.get_current_history_length() @@ -413,9 +410,6 @@ class TerminalInteractiveShell(InteractiveShell): hlen_b4_cell = \ self._replace_rlhist_multiline(source_raw, hlen_b4_cell) - # We are off again... - __builtin__.__dict__['__IPYTHON__active'] -= 1 - # Turn off the exit flag, so the mainloop can be restarted if desired self.exit_now = False