done
This commit is contained in:
		
							
								
								
									
										315
									
								
								lib/python3.11/site-packages/numpy/distutils/exec_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										315
									
								
								lib/python3.11/site-packages/numpy/distutils/exec_command.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,315 @@
 | 
			
		||||
"""
 | 
			
		||||
exec_command
 | 
			
		||||
 | 
			
		||||
Implements exec_command function that is (almost) equivalent to
 | 
			
		||||
commands.getstatusoutput function but on NT, DOS systems the
 | 
			
		||||
returned status is actually correct (though, the returned status
 | 
			
		||||
values may be different by a factor). In addition, exec_command
 | 
			
		||||
takes keyword arguments for (re-)defining environment variables.
 | 
			
		||||
 | 
			
		||||
Provides functions:
 | 
			
		||||
 | 
			
		||||
  exec_command  --- execute command in a specified directory and
 | 
			
		||||
                    in the modified environment.
 | 
			
		||||
  find_executable --- locate a command using info from environment
 | 
			
		||||
                    variable PATH. Equivalent to posix `which`
 | 
			
		||||
                    command.
 | 
			
		||||
 | 
			
		||||
Author: Pearu Peterson <pearu@cens.ioc.ee>
 | 
			
		||||
Created: 11 January 2003
 | 
			
		||||
 | 
			
		||||
Requires: Python 2.x
 | 
			
		||||
 | 
			
		||||
Successfully tested on:
 | 
			
		||||
 | 
			
		||||
========  ============  =================================================
 | 
			
		||||
os.name   sys.platform  comments
 | 
			
		||||
========  ============  =================================================
 | 
			
		||||
posix     linux2        Debian (sid) Linux, Python 2.1.3+, 2.2.3+, 2.3.3
 | 
			
		||||
                        PyCrust 0.9.3, Idle 1.0.2
 | 
			
		||||
posix     linux2        Red Hat 9 Linux, Python 2.1.3, 2.2.2, 2.3.2
 | 
			
		||||
posix     sunos5        SunOS 5.9, Python 2.2, 2.3.2
 | 
			
		||||
posix     darwin        Darwin 7.2.0, Python 2.3
 | 
			
		||||
nt        win32         Windows Me
 | 
			
		||||
                        Python 2.3(EE), Idle 1.0, PyCrust 0.7.2
 | 
			
		||||
                        Python 2.1.1 Idle 0.8
 | 
			
		||||
nt        win32         Windows 98, Python 2.1.1. Idle 0.8
 | 
			
		||||
nt        win32         Cygwin 98-4.10, Python 2.1.1(MSC) - echo tests
 | 
			
		||||
                        fail i.e. redefining environment variables may
 | 
			
		||||
                        not work. FIXED: don't use cygwin echo!
 | 
			
		||||
                        Comment: also `cmd /c echo` will not work
 | 
			
		||||
                        but redefining environment variables do work.
 | 
			
		||||
posix     cygwin        Cygwin 98-4.10, Python 2.3.3(cygming special)
 | 
			
		||||
nt        win32         Windows XP, Python 2.3.3
 | 
			
		||||
========  ============  =================================================
 | 
			
		||||
 | 
			
		||||
Known bugs:
 | 
			
		||||
 | 
			
		||||
* Tests, that send messages to stderr, fail when executed from MSYS prompt
 | 
			
		||||
  because the messages are lost at some point.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
__all__ = ['exec_command', 'find_executable']
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import subprocess
 | 
			
		||||
import locale
 | 
			
		||||
import warnings
 | 
			
		||||
 | 
			
		||||
from numpy.distutils.misc_util import is_sequence, make_temp_file
 | 
			
		||||
from numpy.distutils import log
 | 
			
		||||
 | 
			
		||||
def filepath_from_subprocess_output(output):
 | 
			
		||||
    """
 | 
			
		||||
    Convert `bytes` in the encoding used by a subprocess into a filesystem-appropriate `str`.
 | 
			
		||||
 | 
			
		||||
    Inherited from `exec_command`, and possibly incorrect.
 | 
			
		||||
    """
 | 
			
		||||
    mylocale = locale.getpreferredencoding(False)
 | 
			
		||||
    if mylocale is None:
 | 
			
		||||
        mylocale = 'ascii'
 | 
			
		||||
    output = output.decode(mylocale, errors='replace')
 | 
			
		||||
    output = output.replace('\r\n', '\n')
 | 
			
		||||
    # Another historical oddity
 | 
			
		||||
    if output[-1:] == '\n':
 | 
			
		||||
        output = output[:-1]
 | 
			
		||||
    return output
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def forward_bytes_to_stdout(val):
 | 
			
		||||
    """
 | 
			
		||||
    Forward bytes from a subprocess call to the console, without attempting to
 | 
			
		||||
    decode them.
 | 
			
		||||
 | 
			
		||||
    The assumption is that the subprocess call already returned bytes in
 | 
			
		||||
    a suitable encoding.
 | 
			
		||||
    """
 | 
			
		||||
    if hasattr(sys.stdout, 'buffer'):
 | 
			
		||||
        # use the underlying binary output if there is one
 | 
			
		||||
        sys.stdout.buffer.write(val)
 | 
			
		||||
    elif hasattr(sys.stdout, 'encoding'):
 | 
			
		||||
        # round-trip the encoding if necessary
 | 
			
		||||
        sys.stdout.write(val.decode(sys.stdout.encoding))
 | 
			
		||||
    else:
 | 
			
		||||
        # make a best-guess at the encoding
 | 
			
		||||
        sys.stdout.write(val.decode('utf8', errors='replace'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def temp_file_name():
 | 
			
		||||
    # 2019-01-30, 1.17
 | 
			
		||||
    warnings.warn('temp_file_name is deprecated since NumPy v1.17, use '
 | 
			
		||||
                  'tempfile.mkstemp instead', DeprecationWarning, stacklevel=1)
 | 
			
		||||
    fo, name = make_temp_file()
 | 
			
		||||
    fo.close()
 | 
			
		||||
    return name
 | 
			
		||||
 | 
			
		||||
def get_pythonexe():
 | 
			
		||||
    pythonexe = sys.executable
 | 
			
		||||
    if os.name in ['nt', 'dos']:
 | 
			
		||||
        fdir, fn = os.path.split(pythonexe)
 | 
			
		||||
        fn = fn.upper().replace('PYTHONW', 'PYTHON')
 | 
			
		||||
        pythonexe = os.path.join(fdir, fn)
 | 
			
		||||
        assert os.path.isfile(pythonexe), '%r is not a file' % (pythonexe,)
 | 
			
		||||
    return pythonexe
 | 
			
		||||
 | 
			
		||||
def find_executable(exe, path=None, _cache={}):
 | 
			
		||||
    """Return full path of a executable or None.
 | 
			
		||||
 | 
			
		||||
    Symbolic links are not followed.
 | 
			
		||||
    """
 | 
			
		||||
    key = exe, path
 | 
			
		||||
    try:
 | 
			
		||||
        return _cache[key]
 | 
			
		||||
    except KeyError:
 | 
			
		||||
        pass
 | 
			
		||||
    log.debug('find_executable(%r)' % exe)
 | 
			
		||||
    orig_exe = exe
 | 
			
		||||
 | 
			
		||||
    if path is None:
 | 
			
		||||
        path = os.environ.get('PATH', os.defpath)
 | 
			
		||||
    if os.name=='posix':
 | 
			
		||||
        realpath = os.path.realpath
 | 
			
		||||
    else:
 | 
			
		||||
        realpath = lambda a:a
 | 
			
		||||
 | 
			
		||||
    if exe.startswith('"'):
 | 
			
		||||
        exe = exe[1:-1]
 | 
			
		||||
 | 
			
		||||
    suffixes = ['']
 | 
			
		||||
    if os.name in ['nt', 'dos', 'os2']:
 | 
			
		||||
        fn, ext = os.path.splitext(exe)
 | 
			
		||||
        extra_suffixes = ['.exe', '.com', '.bat']
 | 
			
		||||
        if ext.lower() not in extra_suffixes:
 | 
			
		||||
            suffixes = extra_suffixes
 | 
			
		||||
 | 
			
		||||
    if os.path.isabs(exe):
 | 
			
		||||
        paths = ['']
 | 
			
		||||
    else:
 | 
			
		||||
        paths = [ os.path.abspath(p) for p in path.split(os.pathsep) ]
 | 
			
		||||
 | 
			
		||||
    for path in paths:
 | 
			
		||||
        fn = os.path.join(path, exe)
 | 
			
		||||
        for s in suffixes:
 | 
			
		||||
            f_ext = fn+s
 | 
			
		||||
            if not os.path.islink(f_ext):
 | 
			
		||||
                f_ext = realpath(f_ext)
 | 
			
		||||
            if os.path.isfile(f_ext) and os.access(f_ext, os.X_OK):
 | 
			
		||||
                log.info('Found executable %s' % f_ext)
 | 
			
		||||
                _cache[key] = f_ext
 | 
			
		||||
                return f_ext
 | 
			
		||||
 | 
			
		||||
    log.warn('Could not locate executable %s' % orig_exe)
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
############################################################
 | 
			
		||||
 | 
			
		||||
def _preserve_environment( names ):
 | 
			
		||||
    log.debug('_preserve_environment(%r)' % (names))
 | 
			
		||||
    env = {name: os.environ.get(name) for name in names}
 | 
			
		||||
    return env
 | 
			
		||||
 | 
			
		||||
def _update_environment( **env ):
 | 
			
		||||
    log.debug('_update_environment(...)')
 | 
			
		||||
    for name, value in env.items():
 | 
			
		||||
        os.environ[name] = value or ''
 | 
			
		||||
 | 
			
		||||
def exec_command(command, execute_in='', use_shell=None, use_tee=None,
 | 
			
		||||
                 _with_python = 1, **env ):
 | 
			
		||||
    """
 | 
			
		||||
    Return (status,output) of executed command.
 | 
			
		||||
 | 
			
		||||
    .. deprecated:: 1.17
 | 
			
		||||
        Use subprocess.Popen instead
 | 
			
		||||
 | 
			
		||||
    Parameters
 | 
			
		||||
    ----------
 | 
			
		||||
    command : str
 | 
			
		||||
        A concatenated string of executable and arguments.
 | 
			
		||||
    execute_in : str
 | 
			
		||||
        Before running command ``cd execute_in`` and after ``cd -``.
 | 
			
		||||
    use_shell : {bool, None}, optional
 | 
			
		||||
        If True, execute ``sh -c command``. Default None (True)
 | 
			
		||||
    use_tee : {bool, None}, optional
 | 
			
		||||
        If True use tee. Default None (True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    Returns
 | 
			
		||||
    -------
 | 
			
		||||
    res : str
 | 
			
		||||
        Both stdout and stderr messages.
 | 
			
		||||
 | 
			
		||||
    Notes
 | 
			
		||||
    -----
 | 
			
		||||
    On NT, DOS systems the returned status is correct for external commands.
 | 
			
		||||
    Wild cards will not work for non-posix systems or when use_shell=0.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    # 2019-01-30, 1.17
 | 
			
		||||
    warnings.warn('exec_command is deprecated since NumPy v1.17, use '
 | 
			
		||||
                  'subprocess.Popen instead', DeprecationWarning, stacklevel=1)
 | 
			
		||||
    log.debug('exec_command(%r,%s)' % (command,
 | 
			
		||||
         ','.join(['%s=%r'%kv for kv in env.items()])))
 | 
			
		||||
 | 
			
		||||
    if use_tee is None:
 | 
			
		||||
        use_tee = os.name=='posix'
 | 
			
		||||
    if use_shell is None:
 | 
			
		||||
        use_shell = os.name=='posix'
 | 
			
		||||
    execute_in = os.path.abspath(execute_in)
 | 
			
		||||
    oldcwd = os.path.abspath(os.getcwd())
 | 
			
		||||
 | 
			
		||||
    if __name__[-12:] == 'exec_command':
 | 
			
		||||
        exec_dir = os.path.dirname(os.path.abspath(__file__))
 | 
			
		||||
    elif os.path.isfile('exec_command.py'):
 | 
			
		||||
        exec_dir = os.path.abspath('.')
 | 
			
		||||
    else:
 | 
			
		||||
        exec_dir = os.path.abspath(sys.argv[0])
 | 
			
		||||
        if os.path.isfile(exec_dir):
 | 
			
		||||
            exec_dir = os.path.dirname(exec_dir)
 | 
			
		||||
 | 
			
		||||
    if oldcwd!=execute_in:
 | 
			
		||||
        os.chdir(execute_in)
 | 
			
		||||
        log.debug('New cwd: %s' % execute_in)
 | 
			
		||||
    else:
 | 
			
		||||
        log.debug('Retaining cwd: %s' % oldcwd)
 | 
			
		||||
 | 
			
		||||
    oldenv = _preserve_environment( list(env.keys()) )
 | 
			
		||||
    _update_environment( **env )
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        st = _exec_command(command,
 | 
			
		||||
                           use_shell=use_shell,
 | 
			
		||||
                           use_tee=use_tee,
 | 
			
		||||
                           **env)
 | 
			
		||||
    finally:
 | 
			
		||||
        if oldcwd!=execute_in:
 | 
			
		||||
            os.chdir(oldcwd)
 | 
			
		||||
            log.debug('Restored cwd to %s' % oldcwd)
 | 
			
		||||
        _update_environment(**oldenv)
 | 
			
		||||
 | 
			
		||||
    return st
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _exec_command(command, use_shell=None, use_tee = None, **env):
 | 
			
		||||
    """
 | 
			
		||||
    Internal workhorse for exec_command().
 | 
			
		||||
    """
 | 
			
		||||
    if use_shell is None:
 | 
			
		||||
        use_shell = os.name=='posix'
 | 
			
		||||
    if use_tee is None:
 | 
			
		||||
        use_tee = os.name=='posix'
 | 
			
		||||
 | 
			
		||||
    if os.name == 'posix' and use_shell:
 | 
			
		||||
        # On POSIX, subprocess always uses /bin/sh, override
 | 
			
		||||
        sh = os.environ.get('SHELL', '/bin/sh')
 | 
			
		||||
        if is_sequence(command):
 | 
			
		||||
            command = [sh, '-c', ' '.join(command)]
 | 
			
		||||
        else:
 | 
			
		||||
            command = [sh, '-c', command]
 | 
			
		||||
        use_shell = False
 | 
			
		||||
 | 
			
		||||
    elif os.name == 'nt' and is_sequence(command):
 | 
			
		||||
        # On Windows, join the string for CreateProcess() ourselves as
 | 
			
		||||
        # subprocess does it a bit differently
 | 
			
		||||
        command = ' '.join(_quote_arg(arg) for arg in command)
 | 
			
		||||
 | 
			
		||||
    # Inherit environment by default
 | 
			
		||||
    env = env or None
 | 
			
		||||
    try:
 | 
			
		||||
        # text is set to False so that communicate()
 | 
			
		||||
        # will return bytes. We need to decode the output ourselves
 | 
			
		||||
        # so that Python will not raise a UnicodeDecodeError when
 | 
			
		||||
        # it encounters an invalid character; rather, we simply replace it
 | 
			
		||||
        proc = subprocess.Popen(command, shell=use_shell, env=env, text=False,
 | 
			
		||||
                                stdout=subprocess.PIPE,
 | 
			
		||||
                                stderr=subprocess.STDOUT)
 | 
			
		||||
    except OSError:
 | 
			
		||||
        # Return 127, as os.spawn*() and /bin/sh do
 | 
			
		||||
        return 127, ''
 | 
			
		||||
 | 
			
		||||
    text, err = proc.communicate()
 | 
			
		||||
    mylocale = locale.getpreferredencoding(False)
 | 
			
		||||
    if mylocale is None:
 | 
			
		||||
        mylocale = 'ascii'
 | 
			
		||||
    text = text.decode(mylocale, errors='replace')
 | 
			
		||||
    text = text.replace('\r\n', '\n')
 | 
			
		||||
    # Another historical oddity
 | 
			
		||||
    if text[-1:] == '\n':
 | 
			
		||||
        text = text[:-1]
 | 
			
		||||
 | 
			
		||||
    if use_tee and text:
 | 
			
		||||
        print(text)
 | 
			
		||||
    return proc.returncode, text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _quote_arg(arg):
 | 
			
		||||
    """
 | 
			
		||||
    Quote the argument for safe use in a shell command line.
 | 
			
		||||
    """
 | 
			
		||||
    # If there is a quote in the string, assume relevant parts of the
 | 
			
		||||
    # string are already quoted (e.g. '-I"C:\\Program Files\\..."')
 | 
			
		||||
    if '"' not in arg and ' ' in arg:
 | 
			
		||||
        return '"%s"' % arg
 | 
			
		||||
    return arg
 | 
			
		||||
 | 
			
		||||
############################################################
 | 
			
		||||
		Reference in New Issue
	
	Block a user