root/trunk/twisted/conch/stdio.py

Revision 30752, 2.3 KB (checked in by exarkun, 15 months ago)

Rewrite the copyright headers to exclude date information.

Author: exarkun
Reviewer: glyph
Fixes: #4857

To avoid the need to perpetually update copyright dates in each file in Twisted,
remove the dates from most files and just leave them in the LICENSE file.

As a side effect, some files also have had a trailing newline added where it was
missing before.

Line 
1# -*- test-case-name: twisted.conch.test.test_manhole -*-
2# Copyright (c) Twisted Matrix Laboratories.
3# See LICENSE for details.
4
5"""
6Asynchronous local terminal input handling
7
8@author: Jp Calderone
9"""
10
11import os, tty, sys, termios
12
13from twisted.internet import reactor, stdio, protocol, defer
14from twisted.python import failure, reflect, log
15
16from twisted.conch.insults.insults import ServerProtocol
17from twisted.conch.manhole import ColoredManhole
18
19class UnexpectedOutputError(Exception):
20    pass
21
22class TerminalProcessProtocol(protocol.ProcessProtocol):
23    def __init__(self, proto):
24        self.proto = proto
25        self.onConnection = defer.Deferred()
26
27    def connectionMade(self):
28        self.proto.makeConnection(self)
29        self.onConnection.callback(None)
30        self.onConnection = None
31
32    def write(self, bytes):
33        self.transport.write(bytes)
34
35    def outReceived(self, bytes):
36        self.proto.dataReceived(bytes)
37
38    def errReceived(self, bytes):
39        self.transport.loseConnection()
40        if self.proto is not None:
41            self.proto.connectionLost(failure.Failure(UnexpectedOutputError(bytes)))
42            self.proto = None
43
44    def childConnectionLost(self, childFD):
45        if self.proto is not None:
46            self.proto.childConnectionLost(childFD)
47
48    def processEnded(self, reason):
49        if self.proto is not None:
50            self.proto.connectionLost(reason)
51            self.proto = None
52
53
54
55class ConsoleManhole(ColoredManhole):
56    """
57    A manhole protocol specifically for use with L{stdio.StandardIO}.
58    """
59    def connectionLost(self, reason):
60        """
61        When the connection is lost, there is nothing more to do.  Stop the
62        reactor so that the process can exit.
63        """
64        reactor.stop()
65
66
67
68def runWithProtocol(klass):
69    fd = sys.__stdin__.fileno()
70    oldSettings = termios.tcgetattr(fd)
71    tty.setraw(fd)
72    try:
73        p = ServerProtocol(klass)
74        stdio.StandardIO(p)
75        reactor.run()
76    finally:
77        termios.tcsetattr(fd, termios.TCSANOW, oldSettings)
78        os.write(fd, "\r\x1bc\r")
79
80
81
82def main(argv=None):
83    log.startLogging(file('child.log', 'w'))
84
85    if argv is None:
86        argv = sys.argv[1:]
87    if argv:
88        klass = reflect.namedClass(argv[0])
89    else:
90        klass = ConsoleManhole
91    runWithProtocol(klass)
92
93
94if __name__ == '__main__':
95    main()
Note: See TracBrowser for help on using the browser.