# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Cross-platform utilities for creating subprocesses. For internal use only; no backwards-compatibility guarantees. """ # pytype: skip-file import platform import subprocess import traceback from typing import TYPE_CHECKING # On Windows, we need to use shell=True when creating subprocesses for binary # paths to be resolved correctly. force_shell = platform.system() == 'Windows' # We mimic the interface of the standard Python subprocess module. PIPE = subprocess.PIPE STDOUT = subprocess.STDOUT CalledProcessError = subprocess.CalledProcessError if TYPE_CHECKING: call = subprocess.call check_call = subprocess.check_call check_output = subprocess.check_output Popen = subprocess.Popen else: def call(*args, **kwargs): if force_shell: kwargs['shell'] = True try: out = subprocess.call(*args, **kwargs) except OSError as e: raise RuntimeError("Executable {} not found".format(args[0])) from e except subprocess.CalledProcessError as error: if isinstance(args, tuple) and (args[0][2] == "pip"): raise RuntimeError( \ "Full traceback: {}\n Pip install failed for package: {} \ \n Output from execution of subprocess: {}" \ .format(traceback.format_exc(), args[0][6], error. output)) from error else: raise RuntimeError("Full trace: {}\ \n Output of the failed child process: {} " \ .format(traceback.format_exc(), error.output)) from error return out def check_call(*args, **kwargs): if force_shell: kwargs['shell'] = True try: out = subprocess.check_call(*args, **kwargs) except OSError as e: raise RuntimeError("Executable {} not found".format(args[0])) from e except subprocess.CalledProcessError as error: if isinstance(args, tuple) and (args[0][2] == "pip"): raise RuntimeError( \ "Full traceback: {} \n Pip install failed for package: {} \ \n Output from execution of subprocess: {}" \ .format(traceback.format_exc(), args[0][6], error.output)) from error else: raise RuntimeError("Full trace: {} \ \n Output of the failed child process: {}" \ .format(traceback.format_exc(), error.output)) from error return out def check_output(*args, **kwargs): if force_shell: kwargs['shell'] = True try: out = subprocess.check_output(*args, **kwargs) except OSError as e: raise RuntimeError("Executable {} not found".format(args[0])) from e except subprocess.CalledProcessError as error: if isinstance(args, tuple) and (args[0][2] == "pip"): raise RuntimeError( \ "Full traceback: {} \n Pip install failed for package: {} \ \n Output from execution of subprocess: {}" \ .format(traceback.format_exc(), args[0][6], error.output)) from error else: raise RuntimeError("Full trace: {}, \ output of the failed child process {} "\ .format(traceback.format_exc(), error.output)) from error return out def Popen(*args, **kwargs): if force_shell: kwargs['shell'] = True return subprocess.Popen(*args, **kwargs)