bpo-39763: distutils.spawn now uses subprocess (GH-18743)

Reimplement distutils.spawn.spawn() function with the subprocess
module.

setup.py now uses a basic implementation of the subprocess module if
the subprocess module is not available: before required C extension
modules are built.
This commit is contained in:
Victor Stinner 2020-03-04 14:50:19 +01:00 committed by GitHub
parent dffe4c0709
commit 1ec63b6203
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 117 deletions

View file

@ -10,6 +10,61 @@ import sys
import sysconfig
from glob import glob
try:
import subprocess
del subprocess
SUBPROCESS_BOOTSTRAP = False
except ImportError:
SUBPROCESS_BOOTSTRAP = True
# Bootstrap Python: distutils.spawn uses subprocess to build C extensions,
# subprocess requires C extensions built by setup.py like _posixsubprocess.
#
# Basic subprocess implementation for POSIX (setup.py is not used on
# Windows) which only uses os functions. Only implement features required
# by distutils.spawn.
#
# It is dropped from sys.modules as soon as all C extension modules
# are built.
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
pid, status = os.waitpid(pid, 0)
if os.WIFSIGNALED(status):
self.returncode = -os.WTERMSIG(status)
elif os.WIFEXITED(status):
self.returncode = os.WEXITSTATUS(status)
elif os.WIFSTOPPED(status):
self.returncode = -os.WSTOPSIG(sts)
else:
# Should never happen
raise Exception("Unknown child exit status!")
return self.returncode
mod = type(sys)('subprocess')
mod.Popen = Popen
sys.modules['subprocess'] = mod
del mod
from distutils import log
from distutils.command.build_ext import build_ext
from distutils.command.build_scripts import build_scripts
@ -391,6 +446,11 @@ class PyBuildExt(build_ext):
build_ext.build_extensions(self)
if SUBPROCESS_BOOTSTRAP:
# Drop our custom subprocess module:
# use the newly built subprocess module
del sys.modules['subprocess']
for ext in self.extensions:
self.check_extension_import(ext)