mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-37064: Add option -a to pathfix.py tool (GH-15717)
Add option -a to Tools/Scripts/pathfix.py script: add flags.
This commit is contained in:
		
							parent
							
								
									468f8a6ee0
								
							
						
					
					
						commit
						1dc1acbd73
					
				
					 3 changed files with 88 additions and 23 deletions
				
			
		|  | @ -17,51 +17,90 @@ def setUp(self): | ||||||
|         self.temp_file = support.TESTFN |         self.temp_file = support.TESTFN | ||||||
|         self.addCleanup(support.unlink, support.TESTFN) |         self.addCleanup(support.unlink, support.TESTFN) | ||||||
| 
 | 
 | ||||||
|     def pathfix(self, shebang, pathfix_flags): |     def pathfix(self, shebang, pathfix_flags, exitcode=0, stdout='', stderr=''): | ||||||
|         with open(self.temp_file, 'w', encoding='utf8') as f: |         with open(self.temp_file, 'w', encoding='utf8') as f: | ||||||
|             f.write(f'{shebang}\n' + 'print("Hello world")\n') |             f.write(f'{shebang}\n' + 'print("Hello world")\n') | ||||||
| 
 | 
 | ||||||
|         proc = subprocess.run( |         proc = subprocess.run( | ||||||
|             [sys.executable, self.script, |             [sys.executable, self.script, | ||||||
|              *pathfix_flags, '-n', self.temp_file], |              *pathfix_flags, '-n', self.temp_file], | ||||||
|             capture_output=True) |             capture_output=True, text=1) | ||||||
|         self.assertEqual(proc.returncode, 0, proc) | 
 | ||||||
|  |         if stdout == '' and proc.returncode == 0: | ||||||
|  |             stdout = f'{self.temp_file}: updating\n' | ||||||
|  |         self.assertEqual(proc.returncode, exitcode, proc) | ||||||
|  |         self.assertEqual(proc.stdout, stdout, proc) | ||||||
|  |         self.assertEqual(proc.stderr, stderr, proc) | ||||||
| 
 | 
 | ||||||
|         with open(self.temp_file, 'r', encoding='utf8') as f: |         with open(self.temp_file, 'r', encoding='utf8') as f: | ||||||
|             output = f.read() |             output = f.read() | ||||||
| 
 | 
 | ||||||
|         lines = output.split('\n') |         lines = output.split('\n') | ||||||
|         self.assertEqual(lines[1:], ['print("Hello world")', '']) |         self.assertEqual(lines[1:], ['print("Hello world")', '']) | ||||||
|         shebang = lines[0] |         new_shebang = lines[0] | ||||||
|         return shebang | 
 | ||||||
|  |         if proc.returncode != 0: | ||||||
|  |             self.assertEqual(shebang, new_shebang) | ||||||
|  | 
 | ||||||
|  |         return new_shebang | ||||||
| 
 | 
 | ||||||
|     def test_pathfix(self): |     def test_pathfix(self): | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.pathfix( |             self.pathfix( | ||||||
|                 '#! /usr/bin/env python', |                 '#! /usr/bin/env python', | ||||||
|                 ['-i', '/usr/bin/python3',]), |                 ['-i', '/usr/bin/python3']), | ||||||
|             '#! /usr/bin/python3', |             '#! /usr/bin/python3') | ||||||
|         ) |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.pathfix( |             self.pathfix( | ||||||
|                 '#! /usr/bin/env python -R', |                 '#! /usr/bin/env python -R', | ||||||
|                 ['-i', '/usr/bin/python3', ]), |                 ['-i', '/usr/bin/python3']), | ||||||
|             '#! /usr/bin/python3', |             '#! /usr/bin/python3') | ||||||
|         ) |  | ||||||
| 
 | 
 | ||||||
