1"""Tests for the pindent script in the Tools directory."""
2
3import os
4import sys
5import unittest
6import subprocess
7import textwrap
8from test import support
9from test.support.script_helper import assert_python_ok
10
11from test.test_tools import scriptsdir, skip_if_missing
12
13skip_if_missing()
14
15
16class PindentTests(unittest.TestCase):
17    script = os.path.join(scriptsdir, 'pindent.py')
18
19    def assertFileEqual(self, fn1, fn2):
20        with open(fn1) as f1, open(fn2) as f2:
21            self.assertEqual(f1.readlines(), f2.readlines())
22
23    def pindent(self, source, *args):
24        with subprocess.Popen(
25                (sys.executable, self.script) + args,
26                stdin=subprocess.PIPE, stdout=subprocess.PIPE,
27                universal_newlines=True) as proc:
28            out, err = proc.communicate(source)
29        self.assertIsNone(err)
30        return out
31
32    def lstriplines(self, data):
33        return '\n'.join(line.lstrip() for line in data.splitlines()) + '\n'
34
35    def test_selftest(self):
36        self.maxDiff = None
37        with support.temp_dir() as directory:
38            data_path = os.path.join(directory, '_test.py')
39            with open(self.script) as f:
40                closed = f.read()
41            with open(data_path, 'w') as f:
42                f.write(closed)
43
44            rc, out, err = assert_python_ok(self.script, '-d', data_path)
45            self.assertEqual(out, b'')
46            self.assertEqual(err, b'')
47            backup = data_path + '~'
48            self.assertTrue(os.path.exists(backup))
49            with open(backup) as f:
50                self.assertEqual(f.read(), closed)
51            with open(data_path) as f:
52                clean = f.read()
53            compile(clean, '_test.py', 'exec')
54            self.assertEqual(self.pindent(clean, '-c'), closed)
55            self.assertEqual(self.pindent(closed, '-d'), clean)
56
57            rc, out, err = assert_python_ok(self.script, '-c', data_path)
58            self.assertEqual(out, b'')
59            self.assertEqual(err, b'')
60            with open(backup) as f:
61                self.assertEqual(f.read(), clean)
62            with open(data_path) as f:
63                self.assertEqual(f.read(), closed)
64
65            broken = self.lstriplines(closed)
66            with open(data_path, 'w') as f:
67                f.write(broken)
68            rc, out, err = assert_python_ok(self.script, '-r', data_path)
69            self.assertEqual(out, b'')
70            self.assertEqual(err, b'')
71            with open(backup) as f:
72                self.assertEqual(f.read(), broken)
73            with open(data_path) as f:
74                indented = f.read()
75            compile(indented, '_test.py', 'exec')
76            self.assertEqual(self.pindent(broken, '-r'), indented)
77
78    def pindent_test(self, clean, closed):
79        self.assertEqual(self.pindent(clean, '-c'), closed)
80        self.assertEqual(self.pindent(closed, '-d'), clean)
81        broken = self.lstriplines(closed)
82        self.assertEqual(self.pindent(broken, '-r', '-e', '-s', '4'), closed)
83
84    def test_statements(self):
85        clean = textwrap.dedent("""\
86            if a:
87                pass
88
89            if a:
90                pass
91            else:
92                pass
93
94            if a:
95                pass
96            elif:
97                pass
98            else:
99                pass
100
101            while a:
102                break
103
104            while a:
105                break
106            else:
107                pass
108
109            for i in a:
110                break
111
112            for i in a:
113                break
114            else:
115                pass
116
117            try:
118                pass
119            finally:
120                pass
121
122            try:
123                pass
124            except TypeError:
125                pass
126            except ValueError:
127                pass
128            else:
129                pass
130
131            try:
132                pass
133            except TypeError:
134                pass
135            except ValueError:
136                pass
137            finally:
138                pass
139
140            with a:
141                pass
142
143            class A:
144                pass
145
146            def f():
147                pass
148            """)
149
150        closed = textwrap.dedent("""\
151            if a:
152                pass
153            # end if
154
155            if a:
156                pass
157            else:
158                pass
159            # end if
160
161            if a:
162                pass
163            elif:
164                pass
165            else:
166                pass
167            # end if
168
169            while a:
170                break
171            # end while
172
173            while a:
174                break
175            else:
176                pass
177            # end while
178
179            for i in a:
180                break
181            # end for
182
183            for i in a:
184                break
185            else:
186                pass
187            # end for
188
189            try:
190                pass
191            finally:
192                pass
193            # end try
194
195            try:
196                pass
197            except TypeError:
198                pass
199            except ValueError:
200                pass
201            else:
202                pass
203            # end try
204
205            try:
206                pass
207            except TypeError:
208                pass
209            except ValueError:
210                pass
211            finally:
212                pass
213            # end try
214
215            with a:
216                pass
217            # end with
218
219            class A:
220                pass
221            # end class A
222
223            def f():
224                pass
225            # end def f
226            """)
227        self.pindent_test(clean, closed)
228
229    def test_multilevel(self):
230        clean = textwrap.dedent("""\
231            def foobar(a, b):
232                if a == b:
233                    a = a+1
234                elif a < b:
235                    b = b-1
236                    if b > a: a = a-1
237                else:
238                    print 'oops!'
239            """)
240        closed = textwrap.dedent("""\
241            def foobar(a, b):
242                if a == b:
243                    a = a+1
244                elif a < b:
245                    b = b-1
246                    if b > a: a = a-1
247                    # end if
248                else:
249                    print 'oops!'
250                # end if
251            # end def foobar
252            """)
253        self.pindent_test(clean, closed)
254
255    def test_preserve_indents(self):
256        clean = textwrap.dedent("""\
257            if a:
258                     if b:
259                              pass
260            """)
261        closed = textwrap.dedent("""\
262            if a:
263                     if b:
264                              pass
265                     # end if
266            # end if
267            """)
268        self.assertEqual(self.pindent(clean, '-c'), closed)
269        self.assertEqual(self.pindent(closed, '-d'), clean)
270        broken = self.lstriplines(closed)
271        self.assertEqual(self.pindent(broken, '-r', '-e', '-s', '9'), closed)
272        clean = textwrap.dedent("""\
273            if a:
274            \tif b:
275            \t\tpass
276            """)
277        closed = textwrap.dedent("""\
278            if a:
279            \tif b:
280            \t\tpass
281            \t# end if
282            # end if
283            """)
284        self.assertEqual(self.pindent(clean, '-c'), closed)
285        self.assertEqual(self.pindent(closed, '-d'), clean)
286        broken = self.lstriplines(closed)
287        self.assertEqual(self.pindent(broken, '-r'), closed)
288
289    def test_escaped_newline(self):
290        clean = textwrap.dedent("""\
291            class\\
292            \\
293             A:
294               def\
295            \\
296            f:
297                  pass
298            """)
299        closed = textwrap.dedent("""\
300            class\\
301            \\
302             A:
303               def\
304            \\
305            f:
306                  pass
307               # end def f
308            # end class A
309            """)
310        self.assertEqual(self.pindent(clean, '-c'), closed)
311        self.assertEqual(self.pindent(closed, '-d'), clean)
312
313    def test_empty_line(self):
314        clean = textwrap.dedent("""\
315            if a:
316
317                pass
318            """)
319        closed = textwrap.dedent("""\
320            if a:
321
322                pass
323            # end if
324            """)
325        self.pindent_test(clean, closed)
326
327    def test_oneline(self):
328        clean = textwrap.dedent("""\
329            if a: pass
330            """)
331        closed = textwrap.dedent("""\
332            if a: pass
333            # end if
334            """)
335        self.pindent_test(clean, closed)
336
337
338if __name__ == '__main__':
339    unittest.main()
340