| Index: third_party/twisted_8_1/twisted/internet/_dumbwin32proc.py
|
| diff --git a/third_party/twisted_8_1/twisted/internet/_dumbwin32proc.py b/third_party/twisted_8_1/twisted/internet/_dumbwin32proc.py
|
| deleted file mode 100644
|
| index 4334f77eb3cc5c311514cafd1ebc056aa92210dc..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/internet/_dumbwin32proc.py
|
| +++ /dev/null
|
| @@ -1,337 +0,0 @@
|
| -# -*- test-case-name: twisted.test.test_process -*-
|
| -# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -"""
|
| -http://isometric.sixsided.org/_/gates_in_the_head/
|
| -"""
|
| -
|
| -import os
|
| -
|
| -# Win32 imports
|
| -import win32api
|
| -import win32con
|
| -import win32event
|
| -import win32file
|
| -import win32pipe
|
| -import win32process
|
| -import win32security
|
| -
|
| -import pywintypes
|
| -
|
| -# security attributes for pipes
|
| -PIPE_ATTRS_INHERITABLE = win32security.SECURITY_ATTRIBUTES()
|
| -PIPE_ATTRS_INHERITABLE.bInheritHandle = 1
|
| -
|
| -from zope.interface import implements
|
| -from twisted.internet.interfaces import IProcessTransport, IConsumer, IProducer
|
| -
|
| -from twisted.python.win32 import quoteArguments
|
| -
|
| -from twisted.internet import error
|
| -from twisted.python import failure
|
| -
|
| -from twisted.internet import _pollingfile
|
| -
|
| -def debug(msg):
|
| - import sys
|
| - print msg
|
| - sys.stdout.flush()
|
| -
|
| -class _Reaper(_pollingfile._PollableResource):
|
| -
|
| - def __init__(self, proc):
|
| - self.proc = proc
|
| -
|
| - def checkWork(self):
|
| - if win32event.WaitForSingleObject(self.proc.hProcess, 0) != win32event.WAIT_OBJECT_0:
|
| - return 0
|
| - exitCode = win32process.GetExitCodeProcess(self.proc.hProcess)
|
| - self.deactivate()
|
| - self.proc.processEnded(exitCode)
|
| - return 0
|
| -
|
| -
|
| -def _findShebang(filename):
|
| - """
|
| - Look for a #! line, and return the value following the #! if one exists, or
|
| - None if this file is not a script.
|
| -
|
| - I don't know if there are any conventions for quoting in Windows shebang
|
| - lines, so this doesn't support any; therefore, you may not pass any
|
| - arguments to scripts invoked as filters. That's probably wrong, so if
|
| - somebody knows more about the cultural expectations on Windows, please feel
|
| - free to fix.
|
| -
|
| - This shebang line support was added in support of the CGI tests;
|
| - appropriately enough, I determined that shebang lines are culturally
|
| - accepted in the Windows world through this page:
|
| -
|
| - http://www.cgi101.com/learn/connect/winxp.html
|
| -
|
| - @param filename: str representing a filename
|
| -
|
| - @return: a str representing another filename.
|
| - """
|
| - f = file(filename, 'ru')
|
| - if f.read(2) == '#!':
|
| - exe = f.readline(1024).strip('\n')
|
| - return exe
|
| -
|
| -def _invalidWin32App(pywinerr):
|
| - """
|
| - Determine if a pywintypes.error is telling us that the given process is
|
| - 'not a valid win32 application', i.e. not a PE format executable.
|
| -
|
| - @param pywinerr: a pywintypes.error instance raised by CreateProcess
|
| -
|
| - @return: a boolean
|
| - """
|
| -
|
| - # Let's do this better in the future, but I have no idea what this error
|
| - # is; MSDN doesn't mention it, and there is no symbolic constant in
|
| - # win32process module that represents 193.
|
| -
|
| - return pywinerr.args[0] == 193
|
| -
|
| -class Process(_pollingfile._PollingTimer):
|
| - """A process that integrates with the Twisted event loop.
|
| -
|
| - If your subprocess is a python program, you need to:
|
| -
|
| - - Run python.exe with the '-u' command line option - this turns on
|
| - unbuffered I/O. Buffering stdout/err/in can cause problems, see e.g.
|
| - http://support.microsoft.com/default.aspx?scid=kb;EN-US;q1903
|
| -
|
| - - If you don't want Windows messing with data passed over
|
| - stdin/out/err, set the pipes to be in binary mode::
|
| -
|
| - import os, sys, mscvrt
|
| - msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
|
| - msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
|
| - msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
|
| -
|
| - """
|
| - implements(IProcessTransport, IConsumer, IProducer)
|
| -
|
| - buffer = ''
|
| - pid = None
|
| -
|
| - def __init__(self, reactor, protocol, command, args, environment, path):
|
| - _pollingfile._PollingTimer.__init__(self, reactor)
|
| - self.protocol = protocol
|
| -
|
| - # security attributes for pipes
|
| - sAttrs = win32security.SECURITY_ATTRIBUTES()
|
| - sAttrs.bInheritHandle = 1
|
| -
|
| - # create the pipes which will connect to the secondary process
|
| - self.hStdoutR, hStdoutW = win32pipe.CreatePipe(sAttrs, 0)
|
| - self.hStderrR, hStderrW = win32pipe.CreatePipe(sAttrs, 0)
|
| - hStdinR, self.hStdinW = win32pipe.CreatePipe(sAttrs, 0)
|
| -
|
| - win32pipe.SetNamedPipeHandleState(self.hStdinW,
|
| - win32pipe.PIPE_NOWAIT,
|
| - None,
|
| - None)
|
| -
|
| - # set the info structure for the new process.
|
| - StartupInfo = win32process.STARTUPINFO()
|
| - StartupInfo.hStdOutput = hStdoutW
|
| - StartupInfo.hStdError = hStderrW
|
| - StartupInfo.hStdInput = hStdinR
|
| - StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES
|
| -
|
| - # Create new handles whose inheritance property is false
|
| - currentPid = win32api.GetCurrentProcess()
|
| -
|
| - tmp = win32api.DuplicateHandle(currentPid, self.hStdoutR, currentPid, 0, 0,
|
| - win32con.DUPLICATE_SAME_ACCESS)
|
| - win32file.CloseHandle(self.hStdoutR)
|
| - self.hStdoutR = tmp
|
| -
|
| - tmp = win32api.DuplicateHandle(currentPid, self.hStderrR, currentPid, 0, 0,
|
| - win32con.DUPLICATE_SAME_ACCESS)
|
| - win32file.CloseHandle(self.hStderrR)
|
| - self.hStderrR = tmp
|
| -
|
| - tmp = win32api.DuplicateHandle(currentPid, self.hStdinW, currentPid, 0, 0,
|
| - win32con.DUPLICATE_SAME_ACCESS)
|
| - win32file.CloseHandle(self.hStdinW)
|
| - self.hStdinW = tmp
|
| -
|
| - # Add the specified environment to the current environment - this is
|
| - # necessary because certain operations are only supported on Windows
|
| - # if certain environment variables are present.
|
| -
|
| - env = os.environ.copy()
|
| - env.update(environment or {})
|
| -
|
| - cmdline = quoteArguments(args)
|
| - # TODO: error detection here.
|
| - def doCreate():
|
| - self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess(
|
| - command, cmdline, None, None, 1, 0, env, path, StartupInfo)
|
| - try:
|
| - doCreate()
|
| - except pywintypes.error, pwte:
|
| - if not _invalidWin32App(pwte):
|
| - # This behavior isn't _really_ documented, but let's make it
|
| - # consistent with the behavior that is documented.
|
| - raise OSError(pwte)
|
| - else:
|
| - # look for a shebang line. Insert the original 'command'
|
| - # (actually a script) into the new arguments list.
|
| - sheb = _findShebang(command)
|
| - if sheb is None:
|
| - raise OSError(
|
| - "%r is neither a Windows executable, "
|
| - "nor a script with a shebang line" % command)
|
| - else:
|
| - args = list(args)
|
| - args.insert(0, command)
|
| - cmdline = quoteArguments(args)
|
| - origcmd = command
|
| - command = sheb
|
| - try:
|
| - # Let's try again.
|
| - doCreate()
|
| - except pywintypes.error, pwte2:
|
| - # d'oh, failed again!
|
| - if _invalidWin32App(pwte2):
|
| - raise OSError(
|
| - "%r has an invalid shebang line: "
|
| - "%r is not a valid executable" % (
|
| - origcmd, sheb))
|
| - raise OSError(pwte2)
|
| -
|
| - win32file.CloseHandle(self.hThread)
|
| -
|
| - # close handles which only the child will use
|
| - win32file.CloseHandle(hStderrW)
|
| - win32file.CloseHandle(hStdoutW)
|
| - win32file.CloseHandle(hStdinR)
|
| -
|
| - self.closed = 0
|
| - self.closedNotifies = 0
|
| -
|
| - # set up everything
|
| - self.stdout = _pollingfile._PollableReadPipe(
|
| - self.hStdoutR,
|
| - lambda data: self.protocol.childDataReceived(1, data),
|
| - self.outConnectionLost)
|
| -
|
| - self.stderr = _pollingfile._PollableReadPipe(
|
| - self.hStderrR,
|
| - lambda data: self.protocol.childDataReceived(2, data),
|
| - self.errConnectionLost)
|
| -
|
| - self.stdin = _pollingfile._PollableWritePipe(
|
| - self.hStdinW, self.inConnectionLost)
|
| -
|
| - for pipewatcher in self.stdout, self.stderr, self.stdin:
|
| - self._addPollableResource(pipewatcher)
|
| -
|
| -
|
| - # notify protocol
|
| - self.protocol.makeConnection(self)
|
| -
|
| - # (maybe?) a good idea in win32er, otherwise not
|
| - # self.reactor.addEvent(self.hProcess, self, 'inConnectionLost')
|
| -
|
| -
|
| - def signalProcess(self, signalID):
|
| - if self.pid is None:
|
| - raise error.ProcessExitedAlready()
|
| - if signalID in ("INT", "TERM", "KILL"):
|
| - os.popen('taskkill /T /F /PID %s' % self.pid)
|
| -
|
| - def processEnded(self, status):
|
| - """
|
| - This is called when the child terminates.
|
| - """
|
| - self.pid = None
|
| - if status == 0:
|
| - err = error.ProcessDone(status)
|
| - else:
|
| - err = error.ProcessTerminated(status)
|
| - self.protocol.processEnded(failure.Failure(err))
|
| -
|
| -
|
| - def write(self, data):
|
| - """Write data to the process' stdin."""
|
| - self.stdin.write(data)
|
| -
|
| - def writeSequence(self, seq):
|
| - """Write data to the process' stdin."""
|
| - self.stdin.writeSequence(seq)
|
| -
|
| - def closeChildFD(self, fd):
|
| - if fd == 0:
|
| - self.closeStdin()
|
| - elif fd == 1:
|
| - self.closeStdout()
|
| - elif fd == 2:
|
| - self.closeStderr()
|
| - else:
|
| - raise NotImplementedError("Only standard-IO file descriptors available on win32")
|
| -
|
| - def closeStdin(self):
|
| - """Close the process' stdin.
|
| - """
|
| - self.stdin.close()
|
| -
|
| - def closeStderr(self):
|
| - self.stderr.close()
|
| -
|
| - def closeStdout(self):
|
| - self.stdout.close()
|
| -
|
| - def loseConnection(self):
|
| - """Close the process' stdout, in and err."""
|
| - self.closeStdin()
|
| - self.closeStdout()
|
| - self.closeStderr()
|
| -
|
| - def outConnectionLost(self):
|
| - self.protocol.childConnectionLost(1)
|
| - self.connectionLostNotify()
|
| -
|
| - def errConnectionLost(self):
|
| - self.protocol.childConnectionLost(2)
|
| - self.connectionLostNotify()
|
| -
|
| - def inConnectionLost(self):
|
| - self.protocol.childConnectionLost(0)
|
| - self.connectionLostNotify()
|
| -
|
| - def connectionLostNotify(self):
|
| - """Will be called 3 times, by stdout/err threads and process handle."""
|
| - self.closedNotifies = self.closedNotifies + 1
|
| - if self.closedNotifies == 3:
|
| - self.closed = 1
|
| - self._addPollableResource(_Reaper(self))
|
| -
|
| - # IConsumer
|
| - def registerProducer(self, producer, streaming):
|
| - self.stdin.registerProducer(producer, streaming)
|
| -
|
| - def unregisterProducer(self):
|
| - self.stdin.unregisterProducer()
|
| -
|
| - # IProducer
|
| - def pauseProducing(self):
|
| - self._pause()
|
| -
|
| - def resumeProducing(self):
|
| - self._unpause()
|
| -
|
| - def stopProducing(self):
|
| - self.loseConnection()
|
| -
|
| -
|
| - def __repr__(self):
|
| - """
|
| - Return a string representation of the process.
|
| - """
|
| - return "<%s pid=%s>" % (self.__class__.__name__, self.pid)
|
|
|