mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	Add os.waitstatus_to_exitcode() function to convert a wait status to an exitcode. Suggest waitstatus_to_exitcode() usage in the documentation when appropriate. Use waitstatus_to_exitcode() in: * multiprocessing, os, subprocess and _bootsubprocess modules; * test.support.wait_process(); * setup.py: run_command(); * and many tests.
		
			
				
	
	
		
			97 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
Basic subprocess implementation for POSIX which only uses os functions. Only
 | 
						|
implement features required by setup.py to build C extension modules when
 | 
						|
subprocess is unavailable. setup.py is not used on Windows.
 | 
						|
"""
 | 
						|
import os
 | 
						|
 | 
						|
 | 
						|
# distutils.spawn used by distutils.command.build_ext
 | 
						|
# calls subprocess.Popen().wait()
 | 
						|
class Popen:
 | 
						|
    def __init__(self, cmd, env=None):
 | 
						|
        self._cmd = cmd
 | 
						|
        self._env = env
 | 
						|
        self.returncode = None
 | 
						|
 | 
						|
    def wait(self):
 | 
						|
        pid = os.fork()
 | 
						|
        if pid == 0:
 | 
						|
            # Child process
 | 
						|
            try:
 | 
						|
                if self._env is not None:
 | 
						|
                    os.execve(self._cmd[0], self._cmd, self._env)
 | 
						|
                else:
 | 
						|
                    os.execv(self._cmd[0], self._cmd)
 | 
						|
            finally:
 | 
						|
                os._exit(1)
 | 
						|
        else:
 | 
						|
            # Parent process
 | 
						|
            _, status = os.waitpid(pid, 0)
 | 
						|
            self.returncode = os.waitstatus_to_exitcode(status)
 | 
						|
 | 
						|
        return self.returncode
 | 
						|
 | 
						|
 | 
						|
def _check_cmd(cmd):
 | 
						|
    # Use regex [a-zA-Z0-9./-]+: reject empty string, space, etc.
 | 
						|
    safe_chars = []
 | 
						|
    for first, last in (("a", "z"), ("A", "Z"), ("0", "9")):
 | 
						|
        for ch in range(ord(first), ord(last) + 1):
 | 
						|
            safe_chars.append(chr(ch))
 | 
						|
    safe_chars.append("./-")
 | 
						|
    safe_chars = ''.join(safe_chars)
 | 
						|
 | 
						|
    if isinstance(cmd, (tuple, list)):
 | 
						|
        check_strs = cmd
 | 
						|
    elif isinstance(cmd, str):
 | 
						|
        check_strs = [cmd]
 | 
						|
    else:
 | 
						|
        return False
 | 
						|
 | 
						|
    for arg in check_strs:
 | 
						|
        if not isinstance(arg, str):
 | 
						|
            return False
 | 
						|
        if not arg:
 | 
						|
            # reject empty string
 | 
						|
            return False
 | 
						|
        for ch in arg:
 | 
						|
            if ch not in safe_chars:
 | 
						|
                return False
 | 
						|
 | 
						|
    return True
 | 
						|
 | 
						|
 | 
						|
# _aix_support used by distutil.util calls subprocess.check_output()
 | 
						|
def check_output(cmd, **kwargs):
 | 
						|
    if kwargs:
 | 
						|
        raise NotImplementedError(repr(kwargs))
 | 
						|
 | 
						|
    if not _check_cmd(cmd):
 | 
						|
        raise ValueError(f"unsupported command: {cmd!r}")
 | 
						|
 | 
						|
    tmp_filename = "check_output.tmp"
 | 
						|
    if not isinstance(cmd, str):
 | 
						|
        cmd = " ".join(cmd)
 | 
						|
    cmd = f"{cmd} >{tmp_filename}"
 | 
						|
 | 
						|
    try:
 | 
						|
        # system() spawns a shell
 | 
						|
        status = os.system(cmd)
 | 
						|
        exitcode = os.waitstatus_to_exitcode(status)
 | 
						|
        if exitcode:
 | 
						|
            raise ValueError(f"Command {cmd!r} returned non-zero "
 | 
						|
                             f"exit status {exitcode!r}")
 | 
						|
 | 
						|
        try:
 | 
						|
            with open(tmp_filename, "rb") as fp:
 | 
						|
                stdout = fp.read()
 | 
						|
        except FileNotFoundError:
 | 
						|
            stdout = b''
 | 
						|
    finally:
 | 
						|
        try:
 | 
						|
            os.unlink(tmp_filename)
 | 
						|
        except OSError:
 | 
						|
            pass
 | 
						|
 | 
						|
    return stdout
 |