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