Skip to content
This repository

Tests on Python 3 #845

Merged
merged 18 commits into from over 2 years ago

3 participants

Thomas Kluyver Fernando Perez Min RK
Thomas Kluyver
Collaborator

This gets the bulk of the test suite passing on Python 3 - there's just a few isolated cases where it still doesn't.

Thomas Kluyver
Collaborator

I've added context managers for AssertPrints and AssertNotPrints, removing the need for manually switching stdout (or stderr) in each location we need to check that something is being printed.

IPython/core/page.py
@@ -68,6 +68,55 @@ def page_dumb(strng, start=0, screen_lines=25):
68 68
                 last_escape = esc_list[-1]
69 69
         print >>io.stdout, last_escape + os.linesep.join(screens[-1])
70 70
 
  71
+def _detect_screen_size(use_curses, screen_lines_def):
  72
+    if (TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5':
5
Fernando Perez Owner
fperez added a note October 08, 2011

Now that this is a function, it should have a docstring explaining its call signature.

Fernando Perez Owner
fperez added a note October 08, 2011

It should also be possible to add a small test for this guy, if nothing else at least a smoke test that validates its call form. Even simple tests like that do help catch regressions and api changes.

Thomas Kluyver Collaborator

I'll do a docstring, but the reason I pulled it out like this was that the code was throwing an exception in the test suite (Python 3 termios didn't seem to like sys.stdout not being an actual OS stream), so I wanted to put a try/except around it. So I'm not sure how we can really test it in isolation.

Fernando Perez Owner
fperez added a note October 09, 2011

Oh, the test could be just

def test_smoke():
  try:
   call_func(args)
  except ExpectedException:
    pass

at least that will call it and make sure that if we change the signature or a different exception is thrown, we see it.

As I said, it's just smoke testing so trivial to implement, but better than nothing.

Thomas Kluyver Collaborator

OK, done one like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
IPython/testing/tools.py
@@ -323,6 +325,59 @@ def check_pairs(func, pairs):
323 325
         out = func(inp)
324 326
         assert out == expected, pair_fail_msg.format(name, inp, expected, out)
325 327
 
  328
+if py3compat.PY3:
  329
+    MyStringIO = StringIO
  330
+else:
  331
+    # In Python 2, stdout/stderr can have either bytes or unicode written to them,
  332
+    # so we need a class that can handle both.
  333
+    class MyStringIO(StringIO):
  334
+        def write(self, s):
  335
+            s = py3compat.cast_unicode(s, encoding=getdefaultencoding())
  336
+            super(MyStringIO, self).write(s)
  337
+
  338
+notprinted_msg = """Did not find {0!r} in printed output (on {1}):
  339
+{2!r}"""
  340
+class AssertPrints(object):
1
Fernando Perez Owner
fperez added a note October 08, 2011

blank lines missing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Fernando Perez
Owner

Other than the small comments above, go for it. The code looks clean, thanks!

Fernando Perez
Owner

Great, ran the test suite on oneiric and all looks good. Merging now; excellent work.

Fernando Perez fperez merged commit 9b734ea into from October 09, 2011
Fernando Perez fperez closed this October 09, 2011
Thomas Kluyver
Collaborator

Great, thanks Fernando.

Min RK
Owner

@takluyver - why are you disabling our warning mechanism? Have you removed the entire utils.warn module? And if not, why only in utils.path?

Collaborator

I'm not disabling it, just switching to the standard warnings module. utils.warn's docstring says "Shoudn't we just use the built in warnings module." I came upon it because it caused some unicode/bytes friction with capturing stdout into a StringIO in the test suite. I've since resolved that friction another way, but it seemed sensible to switch to the stdlib warnings system while I had the code open.

If we're happy with using the standard library warning system, I'll look round to see where else utils.warn is used. If not, it's easy enough to change this back.

Fernando Perez fperez referenced this pull request from a commit January 10, 2012
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.

Showing 36 changed files with 450 additions and 238 deletions. Show diff stats Hide diff stats

  1. 3  IPython/core/oinspect.py
  2. 110  IPython/core/page.py
  3. 2  IPython/core/tests/test_autocall.py
  4. 37  IPython/core/tests/test_handlers.py
  5. 6  IPython/core/tests/test_history.py
  6. 78  IPython/core/tests/test_inputsplitter.py
  7. 23  IPython/core/tests/test_iplib.py
  8. 64  IPython/core/tests/test_magic.py
  9. 19  IPython/core/tests/test_page.py
  10. 16  IPython/core/tests/test_run.py
  11. 4  IPython/extensions/autoreload.py
  12. 15  IPython/extensions/tests/test_autoreload.py
  13. 2  IPython/lib/irunner.py
  14. 8  IPython/testing/_paramtestpy3.py
  15. 8  IPython/testing/plugin/dtexample.py
  16. 15  IPython/testing/plugin/test_ipdoctest.py
  17. 2  IPython/testing/plugin/test_refs.py
  18. 33  IPython/testing/tests/test_ipunittest.py
  19. 17  IPython/testing/tests/test_tools.py
  20. 63  IPython/testing/tools.py
  21. 4  IPython/utils/_process_posix.py
  22. 2  IPython/utils/frame.py
  23. 2  IPython/utils/ipstruct.py
  24. 10  IPython/utils/path.py
  25. 4  IPython/utils/pickleshare.py
  26. 2  IPython/utils/process.py
  27. 52  IPython/utils/py3compat.py
  28. 12  IPython/utils/sysinfo.py
  29. 14  IPython/utils/tests/test_io.py
  30. 13  IPython/utils/tests/test_path.py
  31. 2  IPython/utils/tests/test_process.py
  32. 2  IPython/utils/tests/test_text.py
  33. 29  IPython/utils/tests/test_traitlets.py
  34. 2  IPython/utils/warn.py
  35. 9  setup3.py
  36. 4  setupbase.py
3  IPython/core/oinspect.py
@@ -344,8 +344,7 @@ def pdoc(self,obj,oname='',formatter = None):
344 344
             if init_ds is not None:
345 345
                 lines.append(head("Constructor Docstring:"))
346 346
                 lines.append(indent(init_ds))
347  
-        elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
348  
-                 and hasattr(obj,'__call__'):
  347
+        elif hasattr(obj,'__call__'):
349 348
             call_ds = getdoc(obj.__call__)
350 349
             if call_ds:
351 350
                 lines.append(head("Calling Docstring:"))
110  IPython/core/page.py
@@ -31,6 +31,8 @@
31 31
 import sys
32 32
 import tempfile
33 33
 
  34
+from io import UnsupportedOperation
  35
+
34 36
 from IPython.core import ipapi
35 37
 from IPython.core.error import TryNext
36 38
 from IPython.utils.cursesimport import use_curses
@@ -68,6 +70,61 @@ def page_dumb(strng, start=0, screen_lines=25):
68 70
                 last_escape = esc_list[-1]
69 71
         print >>io.stdout, last_escape + os.linesep.join(screens[-1])
70 72
 
  73
+def _detect_screen_size(use_curses, screen_lines_def):
  74
+    """Attempt to work out the number of lines on the screen.
  75
+    
  76
+    This is called by page(). It can raise an error (e.g. when run in the
  77
+    test suite), so it's separated out so it can easily be called in a try block.
  78
+    """
  79
+    TERM = os.environ.get('TERM',None)
  80
+    if (TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5':
  81
+        local_use_curses = use_curses
  82
+    else:
  83
+        # curses causes problems on many terminals other than xterm, and
  84
+        # some termios calls lock up on Sun OS5.
  85
+        local_use_curses = False
  86
+    if local_use_curses:
  87
+        import termios
  88
+        import curses
  89
+        # There is a bug in curses, where *sometimes* it fails to properly
  90
+        # initialize, and then after the endwin() call is made, the
  91
+        # terminal is left in an unusable state.  Rather than trying to
  92
+        # check everytime for this (by requesting and comparing termios
  93
+        # flags each time), we just save the initial terminal state and
  94
+        # unconditionally reset it every time.  It's cheaper than making
  95
+        # the checks.
  96
+        term_flags = termios.tcgetattr(sys.stdout)
  97
+
  98
+        # Curses modifies the stdout buffer size by default, which messes
  99
+        # up Python's normal stdout buffering.  This would manifest itself
  100
+        # to IPython users as delayed printing on stdout after having used
  101
+        # the pager.
  102
+        #
  103
+        # We can prevent this by manually setting the NCURSES_NO_SETBUF
  104
+        # environment variable.  For more details, see:
  105
+        # http://bugs.python.org/issue10144
  106
+        NCURSES_NO_SETBUF = os.environ.get('NCURSES_NO_SETBUF', None)
  107
+        os.environ['NCURSES_NO_SETBUF'] = ''
  108
+        
  109
+        # Proceed with curses initialization
  110
+        scr = curses.initscr()
  111
+        screen_lines_real,screen_cols = scr.getmaxyx()
  112
+        curses.endwin()
  113
+
  114
+        # Restore environment
  115
+        if NCURSES_NO_SETBUF is None:
  116
+            del os.environ['NCURSES_NO_SETBUF']
  117
+        else:
  118
+            os.environ['NCURSES_NO_SETBUF'] = NCURSES_NO_SETBUF
  119
+            
  120
+        # Restore terminal state in case endwin() didn't.
  121
+        termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
  122
+        # Now we have what we needed: the screen size in rows/columns
  123
+        return screen_lines_real
  124
+        #print '***Screen size:',screen_lines_real,'lines x',\
  125
+        #screen_cols,'columns.' # dbg
  126
+    else:
  127
+        return screen_lines_def
71 128
 
72 129
 def page(strng, start=0, screen_lines=0, pager_cmd=None):
73 130
     """Print a string, piping through a pager after a certain length.
@@ -123,54 +180,11 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None):
123 180
 
124 181
     # auto-determine screen size
125 182
     if screen_lines <= 0:
126  
-        if (TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5':
127  
-            local_use_curses = use_curses
128  
-        else:
129  
-            # curses causes problems on many terminals other than xterm, and
130  
-            # some termios calls lock up on Sun OS5.
131  
-            local_use_curses = False
132  
-        if local_use_curses:
133  
-            import termios
134  
-            import curses
135  
-            # There is a bug in curses, where *sometimes* it fails to properly
136  
-            # initialize, and then after the endwin() call is made, the
137  
-            # terminal is left in an unusable state.  Rather than trying to
138  
-            # check everytime for this (by requesting and comparing termios
139  
-            # flags each time), we just save the initial terminal state and
140  
-            # unconditionally reset it every time.  It's cheaper than making
141  
-            # the checks.
142  
-            term_flags = termios.tcgetattr(sys.stdout)
143  
-
144  
-            # Curses modifies the stdout buffer size by default, which messes
145  
-            # up Python's normal stdout buffering.  This would manifest itself
146  
-            # to IPython users as delayed printing on stdout after having used
147  
-            # the pager.
148  
-            #
149  
-            # We can prevent this by manually setting the NCURSES_NO_SETBUF
150  
-            # environment variable.  For more details, see:
151  
-            # http://bugs.python.org/issue10144
152  
-            NCURSES_NO_SETBUF = os.environ.get('NCURSES_NO_SETBUF', None)
153  
-            os.environ['NCURSES_NO_SETBUF'] = ''
154  
-            
155  
-            # Proceed with curses initialization
156  
-            scr = curses.initscr()
157  
-            screen_lines_real,screen_cols = scr.getmaxyx()
158  
-            curses.endwin()
159  
-
160  
-            # Restore environment
161  
-            if NCURSES_NO_SETBUF is None:
162  
-                del os.environ['NCURSES_NO_SETBUF']
163  
-            else:
164  
-                os.environ['NCURSES_NO_SETBUF'] = NCURSES_NO_SETBUF
165  
-                
166  
-            # Restore terminal state in case endwin() didn't.
167  
-            termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
168  
-            # Now we have what we needed: the screen size in rows/columns
169  
-            screen_lines += screen_lines_real
170  
-            #print '***Screen size:',screen_lines_real,'lines x',\
171  
-            #screen_cols,'columns.' # dbg
172  
-        else:
173  
-            screen_lines += screen_lines_def
  183
+        try:
  184
+            screen_lines += _detect_screen_size(use_curses, screen_lines_def)
  185
+        except (TypeError, UnsupportedOperation):
  186
+            print >>io.stdout, str_toprint
  187
+            return
174 188
 
175 189
     #print 'numlines',numlines,'screenlines',screen_lines  # dbg
176 190
     if numlines <= screen_lines :
2  IPython/core/tests/test_autocall.py
@@ -5,7 +5,9 @@
5 5
 we do run the test, though ultimately this functionality should all be tested
6 6
 with better-isolated tests that don't rely on the global instance in iptest.
7 7
 """
  8
+from IPython.utils import py3compat
8 9
 
  10
+@py3compat.doctest_refactor_print
9 11
 def doctest_autocall():
10 12
     """
11 13
     In [1]: def f1(a,b,c):
37  IPython/core/tests/test_handlers.py
@@ -12,6 +12,7 @@
12 12
 from IPython.testing import decorators as dec
13 13
 from IPython.testing import tools as tt
14 14
 from IPython.testing.globalipapp import get_ipython
  15
+from IPython.utils import py3compat
15 16
 
16 17
 #-----------------------------------------------------------------------------
17 18
 # Globals
@@ -59,11 +60,12 @@ def test_handlers():
59 60
     # These are useful for checking a particular recursive alias issue
60 61
     ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
61 62
     ip.alias_manager.alias_table['d'] =   (0, 'true')
62  
-    run([("an_alias",    'get_ipython().system(u"true ")'),     # alias
  63
+    run([(i,py3compat.u_format(o)) for i,o in \
  64
+        [("an_alias",    'get_ipython().system({u}"true ")'),     # alias
63 65
          # Below: recursive aliases should expand whitespace-surrounded
64 66
          # chars, *not* initial chars which happen to be aliases:
65  
-         ("top",         'get_ipython().system(u"d:/cygwin/top ")'),
66  
-         ])
  67
+         ("top",         'get_ipython().system({u}"d:/cygwin/top ")'),
  68
+         ]])
67 69
     ip.system = old_system_cmd
68 70
 
69 71
     call_idx = CallableIndexable()
@@ -72,16 +74,17 @@ def test_handlers():
72 74
     # For many of the below, we're also checking that leading whitespace
73 75
     # turns off the esc char, which it should unless there is a continuation
74 76
     # line.
75  
-    run([('"no change"', '"no change"'),             # normal
76  
-         ("!true",       'get_ipython().system(u"true")'),      # shell_escapes
77  
-         ("!! true",     'get_ipython().magic(u"sx  true")'),   # shell_escapes + magic
78  
-         ("!!true",      'get_ipython().magic(u"sx true")'),    # shell_escapes + magic
79  
-         ("%lsmagic",    'get_ipython().magic(u"lsmagic ")'),   # magic
80  
-         ("lsmagic",     'get_ipython().magic(u"lsmagic ")'),   # magic
  77
+    run([(i,py3compat.u_format(o)) for i,o in \
  78
+        [('"no change"', '"no change"'),             # normal
  79
+         ("!true",       'get_ipython().system({u}"true")'),      # shell_escapes
  80
+         ("!! true",     'get_ipython().magic({u}"sx  true")'),   # shell_escapes + magic
  81
+         ("!!true",      'get_ipython().magic({u}"sx true")'),    # shell_escapes + magic
  82
+         ("%lsmagic",    'get_ipython().magic({u}"lsmagic ")'),   # magic
  83
+         ("lsmagic",     'get_ipython().magic({u}"lsmagic ")'),   # magic
81 84
          #("a = b # PYTHON-MODE", '_i'),          # emacs -- avoids _in cache
82 85
 
83 86
          # post-esc-char whitespace goes inside
84  
-         ("! true",   'get_ipython().system(u" true")'),
  87
+         ("! true",   'get_ipython().system({u}" true")'),
85 88
 
86 89
          # handle_help
87 90
 
@@ -90,7 +93,7 @@ def test_handlers():
90 93
          # lets us check the key paths through the handler.
91 94
 
92 95
          ("x=1 # what?", "x=1 # what?"), # no help if valid python
93  
-         ])
  96
+         ]])
94 97
 
95 98
     # multi_line_specials
96 99
     ip.prefilter_manager.multi_line_specials = False
@@ -103,12 +106,12 @@ def test_handlers():
103 106
 
104 107
     ip.prefilter_manager.multi_line_specials = True
105 108
     # initial indents must be preserved.
106  
-    run([
107  
-         ('if 1:\n    !true',    'if 1:\n    get_ipython().system(u"true")'),
108  
-         ('if 2:\n    lsmagic',  'if 2:\n    get_ipython().magic(u"lsmagic ")'),
109  
-         ('if 1:\n    an_alias', 'if 1:\n    get_ipython().system(u"true ")'),
  109
+    run([(i,py3compat.u_format(o)) for i,o in \
  110
+        [('if 1:\n    !true',    'if 1:\n    get_ipython().system({u}"true")'),
  111
+         ('if 2:\n    lsmagic',  'if 2:\n    get_ipython().magic({u}"lsmagic ")'),
  112
+         ('if 1:\n    an_alias', 'if 1:\n    get_ipython().system({u}"true ")'),
110 113
          # Weird one
111  
-         ('if 1:\n    !!true',   'if 1:\n    get_ipython().magic(u"sx true")'),
  114
+         ('if 1:\n    !!true',   'if 1:\n    get_ipython().magic({u}"sx true")'),
112 115
 
113 116
          # Even with m_l_s on, autocall is off even with special chars
114 117
          ('if 1:\n    /fun 1 2', 'if 1:\n    /fun 1 2'),
@@ -116,7 +119,7 @@ def test_handlers():
116 119
          ('if 1:\n    ,fun 1 2', 'if 1:\n    ,fun 1 2'),
117 120
          ('if 1:\n    ?fun 1 2', 'if 1:\n    ?fun 1 2'),
118 121
          # What about !!
119  
-         ])
  122
+         ]])
120 123
 
121 124
     # Objects which are instances of IPyAutocall are *always* autocalled
122 125
     autocallable = Autocallable()
6  IPython/core/tests/test_history.py
@@ -77,9 +77,9 @@ def test_history():
77 77
             # Cross testing: check that magic %save can get previous session.
78 78
             testfilename = os.path.realpath(os.path.join(tmpdir, "test.py"))
79 79
             ip.magic_save(testfilename + " ~1/1-3")
80  
-            testfile = open(testfilename, "r")
81  
-            nt.assert_equal(testfile.read().decode("utf-8"),
82  
-                    "# coding: utf-8\n" + "\n".join(hist))
  80
+            with py3compat.open(testfilename) as testfile:
  81
+                nt.assert_equal(testfile.read(),
  82
+                                        u"# coding: utf-8\n" + u"\n".join(hist))
83 83
 
84 84
             # Duplicate line numbers - check that it doesn't crash, and
85 85
             # gets a new session
78  IPython/core/tests/test_inputsplitter.py
@@ -26,6 +26,7 @@
26 26
 # Our own
27 27
 from IPython.core import inputsplitter as isp
28 28
 from IPython.testing import tools as tt
  29
+from IPython.utils import py3compat
29 30
 
30 31
 #-----------------------------------------------------------------------------
31 32
 # Semi-complete examples (also used as tests)
@@ -403,18 +404,20 @@ def transform_checker(tests, func):
403 404
 
404 405
 syntax = \
405 406
   dict(assign_system =
406  
-       [('a =! ls', 'a = get_ipython().getoutput(u"ls")'),
407  
-        ('b = !ls', 'b = get_ipython().getoutput(u"ls")'),
  407
+       [(i,py3compat.u_format(o)) for i,o in \
  408
+       [('a =! ls', 'a = get_ipython().getoutput({u}"ls")'),
  409
+        ('b = !ls', 'b = get_ipython().getoutput({u}"ls")'),
408 410
         ('x=1', 'x=1'), # normal input is unmodified
409 411
         ('    ','    '),  # blank lines are kept intact
410  
-        ],
  412
+        ]],
411 413
 
412 414
        assign_magic =
413  
-       [('a =% who', 'a = get_ipython().magic(u"who")'),
414  
-        ('b = %who', 'b = get_ipython().magic(u"who")'),
  415
+       [(i,py3compat.u_format(o)) for i,o in \
  416
+       [('a =% who', 'a = get_ipython().magic({u}"who")'),
  417
+        ('b = %who', 'b = get_ipython().magic({u}"who")'),
415 418
         ('x=1', 'x=1'), # normal input is unmodified
416 419
         ('    ','    '),  # blank lines are kept intact
417  
-        ],
  420
+        ]],
418 421
 
419 422
        classic_prompt =
420 423
        [('>>> x=1', 'x=1'),
@@ -438,41 +441,45 @@ def transform_checker(tests, func):
438 441
 
439 442
        # System calls
440 443
        escaped_shell =
441  
-       [ ('!ls', 'get_ipython().system(u"ls")'),
  444
+       [(i,py3compat.u_format(o)) for i,o in \
  445
+       [ ('!ls', 'get_ipython().system({u}"ls")'),
442 446
          # Double-escape shell, this means to capture the output of the
443 447
          # subprocess and return it
444  
-         ('!!ls', 'get_ipython().getoutput(u"ls")'),
445  
-         ],
  448
+         ('!!ls', 'get_ipython().getoutput({u}"ls")'),
  449
+         ]],
446 450
 
447 451
        # Help/object info
448 452
        escaped_help =
  453
+       [(i,py3compat.u_format(o)) for i,o in \
449 454
        [ ('?', 'get_ipython().show_usage()'),
450  
-         ('?x1', 'get_ipython().magic(u"pinfo x1")'),
451  
-         ('??x2', 'get_ipython().magic(u"pinfo2 x2")'),
452  
-         ('?a.*s', 'get_ipython().magic(u"psearch a.*s")'),
453  
-         ('?%hist', 'get_ipython().magic(u"pinfo %hist")'),
454  
-         ('?abc = qwe', 'get_ipython().magic(u"pinfo abc")'),
455  
-         ],
  455
+         ('?x1', 'get_ipython().magic({u}"pinfo x1")'),
  456
+         ('??x2', 'get_ipython().magic({u}"pinfo2 x2")'),
  457
+         ('?a.*s', 'get_ipython().magic({u}"psearch a.*s")'),
  458
+         ('?%hist', 'get_ipython().magic({u}"pinfo %hist")'),
  459
+         ('?abc = qwe', 'get_ipython().magic({u}"pinfo abc")'),
  460
+         ]],
456 461
 
457 462
       end_help =
458  
-      [ ('x3?', 'get_ipython().magic(u"pinfo x3")'),
459  
-        ('x4??', 'get_ipython().magic(u"pinfo2 x4")'),
460  
-        ('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
461  
-        ('f*?', 'get_ipython().magic(u"psearch f*")'),
462  
-        ('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
463  
-        ('a = abc?', 'get_ipython().magic(u"pinfo abc", next_input=u"a = abc")'),
464  
-        ('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe", next_input=u"a = abc.qe")'),
465  
-        ('a = *.items?', 'get_ipython().magic(u"psearch *.items", next_input=u"a = *.items")'),
466  
-        ('plot(a?', 'get_ipython().magic(u"pinfo a", next_input=u"plot(a")'),
  463
+      [(i,py3compat.u_format(o)) for i,o in \
  464
+      [ ('x3?', 'get_ipython().magic({u}"pinfo x3")'),
  465
+        ('x4??', 'get_ipython().magic({u}"pinfo2 x4")'),
  466
+        ('%hist?', 'get_ipython().magic({u}"pinfo %hist")'),
  467
+        ('f*?', 'get_ipython().magic({u}"psearch f*")'),
  468
+        ('ax.*aspe*?', 'get_ipython().magic({u}"psearch ax.*aspe*")'),
  469
+        ('a = abc?', 'get_ipython().magic({u}"pinfo abc", next_input={u}"a = abc")'),
  470
+        ('a = abc.qe??', 'get_ipython().magic({u}"pinfo2 abc.qe", next_input={u}"a = abc.qe")'),
  471
+        ('a = *.items?', 'get_ipython().magic({u}"psearch *.items", next_input={u}"a = *.items")'),
  472
+        ('plot(a?', 'get_ipython().magic({u}"pinfo a", next_input={u}"plot(a")'),
467 473
         ('a*2 #comment?', 'a*2 #comment?'),
468  
-        ],
  474
+        ]],
469 475
 
470 476
        # Explicit magic calls
471 477
        escaped_magic =
472  
-       [ ('%cd', 'get_ipython().magic(u"cd")'),
473  
-         ('%cd /home', 'get_ipython().magic(u"cd /home")'),
474  
-         ('    %magic', '    get_ipython().magic(u"magic")'),
475  
-         ],
  478
+       [(i,py3compat.u_format(o)) for i,o in \
  479
+       [ ('%cd', 'get_ipython().magic({u}"cd")'),
  480
+         ('%cd /home', 'get_ipython().magic({u}"cd /home")'),
  481
+         ('    %magic', '    get_ipython().magic({u}"magic")'),
  482
+         ]],
476 483
 
477 484
        # Quoting with separate arguments
478 485
        escaped_quote =
@@ -500,12 +507,13 @@ def transform_checker(tests, func):
500 507
 
501 508
        # Check that we transform prompts before other transforms
502 509
        mixed =
503  
-       [ ('In [1]: %lsmagic', 'get_ipython().magic(u"lsmagic")'),
504  
-         ('>>> %lsmagic', 'get_ipython().magic(u"lsmagic")'),
505  
-         ('In [2]: !ls', 'get_ipython().system(u"ls")'),
506  
-         ('In [3]: abs?', 'get_ipython().magic(u"pinfo abs")'),
507  
-         ('In [4]: b = %who', 'b = get_ipython().magic(u"who")'),
508  
-         ],
  510
+       [(i,py3compat.u_format(o)) for i,o in \
  511
+       [ ('In [1]: %lsmagic', 'get_ipython().magic({u}"lsmagic")'),
  512
+         ('>>> %lsmagic', 'get_ipython().magic({u}"lsmagic")'),
  513
+         ('In [2]: !ls', 'get_ipython().system({u}"ls")'),
  514
+         ('In [3]: abs?', 'get_ipython().magic({u}"pinfo abs")'),
  515
+         ('In [4]: b = %who', 'b = get_ipython().magic({u}"who")'),
  516
+         ]],
509 517
        )
510 518
 
511 519
 # multiline syntax examples.  Each of these should be a list of lists, with
23  IPython/core/tests/test_iplib.py
@@ -15,6 +15,7 @@
15 15
 # our own packages
16 16
 from IPython.testing import decorators as dec
17 17
 from IPython.testing.globalipapp import get_ipython
  18
+from IPython.utils import py3compat
18 19
 
19 20
 #-----------------------------------------------------------------------------
20 21
 # Globals
@@ -147,7 +148,7 @@ def doctest_tb_verbose():
147 148
 ZeroDivisionError: ...
148 149
       """
149 150
 
150  
-
  151
+@py3compat.u_format
151 152
 def doctest_tb_sysexit():
152 153
     """
153 154
 In [17]: %xmode plain
@@ -155,11 +156,11 @@ def doctest_tb_sysexit():
155 156
 
156 157
 In [18]: %run simpleerr.py exit
157 158
 An exception has occurred, use %tb to see the full traceback.
158  
-SystemExit: (1, u'Mode = exit')
  159
+SystemExit: (1, {u}'Mode = exit')
159 160
 
160 161
 In [19]: %run simpleerr.py exit 2
161 162
 An exception has occurred, use %tb to see the full traceback.
162  
-SystemExit: (2, u'Mode = exit')
  163
+SystemExit: (2, {u}'Mode = exit')
163 164
 
164 165
 In [20]: %tb
165 166
 Traceback (most recent call last):
@@ -169,7 +170,7 @@ def doctest_tb_sysexit():
169 170
     sysexit(stat, mode)
170 171
   File ... line 11, in sysexit
171 172
     raise SystemExit(stat, 'Mode = %s' % mode)
172  
-SystemExit: (2, u'Mode = exit')
  173
+SystemExit: (2, {u}'Mode = exit')
173 174
 
174 175
 In [21]: %xmode context
175 176
 Exception reporting mode: Context
@@ -197,7 +198,7 @@ def doctest_tb_sysexit():
197 198
      12 
198 199
      13 def bar(mode):
199 200
 <BLANKLINE>
200  
-SystemExit: (2, u'Mode = exit')
  201
+SystemExit: (2, {u}'Mode = exit')
201 202
 
202 203
 In [23]: %xmode verbose
203 204
 Exception reporting mode: Verbose
@@ -211,29 +212,29 @@ def doctest_tb_sysexit():
211 212
      31 
212 213
 ---> 32     bar(mode)
213 214
         global bar = <function bar at ...>
214  
-        global mode = u'exit'
  215
+        global mode = {u}'exit'
215 216
 <BLANKLINE>
216  
-... in bar(mode=u'exit')
  217
+... in bar(mode={u}'exit')
217 218
      20         except:
218 219
      21             stat = 1
219 220
 ---> 22         sysexit(stat, mode)
220 221
         global sysexit = <function sysexit at ...>
221 222
         stat = 2
222  
-        mode = u'exit'
  223
+        mode = {u}'exit'
223 224
      23     else:
224 225
      24         raise ValueError('Unknown mode')
225 226
 <BLANKLINE>
226  
-... in sysexit(stat=2, mode=u'exit')
  227
+... in sysexit(stat=2, mode={u}'exit')
227 228
       9 
228 229
      10 def sysexit(stat, mode):
229 230
 ---> 11     raise SystemExit(stat, 'Mode = %s' % mode)
230 231
         global SystemExit = undefined
231 232
         stat = 2
232  
-        mode = u'exit'
  233
+        mode = {u}'exit'
233 234
      12 
234 235
      13 def bar(mode):
235 236
 <BLANKLINE>
236  
-SystemExit: (2, u'Mode = exit')
  237
+SystemExit: (2, {u}'Mode = exit')
237 238
     """
238 239
 
239 240
 
64  IPython/core/tests/test_magic.py
@@ -19,6 +19,7 @@
19 19
 from IPython.utils.path import get_long_path_name
20 20
 from IPython.testing import decorators as dec
21 21
 from IPython.testing import tools as tt
  22
+from IPython.utils import py3compat
22 23
 
23 24
 #-----------------------------------------------------------------------------
24 25
 # Test functions begin
@@ -88,20 +89,20 @@ def doctest_hist_r():
88 89
 def doctest_hist_op():
89 90
     """Test %hist -op
90 91
 
91  
-    In [1]: class b:
92  
-       ...:         pass
  92
+    In [1]: class b(float):
  93
+       ...:     pass
93 94
        ...: 
94 95
 
95  
-    In [2]: class s(b):
96  
-       ...:         def __str__(self):
97  
-       ...:             return 's'
  96
+    In [2]: class s(object):
  97
+       ...:     def __str__(self):
  98
+       ...:         return 's'
98 99
        ...: 
99 100
 
100 101
     In [3]: 
101 102
 
102 103
     In [4]: class r(b):
103  
-       ...:         def __repr__(self):
104  
-       ...:             return 'r'
  104
+       ...:     def __repr__(self):
  105
+       ...:         return 'r'
105 106
        ...: 
106 107
 
107 108
     In [5]: class sr(s,r): pass
@@ -117,11 +118,11 @@ def doctest_hist_op():
117 118
 
118 119
     In [10]: ssrr=sr()
119 120
 
120  
-    In [11]: bb
121  
-    Out[11]: <...b instance at ...>
  121
+    In [11]: 4.5
  122
+    Out[11]: 4.5
122 123
 
123  
-    In [12]: ss
124  
-    Out[12]: <...s instance at ...>
  124
+    In [12]: str(ss)
  125
+    Out[12]: 's'
125 126
 
126 127
     In [13]: 
127 128
 
@@ -144,10 +145,10 @@ def doctest_hist_op():
144 145
     >>> ss=s()
145 146
     >>> rr=r()
146 147
     >>> ssrr=sr()
147  
-    >>> bb
148  
-    <...b instance at ...>
149  
-    >>> ss
150  
-    <...s instance at ...>
  148
+    >>> 4.5
  149
+    4.5
  150
+    >>> str(ss)
  151
+    's'
151 152
     >>> 
152 153
     """
153 154
   
@@ -167,21 +168,16 @@ def test_macro_run():
167 168
     """Test that we can run a multi-line macro successfully."""
168 169
     ip = get_ipython()
169 170
     ip.history_manager.reset()
170  
-    cmds = ["a=10", "a+=1", "print a", "%macro test 2-3"]
  171
+    cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
  172
+                                                            "%macro test 2-3"]
171 173
     for cmd in cmds:
172 174
         ip.run_cell(cmd)
173  
-    nt.assert_equal(ip.user_ns["test"].value, "a+=1\nprint a\n")
174  
-    original_stdout = sys.stdout
175  
-    new_stdout = StringIO()
176  
-    sys.stdout = new_stdout
177  
-    try:
  175
+    nt.assert_equal(ip.user_ns["test"].value,
  176
+                            py3compat.doctest_refactor_print("a+=1\nprint a\n"))
  177
+    with tt.AssertPrints("12"):
178 178
         ip.run_cell("test")
179  
-        nt.assert_true("12" in new_stdout.getvalue())
  179
+    with tt.AssertPrints("13"):
180 180
         ip.run_cell("test")
181  
-        nt.assert_true("13" in new_stdout.getvalue())
182  
-    finally:
183  
-        sys.stdout = original_stdout
184  
-        new_stdout.close()
185 181
 
186 182
     
187 183
 # XXX failing for now, until we get clearcmd out of quarantine.  But we should
@@ -213,11 +209,6 @@ def paste(txt, flags='-q'):
213 209
     original_clip = hooks.clipboard_get
214 210
 
215 211
     try:
216  
-        # This try/except with an emtpy except clause is here only because
217  
-        # try/yield/finally is invalid syntax in Python 2.4.  This will be
218  
-        # removed when we drop 2.4-compatibility, and the emtpy except below
219  
-        # will be changed to a finally.
220  
-
221 212
         # Run tests with fake clipboard function