|     def test_pathfix_keeping_flags(self): |     def test_pathfix_keeping_flags(self): | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.pathfix( |             self.pathfix( | ||||||
|                 '#! /usr/bin/env python -R', |                 '#! /usr/bin/env python -R', | ||||||
|                 ['-i', '/usr/bin/python3', '-k',]), |                 ['-i', '/usr/bin/python3', '-k']), | ||||||
|             '#! /usr/bin/python3 -R', |             '#! /usr/bin/python3 -R') | ||||||
|         ) |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.pathfix( |             self.pathfix( | ||||||
|                 '#! /usr/bin/env python', |                 '#! /usr/bin/env python', | ||||||
|                 ['-i', '/usr/bin/python3', '-k',]), |                 ['-i', '/usr/bin/python3', '-k']), | ||||||
|             '#! /usr/bin/python3', |             '#! /usr/bin/python3') | ||||||
|         ) | 
 | ||||||
|  |     def test_pathfix_adding_flag(self): | ||||||
|  |         self.assertEqual( | ||||||
|  |             self.pathfix( | ||||||
|  |                 '#! /usr/bin/env python', | ||||||
|  |                 ['-i', '/usr/bin/python3', '-a', 's']), | ||||||
|  |             '#! /usr/bin/python3 -s') | ||||||
|  |         self.assertEqual( | ||||||
|  |             self.pathfix( | ||||||
|  |                 '#! /usr/bin/env python -S', | ||||||
|  |                 ['-i', '/usr/bin/python3', '-a', 's']), | ||||||
|  |             '#! /usr/bin/python3 -s') | ||||||
|  |         self.assertEqual( | ||||||
|  |             self.pathfix( | ||||||
|  |                 '#! /usr/bin/env python -V', | ||||||
|  |                 ['-i', '/usr/bin/python3', '-a', 'v', '-k']), | ||||||
|  |             '#! /usr/bin/python3 -vV') | ||||||
|  |         self.assertEqual( | ||||||
|  |             self.pathfix( | ||||||
|  |                 '#! /usr/bin/env python', | ||||||
|  |                 ['-i', '/usr/bin/python3', '-a', 'Rs']), | ||||||
|  |             '#! /usr/bin/python3 -Rs') | ||||||
|  |         self.assertEqual( | ||||||
|  |             self.pathfix( | ||||||
|  |                 '#! /usr/bin/env python -W default', | ||||||
|  |                 ['-i', '/usr/bin/python3', '-a', 's', '-k']), | ||||||
|  |             '#! /usr/bin/python3 -sW default') | ||||||
|  | 
 | ||||||
|  |     def test_pathfix_adding_errors(self): | ||||||
|  |         self.pathfix( | ||||||
|  |             '#! /usr/bin/env python -E', | ||||||
|  |             ['-i', '/usr/bin/python3', '-a', 'W default', '-k'], | ||||||
|  |             exitcode=2, | ||||||
|  |             stderr="-a option doesn't support whitespaces") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|  |  | ||||||
|  | @ -1 +1,2 @@ | ||||||
| Add flag -k to pathscript.py script: preserve shebang flags. | Add option -k to pathscript.py script: preserve shebang flags. | ||||||
|  | Add option -a to pathscript.py script: add flags. | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ | ||||||
| # Sometimes you may find shebangs with flags such as `#! /usr/bin/env python -si`. | # Sometimes you may find shebangs with flags such as `#! /usr/bin/env python -si`. | ||||||
| # Normally, pathfix overwrites the entire line, including the flags. | # Normally, pathfix overwrites the entire line, including the flags. | ||||||
| # To change interpreter and keep flags from the original shebang line, use -k. | # To change interpreter and keep flags from the original shebang line, use -k. | ||||||
|  | # If you want to keep flags and add to them one single literal flag, use option -a. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Undoubtedly you can do this using find and sed or perl, but this is | # Undoubtedly you can do this using find and sed or perl, but this is | ||||||
|  | @ -39,6 +40,7 @@ | ||||||
| preserve_timestamps = False | preserve_timestamps = False | ||||||
| create_backup = True | create_backup = True | ||||||
| keep_flags = False | keep_flags = False | ||||||
|  | add_flags = b'' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def main(): | def main(): | ||||||
|  | @ -46,11 +48,12 @@ def main(): | ||||||
|     global preserve_timestamps |     global preserve_timestamps | ||||||
|     global create_backup |     global create_backup | ||||||
|     global keep_flags |     global keep_flags | ||||||
|  |     global add_flags | ||||||
| 
 | 
 | ||||||
