@@ -172,6 +172,10 @@ class Telnet(object):
172172 raise EOFError when the end of the connection is read, because
173173 they can return an empty string for other reasons. See the
174174 individual doc strings.
175+
176+ read_until(expected, [timeout])
177+ Read until the expected string has been seen, or a timeout is
178+ hit (default is no timeout); may block.
175179
176180 read_all()
177181 Read all data until EOF; may block.
@@ -309,6 +313,41 @@ def write(self, buffer):
309313 buffer = buffer .replace (IAC , IAC + IAC )
310314 self .msg ("send %s" , repr (buffer ))
311315 self .sock .send (buffer )
316+
317+ def read_until (self , match , timeout = None ):
318+ """Read until a given string is encountered or until timeout.
319+ When no match is found, return whatever is available instead,
320+ possibly the empty string. Raise EOFError if the connection
321+ is closed and no cooked data is available.
322+ """
323+ n = len (match )
324+ self .process_rawq ()
325+ i = self .cookedq .find (match )
326+ if i >= 0 :
327+ i = i + n
328+ buf = self .cookedq [:i ]
329+ self .cookedq = self .cookedq [i :]
330+ return buf
331+ if timeout is not None :
332+ deadline = _time () + timeout
333+ with _TelnetSelector () as selector :
334+ selector .register (self , selectors .EVENT_READ )
335+ while not self .eof :
336+ if selector .select (timeout ):
337+ i = max (0 , len (self .cookedq )- n )
338+ self .fill_rawq ()
339+ self .process_rawq ()
340+ i = self .cookedq .find (match , i )
341+ if i >= 0 :
342+ i = i + n
343+ buf = self .cookedq [:i ]
344+ self .cookedq = self .cookedq [i :]
345+ return buf
346+ if timeout is not None :
347+ timeout = deadline - _time ()
348+ if timeout < 0 :
349+ break
350+ return self .read_very_lazy ()
312351
313352 def read_all (self ):
314353 """Read all data until EOF; block until connection closed."""
0 commit comments