222 213
         user_ns.pop('x', None)
223 214
         paste('x=1')
@@ -260,7 +251,6 @@ def paste(txt, flags='-q'):
260 251
         yield nt.assert_equal(out, code+"\n## -- End pasted text --\n")
261 252
         
262 253
     finally:
263  
-        # This should be in a finally clause, instead of the bare except above.
264 254
         # Restore original hook
265 255
         hooks.clipboard_get = original_clip
266 256
 
@@ -269,6 +259,7 @@ def test_time():
269 259
     _ip.magic('time None')
270 260
 
271 261
 
  262
+@py3compat.doctest_refactor_print
272 263
 def doctest_time():
273 264
     """
274 265
     In [10]: %time None
@@ -442,21 +433,22 @@ def doctest_who():
442 433
     Out[7]: ['alpha', 'beta']
443 434
     """
444 435
 
  436
+@py3compat.u_format
445 437
 def doctest_precision():
446 438
     """doctest for %precision
447 439
     
448 440
     In [1]: f = get_ipython().shell.display_formatter.formatters['text/plain']
449 441
     
450 442
     In [2]: %precision 5
451  
-    Out[2]: u'%.5f'
  443
+    Out[2]: {u}'%.5f'
452 444
     
453 445
     In [3]: f.float_format
454  
-    Out[3]: u'%.5f'
  446
+    Out[3]: {u}'%.5f'
455 447
     
456 448
     In [4]: %precision %e
457  
-    Out[4]: u'%e'
  449
+    Out[4]: {u}'%e'
458 450
     
459 451
     In [5]: f(3.1415927)
460  
-    Out[5]: u'3.141593e+00'
  452
+    Out[5]: {u}'3.141593e+00'
461 453
     """
