1# -*- coding: utf-8 -*- 2import sys 3import codecs 4import logging 5import os 6import re 7import shutil 8import StringIO 9import sys 10import tempfile 11import unittest 12 13from lib2to3 import main 14 15 16TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") 17PY2_TEST_MODULE = os.path.join(TEST_DATA_DIR, "py2_test_grammar.py") 18 19 20class TestMain(unittest.TestCase): 21 22 if not hasattr(unittest.TestCase, 'assertNotRegex'): 23 # This method was only introduced in 3.2. 24 def assertNotRegex(self, text, regexp, msg=None): 25 import re 26 if not hasattr(regexp, 'search'): 27 regexp = re.compile(regexp) 28 if regexp.search(text): 29 self.fail("regexp %s MATCHED text %r" % (regexp.pattern, text)) 30 31 def setUp(self): 32 self.temp_dir = None # tearDown() will rmtree this directory if set. 33 34 def tearDown(self): 35 # Clean up logging configuration down by main. 36 del logging.root.handlers[:] 37 if self.temp_dir: 38 shutil.rmtree(self.temp_dir) 39 40 def run_2to3_capture(self, args, in_capture, out_capture, err_capture): 41 save_stdin = sys.stdin 42 save_stdout = sys.stdout 43 save_stderr = sys.stderr 44 sys.stdin = in_capture 45 sys.stdout = out_capture 46 sys.stderr = err_capture 47 try: 48 return main.main("lib2to3.fixes", args) 49 finally: 50 sys.stdin = save_stdin 51 sys.stdout = save_stdout 52 sys.stderr = save_stderr 53 54 def test_unencodable_diff(self): 55 input_stream = StringIO.StringIO(u"print 'nothing'\nprint u'über'\n") 56 out = StringIO.StringIO() 57 out_enc = codecs.getwriter("ascii")(out) 58 err = StringIO.StringIO() 59 ret = self.run_2to3_capture(["-"], input_stream, out_enc, err) 60 self.assertEqual(ret, 0) 61 output = out.getvalue() 62 self.assertIn("-print 'nothing'", output) 63 self.assertIn("WARNING: couldn't encode <stdin>'s diff for " 64 "your terminal", err.getvalue()) 65 66 def setup_test_source_trees(self): 67 """Setup a test source tree and output destination tree.""" 68 self.temp_dir = tempfile.mkdtemp() # tearDown() cleans this up. 69 self.py2_src_dir = os.path.join(self.temp_dir, "python2_project") 70 self.py3_dest_dir = os.path.join(self.temp_dir, "python3_project") 71 os.mkdir(self.py2_src_dir) 72 os.mkdir(self.py3_dest_dir) 73 # Turn it into a package with a few files. 74 self.setup_files = [] 75 open(os.path.join(self.py2_src_dir, "__init__.py"), "w").close() 76 self.setup_files.append("__init__.py") 77 shutil.copy(PY2_TEST_MODULE, self.py2_src_dir) 78 self.setup_files.append(os.path.basename(PY2_TEST_MODULE)) 79 self.trivial_py2_file = os.path.join(self.py2_src_dir, "trivial.py") 80 self.init_py2_file = os.path.join(self.py2_src_dir, "__init__.py") 81 with open(self.trivial_py2_file, "w") as trivial: 82 trivial.write("print 'I need a simple conversion.'") 83 self.setup_files.append("trivial.py") 84 85 def test_filename_changing_on_output_single_dir(self): 86 """2to3 a single directory with a new output dir and suffix.""" 87 self.setup_test_source_trees() 88 out = StringIO.StringIO() 89 err = StringIO.StringIO() 90 suffix = "TEST" 91 ret = self.run_2to3_capture( 92 ["-n", "--add-suffix", suffix, "--write-unchanged-files", 93 "--no-diffs", "--output-dir", 94 self.py3_dest_dir, self.py2_src_dir], 95 StringIO.StringIO(""), out, err) 96 self.assertEqual(ret, 0) 97 stderr = err.getvalue() 98 self.assertIn(" implies -w.", stderr) 99 self.assertIn( 100 "Output in %r will mirror the input directory %r layout" % ( 101 self.py3_dest_dir, self.py2_src_dir), stderr) 102 self.assertEqual(set(name+suffix for name in self.setup_files), 103 set(os.listdir(self.py3_dest_dir))) 104 for name in self.setup_files: 105 self.assertIn("Writing converted %s to %s" % ( 106 os.path.join(self.py2_src_dir, name), 107 os.path.join(self.py3_dest_dir, name+suffix)), stderr) 108 sep = re.escape(os.sep) 109 self.assertRegexpMatches( 110 stderr, r"No changes to .*/__init__\.py".replace("/", sep)) 111 self.assertNotRegex( 112 stderr, r"No changes to .*/trivial\.py".replace("/", sep)) 113 114 def test_filename_changing_on_output_two_files(self): 115 """2to3 two files in one directory with a new output dir.""" 116 self.setup_test_source_trees() 117 err = StringIO.StringIO() 118 py2_files = [self.trivial_py2_file, self.init_py2_file] 119 expected_files = set(os.path.basename(name) for name in py2_files) 120 ret = self.run_2to3_capture( 121 ["-n", "-w", "--write-unchanged-files", 122 "--no-diffs", "--output-dir", self.py3_dest_dir] + py2_files, 123 StringIO.StringIO(""), StringIO.StringIO(), err) 124 self.assertEqual(ret, 0) 125 stderr = err.getvalue() 126 self.assertIn( 127 "Output in %r will mirror the input directory %r layout" % ( 128 self.py3_dest_dir, self.py2_src_dir), stderr) 129 self.assertEqual(expected_files, set(os.listdir(self.py3_dest_dir))) 130 131 def test_filename_changing_on_output_single_file(self): 132 """2to3 a single file with a new output dir.""" 133 self.setup_test_source_trees() 134 err = StringIO.StringIO() 135 ret = self.run_2to3_capture( 136 ["-n", "-w", "--no-diffs", "--output-dir", self.py3_dest_dir, 137 self.trivial_py2_file], 138 StringIO.StringIO(""), StringIO.StringIO(), err) 139 self.assertEqual(ret, 0) 140 stderr = err.getvalue() 141 self.assertIn( 142 "Output in %r will mirror the input directory %r layout" % ( 143 self.py3_dest_dir, self.py2_src_dir), stderr) 144 self.assertEqual(set([os.path.basename(self.trivial_py2_file)]), 145 set(os.listdir(self.py3_dest_dir))) 146 147 148if __name__ == '__main__': 149 unittest.main() 150