Skip to content

Commit bd51ade

Browse files
committed
new test_print.py from cpython v.3.11.2
1 parent 6f8a652 commit bd51ade

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed

Lib/test/test_print.py

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
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+
def test_normal_string(self):
139+
python2_print_str = 'print "Hello World"'
140+
with self.assertRaises(SyntaxError) as context:
141+
exec(python2_print_str)
142+
143+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
144+
str(context.exception))
145+
146+
def test_string_with_soft_space(self):
147+
python2_print_str = 'print "Hello World",'
148+
with self.assertRaises(SyntaxError) as context:
149+
exec(python2_print_str)
150+
151+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
152+
str(context.exception))
153+
154+
def test_string_with_excessive_whitespace(self):
155+
python2_print_str = 'print "Hello World", '
156+
with self.assertRaises(SyntaxError) as context:
157+
exec(python2_print_str)
158+
159+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
160+
str(context.exception))
161+
162+
def test_string_with_leading_whitespace(self):
163+
python2_print_str = '''if 1:
164+
print "Hello World"
165+
'''
166+
with self.assertRaises(SyntaxError) as context:
167+
exec(python2_print_str)
168+
169+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
170+
str(context.exception))
171+
172+
# bpo-32685: Suggestions for print statement should be proper when
173+
# it is in the same line as the header of a compound statement
174+
# and/or followed by a semicolon
175+
def test_string_with_semicolon(self):
176+
python2_print_str = 'print p;'
177+
with self.assertRaises(SyntaxError) as context:
178+
exec(python2_print_str)
179+
180+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
181+
str(context.exception))
182+
183+
def test_string_in_loop_on_same_line(self):
184+
python2_print_str = 'for i in s: print i'
185+
with self.assertRaises(SyntaxError) as context:
186+
exec(python2_print_str)
187+
188+
self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)",
189+
str(context.exception))
190+
191+
def test_stream_redirection_hint_for_py2_migration(self):
192+
# Test correct hint produced for Py2 redirection syntax
193+
with self.assertRaises(TypeError) as context:
194+
print >> sys.stderr, "message"
195+
self.assertIn('Did you mean "print(<message>, '
196+
'file=<output_stream>)"?', str(context.exception))
197+
198+
# Test correct hint is produced in the case where RHS implements
199+
# __rrshift__ but returns NotImplemented
200+
with self.assertRaises(TypeError) as context:
201+
print >> 42
202+
self.assertIn('Did you mean "print(<message>, '
203+
'file=<output_stream>)"?', str(context.exception))
204+
205+
# Test stream redirection hint is specific to print
206+
with self.assertRaises(TypeError) as context:
207+
max >> sys.stderr
208+
self.assertNotIn('Did you mean ', str(context.exception))
209+
210+
# Test stream redirection hint is specific to rshift
211+
with self.assertRaises(TypeError) as context:
212+
print << sys.stderr
213+
self.assertNotIn('Did you mean', str(context.exception))
214+
215+
# Ensure right operand implementing rrshift still works
216+
class OverrideRRShift:
217+
def __rrshift__(self, lhs):
218+
return 42 # Force result independent of LHS
219+
220+
self.assertEqual(print >> OverrideRRShift(), 42)
221+
222+
223+
224+
if __name__ == "__main__":
225+
unittest.main()

0 commit comments

Comments
 (0)