~canonical-livepatch-dependencies/canonical-livepatch-service-dependencies/twisted

« back to all changes in this revision

Viewing changes to twisted/conch/stdio.py

  • Committer: Free Ekanayaka
  • Date: 2016-07-01 12:22:33 UTC
  • Revision ID: free.ekanayaka@canonical.com-20160701122233-nh55w514zwzoz1ip
Tags: upstream-16.2.0
ImportĀ upstreamĀ versionĀ 16.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- test-case-name: twisted.conch.test.test_manhole -*-
 
2
# Copyright (c) Twisted Matrix Laboratories.
 
3
# See LICENSE for details.
 
4
 
 
5
"""
 
6
Asynchronous local terminal input handling
 
7
 
 
8
@author: Jp Calderone
 
9
"""
 
10
 
 
11
import os, tty, sys, termios
 
12
 
 
13
from twisted.internet import reactor, stdio, protocol, defer
 
14
from twisted.python import failure, reflect, log
 
15
 
 
16
from twisted.conch.insults.insults import ServerProtocol
 
17
from twisted.conch.manhole import ColoredManhole
 
18
 
 
19
class UnexpectedOutputError(Exception):
 
20
    pass
 
21
 
 
22
class 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
 
 
55
class 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
 
 
68
def 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
 
 
82
def 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
 
 
94
if __name__ == '__main__':
 
95
    main()