1import os 2import subprocess 3import sys 4import unittest 5from test import support 6from test.support import os_helper 7from test.test_tools import scriptsdir, skip_if_missing 8 9 10# need Tools/script/ directory: skip if run on Python installed on the system 11skip_if_missing() 12 13 14class TestPathfixFunctional(unittest.TestCase): 15 script = os.path.join(scriptsdir, 'pathfix.py') 16 17 def setUp(self): 18 self.addCleanup(os_helper.unlink, os_helper.TESTFN) 19 20 def pathfix(self, shebang, pathfix_flags, exitcode=0, stdout='', stderr='', 21 directory=''): 22 if directory: 23 # bpo-38347: Test filename should contain lowercase, uppercase, 24 # "-", "_" and digits. 25 filename = os.path.join(directory, 'script-A_1.py') 26 pathfix_arg = directory 27 else: 28 filename = os_helper.TESTFN 29 pathfix_arg = filename 30 31 with open(filename, 'w', encoding='utf8') as f: 32 f.write(f'{shebang}\n' + 'print("Hello world")\n') 33 34 encoding = sys.getfilesystemencoding() 35 proc = subprocess.run( 36 [sys.executable, self.script, 37 *pathfix_flags, '-n', pathfix_arg], 38 env={**os.environ, 'PYTHONIOENCODING': encoding}, 39 capture_output=True) 40 41 if stdout == '' and proc.returncode == 0: 42 stdout = f'{filename}: updating\n' 43 self.assertEqual(proc.returncode, exitcode, proc) 44 self.assertEqual(proc.stdout.decode(encoding), stdout.replace('\n', os.linesep), proc) 45 self.assertEqual(proc.stderr.decode(encoding), stderr.replace('\n', os.linesep), proc) 46 47 with open(filename, 'r', encoding='utf8') as f: 48 output = f.read() 49 50 lines = output.split('\n') 51 self.assertEqual(lines[1:], ['print("Hello world")', '']) 52 new_shebang = lines[0] 53 54 if proc.returncode != 0: 55 self.assertEqual(shebang, new_shebang) 56 57 return new_shebang 58 59 def test_recursive(self): 60 tmpdir = os_helper.TESTFN + '.d' 61 self.addCleanup(os_helper.rmtree, tmpdir) 62 os.mkdir(tmpdir) 63 expected_stderr = f"recursedown('{os.path.basename(tmpdir)}')\n" 64 self.assertEqual( 65 self.pathfix( 66 '#! /usr/bin/env python', 67 ['-i', '/usr/bin/python3'], 68 directory=tmpdir, 69 stderr=expected_stderr), 70 '#! /usr/bin/python3') 71 72 def test_pathfix(self): 73 self.assertEqual( 74 self.pathfix( 75 '#! /usr/bin/env python', 76 ['-i', '/usr/bin/python3']), 77 '#! /usr/bin/python3') 78 self.assertEqual( 79 self.pathfix( 80 '#! /usr/bin/env python -R', 81 ['-i', '/usr/bin/python3']), 82 '#! /usr/bin/python3') 83 84 def test_pathfix_keeping_flags(self): 85 self.assertEqual( 86 self.pathfix( 87 '#! /usr/bin/env python -R', 88 ['-i', '/usr/bin/python3', '-k']), 89 '#! /usr/bin/python3 -R') 90 self.assertEqual( 91 self.pathfix( 92 '#! /usr/bin/env python', 93 ['-i', '/usr/bin/python3', '-k']), 94 '#! /usr/bin/python3') 95 96 def test_pathfix_adding_flag(self): 97 self.assertEqual( 98 self.pathfix( 99 '#! /usr/bin/env python', 100 ['-i', '/usr/bin/python3', '-a', 's']), 101 '#! /usr/bin/python3 -s') 102 self.assertEqual( 103 self.pathfix( 104 '#! /usr/bin/env python -S', 105 ['-i', '/usr/bin/python3', '-a', 's']), 106 '#! /usr/bin/python3 -s') 107 self.assertEqual( 108 self.pathfix( 109 '#! /usr/bin/env python -V', 110 ['-i', '/usr/bin/python3', '-a', 'v', '-k']), 111 '#! /usr/bin/python3 -vV') 112 self.assertEqual( 113 self.pathfix( 114 '#! /usr/bin/env python', 115 ['-i', '/usr/bin/python3', '-a', 'Rs']), 116 '#! /usr/bin/python3 -Rs') 117 self.assertEqual( 118 self.pathfix( 119 '#! /usr/bin/env python -W default', 120 ['-i', '/usr/bin/python3', '-a', 's', '-k']), 121 '#! /usr/bin/python3 -sW default') 122 123 def test_pathfix_adding_errors(self): 124 self.pathfix( 125 '#! /usr/bin/env python -E', 126 ['-i', '/usr/bin/python3', '-a', 'W default', '-k'], 127 exitcode=2, 128 stderr="-a option doesn't support whitespaces") 129 130 131if __name__ == '__main__': 132 unittest.main() 133