r46968 - Merge telnet-py3-8228: Port twisted.conch.telnet to Python 3
hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Thu, 10 Mar 2016 02:32:13 -0700 (MST)
| Newsgroups | gmane.comp.python.twisted.commits |
|---|---|
| Message-ID | <[email protected]> |
Author: hawkowl
Date: Thu Mar 10 02:32:00 2016
New Revision: 46968
Added:
trunk/twisted/conch/topfiles/8228.feature
Modified:
trunk/twisted/conch/telnet.py
trunk/twisted/conch/test/test_telnet.py
trunk/twisted/protocols/telnet.py
trunk/twisted/python/compat.py
trunk/twisted/python/dist3.py
Log:
Merge telnet-py3-8228: Port twisted.conch.telnet to Python 3
Author: hawkowl
Reviewer: adiroiban
Fixes: #8228
Modified: trunk/twisted/conch/telnet.py
==============================================================================
--- trunk/twisted/conch/telnet.py (original)
+++ trunk/twisted/conch/telnet.py Thu Mar 10 02:32:00 2016
@@ -8,12 +8,15 @@
@author: Jean-Paul Calderone
"""
+from __future__ import absolute_import, division
+
import struct
from zope.interface import implementer
from twisted.internet import protocol, interfaces as iinternet, defer
from twisted.python import log
+from twisted.python.compat import _bytesChr as chr, iterbytes
MODE = chr(1)
EDIT = 1
@@ -510,11 +513,11 @@
def dataReceived(self, data):
appDataBuffer = []
- for b in data:
+ for b in iterbytes(data):
if self.state == 'data':
if b == IAC:
self.state = 'escaped'
- elif b == '\r':
+ elif b == b'\r':
self.state = 'newline'
else:
appDataBuffer.append(b)
@@ -528,7 +531,7 @@
elif b in (NOP, DM, BRK, IP, AO, AYT, EC, EL, GA):
self.state = 'data'
if appDataBuffer:
- self.applicationDataReceived(''.join(appDataBuffer))
+ self.applicationDataReceived(b''.join(appDataBuffer))
del appDataBuffer[:]
self.commandReceived(b, None)
elif b in (WILL, WONT, DO, DONT):
@@ -541,19 +544,19 @@
command = self.command
del self.command
if appDataBuffer:
- self.applicationDataReceived(''.join(appDataBuffer))
+ self.applicationDataReceived(b''.join(appDataBuffer))
del appDataBuffer[:]
self.commandReceived(command, b)
elif self.state == 'newline':
self.state = 'data'
- if b == '\n':
- appDataBuffer.append('\n')
- elif b == '\0':
- appDataBuffer.append('\r')
+ if b == b'\n':
+ appDataBuffer.append(b'\n')
+ elif b == b'\0':
+ appDataBuffer.append(b'\r')
elif b == IAC:
# IAC isn't really allowed after \r, according to the
# RFC, but handling it this way is less surprising than
- # delivering the IAC to the app as application data.
+ # delivering the IAC to the app as application data.
# The purpose of the restriction is to allow terminals
# to unambiguously interpret the behavior of the CR
# after reading only one more byte. CR LF is supposed
@@ -561,10 +564,10 @@
# CR NUL another (cursor to first column). Absent the
# NUL, it still makes sense to interpret this as CR and
# then apply all the usual interpretation to the IAC.
- appDataBuffer.append('\r')
+ appDataBuffer.append(b'\r')
self.state = 'escaped'
else:
- appDataBuffer.append('\r' + b)
+ appDataBuffer.append(b'\r' + b)
elif self.state == 'subnegotiation':
if b == IAC:
self.state = 'subnegotiation-escaped'
@@ -576,7 +579,7 @@
commands = self.commands
del self.commands
if appDataBuffer:
- self.applicationDataReceived(''.join(appDataBuffer))
+ self.applicationDataReceived(b''.join(appDataBuffer))
del appDataBuffer[:]
self.negotiate(commands)
else:
@@ -586,7 +589,7 @@
raise ValueError("How'd you do this?")
if appDataBuffer:
- self.applicationDataReceived(''.join(appDataBuffer))
+ self.applicationDataReceived(b''.join(appDataBuffer))
def connectionLost(self, reason):
@@ -812,7 +815,7 @@
class ProtocolTransportMixin:
def write(self, bytes):
- self.transport.write(bytes.replace('\n', '\r\n'))
+ self.transport.write(bytes.replace(b'\n', b'\r\n'))
def writeSequence(self, seq):
self.transport.writeSequence(seq)
@@ -898,7 +901,7 @@
self.protocol.dataReceived(bytes)
def write(self, data):
- ProtocolTransportMixin.write(self, data.replace('\xff','\xff\xff'))
+ ProtocolTransportMixin.write(self, data.replace(b'\xff', b'\xff\xff'))
class TelnetBootstrapProtocol(TelnetProtocol, ProtocolTransportMixin):
@@ -964,7 +967,7 @@
# attribute of which will be an ITerminalProtocol. Maybe.
# You know what, XXX TODO clean this up.
if len(bytes) == 4:
- width, height = struct.unpack('!HH', ''.join(bytes))
+ width, height = struct.unpack('!HH', b''.join(bytes))
self.protocol.terminalProtocol.terminalSize(width, height)
else:
log.msg("Wrong number of NAWS bytes")
@@ -987,7 +990,7 @@
from twisted.protocols import basic
class StatefulTelnetProtocol(basic.LineReceiver, TelnetProtocol):
- delimiter = '\n'
+ delimiter = b'\n'
state = 'Discard'
@@ -1026,7 +1029,7 @@
self.portal = portal
def connectionMade(self):
- self.transport.write("Username: ")
+ self.transport.write(b"Username: ")
def connectionLost(self, reason):
StatefulTelnetProtocol.connectionLost(self, reason)
@@ -1040,7 +1043,7 @@
def telnet_User(self, line):
self.username = line
self.transport.will(ECHO)
- self.transport.write("Password: ")
+ self.transport.write(b"Password: ")
return 'Password'
def telnet_Password(self, line):
@@ -1065,8 +1068,8 @@
self.transport.protocol = protocol
def _ebLogin(self, failure):
- self.transport.write("\nAuthentication failed\n")
- self.transport.write("Username: ")
+ self.transport.write(b"\nAuthentication failed\n")
+ self.transport.write(b"Username: ")
self.state = "User"
__all__ = [
Modified: trunk/twisted/conch/test/test_telnet.py
==============================================================================
--- trunk/twisted/conch/test/test_telnet.py (original)
+++ trunk/twisted/conch/test/test_telnet.py Thu Mar 10 02:32:00 2016
@@ -6,6 +6,8 @@
Tests for L{twisted.conch.telnet}.
"""
+from __future__ import absolute_import, division
+
from zope.interface import implementer
from zope.interface.verify import verifyObject
@@ -15,7 +17,7 @@
from twisted.trial import unittest
from twisted.test import proto_helpers
-
+from twisted.python.compat import iterbytes
@implementer(telnet.ITelnetProtocol)
@@ -24,8 +26,8 @@
remoteEnableable = ()
def __init__(self):
- self.bytes = ''
- self.subcmd = ''
+ self.bytes = b''
+ self.subcmd = []
self.calls = []
self.enabledLocal = []
@@ -35,7 +37,7 @@
def makeConnection(self, transport):
d = transport.negotiationMap = {}
- d['\x12'] = self.neg_TEST_COMMAND
+ d[b'\x12'] = self.neg_TEST_COMMAND
d = transport.commandMap = transport.commandMap.copy()
for cmd in ('NOP', 'DM', 'BRK', 'IP', 'AO', 'AYT', 'EC', 'EL', 'GA'):
@@ -95,34 +97,34 @@
# application layer.
h = self.p.protocol
- L = ["here are some bytes la la la",
- "some more arrive here",
- "lots of bytes to play with",
- "la la la",
- "ta de da",
- "dum"]
+ L = [b"here are some bytes la la la",
+ b"some more arrive here",
+ b"lots of bytes to play with",
+ b"la la la",
+ b"ta de da",
+ b"dum"]
for b in L:
self.p.dataReceived(b)
- self.assertEqual(h.bytes, ''.join(L))
+ self.assertEqual(h.bytes, b''.join(L))
def testNewlineHandling(self):
# Send various kinds of newlines and make sure they get translated
# into \n.
h = self.p.protocol
- L = ["here is the first line\r\n",
- "here is the second line\r\0",
- "here is the third line\r\n",
- "here is the last line\r\0"]
+ L = [b"here is the first line\r\n",
+ b"here is the second line\r\0",
+ b"here is the third line\r\n",
+ b"here is the last line\r\0"]
for b in L:
self.p.dataReceived(b)
- self.assertEqual(h.bytes, L[0][:-2] + '\n' +
- L[1][:-2] + '\r' +
- L[2][:-2] + '\n' +
- L[3][:-2] + '\r')
+ self.assertEqual(h.bytes, L[0][:-2] + b'\n' +
+ L[1][:-2] + b'\r' +
+ L[2][:-2] + b'\n' +
+ L[3][:-2] + b'\r')
def testIACEscape(self):
# Send a bunch of bytes and a couple quoted \xFFs. Unquoted,
@@ -130,14 +132,14 @@
# should be passed through to the application layer.
h = self.p.protocol
- L = ["here are some bytes\xff\xff with an embedded IAC",
- "and here is a test of a border escape\xff",
- "\xff did you get that IAC?"]
+ L = [b"here are some bytes\xff\xff with an embedded IAC",
+ b"and here is a test of a border escape\xff",
+ b"\xff did you get that IAC?"]
for b in L:
self.p.dataReceived(b)
- self.assertEqual(h.bytes, ''.join(L).replace('\xff\xff', '\xff'))
+ self.assertEqual(h.bytes, b''.join(L).replace(b'\xff\xff', b'\xff'))
def _simpleCommandTest(self, cmdName):
# Send a single simple telnet command and make sure
@@ -146,14 +148,14 @@
h = self.p.protocol
cmd = telnet.IAC + getattr(telnet, cmdName)
- L = ["Here's some bytes, tra la la",
- "But ono!" + cmd + " an interrupt"]
+ L = [b"Here's some bytes, tra la la",
+ b"But ono!" + cmd + b" an interrupt"]
for b in L:
self.p.dataReceived(b)
self.assertEqual(h.calls, [cmdName])
- self.assertEqual(h.bytes, ''.join(L).replace(cmd, ''))
+ self.assertEqual(h.bytes, b''.join(L).replace(cmd, b''))
def testInterrupt(self):
self._simpleCommandTest("IP")
@@ -187,15 +189,15 @@
# parsed and that the correct method is called.
h = self.p.protocol
- cmd = telnet.IAC + telnet.SB + '\x12hello world' + telnet.IAC + telnet.SE
- L = ["These are some bytes but soon" + cmd,
- "there will be some more"]
+ cmd = telnet.IAC + telnet.SB + b'\x12hello world' + telnet.IAC + telnet.SE
+ L = [b"These are some bytes but soon" + cmd,
+ b"there will be some more"]
for b in L:
self.p.dataReceived(b)
- self.assertEqual(h.bytes, ''.join(L).replace(cmd, ''))
- self.assertEqual(h.subcmd, list("hello world"))
+ self.assertEqual(h.bytes, b''.join(L).replace(cmd, b''))
+ self.assertEqual(h.subcmd, list(iterbytes(b"hello world")))
def testSubnegotiationWithEmbeddedSE(self):
# Send a subnegotiation command with an embedded SE. Make sure
@@ -203,16 +205,16 @@
h = self.p.protocol
cmd = (telnet.IAC + telnet.SB +
- '\x12' + telnet.SE +
+ b'\x12' + telnet.SE +
telnet.IAC + telnet.SE)
- L = ["Some bytes are here" + cmd + "and here",
- "and here"]
+ L = [b"Some bytes are here" + cmd + b"and here",
+ b"and here"]
for b in L:
self.p.dataReceived(b)
- self.assertEqual(h.bytes, ''.join(L).replace(cmd, ''))
+ self.assertEqual(h.bytes, b''.join(L).replace(cmd, b''))
self.assertEqual(h.subcmd, [telnet.SE])
def testBoundarySubnegotiation(self):
@@ -220,7 +222,7 @@
# and make sure it always gets parsed and that it is passed to the correct
# method.
cmd = (telnet.IAC + telnet.SB +
- '\x12' + telnet.SE + 'hello' +
+ b'\x12' + telnet.SE + b'hello' +
telnet.IAC + telnet.SE)
for i in range(len(cmd)):
@@ -228,14 +230,14 @@
h.makeConnection(self.p)
a, b = cmd[:i], cmd[i:]
- L = ["first part" + a,
- b + "last part"]
+ L = [b"first part" + a,
+ b + b"last part"]
for bytes in L:
self.p.dataReceived(bytes)
- self.assertEqual(h.bytes, ''.join(L).replace(cmd, ''))
- self.assertEqual(h.subcmd, [telnet.SE] + list('hello'))
+ self.assertEqual(h.bytes, b''.join(L).replace(cmd, b''))
+ self.assertEqual(h.subcmd, [telnet.SE] + list(iterbytes(b'hello')))
def _enabledHelper(self, o, eL=[], eR=[], dL=[], dR=[]):
self.assertEqual(o.enabledLocal, eL)
@@ -245,152 +247,152 @@
def testRefuseWill(self):
# Try to enable an option. The server should refuse to enable it.
- cmd = telnet.IAC + telnet.WILL + '\x12'
+ cmd = telnet.IAC + telnet.WILL + b'\x12'
- bytes = "surrounding bytes" + cmd + "to spice things up"
+ bytes = b"surrounding bytes" + cmd + b"to spice things up"
self.p.dataReceived(bytes)
- self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, ''))
- self.assertEqual(self.t.value(), telnet.IAC + telnet.DONT + '\x12')
+ self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, b''))
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.DONT + b'\x12')
self._enabledHelper(self.p.protocol)
def testRefuseDo(self):
# Try to enable an option. The server should refuse to enable it.
- cmd = telnet.IAC + telnet.DO + '\x12'
+ cmd = telnet.IAC + telnet.DO + b'\x12'
- bytes = "surrounding bytes" + cmd + "to spice things up"
+ bytes = b"surrounding bytes" + cmd + b"to spice things up"
self.p.dataReceived(bytes)
- self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, ''))
- self.assertEqual(self.t.value(), telnet.IAC + telnet.WONT + '\x12')
+ self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, b''))
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.WONT + b'\x12')
self._enabledHelper(self.p.protocol)
def testAcceptDo(self):
# Try to enable an option. The option is in our allowEnable
# list, so we will allow it to be enabled.
- cmd = telnet.IAC + telnet.DO + '\x19'
- bytes = 'padding' + cmd + 'trailer'
+ cmd = telnet.IAC + telnet.DO + b'\x19'
+ bytes = b'padding' + cmd + b'trailer'
h = self.p.protocol
- h.localEnableable = ('\x19',)
+ h.localEnableable = (b'\x19',)
self.p.dataReceived(bytes)
- self.assertEqual(self.t.value(), telnet.IAC + telnet.WILL + '\x19')
- self._enabledHelper(h, eL=['\x19'])
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.WILL + b'\x19')
+ self._enabledHelper(h, eL=[b'\x19'])
def testAcceptWill(self):
# Same as testAcceptDo, but reversed.
- cmd = telnet.IAC + telnet.WILL + '\x91'
- bytes = 'header' + cmd + 'padding'
+ cmd = telnet.IAC + telnet.WILL + b'\x91'
+ bytes = b'header' + cmd + b'padding'
h = self.p.protocol
- h.remoteEnableable = ('\x91',)
+ h.remoteEnableable = (b'\x91',)
self.p.dataReceived(bytes)
- self.assertEqual(self.t.value(), telnet.IAC + telnet.DO + '\x91')
- self._enabledHelper(h, eR=['\x91'])
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.DO + b'\x91')
+ self._enabledHelper(h, eR=[b'\x91'])
def testAcceptWont(self):
# Try to disable an option. The server must allow any option to
# be disabled at any time. Make sure it disables it and sends
# back an acknowledgement of this.
- cmd = telnet.IAC + telnet.WONT + '\x29'
+ cmd = telnet.IAC + telnet.WONT + b'\x29'
# Jimmy it - after these two lines, the server will be in a state
# such that it believes the option to have been previously enabled
# via normal negotiation.
- s = self.p.getOptionState('\x29')
+ s = self.p.getOptionState(b'\x29')
s.him.state = 'yes'
- bytes = "fiddle dee" + cmd
+ bytes = b"fiddle dee" + cmd
self.p.dataReceived(bytes)
- self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, ''))
- self.assertEqual(self.t.value(), telnet.IAC + telnet.DONT + '\x29')
+ self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, b''))
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.DONT + b'\x29')
self.assertEqual(s.him.state, 'no')
- self._enabledHelper(self.p.protocol, dR=['\x29'])
+ self._enabledHelper(self.p.protocol, dR=[b'\x29'])
def testAcceptDont(self):
# Try to disable an option. The server must allow any option to
# be disabled at any time. Make sure it disables it and sends
# back an acknowledgement of this.
- cmd = telnet.IAC + telnet.DONT + '\x29'
+ cmd = telnet.IAC + telnet.DONT + b'\x29'
# Jimmy it - after these two lines, the server will be in a state
# such that it believes the option to have beenp previously enabled
# via normal negotiation.
- s = self.p.getOptionState('\x29')
+ s = self.p.getOptionState(b'\x29')
s.us.state = 'yes'
- bytes = "fiddle dum " + cmd
+ bytes = b"fiddle dum " + cmd
self.p.dataReceived(bytes)
- self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, ''))
- self.assertEqual(self.t.value(), telnet.IAC + telnet.WONT + '\x29')
+ self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, b''))
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.WONT + b'\x29')
self.assertEqual(s.us.state, 'no')
- self._enabledHelper(self.p.protocol, dL=['\x29'])
+ self._enabledHelper(self.p.protocol, dL=[b'\x29'])
def testIgnoreWont(self):
# Try to disable an option. The option is already disabled. The
# server should send nothing in response to this.
- cmd = telnet.IAC + telnet.WONT + '\x47'
+ cmd = telnet.IAC + telnet.WONT + b'\x47'
- bytes = "dum de dum" + cmd + "tra la la"
+ bytes = b"dum de dum" + cmd + b"tra la la"
self.p.dataReceived(bytes)
- self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, ''))
- self.assertEqual(self.t.value(), '')
+ self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, b''))
+ self.assertEqual(self.t.value(), b'')
self._enabledHelper(self.p.protocol)
def testIgnoreDont(self):
# Try to disable an option. The option is already disabled. The
# server should send nothing in response to this. Doing so could
# lead to a negotiation loop.
- cmd = telnet.IAC + telnet.DONT + '\x47'
+ cmd = telnet.IAC + telnet.DONT + b'\x47'
- bytes = "dum de dum" + cmd + "tra la la"
+ bytes = b"dum de dum" + cmd + b"tra la la"
self.p.dataReceived(bytes)
- self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, ''))
- self.assertEqual(self.t.value(), '')
+ self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, b''))
+ self.assertEqual(self.t.value(), b'')
self._enabledHelper(self.p.protocol)
def testIgnoreWill(self):
# Try to enable an option. The option is already enabled. The
# server should send nothing in response to this. Doing so could
# lead to a negotiation loop.
- cmd = telnet.IAC + telnet.WILL + '\x56'
+ cmd = telnet.IAC + telnet.WILL + b'\x56'
# Jimmy it - after these two lines, the server will be in a state
# such that it believes the option to have been previously enabled
# via normal negotiation.
- s = self.p.getOptionState('\x56')
+ s = self.p.getOptionState(b'\x56')
s.him.state = 'yes'
- bytes = "tra la la" + cmd + "dum de dum"
+ bytes = b"tra la la" + cmd + b"dum de dum"
self.p.dataReceived(bytes)
- self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, ''))
- self.assertEqual(self.t.value(), '')
+ self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, b''))
+ self.assertEqual(self.t.value(), b'')
self._enabledHelper(self.p.protocol)
def testIgnoreDo(self):
# Try to enable an option. The option is already enabled. The
# server should send nothing in response to this. Doing so could
# lead to a negotiation loop.
- cmd = telnet.IAC + telnet.DO + '\x56'
+ cmd = telnet.IAC + telnet.DO + b'\x56'
# Jimmy it - after these two lines, the server will be in a state
# such that it believes the option to have been previously enabled
# via normal negotiation.
- s = self.p.getOptionState('\x56')
+ s = self.p.getOptionState(b'\x56')
s.us.state = 'yes'
- bytes = "tra la la" + cmd + "dum de dum"
+ bytes = b"tra la la" + cmd + b"dum de dum"
self.p.dataReceived(bytes)
- self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, ''))
- self.assertEqual(self.t.value(), '')
+ self.assertEqual(self.p.protocol.bytes, bytes.replace(cmd, b''))
+ self.assertEqual(self.t.value(), b'')
self._enabledHelper(self.p.protocol)
def testAcceptedEnableRequest(self):
@@ -398,17 +400,17 @@
# returns a Deferred that fires when negotiation about the option
# finishes. Make sure it fires, make sure state gets updated
# properly, make sure the result indicates the option was enabled.
- d = self.p.do('\x42')
+ d = self.p.do(b'\x42')
h = self.p.protocol
- h.remoteEnableable = ('\x42',)
+ h.remoteEnableable = (b'\x42',)
- self.assertEqual(self.t.value(), telnet.IAC + telnet.DO + '\x42')
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.DO + b'\x42')
- self.p.dataReceived(telnet.IAC + telnet.WILL + '\x42')
+ self.p.dataReceived(telnet.IAC + telnet.WILL + b'\x42')
d.addCallback(self.assertEqual, True)
- d.addCallback(lambda _: self._enabledHelper(h, eR=['\x42']))
+ d.addCallback(lambda _: self._enabledHelper(h, eR=[b'\x42']))
return d
@@ -422,18 +424,18 @@
# Deferred that fires when negotiation about the option finishes. Make
# sure it fires, make sure state gets updated properly, make sure the
# result indicates the option was enabled.
- self.p.protocol.remoteEnableable = ('\x42',)
- d = self.p.do('\x42')
+ self.p.protocol.remoteEnableable = (b'\x42',)
+ d = self.p.do(b'\x42')
- self.assertEqual(self.t.value(), telnet.IAC + telnet.DO + '\x42')
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.DO + b'\x42')
- s = self.p.getOptionState('\x42')
+ s = self.p.getOptionState(b'\x42')
self.assertEqual(s.him.state, 'no')
self.assertEqual(s.us.state, 'no')
self.assertEqual(s.him.negotiating, True)
self.assertEqual(s.us.negotiating, False)
- self.p.dataReceived(telnet.IAC + telnet.WONT + '\x42')
+ self.p.dataReceived(telnet.IAC + telnet.WONT + b'\x42')
d = self.assertFailure(d, telnet.OptionRefused)
d.addCallback(lambda ignored: self._enabledHelper(self.p.protocol))
@@ -452,18 +454,18 @@
# Deferred that fires when negotiation about the option finishes. Make
# sure it fires, make sure state gets updated properly, make sure the
# result indicates the option was enabled.
- self.p.protocol.localEnableable = ('\x42',)
- d = self.p.will('\x42')
+ self.p.protocol.localEnableable = (b'\x42',)
+ d = self.p.will(b'\x42')
- self.assertEqual(self.t.value(), telnet.IAC + telnet.WILL + '\x42')
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.WILL + b'\x42')
- s = self.p.getOptionState('\x42')
+ s = self.p.getOptionState(b'\x42')
self.assertEqual(s.him.state, 'no')
self.assertEqual(s.us.state, 'no')
self.assertEqual(s.him.negotiating, False)
self.assertEqual(s.us.negotiating, True)
- self.p.dataReceived(telnet.IAC + telnet.DONT + '\x42')
+ self.p.dataReceived(telnet.IAC + telnet.DONT + b'\x42')
d = self.assertFailure(d, telnet.OptionRefused)
d.addCallback(lambda ignored: self._enabledHelper(self.p.protocol))
@@ -477,48 +479,48 @@
# returns a Deferred that fires when negotiation about the option
# finishes. Make sure it fires, make sure state gets updated
# properly, make sure the result indicates the option was enabled.
- s = self.p.getOptionState('\x42')
+ s = self.p.getOptionState(b'\x42')
s.him.state = 'yes'
- d = self.p.dont('\x42')
+ d = self.p.dont(b'\x42')
- self.assertEqual(self.t.value(), telnet.IAC + telnet.DONT + '\x42')
+ self.assertEqual(self.t.value(), telnet.IAC + telnet.DONT + b'\x42')
- self.p.dataReceived(telnet.IAC + telnet.WONT + '\x42')
+ self.p.dataReceived(telnet.IAC + telnet.WONT + b'\x42')
d.addCallback(self.assertEqual, True)
d.addCallback(lambda _: self._enabledHelper(self.p.protocol,
- dR=['\x42']))
+ dR=[b'\x42']))
return d
def testNegotiationBlocksFurtherNegotiation(self):
# Try to disable an option, then immediately try to enable it, then
# immediately try to disable it. Ensure that the 2nd and 3rd calls
# fail quickly with the right exception.
- s = self.p.getOptionState('\x24')
+ s = self.p.getOptionState(b'\x24')
s.him.state = 'yes'
- self.p.dont('\x24') # fires after the first line of _final
+ self.p.dont(b'\x24') # fires after the first line of _final
def _do(x):
- d = self.p.do('\x24')
+ d = self.p.do(b'\x24')
return self.assertFailure(d, telnet.AlreadyNegotiating)
def _dont(x):
- d = self.p.dont('\x24')
+ d = self.p.dont(b'\x24')
return self.assertFailure(d, telnet.AlreadyNegotiating)
def _final(x):
- self.p.dataReceived(telnet.IAC + telnet.WONT + '\x24')
+ self.p.dataReceived(telnet.IAC + telnet.WONT + b'\x24')
# an assertion that only passes if d2 has fired
- self._enabledHelper(self.p.protocol, dR=['\x24'])
+ self._enabledHelper(self.p.protocol, dR=[b'\x24'])
# Make sure we allow this
- self.p.protocol.remoteEnableable = ('\x24',)
- d = self.p.do('\x24')
- self.p.dataReceived(telnet.IAC + telnet.WILL + '\x24')
+ self.p.protocol.remoteEnableable = (b'\x24',)
+ d = self.p.do(b'\x24')
+ self.p.dataReceived(telnet.IAC + telnet.WILL + b'\x24')
d.addCallback(self.assertEqual, True)
d.addCallback(lambda _: self._enabledHelper(self.p.protocol,
- eR=['\x24'],
- dR=['\x24']))
+ eR=[b'\x24'],
+ dR=[b'\x24']))
return d
d = _do(None)
@@ -528,20 +530,20 @@
def testSuperfluousDisableRequestRaises(self):
# Try to disable a disabled option. Make sure it fails properly.
- d = self.p.dont('\xab')
+ d = self.p.dont(b'\xab')
return self.assertFailure(d, telnet.AlreadyDisabled)
def testSuperfluousEnableRequestRaises(self):
# Try to disable a disabled option. Make sure it fails properly.
- s = self.p.getOptionState('\xab')
+ s = self.p.getOptionState(b'\xab')
s.him.state = 'yes'
- d = self.p.do('\xab')
+ d = self.p.do(b'\xab')
return self.assertFailure(d, telnet.AlreadyEnabled)
def testLostConnectionFailsDeferreds(self):
- d1 = self.p.do('\x12')
- d2 = self.p.do('\x23')
- d3 = self.p.do('\x34')
+ d1 = self.p.do(b'\x12')
+ d2 = self.p.do(b'\x23')
+ d3 = self.p.do(b'\x34')
class TestException(Exception):
pass
@@ -604,7 +606,7 @@
L{telnet.Telnet.enableLocal} should reject all options, since
L{telnet.Telnet} does not know how to implement any options.
"""
- self.assertFalse(self.protocol.enableLocal('\0'))
+ self.assertFalse(self.protocol.enableLocal(b'\0'))
def test_enableRemote(self):
@@ -612,7 +614,7 @@
L{telnet.Telnet.enableRemote} should reject all options, since
L{telnet.Telnet} does not know how to implement any options.
"""
- self.assertFalse(self.protocol.enableRemote('\0'))
+ self.assertFalse(self.protocol.enableRemote(b'\0'))
def test_disableLocal(self):
@@ -622,7 +624,7 @@
locally. If a subclass overrides enableLocal, it must also override
disableLocal.
"""
- self.assertRaises(NotImplementedError, self.protocol.disableLocal, '\0')
+ self.assertRaises(NotImplementedError, self.protocol.disableLocal, b'\0')
def test_disableRemote(self):
@@ -632,7 +634,7 @@
enabled remotely. If a subclass overrides enableRemote, it must also
override disableRemote.
"""
- self.assertRaises(NotImplementedError, self.protocol.disableRemote, '\0')
+ self.assertRaises(NotImplementedError, self.protocol.disableRemote, b'\0')
def test_requestNegotiation(self):
@@ -644,11 +646,11 @@
"""
transport = proto_helpers.StringTransport()
self.protocol.makeConnection(transport)
- self.protocol.requestNegotiation('\x01', '\x02\x03')
+ self.protocol.requestNegotiation(b'\x01', b'\x02\x03')
self.assertEqual(
transport.value(),
# IAC SB feature bytes IAC SE
- '\xff\xfa\x01\x02\x03\xff\xf0')
+ b'\xff\xfa\x01\x02\x03\xff\xf0')
def test_requestNegotiationEscapesIAC(self):
@@ -660,10 +662,10 @@
"""
transport = proto_helpers.StringTransport()
self.protocol.makeConnection(transport)
- self.protocol.requestNegotiation('\x01', '\xff')
+ self.protocol.requestNegotiation(b'\x01', b'\xff')
self.assertEqual(
transport.value(),
- '\xff\xfa\x01\xff\xff\xff\xf0')
+ b'\xff\xfa\x01\xff\xff\xff\xf0')
def _deliver(self, bytes, *expected):
@@ -681,7 +683,7 @@
One application-data byte in the default state gets delivered right
away.
"""
- self._deliver('a', ('bytes', 'a'))
+ self._deliver(b'a', ('bytes', b'a'))
def test_twoApplicationDataBytes(self):
@@ -689,7 +691,7 @@
Two application-data bytes in the default state get delivered
together.
"""
- self._deliver('bc', ('bytes', 'bc'))
+ self._deliver(b'bc', ('bytes', b'bc'))
def test_threeApplicationDataBytes(self):
@@ -697,7 +699,7 @@
Three application-data bytes followed by a control byte get
delivered, but the control byte doesn't.
"""
- self._deliver('def' + telnet.IAC, ('bytes', 'def'))
+ self._deliver(b'def' + telnet.IAC, ('bytes', b'def'))
def test_escapedControl(self):
@@ -706,7 +708,7 @@
application-data byte following it.
"""
self._deliver(telnet.IAC)
- self._deliver(telnet.IAC + 'g', ('bytes', telnet.IAC + 'g'))
+ self._deliver(telnet.IAC + b'g', ('bytes', telnet.IAC + b'g'))
def test_carriageReturn(self):
@@ -715,25 +717,25 @@
linefeed in the newline state causes just the newline to be
delivered. A nul in the newline state causes a carriage return to
be delivered. An IAC in the newline state causes a carriage return
- to be delivered and puts the protocol into the escaped state.
+ to be delivered and puts the protocol into the escaped state.
Anything else causes a carriage return and that thing to be
delivered.
"""
- self._deliver('\r')
- self._deliver('\n', ('bytes', '\n'))
- self._deliver('\r\n', ('bytes', '\n'))
-
- self._deliver('\r')
- self._deliver('\0', ('bytes', '\r'))
- self._deliver('\r\0', ('bytes', '\r'))
-
- self._deliver('\r')
- self._deliver('a', ('bytes', '\ra'))
- self._deliver('\ra', ('bytes', '\ra'))
+ self._deliver(b'\r')
+ self._deliver(b'\n', ('bytes', b'\n'))
+ self._deliver(b'\r\n', ('bytes', b'\n'))
+
+ self._deliver(b'\r')
+ self._deliver(b'\0', ('bytes', b'\r'))
+ self._deliver(b'\r\0', ('bytes', b'\r'))
+
+ self._deliver(b'\r')
+ self._deliver(b'a', ('bytes', b'\ra'))
+ self._deliver(b'\ra', ('bytes', b'\ra'))
- self._deliver('\r')
+ self._deliver(b'\r')
self._deliver(
- telnet.IAC + telnet.IAC + 'x', ('bytes', '\r' + telnet.IAC + 'x'))
+ telnet.IAC + telnet.IAC + b'x', ('bytes', b'\r' + telnet.IAC + b'x'))
def test_applicationDataBeforeSimpleCommand(self):
@@ -742,8 +744,8 @@
command is processed.
"""
self._deliver(
- 'x' + telnet.IAC + telnet.NOP,
- ('bytes', 'x'), ('command', telnet.NOP, None))
+ b'x' + telnet.IAC + telnet.NOP,
+ ('bytes', b'x'), ('command', telnet.NOP, None))
def test_applicationDataBeforeCommand(self):
@@ -753,8 +755,8 @@
"""
self.protocol.commandMap = {}
self._deliver(
- 'y' + telnet.IAC + telnet.WILL + '\x00',
- ('bytes', 'y'), ('command', telnet.WILL, '\x00'))
+ b'y' + telnet.IAC + telnet.WILL + b'\x00',
+ ('bytes', b'y'), ('command', telnet.WILL, b'\x00'))
def test_applicationDataBeforeSubnegotiation(self):
@@ -763,5 +765,5 @@
delivered before the negotiation is processed.
"""
self._deliver(
- 'z' + telnet.IAC + telnet.SB + 'Qx' + telnet.IAC + telnet.SE,
- ('bytes', 'z'), ('negotiate', 'Q', ['x']))
+ b'z' + telnet.IAC + telnet.SB + b'Qx' + telnet.IAC + telnet.SE,
+ ('bytes', b'z'), ('negotiate', b'Q', [b'x']))
Modified: trunk/twisted/protocols/telnet.py
==============================================================================
--- trunk/twisted/protocols/telnet.py (original)
+++ trunk/twisted/protocols/telnet.py Thu Mar 10 02:32:00 2016
@@ -1,10 +1,11 @@
-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
-
-"""TELNET implementation, with line-oriented command handling.
"""
+TELNET implementation, with line-oriented command handling.
+"""
+
+from __future__ import absolute_import, division
import warnings
warnings.warn(
@@ -13,21 +14,16 @@
DeprecationWarning,
stacklevel=2)
+from io import BytesIO
-# System Imports
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
-# Twisted Imports
from twisted import copyright
from twisted.internet import protocol
+from twisted.python.compat import networkString, iterbytes, _bytesChr as chr
# Some utility chars.
ESC = chr(27) # ESC for doing fanciness
-BOLD_MODE_ON = ESC+"[1m" # turn bold on
-BOLD_MODE_OFF= ESC+"[m" # no char attributes
+BOLD_MODE_ON = ESC + b"[1m" # turn bold on
+BOLD_MODE_OFF= ESC + b"[m" # no char attributes
# Characters gleaned from the various (and conflicting) RFCs. Not all of these are correct.
@@ -122,7 +118,7 @@
NOECHO= chr(131) # User-to-Server: Asks the server not to
# return Echos of the transmitted data.
- #
+ #
# Server-to-User: States that the server is
# not sending echos of the transmitted data.
# Sent only as a reply to ECHO or NO ECHO,
@@ -136,7 +132,7 @@
WILL: 'WILL',
WONT: 'WONT',
IP: 'IP'
- }
+}
def multireplace(st, dct):
for k, v in dct.items():
@@ -144,7 +140,8 @@
return st
class Telnet(protocol.Protocol):
- """I am a Protocol for handling Telnet connections. I have two
+ """
+ I am a Protocol for handling Telnet connections. I have two
sets of special methods, telnet_* and iac_*.
telnet_* methods get called on every line sent to me. The method
@@ -165,9 +162,9 @@
gotIAC = 0
iacByte = None
lastLine = None
- buffer = ''
+ buffer = b''
echo = 0
- delimiters = ['\r\n', '\r\000']
+ delimiters = [b'\r\n', b'\r\000']
mode = "User"
def write(self, data):
@@ -183,13 +180,13 @@
"""Override me to return a string which will be sent to the client
before login."""
x = self.factory.__class__
- return ("\r\n" + x.__module__ + '.' + x.__name__ +
+ return networkString("\r\n" + x.__module__ + '.' + x.__name__ +
'\r\nTwisted %s\r\n' % copyright.version
)
def loginPrompt(self):
"""Override me to return a 'login:'-type prompt."""
- return "username: "
+ return b"username: "
def iacSBchunk(self, chunk):
pass
@@ -214,7 +211,7 @@
in by the current mode. telnet_* methods should return a string which
will become the new mode. If None is returned, the mode will not change.
"""
- mode = getattr(self, "telnet_"+self.mode)(line)
+ mode = getattr(self, "telnet_" + self.mode)(line)
if mode is not None:
self.mode = mode
@@ -224,14 +221,14 @@
you want to do something else when the username is received (ie,
create a new user if the user doesn't exist), override me."""
self.username = user
- self.write(IAC+WILL+ECHO+"password: ")
+ self.write(IAC + WILL + ECHO + b"password: ")
return "Password"
def telnet_Password(self, paswd):
"""I accept a password as an argument, and check it with the
checkUserAndPass method. If the login is successful, I call
loggedIn()."""
- self.write(IAC+WONT+ECHO+"*****\r\n")
+ self.write(IAC + WONT + ECHO + b"*****\r\n")
try:
checked = self.checkUserAndPass(self.username, paswd)
except:
@@ -257,7 +254,7 @@
idx = self.buffer.find(delim)
if idx != -1:
break
-
+
while idx != -1:
buf, self.buffer = self.buffer[:idx], self.buffer[idx+2:]
self.processLine(buf)
@@ -270,9 +267,9 @@
break
def dataReceived(self, data):
- chunk = StringIO()
+ chunk = BytesIO()
# silly little IAC state-machine
- for char in data:
+ for char in iterbytes(data):
if self.gotIAC:
# working on an IAC request state
if self.iacByte:
@@ -280,7 +277,7 @@
if self.iacByte == SB:
if char == SE:
self.iacSBchunk(chunk.getvalue())
- chunk = StringIO()
+ chunk = BytesIO()
del self.iacByte
del self.gotIAC
else:
@@ -306,7 +303,7 @@
why = self.processChunk(c)
if why:
return why
- chunk = StringIO()
+ chunk = BytesIO()
self.gotIAC = 1
else:
chunk.write(char)
@@ -319,7 +316,7 @@
def loggedIn(self):
"""Called after the user succesfully logged in.
-
+
Override in subclasses.
"""
pass
Modified: trunk/twisted/python/compat.py
==============================================================================
--- trunk/twisted/python/compat.py (original)
+++ trunk/twisted/python/compat.py Thu Mar 10 02:32:00 2016
@@ -685,6 +685,23 @@
from base64 import decodestring as _b64decodebytes
+
+def _bytesChr(i):
+ """
+ Like L{chr} but always works on ASCII, returning L{bytes}.
+
+ @param i: The ASCII code point to return.
+ @type i: L{int}
+
+ @rtype: L{bytes}
+ """
+ if _PY3:
+ return bytes([i])
+ else:
+ return chr(i)
+
+
+
__all__ = [
"reraise",
"execfile",
@@ -717,4 +734,5 @@
"_keys",
"_b64encodebytes",
"_b64decodebytes",
+ "_bytesChr",
]
Modified: trunk/twisted/python/dist3.py
==============================================================================
--- trunk/twisted/python/dist3.py (original)
+++ trunk/twisted/python/dist3.py Thu Mar 10 02:32:00 2016
@@ -52,6 +52,7 @@
"twisted.conch.ssh.common",
"twisted.conch.ssh.keys",
"twisted.conch.ssh.sexpy",
+ "twisted.conch.telnet",
"twisted.conch.test.__init__",
"twisted.copyright",
"twisted.cred.__init__",
@@ -155,6 +156,7 @@
"twisted.protocols.amp",
"twisted.protocols.basic",
"twisted.protocols.policies",
+ "twisted.protocols.telnet",
"twisted.protocols.test.__init__",
"twisted.protocols.tls",
"twisted.python.__init__",
@@ -255,8 +257,9 @@
testModules = [
"twisted.application.test.test_internet",
"twisted.application.test.test_service",
- "twisted.conch.test.test_keys",
"twisted.conch.test.test_checkers",
+ "twisted.conch.test.test_keys",
+ "twisted.conch.test.test_telnet",
"twisted.cred.test.test_cramauth",
"twisted.cred.test.test_cred",
"twisted.cred.test.test_digestauth",