From bb6dab9470c6f5206b0b49890c81d3061ea3f67a 2012-05-27 09:45:36 From: Thomas Kluyver Date: 2012-05-27 09:45:36 Subject: [PATCH] For doctests, globals must now be a real dictionary. --- diff --git a/IPython/testing/globalipapp.py b/IPython/testing/globalipapp.py index 44717ec..82f752c 100644 --- a/IPython/testing/globalipapp.py +++ b/IPython/testing/globalipapp.py @@ -84,67 +84,6 @@ def _run_ns_sync(self,arg_s,runner=None): return get_ipython().magic_run_ori(arg_s, runner, finder) -class ipnsdict(dict): - """A special subclass of dict for use as an IPython namespace in doctests. - - This subclass adds a simple checkpointing capability so that when testing - machinery clears it (we use it as the test execution context), it doesn't - get completely destroyed. - - In addition, it can handle the presence of the '_' key in a special manner, - which is needed because of how Python's doctest machinery operates with - '_'. See constructor and :meth:`update` for details. - """ - - def __init__(self,*a): - dict.__init__(self,*a) - self._savedict = {} - # If this flag is True, the .update() method will unconditionally - # remove a key named '_'. This is so that such a dict can be used as a - # namespace in doctests that call '_'. - self.protect_underscore = False - - def clear(self): - dict.clear(self) - self.update(self._savedict) - - def _checkpoint(self): - self._savedict.clear() - self._savedict.update(self) - - def update(self,other): - self._checkpoint() - dict.update(self,other) - - if self.protect_underscore: - # If '_' is in the namespace, python won't set it when executing - # code *in doctests*, and we have multiple doctests that use '_'. - # So we ensure that the namespace is always 'clean' of it before - # it's used for test code execution. - # This flag is only turned on by the doctest machinery, so that - # normal test code can assume the _ key is updated like any other - # key and can test for its presence after cell executions. - self.pop('_', None) - - # The builtins namespace must *always* be the real __builtin__ module, - # else weird stuff happens. The main ipython code does have provisions - # to ensure this after %run, but since in this class we do some - # aggressive low-level cleaning of the execution namespace, we need to - # correct for that ourselves, to ensure consitency with the 'real' - # ipython. - self['__builtins__'] = builtin_mod - - def __delitem__(self, key): - """Part of the test suite checks that we can release all - references to an object. So we need to make sure that we're not - keeping a reference in _savedict.""" - dict.__delitem__(self, key) - try: - del self._savedict[key] - except KeyError: - pass - - def get_ipython(): # This will get replaced by the real thing once we start IPython below return start_ipython() @@ -189,7 +128,6 @@ def start_ipython(): # Create and initialize our test-friendly IPython instance. shell = TerminalInteractiveShell.instance(config=config, - user_ns=ipnsdict(), ) # A few more tweaks needed for playing nicely with doctests... diff --git a/IPython/testing/plugin/ipdoctest.py b/IPython/testing/plugin/ipdoctest.py index 50cc72b..1571e31 100644 --- a/IPython/testing/plugin/ipdoctest.py +++ b/IPython/testing/plugin/ipdoctest.py @@ -19,7 +19,7 @@ Limitations: # Module imports # From the standard library -import __builtin__ +import __builtin__ as builtin_mod import commands import doctest import inspect @@ -267,18 +267,18 @@ class DocTestCase(doctests.DocTestCase): def setUp(self): """Modified test setup that syncs with ipython namespace""" #print "setUp test", self._dt_test.examples # dbg - if isinstance(self._dt_test.examples[0],IPExample): + if isinstance(self._dt_test.examples[0], IPExample): # for IPython examples *only*, we swap the globals with the ipython # namespace, after updating it with the globals (which doctest # fills with the necessary info from the module being tested). self.user_ns_orig = {} self.user_ns_orig.update(_ip.user_ns) _ip.user_ns.update(self._dt_test.globs) + # We must remove the _ key in the namespace, so that Python's + # doctest code sets it naturally + _ip.user_ns.pop('_', None) + _ip.user_ns['__builtins__'] = builtin_mod self._dt_test.globs = _ip.user_ns - # IPython must protect the _ key in the namespace (it can't exist) - # so that Python's doctest code sets it naturally, so we enable - # this feature of our testing namespace. - _ip.user_ns.protect_underscore = True super(DocTestCase, self).setUp() @@ -286,13 +286,10 @@ class DocTestCase(doctests.DocTestCase): # Undo the test.globs reassignment we made, so that the parent class # teardown doesn't destroy the ipython namespace - if isinstance(self._dt_test.examples[0],IPExample): + if isinstance(self._dt_test.examples[0], IPExample): self._dt_test.globs = self._dt_test_globs_ori _ip.user_ns.clear() _ip.user_ns.update(self.user_ns_orig) - # Restore the behavior of the '_' key in the user namespace to - # normal after each doctest, so that unittests behave normally - _ip.user_ns.protect_underscore = False # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but # it does look like one to me: its tearDown method tries to run