From 21955d0eee8cebf78079f39c9196f1a522d3f9a5 2010-01-10 01:43:31 From: Fernando Perez Date: 2010-01-10 01:43:31 Subject: [PATCH] Fix extensions test suite (small, but now it runs and passes!) --- diff --git a/IPython/core/iplib.py b/IPython/core/iplib.py index b4fa3b7..065df5e 100644 --- a/IPython/core/iplib.py +++ b/IPython/core/iplib.py @@ -2334,7 +2334,7 @@ class InteractiveShell(Component, Magic): with prepended_to_syspath(self.ipython_extension_dir): __import__(module_str) mod = sys.modules[module_str] - self._call_load_ipython_extension(mod) + return self._call_load_ipython_extension(mod) def unload_extension(self, module_str): """Unload an IPython extension by its module name. @@ -2366,11 +2366,11 @@ class InteractiveShell(Component, Magic): def _call_load_ipython_extension(self, mod): if hasattr(mod, 'load_ipython_extension'): - mod.load_ipython_extension(self) + return mod.load_ipython_extension(self) def _call_unload_ipython_extension(self, mod): if hasattr(mod, 'unload_ipython_extension'): - mod.unload_ipython_extension(self) + return mod.unload_ipython_extension(self) #------------------------------------------------------------------------- # Things related to the prefilter diff --git a/IPython/core/magic.py b/IPython/core/magic.py index 98a844a..2f5a37f 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -3496,7 +3496,7 @@ Defaulting color scheme to 'NoColor'""" def magic_load_ext(self, module_str): """Load an IPython extension by its module name.""" - self.load_extension(module_str) + return self.load_extension(module_str) def magic_unload_ext(self, module_str): """Unload an IPython extension by its module name.""" diff --git a/IPython/core/tests/obj_del.py b/IPython/core/tests/obj_del.py deleted file mode 100644 index d925dc6..0000000 --- a/IPython/core/tests/obj_del.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Test code for https://bugs.launchpad.net/ipython/+bug/239054 - -WARNING: this script exits IPython! It MUST be run in a subprocess. - -When you run the following script from CPython it prints: -__init__ is here -__del__ is here - -and creates the __del__.txt file - -When you run it from IPython it prints: -__init__ is here - -When you exit() or Exit from IPython neothing is printed and no file is created -(the file thing is to make sure __del__ is really never called and not that -just the output is eaten). - -Note that if you call %reset in IPython then everything is Ok. - -IPython should do the equivalent of %reset and release all the references it -holds before exit. This behavior is important when working with binding objects -that rely on __del__. If the current behavior has some use case then I suggest -to add a configuration option to IPython to control it. -""" -import sys - -class A(object): - def __del__(self): - print 'obj_del.py: object A deleted' - -a = A() - -# Now, we force an exit, the caller will check that the del printout was given -_ip = get_ipython() -_ip.ask_exit() diff --git a/IPython/core/tests/tclass.py b/IPython/core/tests/tclass.py index ef2f8ea..ad2c1e6 100644 --- a/IPython/core/tests/tclass.py +++ b/IPython/core/tests/tclass.py @@ -24,6 +24,7 @@ else: c = C(name) #print >> sys.stderr, "ARGV:", sys.argv # dbg -# This print statement is NOT debugging, we're making the check on a completely -# separate process so we verify by capturing stdout. + +# This next print statement is NOT debugging, we're making the check on a +# completely separate process so we verify by capturing stdout: print 'ARGV 1-:', sys.argv[1:] diff --git a/IPython/core/tests/test_run.py b/IPython/core/tests/test_run.py index af0ce14..a6b07fe 100644 --- a/IPython/core/tests/test_run.py +++ b/IPython/core/tests/test_run.py @@ -91,24 +91,7 @@ def doctest_run_builtins(): # For some tests, it will be handy to organize them in a class with a common # setup that makes a temp file -class TempFileMixin(object): - def mktmp(self, src, ext='.py'): - """Make a valid python temp file.""" - fname, f = tt.temp_pyfile(src, ext) - self.tmpfile = f - self.fname = fname - - def teardown(self): - self.tmpfile.close() - try: - os.unlink(self.fname) - except: - # On Windows, even though we close the file, we still can't delete - # it. I have no clue why - pass - - -class TestMagicRunPass(TempFileMixin): +class TestMagicRunPass(tt.TempFileMixin): def setup(self): """Make a valid python temp file.""" @@ -148,7 +131,7 @@ class TestMagicRunPass(TempFileMixin): nt.assert_equals(p2[:3], '...') -class TestMagicRunSimple(TempFileMixin): +class TestMagicRunSimple(tt.TempFileMixin): def test_simpledef(self): """Test that simple class definitions work.""" diff --git a/IPython/extensions/parallelmagic.py b/IPython/extensions/parallelmagic.py old mode 100644 new mode 100755 index f72b3b6..cd3b48f --- a/IPython/extensions/parallelmagic.py +++ b/IPython/extensions/parallelmagic.py @@ -19,6 +19,7 @@ import new from IPython.core.component import Component from IPython.utils.traitlets import Bool, Any from IPython.utils.autoattr import auto_attr +from IPython.testing import decorators as testdec #----------------------------------------------------------------------------- # Definitions of magic functions for use with IPython @@ -58,6 +59,7 @@ class ParalleMagicComponent(Component): self.shell.define_magic('px', self.magic_px) self.shell.define_magic('autopx', self.magic_autopx) + @testdec.skip_doctest def magic_result(self, ipself, parameter_s=''): """Print the result of command i on all engines.. @@ -89,6 +91,7 @@ class ParalleMagicComponent(Component): result = self.active_multiengine_client.get_result(index) return result + @testdec.skip_doctest def magic_px(self, ipself, parameter_s=''): """Executes the given python command in parallel. @@ -112,6 +115,7 @@ class ParalleMagicComponent(Component): result = self.active_multiengine_client.execute(parameter_s) return result + @testdec.skip_doctest def magic_autopx(self, ipself, parameter_s=''): """Toggles auto parallel mode. diff --git a/IPython/extensions/pretty.py b/IPython/extensions/pretty.py index 3ff1bc3..f6448e0 100644 --- a/IPython/extensions/pretty.py +++ b/IPython/extensions/pretty.py @@ -128,13 +128,15 @@ class PrettyResultDisplay(Component): #----------------------------------------------------------------------------- -def load_ipython_extension(ip): +def load_ipython_extension(ip=None): """Load the extension in IPython as a hook.""" + if ip is None: ip = get_ipython() global _loaded if not _loaded: prd = PrettyResultDisplay(ip, name='pretty_result_display') ip.set_hook('result_display', prd, priority=99) _loaded = True + return prd def unload_ipython_extension(ip): """Unload the extension.""" @@ -163,60 +165,3 @@ def dtype_pprinter(obj, p, cycle): p.breakable() p.pretty(field) p.end_group(7, '])') - - -#----------------------------------------------------------------------------- -# Tests -#----------------------------------------------------------------------------- - - -def test_pretty(): - """ - In [1]: from IPython.extensions import ipy_pretty - - In [2]: ipy_pretty.activate() - - In [3]: class A(object): - ...: def __repr__(self): - ...: return 'A()' - ...: - ...: - - In [4]: a = A() - - In [5]: a - Out[5]: A() - - In [6]: def a_pretty_printer(obj, p, cycle): - ...: p.text('') - ...: - ...: - - In [7]: ipy_pretty.for_type(A, a_pretty_printer) - - In [8]: a - Out[8]: - - In [9]: class B(object): - ...: def __repr__(self): - ...: return 'B()' - ...: - ...: - - In [10]: B.__module__, B.__name__ - Out[10]: ('__main__', 'B') - - In [11]: def b_pretty_printer(obj, p, cycle): - ....: p.text('') - ....: - ....: - - In [12]: ipy_pretty.for_type_by_name('__main__', 'B', b_pretty_printer) - - In [13]: b = B() - - In [14]: b - Out[14]: - """ - assert False, "This should only be doctested, not run." - diff --git a/IPython/extensions/tests/test_pretty.py b/IPython/extensions/tests/test_pretty.py old mode 100644 new mode 100755 index 3f9a10b..4df8f9f --- a/IPython/extensions/tests/test_pretty.py +++ b/IPython/extensions/tests/test_pretty.py @@ -15,14 +15,13 @@ Simple tests for :mod:`IPython.extensions.pretty`. # Imports #----------------------------------------------------------------------------- -import sys from unittest import TestCase from IPython.core.component import Component, masquerade_as from IPython.core.iplib import InteractiveShell from IPython.extensions import pretty as pretty_ext from IPython.external import pretty - +from IPython.testing import tools as tt from IPython.utils.traitlets import Bool #----------------------------------------------------------------------------- @@ -43,9 +42,11 @@ class TestPrettyResultDisplay(TestCase): def setUp(self): self.ip = InteractiveShellStub(None) - # This allows our stub to be retrieved instead of the real InteractiveShell + # This allows our stub to be retrieved instead of the real + # InteractiveShell masquerade_as(self.ip, InteractiveShell) - self.prd = pretty_ext.PrettyResultDisplay(self.ip, name='pretty_result_display') + self.prd = pretty_ext.PrettyResultDisplay(self.ip, + name='pretty_result_display') def test_for_type(self): self.prd.for_type(A, a_pprinter) @@ -53,4 +54,44 @@ class TestPrettyResultDisplay(TestCase): result = pretty.pretty(a) self.assertEquals(result, "") +ipy_src = """ +class A(object): + def __repr__(self): + return 'A()' + +class B(object): + def __repr__(self): + return 'B()' + +a = A() +b = B() + +def a_pretty_printer(obj, p, cycle): + p.text('') + +def b_pretty_printer(obj, p, cycle): + p.text('') + + +a +b + +ip = get_ipython() +prd = ip.load_extension('pretty') +prd.for_type(A, a_pretty_printer) +prd.for_type_by_name(B.__module__, B.__name__, b_pretty_printer) + +a +b +""" +ipy_out = """ +A() +B() + + +""" +class TestPrettyInteractively(tt.TempFileMixin): + def test_printers(self): + self.mktmp(ipy_src, '.ipy') + tt.ipexec_validate(self.fname, ipy_out) diff --git a/IPython/testing/tools.py b/IPython/testing/tools.py index 3e53885..5b0d1e0 100644 --- a/IPython/testing/tools.py +++ b/IPython/testing/tools.py @@ -165,12 +165,12 @@ def default_argv(): from IPython.config import default ipcdir = os.path.dirname(default.__file__) ipconf = os.path.join(ipcdir,'ipython_config.py') - #print 'conf:',ipconf # dbg return ['--colors=NoColor', '--no-term-title','--no-banner', - '--config-file=%s' % ipconf, '--autocall=0', '--quick'] + '--config-file=%s' % ipconf, '--autocall=0', + '--prompt-out=""'] -def ipexec(fname): +def ipexec(fname, options=None): """Utility to call 'ipython filename'. Starts IPython witha minimal and safe configuration to make startup as fast @@ -183,19 +183,26 @@ def ipexec(fname): fname : str Name of file to be executed (should have .py or .ipy extension). + options : optional, list + Extra command-line flags to be passed to IPython. + Returns ------- (stdout, stderr) of ipython subprocess. - """ + """ + if options is None: options = [] + cmdargs = ' '.join(default_argv() + options) + _ip = get_ipython() test_dir = os.path.dirname(__file__) full_fname = os.path.join(test_dir, fname) ipython_cmd = platutils.find_cmd('ipython') - cmdargs = ' '.join(default_argv()) - return genutils.getoutputerror('%s %s' % (ipython_cmd, full_fname)) + full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname) + return genutils.getoutputerror(full_cmd) -def ipexec_validate(fname, expected_out, expected_err=None): +def ipexec_validate(fname, expected_out, expected_err=None, + options=None): """Utility to call 'ipython filename' and validate output/error. This function raises an AssertionError if the validation fails. @@ -210,6 +217,12 @@ def ipexec_validate(fname, expected_out, expected_err=None): expected_out : str Expected stdout of the process. + expected_err : optional, str + Expected stderr of the process. + + options : optional, list + Extra command-line flags to be passed to IPython. + Returns ------- None @@ -219,3 +232,25 @@ def ipexec_validate(fname, expected_out, expected_err=None): nt.assert_equals(out.strip(), expected_out.strip()) if expected_err: nt.assert_equals(err.strip(), expected_err.strip()) + + +class TempFileMixin(object): + """Utility class to create temporary Python/IPython files. + + Meant as a mixin class for test cases.""" + + def mktmp(self, src, ext='.py'): + """Make a valid python temp file.""" + fname, f = temp_pyfile(src, ext) + self.tmpfile = f + self.fname = fname + + def teardown(self): + self.tmpfile.close() + try: + os.unlink(self.fname) + except: + # On Windows, even though we close the file, we still can't delete + # it. I have no clue why + pass +