From 520c834fbb6213779ff5ef21a2fe965c0a62c615 Mon Sep 17 00:00:00 2001 From: Brian Curtin Date: Sat, 24 Apr 2010 15:59:50 +0000 Subject: 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 *. ........ --- Lib/subprocess.py | 86 +++++++++++++++++++++------------------------ PC/_subprocess.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 132 insertions(+), 57 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py index fce62bb..08bb679 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -398,31 +398,18 @@ class CalledProcessError(Exception): if mswindows: + from _subprocess import CREATE_NEW_CONSOLE 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 import errno @@ -431,6 +418,8 @@ else: __all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"] +if mswindows: + __all__.append("CREATE_NEW_CONSOLE") try: MAXFD = os.sysconf("SC_OPEN_MAX") except: @@ -722,11 +711,11 @@ class Popen(object): errread, errwrite = None, None 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: @@ -735,11 +724,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: @@ -748,11 +737,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): @@ -769,14 +758,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 @@ -805,17 +795,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() >= 0x80000000L or + if (_subprocess.GetVersion() >= 0x80000000L 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 @@ -829,11 +819,11 @@ class Popen(object): # use at xxx" and a hopeful warning about the # stability of your system. Cost is Ctrl+C wont # 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), @@ -872,8 +862,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 @@ -881,8 +872,9 @@ class Popen(object): """Wait for child process to terminate. Returns returncode attribute.""" if self.returncode is None: - obj = WaitForSingleObject(self._handle, INFINITE) - self.returncode = GetExitCodeProcess(self._handle) + _subprocess.WaitForSingleObject(self._handle, + _subprocess.INFINITE) + self.returncode = _subprocess.GetExitCodeProcess(self._handle) return self.returncode @@ -947,7 +939,7 @@ class Popen(object): def terminate(self): """Terminates the process """ - TerminateProcess(self._handle, 1) + _subprocess.TerminateProcess(self._handle, 1) kill = terminate diff --git a/PC/_subprocess.c b/PC/_subprocess.c index bb240e1..5389d79 100644 --- a/PC/_subprocess.c +++ b/PC/_subprocess.c @@ -154,6 +154,13 @@ statichere 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) { @@ -179,6 +186,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) { @@ -188,6 +200,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) { @@ -230,6 +253,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) { @@ -365,6 +396,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) { @@ -441,6 +484,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) { @@ -461,6 +509,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) { @@ -479,6 +532,13 @@ sp_GetExitCodeProcess(PyObject* self, PyObject* args) return PyInt_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) { @@ -501,6 +561,11 @@ sp_WaitForSingleObject(PyObject* self, PyObject* args) return PyInt_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) { @@ -510,6 +575,18 @@ sp_GetVersion(PyObject* self, PyObject* args) return PyInt_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) { @@ -531,16 +608,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} }; -- cgit v0.12