|     usage = ('usage: %s -i /interpreter -p -n -k file-or-directory ...\n' % |     usage = ('usage: %s -i /interpreter -p -n -k -a file-or-directory ...\n' % | ||||||
|              sys.argv[0]) |              sys.argv[0]) | ||||||
|     try: |     try: | ||||||
|         opts, args = getopt.getopt(sys.argv[1:], 'i:kpn') |         opts, args = getopt.getopt(sys.argv[1:], 'i:a:kpn') | ||||||
|     except getopt.error as msg: |     except getopt.error as msg: | ||||||
|         err(str(msg) + '\n') |         err(str(msg) + '\n') | ||||||
|         err(usage) |         err(usage) | ||||||
|  | @ -64,6 +67,11 @@ def main(): | ||||||
|             create_backup = False |             create_backup = False | ||||||
|         if o == '-k': |         if o == '-k': | ||||||
|             keep_flags = True |             keep_flags = True | ||||||
|  |         if o == '-a': | ||||||
|  |             add_flags = a.encode() | ||||||
|  |             if b' ' in add_flags: | ||||||
|  |                 err("-a option doesn't support whitespaces") | ||||||
|  |                 sys.exit(2) | ||||||
|     if not new_interpreter or not new_interpreter.startswith(b'/') or \ |     if not new_interpreter or not new_interpreter.startswith(b'/') or \ | ||||||
|            not args: |            not args: | ||||||
|         err('-i option or file-or-directory missing\n') |         err('-i option or file-or-directory missing\n') | ||||||
|  | @ -188,15 +196,32 @@ def parse_shebang(shebangline): | ||||||
|     return shebangline[start:] |     return shebangline[start:] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def populate_flags(shebangline): | ||||||
|  |     old_flags = b'' | ||||||
|  |     if keep_flags: | ||||||
|  |         old_flags = parse_shebang(shebangline) | ||||||
|  |         if old_flags: | ||||||
|  |             old_flags = old_flags[2:] | ||||||
|  |     if not (old_flags or add_flags): | ||||||
|  |         return b'' | ||||||
|  |     # On Linux, the entire string following the interpreter name | ||||||
|  |     # is passed as a single argument to the interpreter. | ||||||
|  |     # e.g. "#! /usr/bin/python3 -W Error -s" runs "/usr/bin/python3 "-W Error -s" | ||||||
|  |     # so shebang should have single '-' where flags are given and | ||||||
|  |     # flag might need argument for that reasons adding new flags is | ||||||
|  |     # between '-' and original flags | ||||||
|  |     # e.g. #! /usr/bin/python3 -sW Error | ||||||
|  |     return b' -' + add_flags + old_flags | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def fixline(line): | def fixline(line): | ||||||
|     if not line.startswith(b'#!'): |     if not line.startswith(b'#!'): | ||||||
|         return line |         return line | ||||||
| 
 | 
 | ||||||
|     if b"python" not in line: |     if b"python" not in line: | ||||||
|         return line |         return line | ||||||
|     flags = b'' | 
 | ||||||
|     if keep_flags: |     flags = populate_flags(line) | ||||||
|         flags = parse_shebang(line) |  | ||||||
|     return b'#! ' + new_interpreter + flags + b'\n' |     return b'#! ' + new_interpreter + flags + b'\n' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 PatrikKopkan
						PatrikKopkan