Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b00e63e

Browse filesBrowse files
authored
Merge pull request #4778 from JaeyoungAhn/test_print
added test_print.py and marked TODOs
2 parents 322165f + 074e4b3 commit b00e63e
Copy full SHA for b00e63e

File tree

1 file changed

+240
-0
lines changed
Filter options

1 file changed

+240
-0
lines changed

‎Lib/test/test_print.py

Copy file name to clipboard
+240Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
import unittest
2+
import sys
3+
from io import StringIO
4+
5+
from test import support
6+
7+
NotDefined = object()
8+
9+
# A dispatch table all 8 combinations of providing
10+
# sep, end, and file.
11+
# I use this machinery so that I'm not just passing default
12+
# values to print, I'm either passing or not passing in the
13+
# arguments.
14+
dispatch = {
15+
(False, False, False):
16+
lambda args, sep, end, file: print(*args),
17+
(False, False, True):
18+
lambda args, sep, end, file: print(file=file, *args),
19+
(False, True, False):
20+
lambda args, sep, end, file: print(end=end, *args),
21+
(False, True, True):
22+
lambda args, sep, end, file: print(end=end, file=file, *args),
23+
(True, False, False):
24+
lambda args, sep, end, file: print(sep=sep, *args),
25+
(True, False, True):
26+
lambda args, sep, end, file: print(sep=sep, file=file, *args),
27+
(True, True, False):
28+
lambda args, sep, end, file: print(sep=sep, end=end, *args),
29+
(True, True, True):
30+
lambda args, sep, end, file: print(sep=sep, end=end, file=file, *args),
31+
}
32+
33+
34+
# Class used to test __str__ and print
35+
class ClassWith__str__:
36+
def __init__(self, x):
37+
self.x = x
38+
39+
def __str__(self):
40+
return self.x
41+
42+
43+
class TestPrint(unittest.TestCase):
44+
"""Test correct operation of the print function."""
45+
46+
def check(self, expected, args,
47+
sep=NotDefined, end=NotDefined, file=NotDefined):
48+
# Capture sys.stdout in a StringIO. Call print with args,
49+
# and with sep, end, and file, if they're defined. Result
50+
# must match expected.
51+
52+
# Look up the actual function to call, based on if sep, end,
53+
# and file are defined.
54+
fn = dispatch[(sep is not NotDefined,
55+
end is not NotDefined,
56+
file is not NotDefined)]
57+
58+
with support.captured_stdout() as t:
59+
fn(args, sep, end, file)
60+
61+
self.assertEqual(t.getvalue(), expected)
62+
63+
def test_print(self):
64+
def x(expected, args, sep=NotDefined, end=NotDefined):
65+
# Run the test 2 ways: not using file, and using
66+
# file directed to a StringIO.
67+
68+
self.check(expected, args, sep=sep, end=end)
69+
70+
# When writing to a file, stdout is expected to be empty
71+
o = StringIO()
72+
self.check('', args, sep=sep, end=end, file=o)
73+
74+
# And o will contain the expected output
75+
self.assertEqual(o.getvalue(), expected)
76+
77+
x('\n', ())
78+
x('a\n', ('a',))
79+
x('None\n', (None,))
80+
x('1 2\n', (1, 2))
81+
x('1 2\n', (1, ' ', 2))
82+
x('1*2\n', (1, 2), sep='*')
83+
x('1 s', (1, 's'), end='')
84+
x('a\nb\n', ('a', 'b'), sep='\n')
85+
x('1.01', (1.0, 1), sep='', end='')
86+
x('1*a*1.3+', (1, 'a', 1.3), sep='*', end='+')
87+
x('a\n\nb\n', ('a\n', 'b'), sep='\n')
88+
x('\0+ +\0\n', ('\0', ' ', '\0'), sep='+')
89+
90+
x('a\n b\n', ('a\n', 'b'))
91+
x('a\n b\n', ('a\n', 'b'), sep=None)
92+
x('a\n b\n', ('a\n', 'b'), end=None)
93+
x('a\n b\n', ('a\n', 'b'), sep=None, end=None)
94+
95+
x('*\n', (ClassWith__str__('*'),))
96+
x('abc 1\n', (ClassWith__str__('abc'), 1))
97+
98+
# errors
99+
self.assertRaises(TypeError, print, '', sep=3)
100+
self.assertRaises(TypeError, print, '', end=3)
101+
self.assertRaises(AttributeError, print, '', file='')
102+
103+
def test_print_flush(self):
104+
# operation of the flush flag
105+
class filelike:
106+
def __init__(self):
107+
self.written = ''
108+
self.flushed = 0
109+
110+
def write(self, str):
111+
self.written += str
112+
113+
def flush(self):
114+
self.flushed += 1
115+
116+
f = filelike()
117+
print(1, file=f, end='', flush=True)
118+
print(2, file=f, end='', flush=True)
119+
print(3, file=f, flush=False)
120+
self.assertEqual(f.written, '123\n')
121+
self.assertEqual(f.flushed, 2)
122+
123+
# ensure exceptions from flush are passed through
124+
class noflush:
125+
def write(self, str):
126+
pass
127+
128+
def flush(self):
129+
raise RuntimeError
130+
self.assertRaises(RuntimeError, print, 1, file=noflush(), flush=True)
131+
132+
133+
class TestPy2MigrationHint(unittest.TestCase):
134+
"""Test that correct hint is produced analogous to Python3 syntax,
135+
if print statement is executed as in Python 2.
136+
"""
137+
138+
# TODO: RUSTPYTHON
139+
@unittest.expectedFailure
140+
def test_normal_string(self):
141+
python2_print_str = 'print "Hello World"'
142+
with self.assertRaises(SyntaxError) as context:
143+
exec(python2_print_str)
144+
145+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
146+
str(context.exception))
147+
148+
# TODO: RUSTPYTHON
149+
@unittest.expectedFailure
150+
def test_string_with_soft_space(self):
151+
python2_print_str = 'print "Hello World",'
152+
with self.assertRaises(SyntaxError) as context:
153+
exec(python2_print_str)
154+
155+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
156+
str(context.exception))
157+
158+
# TODO: RUSTPYTHON
159+
@unittest.expectedFailure
160+
def test_string_with_excessive_whitespace(self):
161+
python2_print_str = 'print "Hello World", '
162+
with self.assertRaises(SyntaxError) as context:
163+
exec(python2_print_str)
164+
165+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
166+
str(context.exception))
167+
168+
# TODO: RUSTPYTHON
169+
@unittest.expectedFailure
170+
def test_string_with_leading_whitespace(self):
171+
python2_print_str = '''if 1:
172+
print "Hello World"
173+
'''
174+
with self.assertRaises(SyntaxError) as context:
175+
exec(python2_print_str)
176+
177+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
178+
str(context.exception))
179+
180+
# bpo-32685: Suggestions for print statement should be proper when
181+
# it is in the same line as the header of a compound statement
182+
# and/or followed by a semicolon
183+
184+
# TODO: RUSTPYTHON
185+
@unittest.expectedFailure
186+
def test_string_with_semicolon(self):
187+
python2_print_str = 'print p;'
188+
with self.assertRaises(SyntaxError) as context:
189+
exec(python2_print_str)
190+
191+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
192+
str(context.exception))
193+
194+
# TODO: RUSTPYTHON
195+
@unittest.expectedFailure
196+
def test_string_in_loop_on_same_line(self):
197+
python2_print_str = 'for i in s: print i'
198+
with self.assertRaises(SyntaxError) as context:
199+
exec(python2_print_str)
200+
201+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
202+
str(context.exception))
203+
204+
# TODO: RUSTPYTHON
205+
@unittest.expectedFailure
206+
def test_stream_redirection_hint_for_py2_migration(self):
207+
# Test correct hint produced for Py2 redirection syntax
208+
with self.assertRaises(TypeError) as context:
209+
print >> sys.stderr, "message"
210+
self.assertIn('Did you mean "print(<message>, '
211+
'file=<output_stream>)"?', str(context.exception))
212+
213+
# Test correct hint is produced in the case where RHS implements
214+
# __rrshift__ but returns NotImplemented
215+
with self.assertRaises(TypeError) as context:
216+
print >> 42
217+
self.assertIn('Did you mean "print(<message>, '
218+
'file=<output_stream>)"?', str(context.exception))
219+
220+
# Test stream redirection hint is specific to print
221+
with self.assertRaises(TypeError) as context:
222+
max >> sys.stderr
223+
self.assertNotIn('Did you mean ', str(context.exception))
224+
225+
# Test stream redirection hint is specific to rshift
226+
with self.assertRaises(TypeError) as context:
227+
print << sys.stderr
228+
self.assertNotIn('Did you mean', str(context.exception))
229+
230+
# Ensure right operand implementing rrshift still works
231+
class OverrideRRShift:
232+
def __rrshift__(self, lhs):
233+
return 42 # Force result independent of LHS
234+
235+
self.assertEqual(print >> OverrideRRShift(), 42)
236+
237+
238+
239+
if __name__ == "__main__":
240+
unittest.main()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.