cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1246 lines · 42.6 KB · Python
RawDownload
         needquote = (" " in arg) or ("\t" in arg) or arg == ""        if needquote:            result.append('"')         for c in arg:            if c == '\\':                # Don't know if we need to double yet.                bs_buf.append(c)            elif c == '"':                # Double backspaces.                result.append('\\' * len(bs_buf)*2)                bs_buf = []                result.append('\\"')            else:                # Normal char                if bs_buf:                    result.extend(bs_buf)                    bs_buf = []                result.append(c)         # Add remaining backspaces, if any.        if bs_buf:            result.extend(bs_buf)         if needquote:            result.extend(bs_buf)            result.append('"')     return ''.join(result)  class Popen(object):    def __init__(self, args, bufsize=0, executable=None,                 stdin=None, stdout=None, stderr=None,                 preexec_fn=None, close_fds=False, shell=False,                 cwd=None, env=None, universal_newlines=False,                 startupinfo=None, creationflags=0):        """Create new Popen instance."""        _cleanup()         self._child_created = False        if not isinstance(bufsize, (int, long)):            raise TypeError("bufsize must be an integer")         if mswindows:            if preexec_fn is not None:                raise ValueError("preexec_fn is not supported on Windows "                                 "platforms")            if close_fds:                raise ValueError("close_fds is not supported on Windows "                                 "platforms")        else:            # POSIX            if startupinfo is not None:                raise ValueError("startupinfo is only supported on Windows "                                 "platforms")            if creationflags != 0:                raise ValueError("creationflags is only supported on Windows "                                 "platforms")         self.stdin = None        self.stdout = None        self.stderr = None        self.pid = None        self.returncode = None        self.universal_newlines = universal_newlines         # Input and output objects. The general principle is like        # this:        #        # Parent                   Child        # ------                   -----        # p2cwrite   ---stdin--->  p2cread        # c2pread    <--stdout---  c2pwrite        # errread    <--stderr---  errwrite        #        # On POSIX, the child objects are file descriptors.  On        # Windows, these are Windows file handles.  The parent objects        # are file descriptors on both platforms.  The parent objects        # are None when not using PIPEs. The child objects are None        # when not redirecting.         (p2cread, p2cwrite,         c2pread, c2pwrite,         errread, errwrite) = self._get_handles(stdin, stdout, stderr)         self._execute_child(args, executable, preexec_fn, close_fds,                            cwd, env, universal_newlines,                            startupinfo, creationflags, shell,                            p2cread, p2cwrite,                            c2pread, c2pwrite,                            errread, errwrite)         # On Windows, you cannot just redirect one or two handles: You        # either have to redirect all three or none. If the subprocess        # user has only redirected one or two handles, we are        # automatically creating PIPEs for the rest. We should close        # these after the process is started. See bug #1124861.         if mswindows:            if stdin is None and p2cwrite is not None:                os.close(p2cwrite)                p2cwrite = None            if stdout is None and c2pread is not None:                os.close(c2pread)                c2pread = None            if stderr is None and errread is not None:                os.close(errread)                errread = None         if p2cwrite:            self.stdin = os.fdopen(p2cwrite, 'wb', bufsize)        if c2pread:            if universal_newlines:                self.stdout = os.fdopen(c2pread, 'rU', bufsize)            else:                self.stdout = os.fdopen(c2pread, 'rb', bufsize)        if errread:            if universal_newlines:                self.stderr = os.fdopen(errread, 'rU', bufsize)            else:                self.stderr = os.fdopen(errread, 'rb', bufsize)      def _translate_newlines(self, data):        data = data.replace("\r\n", "\n")        data = data.replace("\r", "\n")        return data      def __del__(self):        if not self._child_created:            # We didn't get to successfully create a child process.            return        # In case the child hasn't been waited on, check if it's done.        self.poll(_deadstate=sys.maxint)        if self.returncode is None and _active is not None:            # Child is still running, keep us alive until we can wait on it.            _active.append(self)      def communicate(self, input=None):        """Interact with process: Send data to stdin.  Read data from        stdout and stderr, until end-of-file is reached.  Wait for        process to terminate.  The optional input argument should be a        string to be sent to the child process, or None, if no data        should be sent to the child.         communicate() returns a tuple (stdout, stderr)."""         # Optimization: If we are only using one pipe, or no pipe at        # all, using select() or threads is unnecessary.        if [self.stdin, self.stdout, self.stderr].count(None) >= 2:            stdout = None            stderr = None            if self.stdin:                if input:                    self.stdin.write(input)                self.stdin.close()            elif self.stdout:                stdout = self.stdout.read()            elif self.stderr:                stderr = self.stderr.read()            self.wait()            return (stdout, stderr)         return self._communicate(input)      if mswindows:        #        # Windows methods        #        def _get_handles(self, stdin, stdout, stderr):            """Construct and return tupel with IO objects:            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite            """            if stdin is None and stdout is None and stderr is None:                return (None, None, None, None, None, None)             p2cread, p2cwrite = None, None            c2pread, c2pwrite = None, None            errread, errwrite = None, None             if stdin is None:                p2cread = GetStdHandle(STD_INPUT_HANDLE)            if p2cread is not None:                pass            elif stdin is None or stdin == PIPE:                p2cread, p2cwrite = CreatePipe(None, 0)                # Detach and turn into fd                p2cwrite = p2cwrite.Detach()                p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0)            elif isinstance(stdin, int):                p2cread = msvcrt.get_osfhandle(stdin)            else:                # Assuming file-like object                p2cread = msvcrt.get_osfhandle(stdin.fileno())            p2cread = self._make_inheritable(p2cread)             if stdout is None:                c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE)            if c2pwrite is not None:                pass            elif stdout is None or stdout == PIPE:                c2pread, c2pwrite = CreatePipe(None, 0)                # Detach and turn into fd                c2pread = c2pread.Detach()                c2pread = msvcrt.open_osfhandle(c2pread, 0)            elif isinstance(stdout, int):                c2pwrite = msvcrt.get_osfhandle(stdout)            else:                # Assuming file-like object                c2pwrite = msvcrt.get_osfhandle(stdout.fileno())            c2pwrite = self._make_inheritable(c2pwrite)             if stderr is None:                errwrite = GetStdHandle(STD_ERROR_HANDLE)            if errwrite is not None:                pass            elif stderr is None or stderr == PIPE:                errread, errwrite = CreatePipe(None, 0)                # Detach and turn into fd                errread = errread.Detach()                errread = msvcrt.open_osfhandle(errread, 0)            elif stderr == STDOUT:                errwrite = c2pwrite            elif isinstance(stderr, int):                errwrite = msvcrt.get_osfhandle(stderr)            else:                # Assuming file-like object                errwrite = msvcrt.get_osfhandle(stderr.fileno())            errwrite = self._make_inheritable(errwrite)             return (p2cread, p2cwrite,                    c2pread, c2pwrite,                    errread, errwrite)          def _make_inheritable(self, handle):            """Return a duplicate of handle, which is inheritable"""            return DuplicateHandle(GetCurrentProcess(), handle,                                   GetCurrentProcess(), 0, 1,                                   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.exe")            if not os.path.exists(w9xpopen):                # Eeek - file-not-found - possibly an embedding                # situation - see if we can locate it in sys.exec_prefix                w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix),                                        "w9xpopen.exe")                if not os.path.exists(w9xpopen):                    raise RuntimeError("Cannot locate w9xpopen.exe, which is "                                       "needed for Popen to work with your "                                       "shell or platform.")            return w9xpopen          def _execute_child(self, args, executable, preexec_fn, close_fds,                           cwd, env, universal_newlines,                           startupinfo, creationflags, shell,                           p2cread, p2cwrite,                           c2pread, c2pwrite,                           errread, errwrite):            """Execute program (MS Windows version)"""             if not isinstance(args, types.StringTypes):                args = list2cmdline(args)             # Process startup details            if startupinfo is None:                startupinfo = STARTUPINFO()            if None not in (p2cread, c2pwrite, errwrite):                startupinfo.dwFlags |= STARTF_USESTDHANDLES                startupinfo.hStdInput = p2cread                startupinfo.hStdOutput = c2pwrite                startupinfo.hStdError = errwrite             if shell:                startupinfo.dwFlags |= STARTF_USESHOWWINDOW                startupinfo.wShowWindow = SW_HIDE                comspec = os.environ.get("COMSPEC", "cmd.exe")                args = comspec + " /c " + args                if (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                    # information, see KB Q150956                    # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp)                    w9xpopen = self._find_w9xpopen()                    args = '"%s" %s' % (w9xpopen, args)                    # Not passing CREATE_NEW_CONSOLE has been known to                    # cause random failures on win9x.  Specifically a                    # dialog: "Your program accessed mem currently in                    # use at xxx" and a hopeful warning about the                    # stability of your system.  Cost is Ctrl+C wont                    # kill children.                    creationflags |= CREATE_NEW_CONSOLE             # Start the process            try:                hp, ht, pid, tid = CreateProcess(executable, args,                                         # no special security                                         None, None,                                         # must inherit handles to pass std                                         # handles                                         1,                                         creationflags,                                         env,                                         cwd,                                         startupinfo)            except pywintypes.error, e:                # Translate pywintypes.error to WindowsError, which is                # a subclass of OSError.  FIXME: We should really                # translate errno using _sys_errlist (or simliar), but                # how can this be done from Python?                raise WindowsError(*e.args)             # Retain the process handle, but close the thread handle            self._child_created = True            self._handle = hp            self.pid = pid            ht.Close()             # Child is launched. Close the parent's copy of those pipe            # handles that only the child should have open.  You need            # to make sure that no handles to the write end of the            # output pipe are maintained in this process or else the            # pipe will not close when the child process exits and the            # ReadFile will hang.            if p2cread is not None:                p2cread.Close()            if c2pwrite is not None:                c2pwrite.Close()            if errwrite is not None:                errwrite.Close()          def poll(self, _deadstate=None):            """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)            return self.returncode          def wait(self):            """Wait for child process to terminate.  Returns returncode            attribute."""            if self.returncode is None:                obj = WaitForSingleObject(self._handle, INFINITE)                self.returncode = GetExitCodeProcess(self._handle)            return self.returncode          def _readerthread(self, fh, buffer):            buffer.append(fh.read())          def _communicate(self, input):            stdout = None # Return            stderr = None # Return             if self.stdout:                stdout = []                stdout_thread = threading.Thread(target=self._readerthread,                                                 args=(self.stdout, stdout))                stdout_thread.setDaemon(True)                stdout_thread.start()            if self.stderr:                stderr = []                stderr_thread = threading.Thread(target=self._readerthread,                                                 args=(self.stderr, stderr))                stderr_thread.setDaemon(True)                stderr_thread.start()             if self.stdin:                if input is not None:                    self.stdin.write(input)                self.stdin.close()             if self.stdout:                stdout_thread.join()            if self.stderr:                stderr_thread.join()             # All data exchanged.  Translate lists into strings.            if stdout is not None:                stdout = stdout[0]            if stderr is not None:                stderr = stderr[0]             # Translate newlines, if requested.  We cannot let the file            # object do the translation: It is based on stdio, which is            # impossible to combine with select (unless forcing no            # buffering).            if self.universal_newlines and hasattr(file, 'newlines'):                if stdout:                    stdout = self._translate_newlines(stdout)                if stderr:                    stderr = self._translate_newlines(stderr)             self.wait()            return (stdout, stderr)     else:        #        # POSIX methods        #        def _get_handles(self, stdin, stdout, stderr):            """Construct and return tupel with IO objects:            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite            """            p2cread, p2cwrite = None, None            c2pread, c2pwrite = None, None            errread, errwrite = None, None             if stdin is None:                pass            elif stdin == PIPE:                p2cread, p2cwrite = os.pipe()            elif isinstance(stdin, int):                p2cread = stdin            else:                # Assuming file-like object                p2cread = stdin.fileno()             if stdout is None:                pass            elif stdout == PIPE:                c2pread, c2pwrite = os.pipe()            elif isinstance(stdout, int):                c2pwrite = stdout            else:                # Assuming file-like object                c2pwrite = stdout.fileno()             if stderr is None:                pass            elif stderr == PIPE:                errread, errwrite = os.pipe()            elif stderr == STDOUT:                errwrite = c2pwrite            elif isinstance(stderr, int):                errwrite = stderr            else:                # Assuming file-like object                errwrite = stderr.fileno()             return (p2cread, p2cwrite,                    c2pread, c2pwrite,                    errread, errwrite)          def _set_cloexec_flag(self, fd):            try:                cloexec_flag = fcntl.FD_CLOEXEC            except AttributeError:                cloexec_flag = 1             old = fcntl.fcntl(fd, fcntl.F_GETFD)            fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag)          def _close_fds(self, but):            for i in xrange(3, MAXFD):                if i == but:                    continue                try:                    os.close(i)                except:                    pass          def _execute_child(self, args, executable, preexec_fn, close_fds,                           cwd, env, universal_newlines,                           startupinfo, creationflags, shell,                           p2cread, p2cwrite,                           c2pread, c2pwrite,                           errread, errwrite):            """Execute program (POSIX version)"""             if isinstance(args, types.StringTypes):                args = [args]            else:                args = list(args)             if shell:                args = ["/bin/sh", "-c"] + args             if executable is None:                executable = args[0]             # For transferring possible exec failure from child to parent            # The first char specifies the exception type: 0 means

Lines 501–1000 of 1246. Previous lines