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