Skip to content

Commit

Permalink
Merge 7ab8662 into 692681f
Browse files Browse the repository at this point in the history
  • Loading branch information
dluyer committed Jan 9, 2020
2 parents 692681f + 7ab8662 commit 80f4117
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 23 deletions.
97 changes: 74 additions & 23 deletions pexpect/expect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,95 @@ class Expecter(object):
def __init__(self, spawn, searcher, searchwindowsize=-1):
self.spawn = spawn
self.searcher = searcher
# A value of -1 means to use the figure from spawn, which should
# be None or a positive number.
if searchwindowsize == -1:
searchwindowsize = spawn.searchwindowsize
self.searchwindowsize = searchwindowsize
self.lookback = None
if hasattr(searcher, 'longest_string'):
self.lookback = searcher.longest_string

def new_data(self, data):
spawn = self.spawn
searcher = self.searcher

pos = spawn._buffer.tell()
spawn._buffer.write(data)
spawn._before.write(data)

# determine which chunk of data to search; if a windowsize is
# specified, this is the *new* data + the preceding <windowsize> bytes
if self.searchwindowsize:
spawn._buffer.seek(max(0, pos - self.searchwindowsize))
window = spawn._buffer.read(self.searchwindowsize + len(data))
if data is None:
# First call from a new call to expect_loop.
# self.searchwindowsize may have changed.
before_len = spawn._before.tell()
buf_len = spawn._buffer.tell()
freshlen = before_len
if before_len > buf_len:
if not self.searchwindowsize:
spawn._buffer = spawn.buffer_type()
window = spawn._before.getvalue()
spawn._buffer.write(spawn._before.getvalue())
elif buf_len < self.searchwindowsize:
spawn._buffer = spawn.buffer_type()
spawn._before.seek(
max(0, before_len - self.searchwindowsize))
window = spawn._before.read()
spawn._buffer.write(window)
else:
spawn._buffer.seek(max(0, buf_len - self.searchwindowsize))
window = spawn._buffer.read()
else:
if self.searchwindowsize:
spawn._buffer.seek(max(0, buf_len - self.searchwindowsize))
window = spawn._buffer.read()
else:
window = spawn._buffer.getvalue()
else:
# otherwise, search the whole buffer (really slow for large datasets)
window = spawn.buffer
index = searcher.search(window, len(data))
freshlen = len(data)
spawn._before.write(data)
if not self.searchwindowsize:
if self.lookback:
# search lookback + new data.
old_len = spawn._buffer.tell()
spawn._buffer.write(data)
spawn._buffer.seek(max(0, old_len - self.lookback))
window = spawn._buffer.read()
else:
# copy the whole buffer (really slow for large datasets).
spawn._buffer.write(data)
window = spawn.buffer
else:
if len(data) >= self.searchwindowsize or not spawn._buffer.tell():
window = data[-self.searchwindowsize:]
spawn._buffer = spawn.buffer_type()
spawn._buffer.write(window[-self.searchwindowsize:])
else:
spawn._buffer.write(data)
new_len = spawn._buffer.tell()
spawn._buffer.seek(max(0, new_len - self.searchwindowsize))
window = spawn._buffer.read()

if freshlen > len(window):
freshlen = len(window)
index = searcher.search(window, freshlen, self.searchwindowsize)
if index >= 0:
spawn._buffer = spawn.buffer_type()
spawn._buffer.write(window[searcher.end:])
spawn.before = spawn._before.getvalue()[0:-(len(window) - searcher.start)]
spawn.before = spawn._before.getvalue()[
0:-(len(window) - searcher.start)]
spawn._before = spawn.buffer_type()
spawn.after = window[searcher.start: searcher.end]
spawn._before.write(window[searcher.end:])
spawn.after = window[searcher.start:searcher.end]
spawn.match = searcher.match
spawn.match_index = index
# Found a match
return index
elif self.searchwindowsize:
spawn._buffer = spawn.buffer_type()
spawn._buffer.write(window)
elif self.searchwindowsize or self.lookback:
maintain = self.searchwindowsize or self.lookback
if spawn._buffer.tell() > maintain:
spawn._buffer = spawn.buffer_type()
spawn._buffer.write(window[-maintain:])

def eof(self, err=None):
spawn = self.spawn

spawn.before = spawn.buffer
spawn.before = spawn._before.getvalue()
spawn._buffer = spawn.buffer_type()
spawn._before = spawn.buffer_type()
spawn.after = EOF
Expand All @@ -68,7 +118,7 @@ def eof(self, err=None):
def timeout(self, err=None):
spawn = self.spawn

spawn.before = spawn.buffer
spawn.before = spawn._before.getvalue()
spawn.after = TIMEOUT
index = self.searcher.timeout_index
if index >= 0:
Expand All @@ -89,7 +139,7 @@ def timeout(self, err=None):

def errored(self):
spawn = self.spawn
spawn.before = spawn.buffer
spawn.before = spawn._before.getvalue()
spawn.after = None
spawn.match = None
spawn.match_index = None
Expand All @@ -102,9 +152,7 @@ def expect_loop(self, timeout=-1):
end_time = time.time() + timeout

try:
incoming = spawn.buffer
spawn._buffer = spawn.buffer_type()
spawn._before = spawn.buffer_type()
incoming = None
while True:
idx = self.new_data(incoming)
# Keep reading until exception or return.
Expand Down Expand Up @@ -154,6 +202,7 @@ def __init__(self, strings):
self.eof_index = -1
self.timeout_index = -1
self._strings = []
self.longest_string = 0
for n, s in enumerate(strings):
if s is EOF:
self.eof_index = n
Expand All @@ -162,6 +211,8 @@ def __init__(self, strings):
self.timeout_index = n
continue
self._strings.append((n, s))
if len(s) > self.longest_string:
self.longest_string = len(s)

def __str__(self):
'''This returns a human-readable string that represents the state of
Expand Down
3 changes: 3 additions & 0 deletions pexpect/spawnbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ def write_to_stdout(b):
self.async_pw_transport = None
# This is the read buffer. See maxread.
self._buffer = self.buffer_type()
# The buffer may be trimmed for efficiency reasons. This is the
# untrimmed buffer, used to create the before attribute.
self._before = self.buffer_type()

def _log(self, s, direction):
if self.logfile is not None:
Expand Down

0 comments on commit 80f4117

Please sign in to comment.