Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests on Python 3 #845

Merged
merged 18 commits into from
Oct 9, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions IPython/core/oinspect.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -344,8 +344,7 @@ def pdoc(self,obj,oname='',formatter = None):
if init_ds is not None: if init_ds is not None:
lines.append(head("Constructor Docstring:")) lines.append(head("Constructor Docstring:"))
lines.append(indent(init_ds)) lines.append(indent(init_ds))
elif (type(obj) is types.InstanceType or isinstance(obj,object)) \ elif hasattr(obj,'__call__'):
and hasattr(obj,'__call__'):
call_ds = getdoc(obj.__call__) call_ds = getdoc(obj.__call__)
if call_ds: if call_ds:
lines.append(head("Calling Docstring:")) lines.append(head("Calling Docstring:"))
Expand Down
110 changes: 62 additions & 48 deletions IPython/core/page.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import sys import sys
import tempfile import tempfile


from io import UnsupportedOperation

from IPython.core import ipapi from IPython.core import ipapi
from IPython.core.error import TryNext from IPython.core.error import TryNext
from IPython.utils.cursesimport import use_curses from IPython.utils.cursesimport import use_curses
Expand Down Expand Up @@ -68,6 +70,61 @@ def page_dumb(strng, start=0, screen_lines=25):
last_escape = esc_list[-1] last_escape = esc_list[-1]
print >>io.stdout, last_escape + os.linesep.join(screens[-1]) print >>io.stdout, last_escape + os.linesep.join(screens[-1])


def _detect_screen_size(use_curses, screen_lines_def):
"""Attempt to work out the number of lines on the screen.

This is called by page(). It can raise an error (e.g. when run in the
test suite), so it's separated out so it can easily be called in a try block.
"""
TERM = os.environ.get('TERM',None)
if (TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, done one like that.

local_use_curses = use_curses
else:
# curses causes problems on many terminals other than xterm, and
# some termios calls lock up on Sun OS5.
local_use_curses = False
if local_use_curses:
import termios
import curses
# There is a bug in curses, where *sometimes* it fails to properly
# initialize, and then after the endwin() call is made, the
# terminal is left in an unusable state. Rather than trying to
# check everytime for this (by requesting and comparing termios
# flags each time), we just save the initial terminal state and
# unconditionally reset it every time. It's cheaper than making
# the checks.
term_flags = termios.tcgetattr(sys.stdout)

# Curses modifies the stdout buffer size by default, which messes
# up Python's normal stdout buffering. This would manifest itself
# to IPython users as delayed printing on stdout after having used
# the pager.
#
# We can prevent this by manually setting the NCURSES_NO_SETBUF
# environment variable. For more details, see:
# http://bugs.python.org/issue10144
NCURSES_NO_SETBUF = os.environ.get('NCURSES_NO_SETBUF', None)
os.environ['NCURSES_NO_SETBUF'] = ''

# Proceed with curses initialization
scr = curses.initscr()
screen_lines_real,screen_cols = scr.getmaxyx()
curses.endwin()

# Restore environment
if NCURSES_NO_SETBUF is None:
del os.environ['NCURSES_NO_SETBUF']
else:
os.environ['NCURSES_NO_SETBUF'] = NCURSES_NO_SETBUF

# Restore terminal state in case endwin() didn't.
termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
# Now we have what we needed: the screen size in rows/columns
return screen_lines_real
#print '***Screen size:',screen_lines_real,'lines x',\
#screen_cols,'columns.' # dbg
else:
return screen_lines_def


def page(strng, start=0, screen_lines=0, pager_cmd=None): def page(strng, start=0, screen_lines=0, pager_cmd=None):
"""Print a string, piping through a pager after a certain length. """Print a string, piping through a pager after a certain length.
Expand Down Expand Up @@ -123,54 +180,11 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None):


