summaryrefslogtreecommitdiff
path: root/Lib/_bootsubprocess.py
diff options
context:
space:
mode:
authorChristian Heimes <christian@python.org>2022-07-14 09:51:49 +0200
committerGitHub <noreply@github.com>2022-07-14 00:51:49 -0700
commit81dca70d704d0834d8c30580e648a973250b2973 (patch)
tree4c3fbd011e05692ae1720457d0e7602484b8dd26 /Lib/_bootsubprocess.py
parentb03a9e8c8a4f3f5bb7196d4825fbfdaff022756f (diff)
downloadcpython-git-81dca70d704d0834d8c30580e648a973250b2973.tar.gz
gh-93939: Build C extensions without setup.py (GH-94474)
Combines GH-93940, GH-94452, and GH-94433
Diffstat (limited to 'Lib/_bootsubprocess.py')
-rw-r--r--Lib/_bootsubprocess.py97
1 files changed, 0 insertions, 97 deletions
diff --git a/Lib/_bootsubprocess.py b/Lib/_bootsubprocess.py
deleted file mode 100644
index 014782f616..0000000000
--- a/Lib/_bootsubprocess.py
+++ /dev/null
@@ -1,97 +0,0 @@
-"""
-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