462 454
 
19  IPython/core/tests/test_page.py
... ...
@@ -0,0 +1,19 @@
  1
+#-----------------------------------------------------------------------------
  2
+#  Copyright (C) 2010 The IPython Development Team.
  3
+#
  4
+#  Distributed under the terms of the BSD License.
  5
+#
  6
+#  The full license is in the file COPYING.txt, distributed with this software.
  7
+#-----------------------------------------------------------------------------
  8
+import io
  9
+
  10
+from IPython.core import page
  11
+
  12
+def test_detect_screen_size():
  13
+    """Simple smoketest for page._detect_screen_size."""
  14
+    try:
  15
+        page._detect_screen_size(True, 25)
  16
+    except (TypeError, io.UnsupportedOperation):
  17
+        # This can happen in the test suite, because stdout may not have a
  18
+        # fileno.
  19
+        pass
16  IPython/core/tests/test_run.py
@@ -21,6 +21,7 @@
21 21
 
22 22
 from IPython.testing import decorators as dec
23 23
 from IPython.testing import tools as tt
  24
+from IPython.utils import py3compat
24 25
 
25 26
 #-----------------------------------------------------------------------------
26 27
 # Test functions begin
@@ -57,7 +58,7 @@ def doctest_run_builtins():
57 58
 
