summaryrefslogtreecommitdiffstats
path: root/Lib/lib2to3/tests/test_refactor.py
blob: 07174796094ed3e15d3f13a6fde055c767f110c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
"""
Unit tests for refactor.py.
"""

import sys
import os
import operator
import io
import tempfile
import unittest

from lib2to3 import refactor, pygram, fixer_base

from . import support


FIXER_DIR = os.path.join(os.path.dirname(__file__), "data/fixers")

sys.path.append(FIXER_DIR)
try:
    _DEFAULT_FIXERS = refactor.get_fixers_from_package("myfixes")
finally:
    sys.path.pop()

class TestRefactoringTool(unittest.TestCase):

    def setUp(self):
        sys.path.append(FIXER_DIR)

    def tearDown(self):
        sys.path.pop()

    def check_instances(self, instances, classes):
        for inst, cls in zip(instances, classes):
            if not isinstance(inst, cls):
                self.fail("%s are not instances of %s" % instances, classes)

    def rt(self, options=None, fixers=_DEFAULT_FIXERS, explicit=None):
        return refactor.RefactoringTool(fixers, options, explicit)

    def test_print_function_option(self):
        gram = pygram.python_grammar
        save = gram.keywords["print"]
        try:
            rt = self.rt({"print_function" : True})
            self.assertRaises(KeyError, operator.itemgetter("print"),
                              gram.keywords)
        finally:
            gram.keywords["print"] = save

    def test_fixer_loading_helpers(self):
        contents = ["explicit", "first", "last", "parrot", "preorder"]
        non_prefixed = refactor.get_all_fix_names("myfixes")
        prefixed = refactor.get_all_fix_names("myfixes", False)
        full_names = refactor.get_fixers_from_package("myfixes")
        self.assertEqual(prefixed, ["fix_" + name for name in contents])
        self.assertEqual(non_prefixed, contents)
        self.assertEqual(full_names,
                         ["myfixes.fix_" + name for name in contents])

    def test_get_headnode_dict(self):
        class NoneFix(fixer_base.BaseFix):
            PATTERN = None

        class FileInputFix(fixer_base.BaseFix):
            PATTERN = "file_input< any * >"

        no_head = NoneFix({}, [])
        with_head = FileInputFix({}, [])
        d = refactor.get_headnode_dict([no_head, with_head])
        expected = {None: [no_head],
                    pygram.python_symbols.file_input : [with_head]}
        self.assertEqual(d, expected)

    def test_fixer_loading(self):
        from myfixes.fix_first import FixFirst
        from myfixes.fix_last import FixLast
        from myfixes.fix_parrot import FixParrot
        from myfixes.fix_preorder import FixPreorder

        rt = self.rt()
        pre, post = rt.get_fixers()

        self.check_instances(pre, [FixPreorder])
        self.check_instances(post, [FixFirst, FixParrot, FixLast])

    def test_naughty_fixers(self):
        self.assertRaises(ImportError, self.rt, fixers=["not_here"])
        self.assertRaises(refactor.FixerError, self.rt, fixers=["no_fixer_cls"])
        self.assertRaises(refactor.FixerError, self.rt, fixers=["bad_order"])

    def test_refactor_string(self):
        rt = self.rt()
        input = "def parrot(): pass\n\n"
        tree = rt.refactor_string(input, "<test>")
        self.assertNotEqual(str(tree), input)

        input = "def f(): pass\n\n"
        tree = rt.refactor_string(input, "<test>")
        self.assertEqual(str(tree), input)

    def test_refactor_stdin(self):

        class MyRT(refactor.RefactoringTool):

            def print_output(self, lines):
                diff_lines.extend(lines)

        diff_lines = []
        rt = MyRT(_DEFAULT_FIXERS)
        save = sys.stdin
        sys.stdin = io.StringIO("def parrot(): pass\n\n")
        try:
            rt.refactor_stdin()
        finally:
            sys.stdin = save
        expected = """--- <stdin> (original)
+++ <stdin> (refactored)
@@ -1,2 +1,2 @@
-def parrot(): pass
+def cheese(): pass""".splitlines()
        self.assertEqual(diff_lines[:-1], expected)

    def test_refactor_file(self):
        test_file = os.path.join(FIXER_DIR, "parrot_example.py")
        backup = test_file + ".bak"
        old_contents = open(test_file, "r").read()
        rt = self.rt()

        rt.refactor_file(test_file)
        self.assertEqual(old_contents, open(test_file, "r").read())

        rt.refactor_file(test_file, True)
        try:
            self.assertNotEqual(old_contents, open(test_file, "r").read())
            self.assertTrue(os.path.exists(backup))
            self.assertEqual(old_contents, open(backup, "r").read())
        finally:
            open(test_file, "w").write(old_contents)
            try:
                os.unlink(backup)
            except OSError:
                pass

    def test_refactor_docstring(self):
        rt = self.rt()

        def example():
            """
            >>> example()
            42
            """
        out = rt.refactor_docstring(example.__doc__, "<test>")
        self.assertEqual(out, example.__doc__)

        def parrot():
            """
            >>> def parrot():
            ...      return 43
            """
        out = rt.refactor_docstring(parrot.__doc__, "<test>")
        self.assertNotEqual(out, parrot.__doc__)

    def test_explicit(self):
        from myfixes.fix_explicit import FixExplicit

        rt = self.rt(fixers=["myfixes.fix_explicit"])
        self.assertEqual(len(rt.post_order), 0)

        rt = self.rt(explicit=["myfixes.fix_explicit"])
        for fix in rt.post_order[None]:
            if isinstance(fix, FixExplicit):
                break
        else:
            self.fail("explicit fixer not loaded")