# auto-determine screen size # auto-determine screen size
if screen_lines <= 0: if screen_lines <= 0:
if (TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5': try:
local_use_curses = use_curses screen_lines += _detect_screen_size(use_curses, screen_lines_def)
else: except (TypeError, UnsupportedOperation):
# curses causes problems on many terminals other than xterm, and print >>io.stdout, str_toprint
# some termios calls lock up on Sun OS5. return
local_use_curses = False
if local_use_curses:
import termios
import curses
# There is a bug in curses, where *sometimes* it fails to properly
# initialize, and then after the endwin() call is made, the
# terminal is left in an unusable state. Rather than trying to
# check everytime for this (by requesting and comparing termios
# flags each time), we just save the initial terminal state and
# unconditionally reset it every time. It's cheaper than making
# the checks.
term_flags = termios.tcgetattr(sys.stdout)

# Curses modifies the stdout buffer size by default, which messes
# up Python's normal stdout buffering. This would manifest itself
# to IPython users as delayed printing on stdout after having used
# the pager.
#
# We can prevent this by manually setting the NCURSES_NO_SETBUF
# environment variable. For more details, see:
# http://bugs.python.org/issue10144
NCURSES_NO_SETBUF = os.environ.get('NCURSES_NO_SETBUF', None)
os.environ['NCURSES_NO_SETBUF'] = ''

# Proceed with curses initialization
scr = curses.initscr()
screen_lines_real,screen_cols = scr.getmaxyx()
curses.endwin()

# Restore environment
if NCURSES_NO_SETBUF is None:
del os.environ['NCURSES_NO_SETBUF']
else:
os.environ['NCURSES_NO_SETBUF'] = NCURSES_NO_SETBUF

# Restore terminal state in case endwin() didn't.
termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
# Now we have what we needed: the screen size in rows/columns
screen_lines += screen_lines_real
#print '***Screen size:',screen_lines_real,'lines x',\
#screen_cols,'columns.' # dbg
else:
screen_lines += screen_lines_def


#print 'numlines',numlines,'screenlines',screen_lines # dbg #print 'numlines',numlines,'screenlines',screen_lines # dbg
if numlines <= screen_lines : if numlines <= screen_lines :
Expand Down
2 changes: 2 additions & 0 deletions IPython/core/tests/test_autocall.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
we do run the test, though ultimately this functionality should all be tested we do run the test, though ultimately this functionality should all be tested
with better-isolated tests that don't rely on the global instance in iptest. with better-isolated tests that don't rely on the global instance in iptest.
""" """
from IPython.utils import py3compat


@py3compat.doctest_refactor_print
def doctest_autocall(): def doctest_autocall():
""" """
In [1]: def f1(a,b,c): In [1]: def f1(a,b,c):
Expand Down
37 changes: 20 additions & 17 deletions IPython/core/tests/test_handlers.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from IPython.testing import decorators as dec from IPython.testing import decorators as dec
from IPython.testing import tools as tt from IPython.testing import tools as tt
from IPython.testing.globalipapp import get_ipython from IPython.testing.globalipapp import get_ipython
from IPython.utils import py3compat


#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# Globals # Globals
Expand Down Expand Up @@ -59,11 +60,12 @@ def test_handlers():
# These are useful for checking a particular recursive alias issue # These are useful for checking a particular recursive alias issue
ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top') ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
ip.alias_manager.alias_table['d'] = (0, 'true') ip.alias_manager.alias_table['d'] = (0, 'true')
run([("an_alias", 'get_ipython().system(u"true ")'), # alias run([(i,py3compat.u_format(o)) for i,o in \
[("an_alias", 'get_ipython().system({u}"true ")'), # alias
# Below: recursive aliases should expand whitespace-surrounded # Below: recursive aliases should expand whitespace-surrounded
# chars, *not* initial chars which happen to be aliases: # chars, *not* initial chars which happen to be aliases:
("top", 'get_ipython().system(u"d:/cygwin/top ")'), ("top", 'get_ipython().system({u}"d:/cygwin/top ")'),
]) ]])
ip.system = old_system_cmd ip.system = old_system_cmd


