blob: e8381122182e059c243654049a5d5053cb2f1c6a [file] [log] [blame]
Eric Smith799c3002008-03-18 15:35:27 +00001import unittest
Sanyam Khurana5e2eb352017-08-18 16:07:36 +05302import sys
Andrew Svetlovace34dd2013-04-04 22:32:28 +03003from io import StringIO
Eric Smith799c3002008-03-18 15:35:27 +00004
Andrew Svetlovace34dd2013-04-04 22:32:28 +03005from test import support
Eric Smith01a3e2b2008-03-18 23:48:28 +00006
Eric Smith799c3002008-03-18 15:35:27 +00007NotDefined = object()
8
9# A dispatch table all 8 combinations of providing
Andrew Svetlovace34dd2013-04-04 22:32:28 +030010# sep, end, and file.
Eric Smith799c3002008-03-18 15:35:27 +000011# I use this machinery so that I'm not just passing default
Andrew Svetlovace34dd2013-04-04 22:32:28 +030012# values to print, I'm either passing or not passing in the
13# arguments.
Eric Smith799c3002008-03-18 15:35:27 +000014dispatch = {
15 (False, False, False):
Andrew Svetlovace34dd2013-04-04 22:32:28 +030016 lambda args, sep, end, file: print(*args),
Eric Smith799c3002008-03-18 15:35:27 +000017 (False, False, True):
Andrew Svetlovace34dd2013-04-04 22:32:28 +030018 lambda args, sep, end, file: print(file=file, *args),
Eric Smith799c3002008-03-18 15:35:27 +000019 (False, True, False):
Andrew Svetlovace34dd2013-04-04 22:32:28 +030020 lambda args, sep, end, file: print(end=end, *args),
Eric Smith799c3002008-03-18 15:35:27 +000021 (False, True, True):
Andrew Svetlovace34dd2013-04-04 22:32:28 +030022 lambda args, sep, end, file: print(end=end, file=file, *args),
Eric Smith799c3002008-03-18 15:35:27 +000023 (True, False, False):
Andrew Svetlovace34dd2013-04-04 22:32:28 +030024 lambda args, sep, end, file: print(sep=sep, *args),
Eric Smith799c3002008-03-18 15:35:27 +000025 (True, False, True):
Andrew Svetlovace34dd2013-04-04 22:32:28 +030026 lambda args, sep, end, file: print(sep=sep, file=file, *args),
Eric Smith799c3002008-03-18 15:35:27 +000027 (True, True, False):
Andrew Svetlovace34dd2013-04-04 22:32:28 +030028 lambda args, sep, end, file: print(sep=sep, end=end, *args),
Eric Smith799c3002008-03-18 15:35:27 +000029 (True, True, True):
Andrew Svetlovace34dd2013-04-04 22:32:28 +030030 lambda args, sep, end, file: print(sep=sep, end=end, file=file, *args),
31}
32
Eric Smith799c3002008-03-18 15:35:27 +000033
Eric Smith799c3002008-03-18 15:35:27 +000034# Class used to test __str__ and print
35class ClassWith__str__:
36 def __init__(self, x):
37 self.x = x
Andrew Svetlovace34dd2013-04-04 22:32:28 +030038
Eric Smith799c3002008-03-18 15:35:27 +000039 def __str__(self):
40 return self.x
41
Eric Smith799c3002008-03-18 15:35:27 +000042
Andrew Svetlovace34dd2013-04-04 22:32:28 +030043class 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.
Eric Smith799c3002008-03-18 15:35:27 +000054 fn = dispatch[(sep is not NotDefined,
55 end is not NotDefined,
56 file is not NotDefined)]
57
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 with support.captured_stdout() as t:
Eric Smith799c3002008-03-18 15:35:27 +000059 fn(args, sep, end, file)
60
61 self.assertEqual(t.getvalue(), expected)
62
63 def test_print(self):
Eric Smith01a3e2b2008-03-18 23:48:28 +000064 def x(expected, args, sep=NotDefined, end=NotDefined):
Eric Smith799c3002008-03-18 15:35:27 +000065 # Run the test 2 ways: not using file, and using
Andrew Svetlovace34dd2013-04-04 22:32:28 +030066 # file directed to a StringIO.
Eric Smith799c3002008-03-18 15:35:27 +000067
68 self.check(expected, args, sep=sep, end=end)
69
70 # When writing to a file, stdout is expected to be empty
Eric Smith01a3e2b2008-03-18 23:48:28 +000071 o = StringIO()
Eric Smith799c3002008-03-18 15:35:27 +000072 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))
Eric Smith01a3e2b2008-03-18 23:48:28 +000081 x('1 2\n', (1, ' ', 2))
Eric Smith799c3002008-03-18 15:35:27 +000082 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='+')
Eric Smith01a3e2b2008-03-18 23:48:28 +000087 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)
Eric Smith799c3002008-03-18 15:35:27 +000094
95 x('*\n', (ClassWith__str__('*'),))
Eric Smith01a3e2b2008-03-18 23:48:28 +000096 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='')
Eric Smith799c3002008-03-18 15:35:27 +0000102
Georg Brandlbc3b6822012-01-13 19:41:25 +0100103 def test_print_flush(self):
104 # operation of the flush flag
Andrew Svetlovace34dd2013-04-04 22:32:28 +0300105 class filelike:
Georg Brandlbc3b6822012-01-13 19:41:25 +0100106 def __init__(self):
107 self.written = ''
108 self.flushed = 0
Andrew Svetlovace34dd2013-04-04 22:32:28 +0300109
Georg Brandlbc3b6822012-01-13 19:41:25 +0100110 def write(self, str):
111 self.written += str
Andrew Svetlovace34dd2013-04-04 22:32:28 +0300112
Georg Brandlbc3b6822012-01-13 19:41:25 +0100113 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
Andrew Svetlovace34dd2013-04-04 22:32:28 +0300124 class noflush:
Georg Brandlbc3b6822012-01-13 19:41:25 +0100125 def write(self, str):
126 pass
Andrew Svetlovace34dd2013-04-04 22:32:28 +0300127
Georg Brandlbc3b6822012-01-13 19:41:25 +0100128 def flush(self):
129 raise RuntimeError
130 self.assertRaises(RuntimeError, print, 1, file=noflush(), flush=True)
131
Sanyam Khurana3a7f0352017-06-20 19:01:32 +0530132
133class 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('print("Hello World")', str(context.exception))
144
145 def test_string_with_soft_space(self):
146 python2_print_str = 'print "Hello World",'
147 with self.assertRaises(SyntaxError) as context:
148 exec(python2_print_str)
149
150 self.assertIn('print("Hello World", end=" ")', str(context.exception))
151
152 def test_string_with_excessive_whitespace(self):
153 python2_print_str = 'print "Hello World", '
154 with self.assertRaises(SyntaxError) as context:
155 exec(python2_print_str)
156
157 self.assertIn('print("Hello World", end=" ")', str(context.exception))
158
Sanyam Khuranad57f26c2018-01-20 08:42:22 +0530159 def test_string_with_leading_whitespace(self):
160 python2_print_str = '''if 1:
161 print "Hello World"
162 '''
163 with self.assertRaises(SyntaxError) as context:
164 exec(python2_print_str)
165
166 self.assertIn('print("Hello World")', str(context.exception))
167
Nitish Chandra43c0f1a2018-01-28 16:26:02 +0530168 # bpo-32685: Suggestions for print statement should be proper when
169 # it is in the same line as the header of a compound statement
170 # and/or followed by a semicolon
171 def test_string_with_semicolon(self):
172 python2_print_str = 'print p;'
173 with self.assertRaises(SyntaxError) as context:
174 exec(python2_print_str)
175
176 self.assertIn('print(p)', str(context.exception))
177
178 def test_string_in_loop_on_same_line(self):
179 python2_print_str = 'for i in s: print i'
180 with self.assertRaises(SyntaxError) as context:
181 exec(python2_print_str)
182
183 self.assertIn('print(i)', str(context.exception))
184
Sanyam Khurana5e2eb352017-08-18 16:07:36 +0530185 def test_stream_redirection_hint_for_py2_migration(self):
186 # Test correct hint produced for Py2 redirection syntax
187 with self.assertRaises(TypeError) as context:
188 print >> sys.stderr, "message"
189 self.assertIn('Did you mean "print(<message>, '
Sanyam Khuranaa7c449b2017-08-18 17:48:14 +0530190 'file=<output_stream>)"?', str(context.exception))
Sanyam Khurana5e2eb352017-08-18 16:07:36 +0530191
192 # Test correct hint is produced in the case where RHS implements
193 # __rrshift__ but returns NotImplemented
194 with self.assertRaises(TypeError) as context:
195 print >> 42
196 self.assertIn('Did you mean "print(<message>, '
Sanyam Khuranaa7c449b2017-08-18 17:48:14 +0530197 'file=<output_stream>)"?', str(context.exception))
Sanyam Khurana5e2eb352017-08-18 16:07:36 +0530198
199 # Test stream redirection hint is specific to print
200 with self.assertRaises(TypeError) as context:
201 max >> sys.stderr
202 self.assertNotIn('Did you mean ', str(context.exception))
203
204 # Test stream redirection hint is specific to rshift
205 with self.assertRaises(TypeError) as context:
206 print << sys.stderr
207 self.assertNotIn('Did you mean', str(context.exception))
208
209 # Ensure right operand implementing rrshift still works
210 class OverrideRRShift:
211 def __rrshift__(self, lhs):
212 return 42 # Force result independent of LHS
213
214 self.assertEqual(print >> OverrideRRShift(), 42)
215
216
Sanyam Khurana3a7f0352017-06-20 19:01:32 +0530217
Eric Smith799c3002008-03-18 15:35:27 +0000218if __name__ == "__main__":
Andrew Svetlovace34dd2013-04-04 22:32:28 +0300219 unittest.main()