]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | """Test correct operation of the print function.\r |
2 | """\r | |
3 | \r | |
4 | # In 2.6, this gives us the behavior we want. In 3.0, it has\r | |
5 | # no function, but it still must parse correctly.\r | |
6 | from __future__ import print_function\r | |
7 | \r | |
8 | import unittest\r | |
9 | from test import test_support\r | |
10 | \r | |
11 | from StringIO import StringIO\r | |
12 | \r | |
13 | NotDefined = object()\r | |
14 | \r | |
15 | # A dispatch table all 8 combinations of providing\r | |
16 | # sep, end, and file\r | |
17 | # I use this machinery so that I'm not just passing default\r | |
18 | # values to print, I'm either passing or not passing in the\r | |
19 | # arguments\r | |
20 | dispatch = {\r | |
21 | (False, False, False):\r | |
22 | lambda args, sep, end, file: print(*args),\r | |
23 | (False, False, True):\r | |
24 | lambda args, sep, end, file: print(file=file, *args),\r | |
25 | (False, True, False):\r | |
26 | lambda args, sep, end, file: print(end=end, *args),\r | |
27 | (False, True, True):\r | |
28 | lambda args, sep, end, file: print(end=end, file=file, *args),\r | |
29 | (True, False, False):\r | |
30 | lambda args, sep, end, file: print(sep=sep, *args),\r | |
31 | (True, False, True):\r | |
32 | lambda args, sep, end, file: print(sep=sep, file=file, *args),\r | |
33 | (True, True, False):\r | |
34 | lambda args, sep, end, file: print(sep=sep, end=end, *args),\r | |
35 | (True, True, True):\r | |
36 | lambda args, sep, end, file: print(sep=sep, end=end, file=file, *args),\r | |
37 | }\r | |
38 | \r | |
39 | # Class used to test __str__ and print\r | |
40 | class ClassWith__str__:\r | |
41 | def __init__(self, x):\r | |
42 | self.x = x\r | |
43 | def __str__(self):\r | |
44 | return self.x\r | |
45 | \r | |
46 | class TestPrint(unittest.TestCase):\r | |
47 | def check(self, expected, args,\r | |
48 | sep=NotDefined, end=NotDefined, file=NotDefined):\r | |
49 | # Capture sys.stdout in a StringIO. Call print with args,\r | |
50 | # and with sep, end, and file, if they're defined. Result\r | |
51 | # must match expected.\r | |
52 | \r | |
53 | # Look up the actual function to call, based on if sep, end, and file\r | |
54 | # are defined\r | |
55 | fn = dispatch[(sep is not NotDefined,\r | |
56 | end is not NotDefined,\r | |
57 | file is not NotDefined)]\r | |
58 | \r | |
59 | with test_support.captured_stdout() as t:\r | |
60 | fn(args, sep, end, file)\r | |
61 | \r | |
62 | self.assertEqual(t.getvalue(), expected)\r | |
63 | \r | |
64 | def test_print(self):\r | |
65 | def x(expected, args, sep=NotDefined, end=NotDefined):\r | |
66 | # Run the test 2 ways: not using file, and using\r | |
67 | # file directed to a StringIO\r | |
68 | \r | |
69 | self.check(expected, args, sep=sep, end=end)\r | |
70 | \r | |
71 | # When writing to a file, stdout is expected to be empty\r | |
72 | o = StringIO()\r | |
73 | self.check('', args, sep=sep, end=end, file=o)\r | |
74 | \r | |
75 | # And o will contain the expected output\r | |
76 | self.assertEqual(o.getvalue(), expected)\r | |
77 | \r | |
78 | x('\n', ())\r | |
79 | x('a\n', ('a',))\r | |
80 | x('None\n', (None,))\r | |
81 | x('1 2\n', (1, 2))\r | |
82 | x('1 2\n', (1, ' ', 2))\r | |
83 | x('1*2\n', (1, 2), sep='*')\r | |
84 | x('1 s', (1, 's'), end='')\r | |
85 | x('a\nb\n', ('a', 'b'), sep='\n')\r | |
86 | x('1.01', (1.0, 1), sep='', end='')\r | |
87 | x('1*a*1.3+', (1, 'a', 1.3), sep='*', end='+')\r | |
88 | x('a\n\nb\n', ('a\n', 'b'), sep='\n')\r | |
89 | x('\0+ +\0\n', ('\0', ' ', '\0'), sep='+')\r | |
90 | \r | |
91 | x('a\n b\n', ('a\n', 'b'))\r | |
92 | x('a\n b\n', ('a\n', 'b'), sep=None)\r | |
93 | x('a\n b\n', ('a\n', 'b'), end=None)\r | |
94 | x('a\n b\n', ('a\n', 'b'), sep=None, end=None)\r | |
95 | \r | |
96 | x('*\n', (ClassWith__str__('*'),))\r | |
97 | x('abc 1\n', (ClassWith__str__('abc'), 1))\r | |
98 | \r | |
99 | # 2.x unicode tests\r | |
100 | x(u'1 2\n', ('1', u'2'))\r | |
101 | x(u'u\1234\n', (u'u\1234',))\r | |
102 | x(u' abc 1\n', (' ', ClassWith__str__(u'abc'), 1))\r | |
103 | \r | |
104 | # errors\r | |
105 | self.assertRaises(TypeError, print, '', sep=3)\r | |
106 | self.assertRaises(TypeError, print, '', end=3)\r | |
107 | self.assertRaises(AttributeError, print, '', file='')\r | |
108 | \r | |
109 | def test_mixed_args(self):\r | |
110 | # If an unicode arg is passed, sep and end should be unicode, too.\r | |
111 | class Recorder(object):\r | |
112 | \r | |
113 | def __init__(self, must_be_unicode):\r | |
114 | self.buf = []\r | |
115 | self.force_unicode = must_be_unicode\r | |
116 | \r | |
117 | def write(self, what):\r | |
118 | if self.force_unicode and not isinstance(what, unicode):\r | |
119 | raise AssertionError("{0!r} is not unicode".format(what))\r | |
120 | self.buf.append(what)\r | |
121 | \r | |
122 | buf = Recorder(True)\r | |
123 | print(u'hi', file=buf)\r | |
124 | self.assertEqual(u''.join(buf.buf), 'hi\n')\r | |
125 | del buf.buf[:]\r | |
126 | print(u'hi', u'nothing', file=buf)\r | |
127 | self.assertEqual(u''.join(buf.buf), 'hi nothing\n')\r | |
128 | buf = Recorder(False)\r | |
129 | print('hi', 'bye', end=u'\n', file=buf)\r | |
130 | self.assertIsInstance(buf.buf[1], unicode)\r | |
131 | self.assertIsInstance(buf.buf[3], unicode)\r | |
132 | del buf.buf[:]\r | |
133 | print(sep=u'x', file=buf)\r | |
134 | self.assertIsInstance(buf.buf[-1], unicode)\r | |
135 | \r | |
136 | \r | |
137 | def test_main():\r | |
138 | test_support.run_unittest(TestPrint)\r | |
139 | \r | |
140 | if __name__ == "__main__":\r | |
141 | test_main()\r |