call_idx = CallableIndexable() call_idx = CallableIndexable()
Expand All @@ -72,16 +74,17 @@ def test_handlers():
# For many of the below, we're also checking that leading whitespace # For many of the below, we're also checking that leading whitespace
# turns off the esc char, which it should unless there is a continuation # turns off the esc char, which it should unless there is a continuation
# line. # line.
run([('"no change"', '"no change"'), # normal run([(i,py3compat.u_format(o)) for i,o in \
("!true", 'get_ipython().system(u"true")'), # shell_escapes [('"no change"', '"no change"'), # normal
("!! true", 'get_ipython().magic(u"sx true")'), # shell_escapes + magic ("!true", 'get_ipython().system({u}"true")'), # shell_escapes
("!!true", 'get_ipython().magic(u"sx true")'), # shell_escapes + magic ("!! true", 'get_ipython().magic({u}"sx true")'), # shell_escapes + magic
("%lsmagic", 'get_ipython().magic(u"lsmagic ")'), # magic ("!!true", 'get_ipython().magic({u}"sx true")'), # shell_escapes + magic
("lsmagic", 'get_ipython().magic(u"lsmagic ")'), # magic ("%lsmagic", 'get_ipython().magic({u}"lsmagic ")'), # magic
("lsmagic", 'get_ipython().magic({u}"lsmagic ")'), # magic
#("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache


# post-esc-char whitespace goes inside # post-esc-char whitespace goes inside
("! true", 'get_ipython().system(u" true")'), ("! true", 'get_ipython().system({u}" true")'),


# handle_help # handle_help


Expand All @@ -90,7 +93,7 @@ def test_handlers():
# lets us check the key paths through the handler. # lets us check the key paths through the handler.


("x=1 # what?", "x=1 # what?"), # no help if valid python ("x=1 # what?", "x=1 # what?"), # no help if valid python
]) ]])


# multi_line_specials # multi_line_specials
ip.prefilter_manager.multi_line_specials = False ip.prefilter_manager.multi_line_specials = False
Expand All @@ -103,20 +106,20 @@ def test_handlers():


ip.prefilter_manager.multi_line_specials = True ip.prefilter_manager.multi_line_specials = True
# initial indents must be preserved. # initial indents must be preserved.
run([ run([(i,py3compat.u_format(o)) for i,o in \
('if 1:\n !true', 'if 1:\n get_ipython().system(u"true")'), [('if 1:\n !true', 'if 1:\n get_ipython().system({u}"true")'),
('if 2:\n lsmagic', 'if 2:\n get_ipython().magic(u"lsmagic ")'), ('if 2:\n lsmagic', 'if 2:\n get_ipython().magic({u}"lsmagic ")'),
('if 1:\n an_alias', 'if 1:\n get_ipython().system(u"true ")'), ('if 1:\n an_alias', 'if 1:\n get_ipython().system({u}"true ")'),
# Weird one # Weird one
('if 1:\n !!true', 'if 1:\n get_ipython().magic(u"sx true")'), ('if 1:\n !!true', 'if 1:\n get_ipython().magic({u}"sx true")'),


# Even with m_l_s on, autocall is off even with special chars # Even with m_l_s on, autocall is off even with special chars
('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'), ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'),
('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'), ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'),
('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'), ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'),
('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'), ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'),
# What about !! # What about !!
]) ]])