58 59
     In [3]: f = open(fname,'w')
59 60
 
60  
-    In [4]: f.write('pass\n')
  61
+    In [4]: dummy= f.write('pass\n')
61 62
 
62 63
     In [5]: f.flush()
63 64
 
@@ -84,6 +85,7 @@ def doctest_run_builtins():
84 85
        ....:
85 86
     """
86 87
 
  88
+@py3compat.doctest_refactor_print
87 89
 def doctest_reset_del():
88 90
     """Test that resetting doesn't cause errors in __del__ methods.
89 91
 
@@ -166,7 +168,7 @@ def test_obj_del(self):
166 168
                "    def __del__(self):\n"
167 169
                "        print 'object A deleted'\n"
168 170
                "a = A()\n")
169  
-        self.mktmp(src)
  171
+        self.mktmp(py3compat.doctest_refactor_print(src))
170 172
         tt.ipexec_validate(self.fname, 'object A deleted')
171 173
 
172 174
     @dec.skip_known_failure
@@ -184,7 +186,7 @@ class secondtmp(tt.TempFileMixin): pass
184 186
                "       ip.magic('run %s')\n"
185 187
                "   except NameError, e:\n"
186 188
                "       print i;break\n" % empty.fname)
187  
-        self.mktmp(src)
  189
+        self.mktmp(py3compat.doctest_refactor_print(src))
188 190
         _ip.magic('run %s' % self.fname)
189 191
         _ip.run_cell('ip == get_ipython()')
190 192
         tt.assert_equals(_ip.user_ns['i'], 5)
@@ -198,11 +200,11 @@ def test_tclass(self):
198 200
                "%%run '%s' C-third\n") % (tc, tc, tc)
199 201
         self.mktmp(src, '.ipy')
200 202
         out = """\
201  
-ARGV 1-: [u'C-first']
202  
-ARGV 1-: [u'C-second']
  203
+ARGV 1-: [{u}'C-first']
  204
+ARGV 1-: [{u}'C-second']
203 205
 tclass.py: deleting object: C-first
204  
-ARGV 1-: [u'C-third']
  206
+ARGV 1-: [{u}'C-third']
205 207
 tclass.py: deleting object: C-second
206 208
 tclass.py: deleting object: C-third
207 209
 """
208  
-        tt.ipexec_validate(self.fname, out)
  210
+        tt.ipexec_validate(self.fname, py3compat.u_format(out))
4  IPython/extensions/autoreload.py
@@ -103,6 +103,10 @@
103 103
 
104 104
 import time, os, threading, sys, types, imp, inspect, traceback, atexit
105 105
 import weakref
  106
+try:
  107
+    reload
  108
+except NameError:
  109
+    from imp import reload
106 110
 
107 111
 def _get_compiled_ext():
108 112
     """Official way to get the extension of compiled files (.pyc or .pyo)"""
15  IPython/extensions/tests/test_autoreload.py
@@ -7,6 +7,7 @@
7 7
 from StringIO import StringIO
8 8
 
9 9
 import nose.tools as nt
  10
+import IPython.testing.tools as tt
10 11
 
11 12
 from IPython.extensions.autoreload import AutoreloadInterface
12 13
 from IPython.core.hooks import TryNext
@@ -197,19 +198,11 @@ def check_module_contents():
197 198
 a syntax error
198 199
 """)
199 200
 
200  
-        old_stderr = sys.stderr
201  
-        new_stderr = StringIO()
202  
-        sys.stderr = new_stderr
203  
-        try:
  201
+        with tt.AssertPrints(('[autoreload of %s failed:' % mod_name), channel='stderr'):
204 202
             self.shell.run_code("pass") # trigger reload
  203
+        with tt.AssertNotPrints(('[autoreload of %s failed:' % mod_name), channel='stderr'):
205 204
             self.shell.run_code("pass") # trigger another reload
206  
-            check_module_contents()
207  
-        finally:
208  
-            sys.stderr = old_stderr
209  
-
210  
-        nt.assert_true(('[autoreload of %s failed:' % mod_name) in
211  
-                       new_stderr.getvalue())
212  
-        nt.assert_equal(new_stderr.getvalue().count('[autoreload of'), 1)
  205
+        check_module_contents()
213 206
 
214 207
         #
215 208
         # Rewrite module (this time reload should succeed)
2  IPython/lib/irunner.py
@@ -189,7 +189,7 @@ def run_source(self,source,interact=False,get_output=False):
189 189
 
190 190
         # if the source is a string, chop it up in lines so we can iterate
191 191
         # over it just as if it were an open file.
192  
-        if not isinstance(source,file):
  192
+        if isinstance(source, basestring):
193 193
             source = source.splitlines(True)
194 194
 
195 195
         if self.echo:
8  IPython/testing/_paramtestpy3.py
@@ -46,9 +46,11 @@ def run(self, result=None):
46 46
        # For normal tests, we just call the base class and return that
47 47
        if isgenerator(testMethod):
48 48
            def adapter(next_test):
49  
-               return unittest.FunctionTestCase(next_test,
50  
-                                                self.setUp,
51  
-                                                self.tearDown)
  49
+               ftc = unittest.FunctionTestCase(next_test,
  50
+                                               self.setUp,
  51
+                                               self.tearDown)
  52
+               self._nose_case = ftc   # Nose 1.0 rejects the test without this
  53
+               return ftc
52 54
 
53 55
            return IterCallableSuite(testMethod(),adapter).run(result)
54 56
        else:
8  IPython/testing/plugin/dtexample.py
@@ -3,6 +3,7 @@
3 3
 This file just contains doctests both using plain python and IPython prompts.
4 4
 All tests should be loaded by nose.
5 5
 """
  6
