Show More
@@ -1119,7 +1119,49 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||||
1119 |
|
1119 | |||
1120 | # Clear out the namespace from the last %run |
|
1120 | # Clear out the namespace from the last %run | |
1121 | self.new_main_mod() |
|
1121 | self.new_main_mod() | |
1122 |
|
1122 | |||
|
1123 | def del_var(self, varname, by_name=False): | |||
|
1124 | """Delete a variable from the various namespaces, so that, as | |||
|
1125 | far as possible, we're not keeping any hidden references to it. | |||
|
1126 | ||||
|
1127 | Parameters | |||
|
1128 | ---------- | |||
|
1129 | varname : str | |||
|
1130 | The name of the variable to delete. | |||
|
1131 | by_name : bool | |||
|
1132 | If True, delete variables with the given name in each | |||
|
1133 | namespace. If False (default), find the variable in the user | |||
|
1134 | namespace, and delete references to it. | |||
|
1135 | """ | |||
|
1136 | if varname in ('__builtin__', '__builtins__'): | |||
|
1137 | raise ValueError("Refusing to delete %s" % varname) | |||
|
1138 | ns_refs = self.ns_refs_table + [self.user_ns, | |||
|
1139 | self.user_global_ns, self._user_main_module.__dict__] +\ | |||
|
1140 | self._main_ns_cache.values() | |||
|
1141 | ||||
|
1142 | if by_name: # Delete by name | |||
|
1143 | for ns in ns_refs: | |||
|
1144 | try: | |||
|
1145 | del ns[varname] | |||
|
1146 | except KeyError: | |||
|
1147 | pass | |||
|
1148 | else: # Delete by object | |||
|
1149 | try: | |||
|
1150 | obj = self.user_ns[varname] | |||
|
1151 | except KeyError: | |||
|
1152 | raise NameError("name '%s' is not defined" % varname) | |||
|
1153 | # Also check in output history | |||
|
1154 | ns_refs.append(self.history_manager.output_hist) | |||
|
1155 | for ns in ns_refs: | |||
|
1156 | to_delete = [n for n, o in ns.iteritems() if o is obj] | |||
|
1157 | for name in to_delete: | |||
|
1158 | del ns[name] | |||
|
1159 | ||||
|
1160 | # displayhook keeps extra references, but not in a dictionary | |||
|
1161 | for name in ('_', '__', '___'): | |||
|
1162 | if getattr(self.displayhook, name) is obj: | |||
|
1163 | setattr(self.displayhook, name, None) | |||
|
1164 | ||||
1123 | def reset_selective(self, regex=None): |
|
1165 | def reset_selective(self, regex=None): | |
1124 | """Clear selective variables from internal namespaces based on a |
|
1166 | """Clear selective variables from internal namespaces based on a | |
1125 | specified regular expression. |
|
1167 | specified regular expression. |
@@ -1084,7 +1084,24 b' Currently the magic system has the following functions:\\n"""' | |||||
1084 | raise TypeError('regex must be a string or compiled pattern') |
|
1084 | raise TypeError('regex must be a string or compiled pattern') | |
1085 | for i in self.magic_who_ls(): |
|
1085 | for i in self.magic_who_ls(): | |
1086 | if m.search(i): |
|
1086 | if m.search(i): | |
1087 |
del(user_ns[i]) |
|
1087 | del(user_ns[i]) | |
|
1088 | ||||
|
1089 | def magic_xdel(self, parameter_s=''): | |||
|
1090 | """Delete a variable, trying to clear it from anywhere that | |||
|
1091 | IPython's machinery has references to it. By default, this uses | |||
|
1092 | the identity of the named object in the user namespace to remove | |||
|
1093 | references held under other names. The object is also removed | |||
|
1094 | from the output history. | |||
|
1095 | ||||
|
1096 | Options | |||
|
1097 | -n : Delete the specified name from all namespaces, without | |||
|
1098 | checking their identity. | |||
|
1099 | """ | |||
|
1100 | opts, varname = self.parse_options(parameter_s,'n') | |||
|
1101 | try: | |||
|
1102 | self.shell.del_var(varname, ('n' in opts)) | |||
|
1103 | except (NameError, ValueError) as e: | |||
|
1104 | print type(e).__name__ +": "+ str(e) | |||
1088 |
|
1105 | |||
1089 | def magic_logstart(self,parameter_s=''): |
|
1106 | def magic_logstart(self,parameter_s=''): | |
1090 | """Start logging anywhere in a session. |
|
1107 | """Start logging anywhere in a session. |
@@ -394,6 +394,28 b' def test_reset_hard():' | |||||
394 | nt.assert_equal(monitor, []) |
|
394 | nt.assert_equal(monitor, []) | |
395 | _ip.magic_reset("-f") |
|
395 | _ip.magic_reset("-f") | |
396 | nt.assert_equal(monitor, [1]) |
|
396 | nt.assert_equal(monitor, [1]) | |
|
397 | ||||
|
398 | class TestXdel(tt.TempFileMixin): | |||
|
399 | def test_xdel(self): | |||
|
400 | """Test that references from %run are cleared by xdel.""" | |||
|
401 | src = ("class A(object):\n" | |||
|
402 | " monitor = []\n" | |||
|
403 | " def __del__(self):\n" | |||
|
404 | " self.monitor.append(1)\n" | |||
|
405 | "a = A()\n") | |||
|
406 | self.mktmp(src) | |||
|
407 | # %run creates some hidden references... | |||
|
408 | _ip.magic("run %s" % self.fname) | |||
|
409 | # ... as does the displayhook. | |||
|
410 | _ip.run_cell("a") | |||
|
411 | ||||
|
412 | monitor = _ip.user_ns["A"].monitor | |||
|
413 | nt.assert_equal(monitor, []) | |||
|
414 | ||||
|
415 | _ip.magic("xdel a") | |||
|
416 | ||||
|
417 | # Check that a's __del__ method has been called. | |||
|
418 | nt.assert_equal(monitor, [1]) | |||
397 |
|
419 | |||
398 | def doctest_who(): |
|
420 | def doctest_who(): | |
399 | """doctest for %who |
|
421 | """doctest for %who |
@@ -132,6 +132,16 b' class ipnsdict(dict):' | |||||
132 | # correct for that ourselves, to ensure consitency with the 'real' |
|
132 | # correct for that ourselves, to ensure consitency with the 'real' | |
133 | # ipython. |
|
133 | # ipython. | |
134 | self['__builtins__'] = __builtin__ |
|
134 | self['__builtins__'] = __builtin__ | |
|
135 | ||||
|
136 | def __delitem__(self, key): | |||
|
137 | """Part of the test suite checks that we can release all | |||
|
138 | references to an object. So we need to make sure that we're not | |||
|
139 | keeping a reference in _savedict.""" | |||
|
140 | dict.__delitem__(self, key) | |||
|
141 | try: | |||
|
142 | del self._savedict[key] | |||
|
143 | except KeyError: | |||
|
144 | pass | |||
135 |
|
145 | |||
136 |
|
146 | |||
137 | def get_ipython(): |
|
147 | def get_ipython(): |
General Comments 0
You need to be logged in to leave comments.
Login now