# Objects which are instances of IPyAutocall are *always* autocalled # Objects which are instances of IPyAutocall are *always* autocalled
autocallable = Autocallable() autocallable = Autocallable()
Expand Down
6 changes: 3 additions & 3 deletions IPython/core/tests/test_history.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ def test_history():
# Cross testing: check that magic %save can get previous session. # Cross testing: check that magic %save can get previous session.
testfilename = os.path.realpath(os.path.join(tmpdir, "test.py")) testfilename = os.path.realpath(os.path.join(tmpdir, "test.py"))
ip.magic_save(testfilename + " ~1/1-3") ip.magic_save(testfilename + " ~1/1-3")
testfile = open(testfilename, "r") with py3compat.open(testfilename) as testfile:
nt.assert_equal(testfile.read().decode("utf-8"), nt.assert_equal(testfile.read(),
"# coding: utf-8\n" + "\n".join(hist)) u"# coding: utf-8\n" + u"\n".join(hist))


# Duplicate line numbers - check that it doesn't crash, and # Duplicate line numbers - check that it doesn't crash, and
# gets a new session # gets a new session
Expand Down
78 changes: 43 additions & 35 deletions IPython/core/tests/test_inputsplitter.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
# Our own # Our own
from IPython.core import inputsplitter as isp from IPython.core import inputsplitter as isp
from IPython.testing import tools as tt from IPython.testing import tools as tt
from IPython.utils import py3compat


#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# Semi-complete examples (also used as tests) # Semi-complete examples (also used as tests)
Expand Down Expand Up @@ -403,18 +404,20 @@ def transform_checker(tests, func):