+from IPython.utils.py3compat import doctest_refactor_print
6 7
 
7 8
 def pyfunc():
8 9
     """Some pure python tests...
@@ -23,7 +24,7 @@ def pyfunc():
23 24
     """
24 25
     return 'pyfunc'
25 26
 
26  
-
  27
+@doctest_refactor_print
27 28
 def ipfunc():
28 29
     """Some ipython tests...
29 30
 
@@ -127,7 +128,7 @@ def random_all():
127 128
     """
128 129
     pass
129 130
 
130  
-
  131
+@doctest_refactor_print
131 132
 def iprand():
132 133
     """Some ipython tests with random output.
133 134
 
@@ -142,7 +143,7 @@ def iprand():
142 143
     """
143 144
     return 'iprand'
144 145
 
145  
-
  146
+@doctest_refactor_print
146 147
 def iprand_all():
147 148
     """Some ipython tests with fully random output.
148 149
 
@@ -160,3 +161,4 @@ def iprand_all():
160 161
     return 'iprand_all'
161 162
 
162 163
 
  164
+    
15  IPython/testing/plugin/test_ipdoctest.py
@@ -6,7 +6,9 @@
6 6
 empty function call is counted as a test, which just inflates tests numbers
7 7
 artificially).
8 8
 """
  9
+from IPython.utils.py3compat import doctest_refactor_print
9 10
 
  11
+@doctest_refactor_print
10 12
 def doctest_simple():
11 13
     """ipdoctest must handle simple inputs
12 14
     
@@ -17,17 +19,20 @@ def doctest_simple():
17 19
     1
18 20
     """
19 21
 
20  
-
  22
+@doctest_refactor_print
21 23
 def doctest_multiline1():
22 24
     """The ipdoctest machinery must handle multiline examples gracefully.
23 25
 
24  
-    In [2]: for i in range(10):
25  
-       ...:     print i,
  26
+    In [2]: for i in range(4):
  27
+       ...:     print i
26 28
        ...:      
27  
-    0 1 2 3 4 5 6 7 8 9
  29
+    0
  30
+    1
  31
+    2
  32
+    3
28 33
     """
29 34
 
30  
-    
  35
+@doctest_refactor_print
31 36
 def doctest_multiline2():
32 37
     """Multiline examples that define functions and print output.
33 38
 
2  IPython/testing/plugin/test_refs.py
@@ -42,5 +42,5 @@ def doctest_refs():
42 42
     """DocTest reference holding issues when running scripts.
43 43
 
44 44
     In [32]: run show_refs.py
45  
-    c referrers: [<type 'dict'>]
  45
+    c referrers: [<... 'dict'>]
46 46
     """
33  IPython/testing/tests/test_ipunittest.py
@@ -46,11 +46,13 @@
46 46
 #-----------------------------------------------------------------------------
47 47
 
48 48
 from IPython.testing.ipunittest import ipdoctest, ipdocstring
  49
+from IPython.utils.py3compat import doctest_refactor_print
49 50
 
50 51
 #-----------------------------------------------------------------------------
51 52
 # Test classes and functions
52 53
 #-----------------------------------------------------------------------------
53 54
 @ipdoctest
  55
+@doctest_refactor_print
54 56
 def simple_dt():
55 57
     """
56 58
     >>> print 1+1
@@ -59,16 +61,20 @@ def simple_dt():
59 61
 
60 62
 
61 63
 @ipdoctest
  64
+@doctest_refactor_print
62 65
 def ipdt_flush():
63 66
     """
64 67
 In [20]: print 1
65 68
 1
66 69
 
67  
-In [26]: for i in range(10):
68  
-   ....:     print i,
  70
+In [26]: for i in range(4):
  71
+   ....:     print i
69 72
    ....:     
70 73
    ....: 
71  
-0 1 2 3 4 5 6 7 8 9
  74
+0
  75
+1
  76
+2
  77
+3
72 78
 
73 79
 In [27]: 3+4
74 80
 Out[27]: 7
@@ -76,16 +82,20 @@ def ipdt_flush():
76 82
 
77 83
 
78 84
 @ipdoctest
  85
+@doctest_refactor_print
79 86
 def ipdt_indented_test():
80 87
     """
81 88
     In [20]: print 1
82 89
     1
83 90
 
84  
-    In [26]: for i in range(10):
85  
-       ....:     print i,
  91
+    In [26]: for i in range(4):
  92
+       ....:     print i
86 93
        ....:     
87 94
        ....: 
88  
-    0 1 2 3 4 5 6 7 8 9
  95
+    0
  96
+    1
  97
+    2
  98
+    3
89 99
 
90 100
     In [27]: 3+4
91 101
     Out[27]: 7
@@ -100,21 +110,26 @@ class Foo(object):
100 110
     """
101 111
 
102 112
     @ipdocstring
  113
+    @doctest_refactor_print
103 114
     def ipdt_method(self):
104 115
         """
105 116
         In [20]: print 1
106 117
         1
107 118
 
108  
-        In [26]: for i in range(10):
109  
-           ....:     print i,
  119
+        In [26]: for i in range(4):
  120
+           ....:     print i
110 121
            ....:     
111 122
            ....: 
112