1205fd03aSDavide Italianofrom io import StringIO, BytesIO 2205fd03aSDavide Italianoimport codecs 3205fd03aSDavide Italianoimport os 4205fd03aSDavide Italianoimport sys 5205fd03aSDavide Italianoimport re 6205fd03aSDavide Italianoimport errno 7205fd03aSDavide Italianofrom .exceptions import ExceptionPexpect, EOF, TIMEOUT 8205fd03aSDavide Italianofrom .expect import Expecter, searcher_string, searcher_re 9205fd03aSDavide Italiano 10205fd03aSDavide ItalianoPY3 = (sys.version_info[0] >= 3) 11205fd03aSDavide Italianotext_type = str if PY3 else unicode 12205fd03aSDavide Italiano 13205fd03aSDavide Italianoclass _NullCoder(object): 14205fd03aSDavide Italiano """Pass bytes through unchanged.""" 15205fd03aSDavide Italiano @staticmethod 16205fd03aSDavide Italiano def encode(b, final=False): 17205fd03aSDavide Italiano return b 18205fd03aSDavide Italiano 19205fd03aSDavide Italiano @staticmethod 20205fd03aSDavide Italiano def decode(b, final=False): 21205fd03aSDavide Italiano return b 22205fd03aSDavide Italiano 23205fd03aSDavide Italianoclass SpawnBase(object): 24205fd03aSDavide Italiano """A base class providing the backwards-compatible spawn API for Pexpect. 25205fd03aSDavide Italiano 26205fd03aSDavide Italiano This should not be instantiated directly: use :class:`pexpect.spawn` or 27205fd03aSDavide Italiano :class:`pexpect.fdpexpect.fdspawn`. 28205fd03aSDavide Italiano """ 29205fd03aSDavide Italiano encoding = None 30205fd03aSDavide Italiano pid = None 31205fd03aSDavide Italiano flag_eof = False 32205fd03aSDavide Italiano 33*97c6ef4eSMuhammad Omair Javaid def __init__(self, timeout=60, maxread=2000, searchwindowsize=None, 34205fd03aSDavide Italiano logfile=None, encoding=None, codec_errors='strict'): 35205fd03aSDavide Italiano self.stdin = sys.stdin 36205fd03aSDavide Italiano self.stdout = sys.stdout 37205fd03aSDavide Italiano self.stderr = sys.stderr 38205fd03aSDavide Italiano 39205fd03aSDavide Italiano self.searcher = None 40205fd03aSDavide Italiano self.ignorecase = False 41205fd03aSDavide Italiano self.before = None 42205fd03aSDavide Italiano self.after = None 43205fd03aSDavide Italiano self.match = None 44205fd03aSDavide Italiano self.match_index = None 45205fd03aSDavide Italiano self.terminated = True 46205fd03aSDavide Italiano self.exitstatus = None 47205fd03aSDavide Italiano self.signalstatus = None 48205fd03aSDavide Italiano # status returned by os.waitpid 49205fd03aSDavide Italiano self.status = None 50205fd03aSDavide Italiano # the child file descriptor is initially closed 51205fd03aSDavide Italiano self.child_fd = -1 52205fd03aSDavide Italiano self.timeout = timeout 53205fd03aSDavide Italiano self.delimiter = EOF 54205fd03aSDavide Italiano self.logfile = logfile 55205fd03aSDavide Italiano # input from child (read_nonblocking) 56205fd03aSDavide Italiano self.logfile_read = None 57205fd03aSDavide Italiano # output to send (send, sendline) 58205fd03aSDavide Italiano self.logfile_send = None 59205fd03aSDavide Italiano # max bytes to read at one time into buffer 60205fd03aSDavide Italiano self.maxread = maxread 61205fd03aSDavide Italiano # Data before searchwindowsize point is preserved, but not searched. 62205fd03aSDavide Italiano self.searchwindowsize = searchwindowsize 63205fd03aSDavide Italiano # Delay used before sending data to child. Time in seconds. 64205fd03aSDavide Italiano # Set this to None to skip the time.sleep() call completely. 65205fd03aSDavide Italiano self.delaybeforesend = 0.05 66205fd03aSDavide Italiano # Used by close() to give kernel time to update process status. 67205fd03aSDavide Italiano # Time in seconds. 68205fd03aSDavide Italiano self.delayafterclose = 0.1 69205fd03aSDavide Italiano # Used by terminate() to give kernel time to update process status. 70205fd03aSDavide Italiano # Time in seconds. 71205fd03aSDavide Italiano self.delayafterterminate = 0.1 72205fd03aSDavide Italiano # Delay in seconds to sleep after each call to read_nonblocking(). 73205fd03aSDavide Italiano # Set this to None to skip the time.sleep() call completely: that 74205fd03aSDavide Italiano # would restore the behavior from pexpect-2.0 (for performance 75205fd03aSDavide Italiano # reasons or because you don't want to release Python's global 76205fd03aSDavide Italiano # interpreter lock). 77205fd03aSDavide Italiano self.delayafterread = 0.0001 78205fd03aSDavide Italiano self.softspace = False 79205fd03aSDavide Italiano self.name = '<' + repr(self) + '>' 80205fd03aSDavide Italiano self.closed = True 81205fd03aSDavide Italiano 82205fd03aSDavide Italiano # Unicode interface 83205fd03aSDavide Italiano self.encoding = encoding 84205fd03aSDavide Italiano self.codec_errors = codec_errors 85205fd03aSDavide Italiano if encoding is None: 86205fd03aSDavide Italiano # bytes mode (accepts some unicode for backwards compatibility) 87205fd03aSDavide Italiano self._encoder = self._decoder = _NullCoder() 88205fd03aSDavide Italiano self.string_type = bytes 89205fd03aSDavide Italiano self.buffer_type = BytesIO 90205fd03aSDavide Italiano self.crlf = b'\r\n' 91205fd03aSDavide Italiano if PY3: 92205fd03aSDavide Italiano self.allowed_string_types = (bytes, str) 93205fd03aSDavide Italiano self.linesep = os.linesep.encode('ascii') 94205fd03aSDavide Italiano def write_to_stdout(b): 95205fd03aSDavide Italiano try: 96205fd03aSDavide Italiano return sys.stdout.buffer.write(b) 97205fd03aSDavide Italiano except AttributeError: 98205fd03aSDavide Italiano # If stdout has been replaced, it may not have .buffer 99205fd03aSDavide Italiano return sys.stdout.write(b.decode('ascii', 'replace')) 100205fd03aSDavide Italiano self.write_to_stdout = write_to_stdout 101205fd03aSDavide Italiano else: 102205fd03aSDavide Italiano self.allowed_string_types = (basestring,) # analysis:ignore 103205fd03aSDavide Italiano self.linesep = os.linesep 104205fd03aSDavide Italiano self.write_to_stdout = sys.stdout.write 105205fd03aSDavide Italiano else: 106205fd03aSDavide Italiano # unicode mode 107205fd03aSDavide Italiano self._encoder = codecs.getincrementalencoder(encoding)(codec_errors) 108205fd03aSDavide Italiano self._decoder = codecs.getincrementaldecoder(encoding)(codec_errors) 109205fd03aSDavide Italiano self.string_type = text_type 110205fd03aSDavide Italiano self.buffer_type = StringIO 111205fd03aSDavide Italiano self.crlf = u'\r\n' 112205fd03aSDavide Italiano self.allowed_string_types = (text_type, ) 113205fd03aSDavide Italiano if PY3: 114205fd03aSDavide Italiano self.linesep = os.linesep 115205fd03aSDavide Italiano else: 116205fd03aSDavide Italiano self.linesep = os.linesep.decode('ascii') 117205fd03aSDavide Italiano # This can handle unicode in both Python 2 and 3 118205fd03aSDavide Italiano self.write_to_stdout = sys.stdout.write 119205fd03aSDavide Italiano # storage for async transport 120205fd03aSDavide Italiano self.async_pw_transport = None 121205fd03aSDavide Italiano # This is the read buffer. See maxread. 122205fd03aSDavide Italiano self._buffer = self.buffer_type() 123205fd03aSDavide Italiano 124205fd03aSDavide Italiano def _log(self, s, direction): 125205fd03aSDavide Italiano if self.logfile is not None: 126205fd03aSDavide Italiano self.logfile.write(s) 127205fd03aSDavide Italiano self.logfile.flush() 128205fd03aSDavide Italiano second_log = self.logfile_send if (direction=='send') else self.logfile_read 129205fd03aSDavide Italiano if second_log is not None: 130205fd03aSDavide Italiano second_log.write(s) 131205fd03aSDavide Italiano second_log.flush() 132205fd03aSDavide Italiano 133205fd03aSDavide Italiano # For backwards compatibility, in bytes mode (when encoding is None) 134205fd03aSDavide Italiano # unicode is accepted for send and expect. Unicode mode is strictly unicode 135205fd03aSDavide Italiano # only. 136205fd03aSDavide Italiano def _coerce_expect_string(self, s): 137205fd03aSDavide Italiano if self.encoding is None and not isinstance(s, bytes): 138205fd03aSDavide Italiano return s.encode('ascii') 139205fd03aSDavide Italiano return s 140205fd03aSDavide Italiano 141205fd03aSDavide Italiano def _coerce_send_string(self, s): 142205fd03aSDavide Italiano if self.encoding is None and not isinstance(s, bytes): 143205fd03aSDavide Italiano return s.encode('utf-8') 144205fd03aSDavide Italiano return s 145205fd03aSDavide Italiano 146205fd03aSDavide Italiano def _get_buffer(self): 147205fd03aSDavide Italiano return self._buffer.getvalue() 148205fd03aSDavide Italiano 149205fd03aSDavide Italiano def _set_buffer(self, value): 150205fd03aSDavide Italiano self._buffer = self.buffer_type() 151205fd03aSDavide Italiano self._buffer.write(value) 152205fd03aSDavide Italiano 153e9264b74SKazuaki Ishizaki # This property is provided for backwards compatibility (self.buffer used 154205fd03aSDavide Italiano # to be a string/bytes object) 155205fd03aSDavide Italiano buffer = property(_get_buffer, _set_buffer) 156205fd03aSDavide Italiano 157205fd03aSDavide Italiano def read_nonblocking(self, size=1, timeout=None): 158205fd03aSDavide Italiano """This reads data from the file descriptor. 159205fd03aSDavide Italiano 160205fd03aSDavide Italiano This is a simple implementation suitable for a regular file. Subclasses using ptys or pipes should override it. 161205fd03aSDavide Italiano 162205fd03aSDavide Italiano The timeout parameter is ignored. 163205fd03aSDavide Italiano """ 164205fd03aSDavide Italiano 165205fd03aSDavide Italiano try: 166205fd03aSDavide Italiano s = os.read(self.child_fd, size) 167205fd03aSDavide Italiano except OSError as err: 168205fd03aSDavide Italiano if err.args[0] == errno.EIO: 169205fd03aSDavide Italiano # Linux-style EOF 170205fd03aSDavide Italiano self.flag_eof = True 171205fd03aSDavide Italiano raise EOF('End Of File (EOF). Exception style platform.') 172205fd03aSDavide Italiano raise 173205fd03aSDavide Italiano if s == b'': 174205fd03aSDavide Italiano # BSD-style EOF 175205fd03aSDavide Italiano self.flag_eof = True 176205fd03aSDavide Italiano raise EOF('End Of File (EOF). Empty string style platform.') 177205fd03aSDavide Italiano 178205fd03aSDavide Italiano s = self._decoder.decode(s, final=False) 179205fd03aSDavide Italiano self._log(s, 'read') 180205fd03aSDavide Italiano return s 181205fd03aSDavide Italiano 182205fd03aSDavide Italiano def _pattern_type_err(self, pattern): 183205fd03aSDavide Italiano raise TypeError('got {badtype} ({badobj!r}) as pattern, must be one' 184205fd03aSDavide Italiano ' of: {goodtypes}, pexpect.EOF, pexpect.TIMEOUT'\ 185205fd03aSDavide Italiano .format(badtype=type(pattern), 186205fd03aSDavide Italiano badobj=pattern, 187205fd03aSDavide Italiano goodtypes=', '.join([str(ast)\ 188205fd03aSDavide Italiano for ast in self.allowed_string_types]) 189205fd03aSDavide Italiano ) 190205fd03aSDavide Italiano ) 191205fd03aSDavide Italiano 192205fd03aSDavide Italiano def compile_pattern_list(self, patterns): 193205fd03aSDavide Italiano '''This compiles a pattern-string or a list of pattern-strings. 194205fd03aSDavide Italiano Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of 195205fd03aSDavide Italiano those. Patterns may also be None which results in an empty list (you 196205fd03aSDavide Italiano might do this if waiting for an EOF or TIMEOUT condition without 197205fd03aSDavide Italiano expecting any pattern). 198205fd03aSDavide Italiano 199205fd03aSDavide Italiano This is used by expect() when calling expect_list(). Thus expect() is 200205fd03aSDavide Italiano nothing more than:: 201205fd03aSDavide Italiano 202205fd03aSDavide Italiano cpl = self.compile_pattern_list(pl) 203205fd03aSDavide Italiano return self.expect_list(cpl, timeout) 204205fd03aSDavide Italiano 205205fd03aSDavide Italiano If you are using expect() within a loop it may be more 206205fd03aSDavide Italiano efficient to compile the patterns first and then call expect_list(). 207205fd03aSDavide Italiano This avoid calls in a loop to compile_pattern_list():: 208205fd03aSDavide Italiano 209205fd03aSDavide Italiano cpl = self.compile_pattern_list(my_pattern) 210205fd03aSDavide Italiano while some_condition: 211205fd03aSDavide Italiano ... 212205fd03aSDavide Italiano i = self.expect_list(cpl, timeout) 213205fd03aSDavide Italiano ... 214205fd03aSDavide Italiano ''' 215205fd03aSDavide Italiano 216205fd03aSDavide Italiano if patterns is None: 217205fd03aSDavide Italiano return [] 218205fd03aSDavide Italiano if not isinstance(patterns, list): 219205fd03aSDavide Italiano patterns = [patterns] 220205fd03aSDavide Italiano 221205fd03aSDavide Italiano # Allow dot to match \n 222205fd03aSDavide Italiano compile_flags = re.DOTALL 223205fd03aSDavide Italiano if self.ignorecase: 224205fd03aSDavide Italiano compile_flags = compile_flags | re.IGNORECASE 225205fd03aSDavide Italiano compiled_pattern_list = [] 226205fd03aSDavide Italiano for idx, p in enumerate(patterns): 227205fd03aSDavide Italiano if isinstance(p, self.allowed_string_types): 228205fd03aSDavide Italiano p = self._coerce_expect_string(p) 229205fd03aSDavide Italiano compiled_pattern_list.append(re.compile(p, compile_flags)) 230205fd03aSDavide Italiano elif p is EOF: 231205fd03aSDavide Italiano compiled_pattern_list.append(EOF) 232205fd03aSDavide Italiano elif p is TIMEOUT: 233205fd03aSDavide Italiano compiled_pattern_list.append(TIMEOUT) 234205fd03aSDavide Italiano elif isinstance(p, type(re.compile(''))): 235205fd03aSDavide Italiano compiled_pattern_list.append(p) 236205fd03aSDavide Italiano else: 237205fd03aSDavide Italiano self._pattern_type_err(p) 238205fd03aSDavide Italiano return compiled_pattern_list 239205fd03aSDavide Italiano 240205fd03aSDavide Italiano def expect(self, pattern, timeout=-1, searchwindowsize=-1, async_=False, **kw): 241205fd03aSDavide Italiano '''This seeks through the stream until a pattern is matched. The 242205fd03aSDavide Italiano pattern is overloaded and may take several types. The pattern can be a 243205fd03aSDavide Italiano StringType, EOF, a compiled re, or a list of any of those types. 244205fd03aSDavide Italiano Strings will be compiled to re types. This returns the index into the 245205fd03aSDavide Italiano pattern list. If the pattern was not a list this returns index 0 on a 246205fd03aSDavide Italiano successful match. This may raise exceptions for EOF or TIMEOUT. To 247205fd03aSDavide Italiano avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern 248205fd03aSDavide Italiano list. That will cause expect to match an EOF or TIMEOUT condition 249205fd03aSDavide Italiano instead of raising an exception. 250205fd03aSDavide Italiano 251205fd03aSDavide Italiano If you pass a list of patterns and more than one matches, the first 252205fd03aSDavide Italiano match in the stream is chosen. If more than one pattern matches at that 253205fd03aSDavide Italiano point, the leftmost in the pattern list is chosen. For example:: 254205fd03aSDavide Italiano 255205fd03aSDavide Italiano # the input is 'foobar' 256205fd03aSDavide Italiano index = p.expect(['bar', 'foo', 'foobar']) 257205fd03aSDavide Italiano # returns 1('foo') even though 'foobar' is a "better" match 258205fd03aSDavide Italiano 259205fd03aSDavide Italiano Please note, however, that buffering can affect this behavior, since 260205fd03aSDavide Italiano input arrives in unpredictable chunks. For example:: 261205fd03aSDavide Italiano 262205fd03aSDavide Italiano # the input is 'foobar' 263205fd03aSDavide Italiano index = p.expect(['foobar', 'foo']) 264205fd03aSDavide Italiano # returns 0('foobar') if all input is available at once, 265205fd03aSDavide Italiano # but returns 1('foo') if parts of the final 'bar' arrive late 266205fd03aSDavide Italiano 267205fd03aSDavide Italiano When a match is found for the given pattern, the class instance 268205fd03aSDavide Italiano attribute *match* becomes an re.MatchObject result. Should an EOF 269205fd03aSDavide Italiano or TIMEOUT pattern match, then the match attribute will be an instance 270205fd03aSDavide Italiano of that exception class. The pairing before and after class 271205fd03aSDavide Italiano instance attributes are views of the data preceding and following 272205fd03aSDavide Italiano the matching pattern. On general exception, class attribute 273205fd03aSDavide Italiano *before* is all data received up to the exception, while *match* and 274205fd03aSDavide Italiano *after* attributes are value None. 275205fd03aSDavide Italiano 276205fd03aSDavide Italiano When the keyword argument timeout is -1 (default), then TIMEOUT will 277205fd03aSDavide Italiano raise after the default value specified by the class timeout 278205fd03aSDavide Italiano attribute. When None, TIMEOUT will not be raised and may block 279205fd03aSDavide Italiano indefinitely until match. 280205fd03aSDavide Italiano 281205fd03aSDavide Italiano When the keyword argument searchwindowsize is -1 (default), then the 282205fd03aSDavide Italiano value specified by the class maxread attribute is used. 283205fd03aSDavide Italiano 284205fd03aSDavide Italiano A list entry may be EOF or TIMEOUT instead of a string. This will 285205fd03aSDavide Italiano catch these exceptions and return the index of the list entry instead 286205fd03aSDavide Italiano of raising the exception. The attribute 'after' will be set to the 287205fd03aSDavide Italiano exception type. The attribute 'match' will be None. This allows you to 288205fd03aSDavide Italiano write code like this:: 289205fd03aSDavide Italiano 290205fd03aSDavide Italiano index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT]) 291205fd03aSDavide Italiano if index == 0: 292205fd03aSDavide Italiano do_something() 293205fd03aSDavide Italiano elif index == 1: 294205fd03aSDavide Italiano do_something_else() 295205fd03aSDavide Italiano elif index == 2: 296205fd03aSDavide Italiano do_some_other_thing() 297205fd03aSDavide Italiano elif index == 3: 298205fd03aSDavide Italiano do_something_completely_different() 299205fd03aSDavide Italiano 300205fd03aSDavide Italiano instead of code like this:: 301205fd03aSDavide Italiano 302205fd03aSDavide Italiano try: 303205fd03aSDavide Italiano index = p.expect(['good', 'bad']) 304205fd03aSDavide Italiano if index == 0: 305205fd03aSDavide Italiano do_something() 306205fd03aSDavide Italiano elif index == 1: 307205fd03aSDavide Italiano do_something_else() 308205fd03aSDavide Italiano except EOF: 309205fd03aSDavide Italiano do_some_other_thing() 310205fd03aSDavide Italiano except TIMEOUT: 311205fd03aSDavide Italiano do_something_completely_different() 312205fd03aSDavide Italiano 313205fd03aSDavide Italiano These two forms are equivalent. It all depends on what you want. You 314205fd03aSDavide Italiano can also just expect the EOF if you are waiting for all output of a 315205fd03aSDavide Italiano child to finish. For example:: 316205fd03aSDavide Italiano 317205fd03aSDavide Italiano p = pexpect.spawn('/bin/ls') 318205fd03aSDavide Italiano p.expect(pexpect.EOF) 319205fd03aSDavide Italiano print p.before 320205fd03aSDavide Italiano 321205fd03aSDavide Italiano If you are trying to optimize for speed then see expect_list(). 322205fd03aSDavide Italiano 323205fd03aSDavide Italiano On Python 3.4, or Python 3.3 with asyncio installed, passing 324205fd03aSDavide Italiano ``async_=True`` will make this return an :mod:`asyncio` coroutine, 325205fd03aSDavide Italiano which you can yield from to get the same result that this method would 326205fd03aSDavide Italiano normally give directly. So, inside a coroutine, you can replace this code:: 327205fd03aSDavide Italiano 328205fd03aSDavide Italiano index = p.expect(patterns) 329205fd03aSDavide Italiano 330205fd03aSDavide Italiano With this non-blocking form:: 331205fd03aSDavide Italiano 332205fd03aSDavide Italiano index = yield from p.expect(patterns, async_=True) 333205fd03aSDavide Italiano ''' 334205fd03aSDavide Italiano if 'async' in kw: 335205fd03aSDavide Italiano async_ = kw.pop('async') 336205fd03aSDavide Italiano if kw: 337205fd03aSDavide Italiano raise TypeError("Unknown keyword arguments: {}".format(kw)) 338205fd03aSDavide Italiano 339205fd03aSDavide Italiano compiled_pattern_list = self.compile_pattern_list(pattern) 340205fd03aSDavide Italiano return self.expect_list(compiled_pattern_list, 341205fd03aSDavide Italiano timeout, searchwindowsize, async_) 342205fd03aSDavide Italiano 343205fd03aSDavide Italiano def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1, 344205fd03aSDavide Italiano async_=False, **kw): 345205fd03aSDavide Italiano '''This takes a list of compiled regular expressions and returns the 346205fd03aSDavide Italiano index into the pattern_list that matched the child output. The list may 347205fd03aSDavide Italiano also contain EOF or TIMEOUT(which are not compiled regular 348205fd03aSDavide Italiano expressions). This method is similar to the expect() method except that 349205fd03aSDavide Italiano expect_list() does not recompile the pattern list on every call. This 350205fd03aSDavide Italiano may help if you are trying to optimize for speed, otherwise just use 351205fd03aSDavide Italiano the expect() method. This is called by expect(). 352205fd03aSDavide Italiano 353205fd03aSDavide Italiano 354205fd03aSDavide Italiano Like :meth:`expect`, passing ``async_=True`` will make this return an 355205fd03aSDavide Italiano asyncio coroutine. 356205fd03aSDavide Italiano ''' 357205fd03aSDavide Italiano if timeout == -1: 358205fd03aSDavide Italiano timeout = self.timeout 359205fd03aSDavide Italiano if 'async' in kw: 360205fd03aSDavide Italiano async_ = kw.pop('async') 361205fd03aSDavide Italiano if kw: 362205fd03aSDavide Italiano raise TypeError("Unknown keyword arguments: {}".format(kw)) 363205fd03aSDavide Italiano 364205fd03aSDavide Italiano exp = Expecter(self, searcher_re(pattern_list), searchwindowsize) 365205fd03aSDavide Italiano if async_: 366205fd03aSDavide Italiano from ._async import expect_async 367205fd03aSDavide Italiano return expect_async(exp, timeout) 368205fd03aSDavide Italiano else: 369205fd03aSDavide Italiano return exp.expect_loop(timeout) 370205fd03aSDavide Italiano 371205fd03aSDavide Italiano def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1, 372205fd03aSDavide Italiano async_=False, **kw): 373205fd03aSDavide Italiano 374205fd03aSDavide Italiano '''This is similar to expect(), but uses plain string matching instead 375205fd03aSDavide Italiano of compiled regular expressions in 'pattern_list'. The 'pattern_list' 376205fd03aSDavide Italiano may be a string; a list or other sequence of strings; or TIMEOUT and 377205fd03aSDavide Italiano EOF. 378205fd03aSDavide Italiano 379205fd03aSDavide Italiano This call might be faster than expect() for two reasons: string 380205fd03aSDavide Italiano searching is faster than RE matching and it is possible to limit the 381205fd03aSDavide Italiano search to just the end of the input buffer. 382205fd03aSDavide Italiano 383205fd03aSDavide Italiano This method is also useful when you don't want to have to worry about 384205fd03aSDavide Italiano escaping regular expression characters that you want to match. 385205fd03aSDavide Italiano 386205fd03aSDavide Italiano Like :meth:`expect`, passing ``async_=True`` will make this return an 387205fd03aSDavide Italiano asyncio coroutine. 388205fd03aSDavide Italiano ''' 389205fd03aSDavide Italiano if timeout == -1: 390205fd03aSDavide Italiano timeout = self.timeout 391205fd03aSDavide Italiano if 'async' in kw: 392205fd03aSDavide Italiano async_ = kw.pop('async') 393205fd03aSDavide Italiano if kw: 394205fd03aSDavide Italiano raise TypeError("Unknown keyword arguments: {}".format(kw)) 395205fd03aSDavide Italiano 396205fd03aSDavide Italiano if (isinstance(pattern_list, self.allowed_string_types) or 397205fd03aSDavide Italiano pattern_list in (TIMEOUT, EOF)): 398205fd03aSDavide Italiano pattern_list = [pattern_list] 399205fd03aSDavide Italiano 400205fd03aSDavide Italiano def prepare_pattern(pattern): 401205fd03aSDavide Italiano if pattern in (TIMEOUT, EOF): 402205fd03aSDavide Italiano return pattern 403205fd03aSDavide Italiano if isinstance(pattern, self.allowed_string_types): 404205fd03aSDavide Italiano return self._coerce_expect_string(pattern) 405205fd03aSDavide Italiano self._pattern_type_err(pattern) 406205fd03aSDavide Italiano 407205fd03aSDavide Italiano try: 408205fd03aSDavide Italiano pattern_list = iter(pattern_list) 409205fd03aSDavide Italiano except TypeError: 410205fd03aSDavide Italiano self._pattern_type_err(pattern_list) 411205fd03aSDavide Italiano pattern_list = [prepare_pattern(p) for p in pattern_list] 412205fd03aSDavide Italiano 413205fd03aSDavide Italiano exp = Expecter(self, searcher_string(pattern_list), searchwindowsize) 414205fd03aSDavide Italiano if async_: 415205fd03aSDavide Italiano from ._async import expect_async 416205fd03aSDavide Italiano return expect_async(exp, timeout) 417205fd03aSDavide Italiano else: 418205fd03aSDavide Italiano return exp.expect_loop(timeout) 419205fd03aSDavide Italiano 420205fd03aSDavide Italiano def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1): 421205fd03aSDavide Italiano '''This is the common loop used inside expect. The 'searcher' should be 422205fd03aSDavide Italiano an instance of searcher_re or searcher_string, which describes how and 423205fd03aSDavide Italiano what to search for in the input. 424205fd03aSDavide Italiano 425205fd03aSDavide Italiano See expect() for other arguments, return value and exceptions. ''' 426205fd03aSDavide Italiano 427205fd03aSDavide Italiano exp = Expecter(self, searcher, searchwindowsize) 428205fd03aSDavide Italiano return exp.expect_loop(timeout) 429205fd03aSDavide Italiano 430205fd03aSDavide Italiano def read(self, size=-1): 431205fd03aSDavide Italiano '''This reads at most "size" bytes from the file (less if the read hits 432205fd03aSDavide Italiano EOF before obtaining size bytes). If the size argument is negative or 433205fd03aSDavide Italiano omitted, read all data until EOF is reached. The bytes are returned as 434205fd03aSDavide Italiano a string object. An empty string is returned when EOF is encountered 435205fd03aSDavide Italiano immediately. ''' 436205fd03aSDavide Italiano 437205fd03aSDavide Italiano if size == 0: 438205fd03aSDavide Italiano return self.string_type() 439205fd03aSDavide Italiano if size < 0: 440205fd03aSDavide Italiano # delimiter default is EOF 441205fd03aSDavide Italiano self.expect(self.delimiter) 442205fd03aSDavide Italiano return self.before 443205fd03aSDavide Italiano 444205fd03aSDavide Italiano # I could have done this more directly by not using expect(), but 445205fd03aSDavide Italiano # I deliberately decided to couple read() to expect() so that 446205fd03aSDavide Italiano # I would catch any bugs early and ensure consistent behavior. 447205fd03aSDavide Italiano # It's a little less efficient, but there is less for me to 448205fd03aSDavide Italiano # worry about if I have to later modify read() or expect(). 449205fd03aSDavide Italiano # Note, it's OK if size==-1 in the regex. That just means it 450205fd03aSDavide Italiano # will never match anything in which case we stop only on EOF. 451205fd03aSDavide Italiano cre = re.compile(self._coerce_expect_string('.{%d}' % size), re.DOTALL) 452205fd03aSDavide Italiano # delimiter default is EOF 453205fd03aSDavide Italiano index = self.expect([cre, self.delimiter]) 454205fd03aSDavide Italiano if index == 0: 455205fd03aSDavide Italiano ### FIXME self.before should be ''. Should I assert this? 456205fd03aSDavide Italiano return self.after 457205fd03aSDavide Italiano return self.before 458205fd03aSDavide Italiano 459205fd03aSDavide Italiano def readline(self, size=-1): 460205fd03aSDavide Italiano '''This reads and returns one entire line. The newline at the end of 461205fd03aSDavide Italiano line is returned as part of the string, unless the file ends without a 462205fd03aSDavide Italiano newline. An empty string is returned if EOF is encountered immediately. 463205fd03aSDavide Italiano This looks for a newline as a CR/LF pair (\\r\\n) even on UNIX because 464205fd03aSDavide Italiano this is what the pseudotty device returns. So contrary to what you may 465205fd03aSDavide Italiano expect you will receive newlines as \\r\\n. 466205fd03aSDavide Italiano 467205fd03aSDavide Italiano If the size argument is 0 then an empty string is returned. In all 468205fd03aSDavide Italiano other cases the size argument is ignored, which is not standard 469205fd03aSDavide Italiano behavior for a file-like object. ''' 470205fd03aSDavide Italiano 471205fd03aSDavide Italiano if size == 0: 472205fd03aSDavide Italiano return self.string_type() 473205fd03aSDavide Italiano # delimiter default is EOF 474205fd03aSDavide Italiano index = self.expect([self.crlf, self.delimiter]) 475205fd03aSDavide Italiano if index == 0: 476205fd03aSDavide Italiano return self.before + self.crlf 477205fd03aSDavide Italiano else: 478205fd03aSDavide Italiano return self.before 479205fd03aSDavide Italiano 480205fd03aSDavide Italiano def __iter__(self): 481205fd03aSDavide Italiano '''This is to support iterators over a file-like object. 482205fd03aSDavide Italiano ''' 483205fd03aSDavide Italiano return iter(self.readline, self.string_type()) 484205fd03aSDavide Italiano 485205fd03aSDavide Italiano def readlines(self, sizehint=-1): 486205fd03aSDavide Italiano '''This reads until EOF using readline() and returns a list containing 487205fd03aSDavide Italiano the lines thus read. The optional 'sizehint' argument is ignored. 488205fd03aSDavide Italiano Remember, because this reads until EOF that means the child 489205fd03aSDavide Italiano process should have closed its stdout. If you run this method on 490205fd03aSDavide Italiano a child that is still running with its stdout open then this 491205fd03aSDavide Italiano method will block until it timesout.''' 492205fd03aSDavide Italiano 493205fd03aSDavide Italiano lines = [] 494205fd03aSDavide Italiano while True: 495205fd03aSDavide Italiano line = self.readline() 496205fd03aSDavide Italiano if not line: 497205fd03aSDavide Italiano break 498205fd03aSDavide Italiano lines.append(line) 499205fd03aSDavide Italiano return lines 500205fd03aSDavide Italiano 501205fd03aSDavide Italiano def fileno(self): 502205fd03aSDavide Italiano '''Expose file descriptor for a file-like interface 503205fd03aSDavide Italiano ''' 504205fd03aSDavide Italiano return self.child_fd 505205fd03aSDavide Italiano 506205fd03aSDavide Italiano def flush(self): 507205fd03aSDavide Italiano '''This does nothing. It is here to support the interface for a 508205fd03aSDavide Italiano File-like object. ''' 509205fd03aSDavide Italiano pass 510205fd03aSDavide Italiano 511205fd03aSDavide Italiano def isatty(self): 512205fd03aSDavide Italiano """Overridden in subclass using tty""" 513205fd03aSDavide Italiano return False 514205fd03aSDavide Italiano 515205fd03aSDavide Italiano # For 'with spawn(...) as child:' 516205fd03aSDavide Italiano def __enter__(self): 517205fd03aSDavide Italiano return self 518205fd03aSDavide Italiano 519205fd03aSDavide Italiano def __exit__(self, etype, evalue, tb): 520205fd03aSDavide Italiano # We rely on subclasses to implement close(). If they don't, it's not 521205fd03aSDavide Italiano # clear what a context manager should do. 522205fd03aSDavide Italiano self.close() 523