syntax = \ syntax = \
dict(assign_system = dict(assign_system =
[('a =! ls', 'a = get_ipython().getoutput(u"ls")'), [(i,py3compat.u_format(o)) for i,o in \
('b = !ls', 'b = get_ipython().getoutput(u"ls")'), [('a =! ls', 'a = get_ipython().getoutput({u}"ls")'),
('b = !ls', 'b = get_ipython().getoutput({u}"ls")'),
('x=1', 'x=1'), # normal input is unmodified ('x=1', 'x=1'), # normal input is unmodified
(' ',' '), # blank lines are kept intact (' ',' '), # blank lines are kept intact
], ]],


assign_magic = assign_magic =
[('a =% who', 'a = get_ipython().magic(u"who")'), [(i,py3compat.u_format(o)) for i,o in \
('b = %who', 'b = get_ipython().magic(u"who")'), [('a =% who', 'a = get_ipython().magic({u}"who")'),
('b = %who', 'b = get_ipython().magic({u}"who")'),
('x=1', 'x=1'), # normal input is unmodified ('x=1', 'x=1'), # normal input is unmodified
(' ',' '), # blank lines are kept intact (' ',' '), # blank lines are kept intact
], ]],


classic_prompt = classic_prompt =
[('>>> x=1', 'x=1'), [('>>> x=1', 'x=1'),
Expand All @@ -438,41 +441,45 @@ def transform_checker(tests, func):


# System calls # System calls
escaped_shell = escaped_shell =
[ ('!ls', 'get_ipython().system(u"ls")'), [(i,py3compat.u_format(o)) for i,o in \
[ ('!ls', 'get_ipython().system({u}"ls")'),
# Double-escape shell, this means to capture the output of the # Double-escape shell, this means to capture the output of the
# subprocess and return it # subprocess and return it
('!!ls', 'get_ipython().getoutput(u"ls")'), ('!!ls', 'get_ipython().getoutput({u}"ls")'),
], ]],


# Help/object info # Help/object info
escaped_help = escaped_help =
[(i,py3compat.u_format(o)) for i,o in \
[ ('?', 'get_ipython().show_usage()'), [ ('?', 'get_ipython().show_usage()'),
('?x1', 'get_ipython().magic(u"pinfo x1")'), ('?x1', 'get_ipython().magic({u}"pinfo x1")'),
('??x2', 'get_ipython().magic(u"pinfo2 x2")'), ('??x2', 'get_ipython().magic({u}"pinfo2 x2")'),
('?a.*s', 'get_ipython().magic(u"psearch a.*s")'), ('?a.*s', 'get_ipython().magic({u}"psearch a.*s")'),
('?%hist', 'get_ipython().magic(u"pinfo %hist")'), ('?%hist', 'get_ipython().magic({u}"pinfo %hist")'),
('?abc = qwe', 'get_ipython().magic(u"pinfo abc")'), ('?abc = qwe', 'get_ipython().magic({u}"pinfo abc")'),
], ]],


end_help = end_help =
[ ('x3?', 'get_ipython().magic(u"pinfo x3")'), [(i,py3compat.u_format(o)) for i,o in \
('x4??', 'get_ipython().magic(u"pinfo2 x4")'), [ ('x3?', 'get_ipython().magic({u}"pinfo x3")'),
('%hist?', 'get_ipython().magic(u"pinfo %hist")'), ('x4??', 'get_ipython().magic({u}"pinfo2 x4")'),
('f*?', 'get_ipython().magic(u"psearch f*")'), ('%hist?', 'get_ipython().magic({u}"pinfo %hist")'),
('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'), ('f*?', 'get_ipython().magic({u}"psearch f*")'),
('a = abc?', 'get_ipython().magic(u"pinfo abc", next_input=u"a = abc")'), ('ax.*aspe*?', 'get_ipython().magic({u}"psearch ax.*aspe*")'),
('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe", next_input=u"a = abc.qe")'), ('a = abc?', 'get_ipython().magic({u}"pinfo abc", next_input={u}"a = abc")'),
('a = *.items?', 'get_ipython().magic(u"psearch *.items", next_input=u"a = *.items")'), ('a = abc.qe??', 'get_ipython().magic({u}"pinfo2 abc.qe", next_input={u}"a = abc.qe")'),
('plot(a?', 'get_ipython().magic(u"pinfo a", next_input=u"plot(a")'), ('a = *.items?', 'get_ipython().magic({u}"psearch *.items", next_input={u}"a = *.items")'),
('plot(a?', 'get_ipython().magic({u}"pinfo a", next_input={u}"plot(a")'),
('a*2 #comment?', 'a*2 #comment?'), ('a*2 #comment?', 'a*2 #comment?'),
], ]],


# Explicit magic calls # Explicit magic calls
escaped_magic = escaped_magic =
[ ('%cd', 'get_ipython().magic(u"cd")'), [(i,py3compat.u_format(o)) for i,o in \
('%cd /home', 'get_ipython().magic(u"cd /home")'), [ ('%cd', 'get_ipython().magic({u}"cd")'),
(' %magic', ' get_ipython().magic(u"magic")'), ('%cd /home', 'get_ipython().magic({u}"cd /home")'),
], (' %magic', ' get_ipython().magic({u}"magic")'),
]],


# Quoting with separate arguments # Quoting with separate arguments
escaped_quote = escaped_quote =
Expand Down Expand Up @@ -500,12 +507,13 @@ def transform_checker(tests, func):


# Check that we transform prompts before other transforms # Check that we transform prompts before other transforms
mixed = mixed =
[ ('In [1]: %lsmagic', 'get_ipython().magic(u"lsmagic")'), [(i,py3compat.u_format(o)) for i,o in \
('>>> %lsmagic', 'get_ipython().magic(u"lsmagic")'), [ ('In [1]: %lsmagic', 'get_ipython().magic({u}"lsmagic")'),
('In [2]: !ls', 'get_ipython().system(u"ls")'), ('>>> %lsmagic', 'get_ipython().magic({u}"lsmagic")'),
('In [3]: abs?', 'get_ipython().magic(u"pinfo abs")'), ('In [2]: !ls', 'get_ipython().system({u}"ls")'),
('In [4]: b = %who', 'b = get_ipython().magic(u"who")'), ('In [3]: abs?', 'get_ipython().magic({u}"pinfo abs")'),
], ('In [4]: b = %who', 'b = get_ipython().magic({u}"who")'),
]],
) )


# multiline syntax examples. Each of these should be a list of lists, with # multiline syntax examples. Each of these should be a list of lists, with
Expand Down
Loading