diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 3761dc8..1f086bd 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -1079,7 +1079,49 @@ class InteractiveShell(Configurable, Magic): # Clear out the namespace from the last %run self.new_main_mod() - + + def del_var(self, varname, by_name=False): + """Delete a variable from the various namespaces, so that, as + far as possible, we're not keeping any hidden references to it. + + Parameters + ---------- + varname : str + The name of the variable to delete. + by_name : bool + If True, delete variables with the given name in each + namespace. If False (default), find the variable in the user + namespace, and delete references to it. + """ + if varname in ('__builtin__', '__builtins__'): + raise ValueError("Refusing to delete %s" % varname) + ns_refs = self.ns_refs_table + [self.user_ns, + self.user_global_ns, self._user_main_module.__dict__] +\ + self._main_ns_cache.values() + + if by_name: # Delete by name + for ns in ns_refs: + try: + del ns[varname] + except KeyError: + pass + else: # Delete by object + try: + obj = self.user_ns[varname] + except KeyError: + raise NameError("name '%s' is not defined" % varname) + # Also check in output history + ns_refs.append(self.history_manager.output_hist) + for ns in ns_refs: + to_delete = [n for n, o in ns.iteritems() if o is obj] + for name in to_delete: + del ns[name] + + # displayhook keeps extra references, but not in a dictionary + for name in ('_', '__', '___'): + if getattr(self.displayhook, name) is obj: + setattr(self.displayhook, name, None) + def reset_selective(self, regex=None): """Clear selective variables from internal namespaces based on a specified regular expression. diff --git a/IPython/core/magic.py b/IPython/core/magic.py index a298e36..c304a59 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -1081,7 +1081,24 @@ Currently the magic system has the following functions:\n""" raise TypeError('regex must be a string or compiled pattern') for i in self.magic_who_ls(): if m.search(i): - del(user_ns[i]) + del(user_ns[i]) + + def magic_xdel(self, parameter_s=''): + """Delete a variable, trying to clear it from anywhere that + IPython's machinery has references to it. By default, this uses + the identity of the named object in the user namespace to remove + references held under other names. The object is also removed + from the output history. + + Options + -n : Delete the specified name from all namespaces, without + checking their identity. + """ + opts, varname = self.parse_options(parameter_s,'n') + try: + self.shell.del_var(varname, ('n' in opts)) + except (NameError, ValueError) as e: + print type(e).__name__ +": "+ str(e) def magic_logstart(self,parameter_s=''): """Start logging anywhere in a session.