cpython: f713d9b6393c (original) (raw)

Mercurial > cpython

changeset 86549:f713d9b6393c

Issue #19170: telnetlib: use selectors. [#19170]

Charles-François Natali cf.natali@gmail.com
date Mon, 21 Oct 2013 14:02:12 +0200
parents 10dbe5591e62
children dad1debba93c
files Lib/telnetlib.py Lib/test/test_telnetlib.py
diffstat 2 files changed, 100 insertions(+), 274 deletions(-)[+] [-] Lib/telnetlib.py 273 Lib/test/test_telnetlib.py 101

line wrap: on

line diff

--- a/Lib/telnetlib.py +++ b/Lib/telnetlib.py @@ -17,13 +17,12 @@ guido Guido van Rossum pts/2 Note that read_all() won't read until eof -- it just reads some data -- but it guarantees to read at least one byte unless EOF is hit. -It is possible to pass a Telnet object to select.select() in order to -wait until more data is available. Note that in this case, -read_eager() may return b'' even if there was data on the socket, -because the protocol negotiation may have eaten the data. This is why -EOFError is needed in some cases to distinguish between "no data" and -"connection closed" (since the socket also appears ready for reading -when it is closed). +It is possible to pass a Telnet object to a selector in order to wait until +more data is available. Note that in this case, read_eager() may return b'' +even if there was data on the socket, because the protocol negotiation may have +eaten the data. This is why EOFError is needed in some cases to distinguish +between "no data" and "connection closed" (since the socket also appears ready +for reading when it is closed). To do:

Imported modules

-import errno import sys import socket -import select +import selectors all = ["Telnet"] @@ -130,6 +128,15 @@ PRAGMA_HEARTBEAT = bytes([140]) # TELOPT EXOPL = bytes([255]) # Extended-Options-List NOOPT = bytes([0]) + +# poll/select have the advantage of not requiring any extra file descriptor, +# contrarily to epoll/kqueue (also, they require a single syscall). +if hasattr(selectors, 'PollSelector'):

+else:

+ + class Telnet: """Telnet interface class. @@ -206,7 +213,6 @@ class Telnet: self.sb = 0 # flag for SB and SE sequence. self.sbdataq = b'' self.option_callback = None

@@ -289,61 +295,6 @@ class Telnet: is closed and no cooked data is available. """

-

-

-

-

@@ -352,27 +303,26 @@ class Telnet: buf = self.cookedq[:i] self.cookedq = self.cookedq[i:] return buf

def read_all(self): @@ -577,29 +527,35 @@ class Telnet: def sock_avail(self): """Test whether data is available on the socket."""

def interact(self): """Interaction function, emulates a very dumb telnet client.""" if sys.platform == "win32": self.mt_interact() return

+

def mt_interact(self): """Multithreaded version of interact().""" @@ -646,79 +602,6 @@ class Telnet: results are undeterministic, and may depend on the I/O timing. """

-

-

-

-

@@ -728,27 +611,27 @@ class Telnet: list[i] = re.compile(list[i]) if timeout is not None: from time import time

--- a/Lib/test/test_telnetlib.py +++ b/Lib/test/test_telnetlib.py @@ -1,10 +1,9 @@ import socket -import select +import selectors import telnetlib import time import contextlib -import unittest from unittest import TestCase from test import support threading = support.import_module('threading') @@ -112,40 +111,32 @@ class TelnetAlike(telnetlib.Telnet): self._messages += out.getvalue() return -def mock_select(*s_args):

- -class MockPoller(object):

+class MockSelector(selectors.BaseSelector): def init(self):

+

@contextlib.contextmanager def test_socket(reads): @@ -159,7 +150,7 @@ def test_socket(reads): socket.create_connection = old_conn return -def test_telnet(reads=(), cls=TelnetAlike, use_poll=None): +def test_telnet(reads=(), cls=TelnetAlike): ''' return a telnetlib.Telnet object that uses a SocketStub with reads queued up to be read ''' for x in reads: @@ -167,29 +158,14 @@ def test_telnet(reads=(), cls=TelnetAlik with test_socket(reads): telnet = cls('dummy', 0) telnet._messages = '' # debuglevel output

-

-

class ReadTests(ExpectAndReadTestCase): def test_read_until(self): @@ -208,22 +184,6 @@ class ReadTests(ExpectAndReadTestCase): data = telnet.read_until(b'match') self.assertEqual(data, expect)

-

def test_read_all(self): """ @@ -427,23 +387,6 @@ class ExpectTests(ExpectAndReadTestCase) (,,data) = telnet.expect([b'match']) self.assertEqual(data, b''.join(want[:-1]))

-

- def test_main(verbose=None): support.run_unittest(GeneralTests, ReadTests, WriteTests, OptionTests,