Merged revisions 80439 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r80439 | brian.curtin | 2010-04-24 10:40:11 -0500 (Sat, 24 Apr 2010) | 6 lines Fix #7838. Add docstrings and privatize _subprocess implementation details. Since CREATE_NEW_* are used for the creation flags of a subprocess, they were added to __all__. The rest of the previously exposed attributes are now qualified by _subprocess.ATTR rather than importing *. ........
This commit is contained in:
parent
e322024449
commit
1ce6b58153
|
@ -356,31 +356,18 @@ class CalledProcessError(Exception):
|
|||
|
||||
|
||||
if mswindows:
|
||||
from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP
|
||||
import threading
|
||||
import msvcrt
|
||||
if 0: # <-- change this to use pywin32 instead of the _subprocess driver
|
||||
import pywintypes
|
||||
from win32api import GetStdHandle, STD_INPUT_HANDLE, \
|
||||
STD_OUTPUT_HANDLE, STD_ERROR_HANDLE
|
||||
from win32api import GetCurrentProcess, DuplicateHandle, \
|
||||
GetModuleFileName, GetVersion
|
||||
from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE
|
||||
from win32pipe import CreatePipe
|
||||
from win32process import CreateProcess, STARTUPINFO, \
|
||||
GetExitCodeProcess, STARTF_USESTDHANDLES, \
|
||||
STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE
|
||||
from win32process import TerminateProcess
|
||||
from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0
|
||||
else:
|
||||
from _subprocess import *
|
||||
class STARTUPINFO:
|
||||
dwFlags = 0
|
||||
hStdInput = None
|
||||
hStdOutput = None
|
||||
hStdError = None
|
||||
wShowWindow = 0
|
||||
class pywintypes:
|
||||
error = IOError
|
||||
import _subprocess
|
||||
class STARTUPINFO:
|
||||
dwFlags = 0
|
||||
hStdInput = None
|
||||
hStdOutput = None
|
||||
hStdError = None
|
||||
wShowWindow = 0
|
||||
class pywintypes:
|
||||
error = IOError
|
||||
else:
|
||||
import select
|
||||
_has_poll = hasattr(select, 'poll')
|
||||
|
@ -406,6 +393,8 @@ else:
|
|||
__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput",
|
||||
"getoutput", "check_output", "CalledProcessError"]
|
||||
|
||||
if mswindows:
|
||||
__all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP"])
|
||||
try:
|
||||
MAXFD = os.sysconf("SC_OPEN_MAX")
|
||||
except:
|
||||
|
@ -770,11 +759,11 @@ class Popen(object):
|
|||
errread, errwrite = -1, -1
|
||||
|
||||
if stdin is None:
|
||||
p2cread = GetStdHandle(STD_INPUT_HANDLE)
|
||||
p2cread = _subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE)
|
||||
if p2cread is None:
|
||||
p2cread, _ = CreatePipe(None, 0)
|
||||
p2cread, _ = _subprocess.CreatePipe(None, 0)
|
||||
elif stdin == PIPE:
|
||||
p2cread, p2cwrite = CreatePipe(None, 0)
|
||||
p2cread, p2cwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif isinstance(stdin, int):
|
||||
p2cread = msvcrt.get_osfhandle(stdin)
|
||||
else:
|
||||
|
@ -783,11 +772,11 @@ class Popen(object):
|
|||
p2cread = self._make_inheritable(p2cread)
|
||||
|
||||
if stdout is None:
|
||||
c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
c2pwrite = _subprocess.GetStdHandle(_subprocess.STD_OUTPUT_HANDLE)
|
||||
if c2pwrite is None:
|
||||
_, c2pwrite = CreatePipe(None, 0)
|
||||
_, c2pwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif stdout == PIPE:
|
||||
c2pread, c2pwrite = CreatePipe(None, 0)
|
||||
c2pread, c2pwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif isinstance(stdout, int):
|
||||
c2pwrite = msvcrt.get_osfhandle(stdout)
|
||||
else:
|
||||
|
@ -796,11 +785,11 @@ class Popen(object):
|
|||
c2pwrite = self._make_inheritable(c2pwrite)
|
||||
|
||||
if stderr is None:
|
||||
errwrite = GetStdHandle(STD_ERROR_HANDLE)
|
||||
errwrite = _subprocess.GetStdHandle(_subprocess.STD_ERROR_HANDLE)
|
||||
if errwrite is None:
|
||||
_, errwrite = CreatePipe(None, 0)
|
||||
_, errwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif stderr == PIPE:
|
||||
errread, errwrite = CreatePipe(None, 0)
|
||||
errread, errwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif stderr == STDOUT:
|
||||
errwrite = c2pwrite
|
||||
elif isinstance(stderr, int):
|
||||
|
@ -817,14 +806,15 @@ class Popen(object):
|
|||
|
||||
def _make_inheritable(self, handle):
|
||||
"""Return a duplicate of handle, which is inheritable"""
|
||||
return DuplicateHandle(GetCurrentProcess(), handle,
|
||||
GetCurrentProcess(), 0, 1,
|
||||
DUPLICATE_SAME_ACCESS)
|
||||
return _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(),
|
||||
handle, _subprocess.GetCurrentProcess(), 0, 1,
|
||||
_subprocess.DUPLICATE_SAME_ACCESS)
|
||||
|
||||
|
||||
def _find_w9xpopen(self):
|
||||
"""Find and return absolut path to w9xpopen.exe"""
|
||||
w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)),
|
||||
w9xpopen = os.path.join(
|
||||
os.path.dirname(_subprocess.GetModuleFileName(0)),
|
||||
"w9xpopen.exe")
|
||||
if not os.path.exists(w9xpopen):
|
||||
# Eeek - file-not-found - possibly an embedding
|
||||
|
@ -854,17 +844,17 @@ class Popen(object):
|
|||
if startupinfo is None:
|
||||
startupinfo = STARTUPINFO()
|
||||
if None not in (p2cread, c2pwrite, errwrite):
|
||||
startupinfo.dwFlags |= STARTF_USESTDHANDLES
|
||||
startupinfo.dwFlags |= _subprocess.STARTF_USESTDHANDLES
|
||||
startupinfo.hStdInput = p2cread
|
||||
startupinfo.hStdOutput = c2pwrite
|
||||
startupinfo.hStdError = errwrite
|
||||
|
||||
if shell:
|
||||
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
|
||||
startupinfo.wShowWindow = SW_HIDE
|
||||
startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
|
||||
startupinfo.wShowWindow = _subprocess.SW_HIDE
|
||||
comspec = os.environ.get("COMSPEC", "cmd.exe")
|
||||
args = comspec + " /c " + args
|
||||
if (GetVersion() >= 0x80000000 or
|
||||
if (_subprocess.GetVersion() >= 0x80000000 or
|
||||
os.path.basename(comspec).lower() == "command.com"):
|
||||
# Win9x, or using command.com on NT. We need to
|
||||
# use the w9xpopen intermediate program. For more
|
||||
|
@ -878,11 +868,11 @@ class Popen(object):
|
|||
# use at xxx" and a hopeful warning about the
|
||||
# stability of your system. Cost is Ctrl+C won't
|
||||
# kill children.
|
||||
creationflags |= CREATE_NEW_CONSOLE
|
||||
creationflags |= _subprocess.CREATE_NEW_CONSOLE
|
||||
|
||||
# Start the process
|
||||
try:
|
||||
hp, ht, pid, tid = CreateProcess(executable, args,
|
||||
hp, ht, pid, tid = _subprocess.CreateProcess(executable, args,
|
||||
# no special security
|
||||
None, None,
|
||||
int(not close_fds),
|
||||
|
@ -921,8 +911,9 @@ class Popen(object):
|
|||
"""Check if child process has terminated. Returns returncode
|
||||
attribute."""
|
||||
if self.returncode is None:
|
||||
if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0:
|
||||
self.returncode = GetExitCodeProcess(self._handle)
|
||||
if(_subprocess.WaitForSingleObject(self._handle, 0) ==
|
||||
_subprocess.WAIT_OBJECT_0):
|
||||
self.returncode = _subprocess.GetExitCodeProcess(self._handle)
|
||||
return self.returncode
|
||||
|
||||
|
||||
|
@ -930,8 +921,9 @@ class Popen(object):
|
|||
"""Wait for child process to terminate. Returns returncode
|
||||
attribute."""
|
||||
if self.returncode is None:
|
||||
WaitForSingleObject(self._handle, INFINITE)
|
||||
self.returncode = GetExitCodeProcess(self._handle)
|
||||
_subprocess.WaitForSingleObject(self._handle,
|
||||
_subprocess.INFINITE)
|
||||
self.returncode = _subprocess.GetExitCodeProcess(self._handle)
|
||||
return self.returncode
|
||||
|
||||
|
||||
|
@ -990,7 +982,7 @@ class Popen(object):
|
|||
def terminate(self):
|
||||
"""Terminates the process
|
||||
"""
|
||||
TerminateProcess(self._handle, 1)
|
||||
_subprocess.TerminateProcess(self._handle, 1)
|
||||
|
||||
kill = terminate
|
||||
|
||||
|
|
103
PC/_subprocess.c
103
PC/_subprocess.c
|
@ -158,6 +158,13 @@ static PyTypeObject sp_handle_type = {
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* windows API functions */
|
||||
|
||||
PyDoc_STRVAR(GetStdHandle_doc,
|
||||
"GetStdHandle(handle) -> integer\n\
|
||||
\n\
|
||||
Return a handle to the specified standard device\n\
|
||||
(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\
|
||||
The integer associated with the handle object is returned.");
|
||||
|
||||
static PyObject *
|
||||
sp_GetStdHandle(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -183,6 +190,11 @@ sp_GetStdHandle(PyObject* self, PyObject* args)
|
|||
return HANDLE_TO_PYNUM(handle);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(GetCurrentProcess_doc,
|
||||
"GetCurrentProcess() -> handle\n\
|
||||
\n\
|
||||
Return a handle object for the current process.");
|
||||
|
||||
static PyObject *
|
||||
sp_GetCurrentProcess(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -192,6 +204,17 @@ sp_GetCurrentProcess(PyObject* self, PyObject* args)
|
|||
return sp_handle_new(GetCurrentProcess());
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(DuplicateHandle_doc,
|
||||
"DuplicateHandle(source_proc_handle, source_handle,\n\
|
||||
target_proc_handle, target_handle, access,\n\
|
||||
inherit[, options]) -> handle\n\
|
||||
\n\
|
||||
Return a duplicate handle object.\n\
|
||||
\n\
|
||||
The duplicate handle refers to the same object as the original\n\
|
||||
handle. Therefore, any changes to the object are reflected\n\
|
||||
through both handles.");
|
||||
|
||||
static PyObject *
|
||||
sp_DuplicateHandle(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -234,6 +257,14 @@ sp_DuplicateHandle(PyObject* self, PyObject* args)
|
|||
return sp_handle_new(target_handle);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(CreatePipe_doc,
|
||||
"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\
|
||||
\n\
|
||||
Create an anonymous pipe, and return handles to the read and\n\
|
||||
write ends of the pipe.\n\
|
||||
\n\
|
||||
pipe_attrs is ignored internally and can be None.");
|
||||
|
||||
static PyObject *
|
||||
sp_CreatePipe(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -369,6 +400,18 @@ getenvironment(PyObject* environment)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(CreateProcess_doc,
|
||||
"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\
|
||||
inherit, flags, env_mapping, curdir,\n\
|
||||
startup_info) -> (proc_handle, thread_handle,\n\
|
||||
pid, tid)\n\
|
||||
\n\
|
||||
Create a new process and its primary thread. The return\n\
|
||||
value is a tuple of the process handle, thread handle,\n\
|
||||
process ID, and thread ID.\n\
|
||||
\n\
|
||||
proc_attrs and thread_attrs are ignored internally and can be None.");
|
||||
|
||||
static PyObject *
|
||||
sp_CreateProcess(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -445,6 +488,11 @@ sp_CreateProcess(PyObject* self, PyObject* args)
|
|||
pi.dwThreadId);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(TerminateProcess_doc,
|
||||
"TerminateProcess(handle, exit_code) -> None\n\
|
||||
\n\
|
||||
Terminate the specified process and all of its threads.");
|
||||
|
||||
static PyObject *
|
||||
sp_TerminateProcess(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -465,6 +513,11 @@ sp_TerminateProcess(PyObject* self, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(GetExitCodeProcess_doc,
|
||||
"GetExitCodeProcess(handle) -> Exit code\n\
|
||||
\n\
|
||||
Return the termination status of the specified process.");
|
||||
|
||||
static PyObject *
|
||||
sp_GetExitCodeProcess(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -483,6 +536,13 @@ sp_GetExitCodeProcess(PyObject* self, PyObject* args)
|
|||
return PyLong_FromLong(exit_code);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(WaitForSingleObject_doc,
|
||||
"WaitForSingleObject(handle, timeout) -> result\n\
|
||||
\n\
|
||||
Wait until the specified object is in the signaled state or\n\
|
||||
the time-out interval elapses. The timeout value is specified\n\
|
||||
in milliseconds.");
|
||||
|
||||
static PyObject *
|
||||
sp_WaitForSingleObject(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -505,6 +565,11 @@ sp_WaitForSingleObject(PyObject* self, PyObject* args)
|
|||
return PyLong_FromLong((int) result);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(GetVersion_doc,
|
||||
"GetVersion() -> version\n\
|
||||
\n\
|
||||
Return the version number of the current operating system.");
|
||||
|
||||
static PyObject *
|
||||
sp_GetVersion(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -514,6 +579,18 @@ sp_GetVersion(PyObject* self, PyObject* args)
|
|||
return PyLong_FromLong((int) GetVersion());
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(GetModuleFileName_doc,
|
||||
"GetModuleFileName(module) -> path\n\
|
||||
\n\
|
||||
Return the fully-qualified path for the file that contains\n\
|
||||
the specified module. The module must have been loaded by the\n\
|
||||
current process.\n\
|
||||
\n\
|
||||
The module parameter should be a handle to the loaded module\n\
|
||||
whose path is being requested. If this parameter is 0, \n\
|
||||
GetModuleFileName retrieves the path of the executable file\n\
|
||||
of the current process.");
|
||||
|
||||
static PyObject *
|
||||
sp_GetModuleFileName(PyObject* self, PyObject* args)
|
||||
{
|
||||
|
@ -535,16 +612,22 @@ sp_GetModuleFileName(PyObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
static PyMethodDef sp_functions[] = {
|
||||
{"GetStdHandle", sp_GetStdHandle, METH_VARARGS},
|
||||
{"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS},
|
||||
{"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS},
|
||||
{"CreatePipe", sp_CreatePipe, METH_VARARGS},
|
||||
{"CreateProcess", sp_CreateProcess, METH_VARARGS},
|
||||
{"TerminateProcess", sp_TerminateProcess, METH_VARARGS},
|
||||
{"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS},
|
||||
{"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS},
|
||||
{"GetVersion", sp_GetVersion, METH_VARARGS},
|
||||
{"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS},
|
||||
{"GetStdHandle", sp_GetStdHandle, METH_VARARGS, GetStdHandle_doc},
|
||||
{"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS,
|
||||
GetCurrentProcess_doc},
|
||||
{"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS,
|
||||
DuplicateHandle_doc},
|
||||
{"CreatePipe", sp_CreatePipe, METH_VARARGS, CreatePipe_doc},
|
||||
{"CreateProcess", sp_CreateProcess, METH_VARARGS, CreateProcess_doc},
|
||||
{"TerminateProcess", sp_TerminateProcess, METH_VARARGS,
|
||||
TerminateProcess_doc},
|
||||
{"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS,
|
||||
GetExitCodeProcess_doc},
|
||||
{"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS,
|
||||
WaitForSingleObject_doc},
|
||||
{"GetVersion", sp_GetVersion, METH_VARARGS, GetVersion_doc},
|
||||
{"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS,
|
||||
GetModuleFileName_doc},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue