diff --git a/IPython/core/completerlib.py b/IPython/core/completerlib.py index 7717039dbec..466041f66d5 100644 --- a/IPython/core/completerlib.py +++ b/IPython/core/completerlib.py @@ -181,7 +181,6 @@ def do_complete(self, event): get_ipython().set_hook('complete_command',do_complete, str_key = cmd) - def module_completion(line): """ Returns a list containing the completion possibilities for an import line. @@ -316,3 +315,7 @@ def cd_completer(self, event): raise TryNext return [compress_user(p, tilde_expand, tilde_val) for p in found] + +def reset_completer(self, event): + "A completer for %reset magic" + return '-f -s in out array dhist'.split() diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index f3fa1ee7b97..804c4a452a9 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -1840,7 +1840,7 @@ def init_completer(self): """ from IPython.core.completer import IPCompleter from IPython.core.completerlib import (module_completer, - magic_run_completer, cd_completer) + magic_run_completer, cd_completer, reset_completer) self.Completer = IPCompleter(shell=self, namespace=self.user_ns, @@ -1860,6 +1860,7 @@ def init_completer(self): self.set_hook('complete_command', module_completer, str_key = 'from') self.set_hook('complete_command', magic_run_completer, str_key = '%run') self.set_hook('complete_command', cd_completer, str_key = '%cd') + self.set_hook('complete_command', reset_completer, str_key = '%reset') # Only configure readline if we truly are using readline. IPython can # do tab-completion over the network, in GUIs, etc, where readline diff --git a/IPython/core/magic.py b/IPython/core/magic.py index 5e60d37b224..ff3b971bd6e 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -25,6 +25,7 @@ import shutil import re import time +import gc from StringIO import StringIO from getopt import getopt,GetoptError from pprint import pformat @@ -959,16 +960,31 @@ def type_name(v): print vstr[:25] + "<...>" + vstr[-25:] def magic_reset(self, parameter_s=''): - """Resets the namespace by removing all names defined by the user. + """Resets the namespace by removing all names defined by the user, if + called without arguments, or by removing some types of objects, such + as everything currently in IPython's In[] and Out[] containers (see + the parameters for details). Parameters ---------- - -f : force reset without asking for confirmation. + -f : force reset without asking for confirmation. + + -s : 'Soft' reset: Only clears your namespace, leaving history intact. + References to objects may be kept. By default (without this option), + we do a 'hard' reset, giving you a new session and removing all + references to objects from the current session. + + in : reset input history + + out : reset output history + + dhist : reset directory history + + array : reset only variables that are NumPy arrays - -s : 'Soft' reset: Only clears your namespace, leaving history intact. - References to objects may be kept. By default (without this option), - we do a 'hard' reset, giving you a new session and removing all - references to objects from the current session. + See Also + -------- + %reset_selective Examples -------- @@ -985,13 +1001,20 @@ def magic_reset(self, parameter_s=''): In [1]: 'a' in _ip.user_ns Out[1]: False + In [2]: %reset -f in + Flushing input history + + In [3]: %reset -f dhist in + Flushing directory history + Flushing input history + Notes ----- Calling this magic from clients that do not implement standard input, such as the ipython notebook interface, will reset the namespace without confirmation. """ - opts, args = self.parse_options(parameter_s,'sf') + opts, args = self.parse_options(parameter_s,'sf', mode='list') if 'f' in opts: ans = True else: @@ -1008,11 +1031,55 @@ def magic_reset(self, parameter_s=''): user_ns = self.shell.user_ns for i in self.magic_who_ls(): del(user_ns[i]) - - else: # Hard reset + elif len(args) == 0: # Hard reset self.shell.reset(new_session = False) + + # reset in/out/dhist/array: previously extensinions/clearcmd.py + ip = self.shell + user_ns = self.user_ns # local lookup, heavily used + + for target in args: + target = target.lower() # make matches case insensitive + if target == 'out': + print "Flushing output cache (%d entries)" % len(user_ns['_oh']) + self.displayhook.flush() + + elif target == 'in': + print "Flushing input history" + pc = self.displayhook.prompt_count + 1 + for n in range(1, pc): + key = '_i'+repr(n) + user_ns.pop(key,None) + user_ns.update(dict(_i=u'',_ii=u'',_iii=u'')) + hm = ip.history_manager + # don't delete these, as %save and %macro depending on the length + # of these lists to be preserved + hm.input_hist_parsed[:] = [''] * pc + hm.input_hist_raw[:] = [''] * pc + # hm has internal machinery for _i,_ii,_iii, clear it out + hm._i = hm._ii = hm._iii = hm._i00 = u'' + + elif target == 'array': + # Support cleaning up numpy arrays + try: + from numpy import ndarray + # This must be done with items and not iteritems because we're + # going to modify the dict in-place. + for x,val in user_ns.items(): + if isinstance(val,ndarray): + del user_ns[x] + except ImportError: + print "reset array only works if Numpy is available." + + elif target == 'dhist': + print "Flushing directory history" + del user_ns['_dh'][:] + else: + print "Don't know how to reset ", + print target + ", please run `%reset?` for details" + gc.collect() def magic_reset_selective(self, parameter_s=''): """Resets the namespace by removing names defined by the user. @@ -1026,6 +1093,10 @@ def magic_reset_selective(self, parameter_s=''): Options -f : force reset without asking for confirmation. + See Also + -------- + %reset + Examples -------- diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py index 62bd25a14ad..dd42552224b 100644 --- a/IPython/core/tests/test_magic.py +++ b/IPython/core/tests/test_magic.py @@ -183,20 +183,50 @@ def test_macro_run(): with tt.AssertPrints("13"): ip.run_cell("test") - -# XXX failing for now, until we get clearcmd out of quarantine. But we should -# fix this and revert the skip to happen only if numpy is not around. -#@dec.skipif_not_numpy -@dec.skip_known_failure -def test_numpy_clear_array_undec(): - from IPython.extensions import clearcmd +@dec.skipif_not_numpy +def test_numpy_reset_array_undec(): + "Test '%reset array' functionality" _ip.ex('import numpy as np') _ip.ex('a = np.empty(2)') yield (nt.assert_true, 'a' in _ip.user_ns) - _ip.magic('clear array') + _ip.magic('reset -f array') yield (nt.assert_false, 'a' in _ip.user_ns) - + +def test_reset_out(): + "Test '%reset out' magic" + _ip.run_cell("parrot = 'dead'", store_history=True) + # test '%reset -f out', make an Out prompt + _ip.run_cell("parrot", store_history=True) + nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___']) + _ip.magic('reset -f out') + nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___']) + nt.assert_true(len(_ip.user_ns['Out']) == 0) + +def test_reset_in(): + "Test '%reset in' magic" + # test '%reset -f in' + _ip.run_cell("parrot", store_history=True) + nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii']) + _ip.magic('%reset -f in') + nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii']) + nt.assert_true(len(set(_ip.user_ns['In'])) == 1) + +def test_reset_dhist(): + "Test '%reset dhist' magic" + _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing + _ip.magic('cd ' + os.path.dirname(nt.__file__)) + _ip.magic('cd -') + nt.assert_true(len(_ip.user_ns['_dh']) > 0) + _ip.magic('reset -f dhist') + nt.assert_true(len(_ip.user_ns['_dh']) == 0) + _ip.run_cell("_dh = [d for d in tmp]") #restore + +def test_reset_in_length(): + "Test that '%reset in' preserves In[] length" + _ip.run_cell("print 'foo'") + _ip.run_cell("reset -f in") + nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1) def test_time(): _ip.magic('time None') diff --git a/IPython/quarantine/clearcmd.py b/IPython/quarantine/clearcmd.py deleted file mode 100644 index 7b140e483c9..00000000000 --- a/IPython/quarantine/clearcmd.py +++ /dev/null @@ -1,87 +0,0 @@ -# -*- coding: utf-8 -*- -""" IPython extension: add %clear magic """ - -from IPython.core import ipapi -import gc -ip = ipapi.get() - -def clear_f(self,arg): - """ Clear various data (e.g. stored history data) - - %clear in - clear input history - %clear out - clear output history - %clear shadow_compress - Compresses shadow history (to speed up ipython) - %clear shadow_nuke - permanently erase all entries in shadow history - %clear dhist - clear dir history - %clear array - clear only variables that are NumPy arrays - - Examples: - - In [1]: clear in - Flushing input history - - In [2]: clear shadow_compress - Compressing shadow history - - In [3]: clear shadow_nuke - Erased all keys from shadow history - - In [4]: clear dhist - Clearing directory history - """ - - api = self.getapi() - user_ns = self.user_ns # local lookup, heavily used - - - for target in arg.split(): - - if target == 'out': - print "Flushing output cache (%d entries)" % len(user_ns['_oh']) - self.outputcache.flush() - - elif target == 'in': - print "Flushing input history" - pc = self.outputcache.prompt_count + 1 - for n in range(1, pc): - key = '_i'+`n` - user_ns.pop(key,None) - try: - del user_ns[key] - except: pass - # must be done in-place - self.history_manager.input_hist_parsed[:] = ['\n'] * pc - self.history_manager.input_hist_raw[:] = ['\n'] * pc - - elif target == 'array': - # Support cleaning up numpy arrays - try: - from numpy import ndarray - # This must be done with items and not iteritems because we're - # going to modify the dict in-place. - for x,val in user_ns.items(): - if isinstance(val,ndarray): - del user_ns[x] - except AttributeError: - print "Clear array only works if Numpy is available." - - elif target == 'shadow_compress': - print "Compressing shadow history" - api.db.hcompress('shadowhist') - - elif target == 'shadow_nuke': - print "Erased all keys from shadow history " - for k in ip.db.keys('shadowhist/*'): - del ip.db[k] - - elif target == 'dhist': - print "Clearing directory history" - del user_ns['_dh'][:] - - gc.collect() - -# Activate the extension -ip.define_magic("clear",clear_f) -import ipy_completers -ipy_completers.quick_completer( - '%clear','in out shadow_nuke shadow_compress dhist') diff --git a/IPython/quarantine/ipy_jot.py b/IPython/quarantine/ipy_jot.py index 5a8fec369f5..fce9099da02 100644 --- a/IPython/quarantine/ipy_jot.py +++ b/IPython/quarantine/ipy_jot.py @@ -116,8 +116,6 @@ def jot_obj(self, obj, name, comment=''): uname = 'jot/'+name+suffix - # which one works better? - #all = ip.shadowhist.all() all = ip.shell.history_manager.input_hist_parsed # We may actually want to make snapshot of files that are run-ned.