##// END OF EJS Templates
For doctests, globals must now be a real dictionary.
Thomas Kluyver -
Show More
@@ -84,67 +84,6 b' def _run_ns_sync(self,arg_s,runner=None):'
84 return get_ipython().magic_run_ori(arg_s, runner, finder)
84 return get_ipython().magic_run_ori(arg_s, runner, finder)
85
85
86
86
87 class ipnsdict(dict):
88 """A special subclass of dict for use as an IPython namespace in doctests.
89
90 This subclass adds a simple checkpointing capability so that when testing
91 machinery clears it (we use it as the test execution context), it doesn't
92 get completely destroyed.
93
94 In addition, it can handle the presence of the '_' key in a special manner,
95 which is needed because of how Python's doctest machinery operates with
96 '_'. See constructor and :meth:`update` for details.
97 """
98
99 def __init__(self,*a):
100 dict.__init__(self,*a)
101 self._savedict = {}
102 # If this flag is True, the .update() method will unconditionally
103 # remove a key named '_'. This is so that such a dict can be used as a
104 # namespace in doctests that call '_'.
105 self.protect_underscore = False
106
107 def clear(self):
108 dict.clear(self)
109 self.update(self._savedict)
110
111 def _checkpoint(self):
112 self._savedict.clear()
113 self._savedict.update(self)
114
115 def update(self,other):
116 self._checkpoint()
117 dict.update(self,other)
118
119 if self.protect_underscore:
120 # If '_' is in the namespace, python won't set it when executing
121 # code *in doctests*, and we have multiple doctests that use '_'.
122 # So we ensure that the namespace is always 'clean' of it before
123 # it's used for test code execution.
124 # This flag is only turned on by the doctest machinery, so that
125 # normal test code can assume the _ key is updated like any other
126 # key and can test for its presence after cell executions.
127 self.pop('_', None)
128
129 # The builtins namespace must *always* be the real __builtin__ module,
130 # else weird stuff happens. The main ipython code does have provisions
131 # to ensure this after %run, but since in this class we do some
132 # aggressive low-level cleaning of the execution namespace, we need to
133 # correct for that ourselves, to ensure consitency with the 'real'
134 # ipython.
135 self['__builtins__'] = builtin_mod
136
137 def __delitem__(self, key):
138 """Part of the test suite checks that we can release all
139 references to an object. So we need to make sure that we're not
140 keeping a reference in _savedict."""
141 dict.__delitem__(self, key)
142 try:
143 del self._savedict[key]
144 except KeyError:
145 pass
146
147
148 def get_ipython():
87 def get_ipython():
149 # This will get replaced by the real thing once we start IPython below
88 # This will get replaced by the real thing once we start IPython below
150 return start_ipython()
89 return start_ipython()
@@ -189,7 +128,6 b' def start_ipython():'
189
128
190 # Create and initialize our test-friendly IPython instance.
129 # Create and initialize our test-friendly IPython instance.
191 shell = TerminalInteractiveShell.instance(config=config,
130 shell = TerminalInteractiveShell.instance(config=config,
192 user_ns=ipnsdict(),
193 )
131 )
194
132
195 # A few more tweaks needed for playing nicely with doctests...
133 # A few more tweaks needed for playing nicely with doctests...
@@ -19,7 +19,7 b' Limitations:'
19 # Module imports
19 # Module imports
20
20
21 # From the standard library
21 # From the standard library
22 import __builtin__
22 import __builtin__ as builtin_mod
23 import commands
23 import commands
24 import doctest
24 import doctest
25 import inspect
25 import inspect
@@ -267,18 +267,18 b' class DocTestCase(doctests.DocTestCase):'
267 def setUp(self):
267 def setUp(self):
268 """Modified test setup that syncs with ipython namespace"""
268 """Modified test setup that syncs with ipython namespace"""
269 #print "setUp test", self._dt_test.examples # dbg
269 #print "setUp test", self._dt_test.examples # dbg
270 if isinstance(self._dt_test.examples[0],IPExample):
270 if isinstance(self._dt_test.examples[0], IPExample):
271 # for IPython examples *only*, we swap the globals with the ipython
271 # for IPython examples *only*, we swap the globals with the ipython
272 # namespace, after updating it with the globals (which doctest
272 # namespace, after updating it with the globals (which doctest
273 # fills with the necessary info from the module being tested).
273 # fills with the necessary info from the module being tested).
274 self.user_ns_orig = {}
274 self.user_ns_orig = {}
275 self.user_ns_orig.update(_ip.user_ns)
275 self.user_ns_orig.update(_ip.user_ns)
276 _ip.user_ns.update(self._dt_test.globs)
276 _ip.user_ns.update(self._dt_test.globs)
277 # We must remove the _ key in the namespace, so that Python's
278 # doctest code sets it naturally
279 _ip.user_ns.pop('_', None)
280 _ip.user_ns['__builtins__'] = builtin_mod
277 self._dt_test.globs = _ip.user_ns
281 self._dt_test.globs = _ip.user_ns
278 # IPython must protect the _ key in the namespace (it can't exist)
279 # so that Python's doctest code sets it naturally, so we enable
280 # this feature of our testing namespace.
281 _ip.user_ns.protect_underscore = True
282
282
283 super(DocTestCase, self).setUp()
283 super(DocTestCase, self).setUp()
284
284
@@ -286,13 +286,10 b' class DocTestCase(doctests.DocTestCase):'
286
286
287 # Undo the test.globs reassignment we made, so that the parent class
287 # Undo the test.globs reassignment we made, so that the parent class
288 # teardown doesn't destroy the ipython namespace
288 # teardown doesn't destroy the ipython namespace
289 if isinstance(self._dt_test.examples[0],IPExample):
289 if isinstance(self._dt_test.examples[0], IPExample):
290 self._dt_test.globs = self._dt_test_globs_ori
290 self._dt_test.globs = self._dt_test_globs_ori
291 _ip.user_ns.clear()
291 _ip.user_ns.clear()
292 _ip.user_ns.update(self.user_ns_orig)
292 _ip.user_ns.update(self.user_ns_orig)
293 # Restore the behavior of the '_' key in the user namespace to
294 # normal after each doctest, so that unittests behave normally
295 _ip.user_ns.protect_underscore = False
296
293
297 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
294 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
298 # it does look like one to me: its tearDown method tries to run
295 # it does look like one to me: its tearDown method tries to run
General Comments 0
You need to be logged in to leave comments. Login now