|
@@
-9,17
+9,19
b' use C, Expect, or TCL extensions. It should work on any platform that supports'
|
|
9
|
the standard Python pty module. The Pexpect interface focuses on ease of use so
|
|
9
|
the standard Python pty module. The Pexpect interface focuses on ease of use so
|
|
10
|
that simple tasks are easy.
|
|
10
|
that simple tasks are easy.
|
|
11
|
|
|
11
|
|
|
12
|
There are two main interfaces to Pexpect -- the function, run() and the class,
|
|
12
|
There are two main interfaces to the Pexpect system; these are the function,
|
|
13
|
spawn. You can call the run() function to execute a command and return the
|
|
13
|
run() and the class, spawn. The spawn class is more powerful. The run()
|
|
|
|
|
14
|
function is simpler than spawn, and is good for quickly calling program. When
|
|
|
|
|
15
|
you call the run() function it executes a given program and then returns the
|
|
14
|
output. This is a handy replacement for os.system().
|
|
16
|
output. This is a handy replacement for os.system().
|
|
15
|
|
|
17
|
|
|
16
|
For example::
|
|
18
|
For example::
|
|
17
|
|
|
19
|
|
|
18
|
pexpect.run('ls -la')
|
|
20
|
pexpect.run('ls -la')
|
|
19
|
|
|
21
|
|
|
20
|
The more powerful interface is the spawn class. You can use this to spawn an
|
|
22
|
The spawn class is the more powerful interface to the Pexpect system. You can
|
|
21
|
external child command and then interact with the child by sending lines and
|
|
23
|
use this to spawn a child program then interact with it by sending input and
|
|
22
|
expecting responses.
|
|
24
|
expecting responses (waiting for patterns in the child's output).
|
|
23
|
|
|
25
|
|
|
24
|
For example::
|
|
26
|
For example::
|
|
25
|
|
|
27
|
|
|
@@
-28,16
+30,18
b' For example::'
|
|
28
|
child.sendline (mypassword)
|
|
30
|
child.sendline (mypassword)
|
|
29
|
|
|
31
|
|
|
30
|
This works even for commands that ask for passwords or other input outside of
|
|
32
|
This works even for commands that ask for passwords or other input outside of
|
|
31
|
the normal stdio streams.
|
|
33
|
the normal stdio streams. For example, ssh reads input directly from the TTY
|
|
|
|
|
34
|
device which bypasses stdin.
|
|
32
|
|
|
35
|
|
|
33
|
Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
|
|
36
|
Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
|
|
34
|
Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
|
|
37
|
Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
|
|
35
|
vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
|
|
38
|
vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
|
|
36
|
Geoffrey Marshall, Francisco Lourenco, Glen Mabey, Karthik Gurusamy, Fernando
|
|
39
|
Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey,
|
|
37
|
Perez, Corey Minyard, Jon Cohen, Guillaume Chazarain, Andrew Ryan, Nick
|
|
40
|
Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume
|
|
38
|
Craig-Wood, Andrew Stone, Jorgen Grahn (Let me know if I forgot anyone.)
|
|
41
|
Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John
|
|
|
|
|
42
|
Spiegel, Jan Grant, Shane Kerr and Thomas Kluyver. Let me know if I forgot anyone.
|
|
39
|
|
|
43
|
|
|
40
|
Free, open source, and all that good stuff.
|
|
44
|
Pexpect is free, open source, and all that good stuff.
|
|
41
|
|
|
45
|
|
|
42
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
46
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
43
|
this software and associated documentation files (the "Software"), to deal in
|
|
47
|
this software and associated documentation files (the "Software"), to deal in
|
|
@@
-57,10
+61,8
b' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,'
|
|
57
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
61
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
58
|
SOFTWARE.
|
|
62
|
SOFTWARE.
|
|
59
|
|
|
63
|
|
|
60
|
Pexpect Copyright (c) 2008 Noah Spurrier
|
|
64
|
Pexpect Copyright (c) 2008-2011 Noah Spurrier
|
|
61
|
http://pexpect.sourceforge.net/
|
|
65
|
http://pexpect.sourceforge.net/
|
|
62
|
|
|
|
|
|
63
|
$Id: pexpect.py 507 2007-12-27 02:40:52Z noah $
|
|
|
|
|
64
|
"""
|
|
66
|
"""
|
|
65
|
|
|
67
|
|
|
66
|
try:
|
|
68
|
try:
|
|
@@
-83,10
+85,11
b' except ImportError, e:'
|
|
83
|
A critical module was not found. Probably this operating system does not
|
|
85
|
A critical module was not found. Probably this operating system does not
|
|
84
|
support it. Pexpect is intended for UNIX-like operating systems.""")
|
|
86
|
support it. Pexpect is intended for UNIX-like operating systems.""")
|
|
85
|
|
|
87
|
|
|
86
|
__version__ = '2.3'
|
|
88
|
__version__ = '2.6.dev'
|
|
87
|
__revision__ = '$Revision: 399 $'
|
|
89
|
version = __version__
|
|
88
|
__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run', 'which',
|
|
90
|
version_info = (2,6,'dev')
|
|
89
|
'split_command_line', '__version__', '__revision__']
|
|
91
|
__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnb', 'run', 'which',
|
|
|
|
|
92
|
'split_command_line', '__version__']
|
|
90
|
|
|
93
|
|
|
91
|
# Exception classes used by this module.
|
|
94
|
# Exception classes used by this module.
|
|
92
|
class ExceptionPexpect(Exception):
|
|
95
|
class ExceptionPexpect(Exception):
|
|
@@
-140,7
+143,22
b' class TIMEOUT(ExceptionPexpect):'
|
|
140
|
##class MAXBUFFER(ExceptionPexpect):
|
|
143
|
##class MAXBUFFER(ExceptionPexpect):
|
|
141
|
## """Raised when a scan buffer fills before matching an expected pattern."""
|
|
144
|
## """Raised when a scan buffer fills before matching an expected pattern."""
|
|
142
|
|
|
145
|
|
|
143
|
def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None, logfile=None, cwd=None, env=None):
|
|
146
|
PY3 = (sys.version_info[0] >= 3)
|
|
|
|
|
147
|
|
|
|
|
|
148
|
def _cast_bytes(s, enc):
|
|
|
|
|
149
|
if isinstance(s, unicode):
|
|
|
|
|
150
|
return s.encode(enc)
|
|
|
|
|
151
|
return s
|
|
|
|
|
152
|
|
|
|
|
|
153
|
def _cast_unicode(s, enc):
|
|
|
|
|
154
|
if isinstance(s, bytes):
|
|
|
|
|
155
|
return s.decode(enc)
|
|
|
|
|
156
|
return s
|
|
|
|
|
157
|
|
|
|
|
|
158
|
re_type = type(re.compile(''))
|
|
|
|
|
159
|
|
|
|
|
|
160
|
def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None,
|
|
|
|
|
161
|
logfile=None, cwd=None, env=None, encoding='utf-8'):
|
|
144
|
|
|
162
|
|
|
145
|
"""
|
|
163
|
"""
|
|
146
|
This function runs the given command; waits for it to finish; then
|
|
164
|
This function runs the given command; waits for it to finish; then
|
|
@@
-215,9
+233,11
b' def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None'
|
|
215
|
dictionary passed to a callback. """
|
|
233
|
dictionary passed to a callback."""
|
|
216
|
|
|
234
|
|
|
217
|
if timeout == -1:
|
|
235
|
if timeout == -1:
|
|
218
|
child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env)
|
|
236
|
child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env,
|
|
|
|
|
237
|
encoding=encoding)
|
|
219
|
else:
|
|
238
|
else:
|
|
220
|
child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, cwd=cwd, env=env)
|
|
239
|
child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile,
|
|
|
|
|
240
|
cwd=cwd, env=env, encoding=encoding)
|
|
221
|
if events is not None:
|
|
241
|
if events is not None:
|
|
222
|
patterns = events.keys()
|
|
242
|
patterns = events.keys()
|
|
223
|
responses = events.values()
|
|
243
|
responses = events.values()
|
|
@@
-235,7
+255,7
b' def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None'
|
|
235
|
child_result_list.append(child.before)
|
|
255
|
child_result_list.append(child.before)
|
|
236
|
if isinstance(responses[index], basestring):
|
|
256
|
if isinstance(responses[index], basestring):
|
|
237
|
child.send(responses[index])
|
|
257
|
child.send(responses[index])
|
|
238
|
elif isinstance(responses[index], types.FunctionType):
|
|
258
|
elif type(responses[index]) is types.FunctionType:
|
|
239
|
callback_result = responses[index](locals())
|
|
259
|
callback_result = responses[index](locals())
|
|
240
|
sys.stdout.flush()
|
|
260
|
sys.stdout.flush()
|
|
241
|
if isinstance(callback_result, basestring):
|
|
261
|
if isinstance(callback_result, basestring):
|
|
@@
-251,19
+271,28
b' def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None'
|
|
251
|
except EOF, e:
|
|
271
|
except EOF, e:
|
|
252
|
child_result_list.append(child.before)
|
|
272
|
child_result_list.append(child.before)
|
|
253
|
break
|
|
273
|
break
|
|
254
|
child_result = ''.join(child_result_list)
|
|
274
|
child_result = child._empty_buffer.join(child_result_list)
|
|
255
|
if withexitstatus:
|
|
275
|
if withexitstatus:
|
|
256
|
child.close()
|
|
276
|
child.close()
|
|
257
|
return (child_result, child.exitstatus)
|
|
277
|
return (child_result, child.exitstatus)
|
|
258
|
else:
|
|
278
|
else:
|
|
259
|
return child_result
|
|
279
|
return child_result
|
|
260
|
|
|
280
|
|
|
261
|
class spawn (object):
|
|
281
|
class spawnb(object):
|
|
|
|
|
282
|
"""Use this class to start and control child applications with a pure-bytes
|
|
|
|
|
283
|
interface."""
|
|
262
|
|
|
284
|
|
|
263
|
"""This is the main class interface for Pexpect. Use this class to start
|
|
285
|
_buffer_type = bytes
|
|
264
|
and control child applications. """
|
|
286
|
def _cast_buffer_type(self, s):
|
|
|
|
|
287
|
return _cast_bytes(s, self.encoding)
|
|
|
|
|
288
|
_empty_buffer = b''
|
|
|
|
|
289
|
_pty_newline = b'\r\n'
|
|
265
|
|
|
290
|
|
|
266
|
def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None):
|
|
291
|
# Some code needs this to exist, but it's mainly for the spawn subclass.
|
|
|
|
|
292
|
encoding = 'utf-8'
|
|
|
|
|
293
|
|
|
|
|
|
294
|
def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None,
|
|
|
|
|
295
|
logfile=None, cwd=None, env=None):
|
|
267
|
|
|
296
|
|
|
268
|
"""This is the constructor. The command parameter may be a string that
|
|
297
|
"""This is the constructor. The command parameter may be a string that
|
|
269
|
includes a command and any arguments to the command. For example::
|
|
298
|
includes a command and any arguments to the command. For example::
|
|
@@
-399,7
+428,7
b' class spawn (object):'
|
|
399
|
self.logfile_read = None # input from child (read_nonblocking)
|
|
428
|
self.logfile_read = None # input from child (read_nonblocking)
|
|
400
|
self.logfile_send = None # output to send (send, sendline)
|
|
429
|
self.logfile_send = None # output to send (send, sendline)
|
|
401
|
self.maxread = maxread # max bytes to read at one time into buffer
|
|
430
|
self.maxread = maxread # max bytes to read at one time into buffer
|
|
402
|
self.buffer = b'' # This is the read buffer. See maxread.
|
|
431
|
self.buffer = self._empty_buffer # This is the read buffer. See maxread.
|
|
403
|
self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched.
|
|
432
|
self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched.
|
|
404
|
# Most Linux machines don't like delaybeforesend to be below 0.03 (30 ms).
|
|
433
|
# Most Linux machines don't like delaybeforesend to be below 0.03 (30 ms).
|
|
405
|
self.delaybeforesend = 0.05 # Sets sleep time used just before sending data to child. Time in seconds.
|
|
434
|
self.delaybeforesend = 0.05 # Sets sleep time used just before sending data to child. Time in seconds.
|
|
@@
-407,13
+436,12
b' class spawn (object):'
|
|
407
|
self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds.
|
|
436
|
self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds.
|
|
408
|
self.softspace = False # File-like object.
|
|
437
|
self.softspace = False # File-like object.
|
|
409
|
self.name = '<' + repr(self) + '>' # File-like object.
|
|
438
|
self.name = '<' + repr(self) + '>' # File-like object.
|
|
410
|
self.encoding = None # File-like object.
|
|
|
|
|
411
|
self.closed = True # File-like object.
|
|
439
|
self.closed = True # File-like object.
|
|
412
|
self.cwd = cwd
|
|
440
|
self.cwd = cwd
|
|
413
|
self.env = env
|
|
441
|
self.env = env
|
|
414
|
self.__irix_hack = (sys.platform.lower().find('irix')>=0) # This flags if we are running on irix
|
|
442
|
self.__irix_hack = (sys.platform.lower().find('irix')>=0) # This flags if we are running on irix
|
|
415
|
# Solaris uses internal __fork_pty(). All others use pty.fork().
|
|
443
|
# Solaris uses internal __fork_pty(). All others use pty.fork().
|
|
416
|
if (sys.platform.lower().find('solaris')>=0) or (sys.platform.lower().find('sunos5')>=0):
|
|
444
|
if 'solaris' in sys.platform.lower() or 'sunos5' in sys.platform.lower():
|
|
417
|
self.use_native_pty_fork = False
|
|
445
|
self.use_native_pty_fork = False
|
|
418
|
else:
|
|
446
|
else:
|
|
419
|
self.use_native_pty_fork = True
|
|
447
|
self.use_native_pty_fork = True
|
|
@@
-442,7
+470,7
b' class spawn (object):'
|
|
442
|
# -- Fernando Perez
|
|
470
|
# -- Fernando Perez
|
|
443
|
try:
|
|
471
|
try:
|
|
444
|
self.close()
|
|
472
|
self.close()
|
|
445
|
except AttributeError:
|
|
473
|
except:
|
|
446
|
pass
|
|
474
|
pass
|
|
447
|
|
|
475
|
|
|
448
|
def __str__(self):
|
|
476
|
def __str__(self):
|
|
@@
-452,7
+480,7
b' class spawn (object):'
|
|
452
|
|
|
480
|
|
|
453
|
s = []
|
|
481
|
s = []
|
|
454
|
s.append(repr(self))
|
|
482
|
s.append(repr(self))
|
|
455
|
s.append('version: ' + __version__ + ' (' + __revision__ + ')')
|
|
483
|
s.append('version: ' + __version__)
|
|
456
|
s.append('command: ' + str(self.command))
|
|
484
|
s.append('command: ' + str(self.command))
|
|
457
|
s.append('args: ' + str(self.args))
|
|
485
|
s.append('args: ' + str(self.args))
|
|
458
|
s.append('searcher: ' + str(self.searcher))
|
|
486
|
s.append('searcher: ' + str(self.searcher))
|
|
@@
-610,19
+638,24
b' class spawn (object):'
|
|
610
|
|
|
638
|
|
|
611
|
child_name = os.ttyname(tty_fd)
|
|
639
|
child_name = os.ttyname(tty_fd)
|
|
612
|
|
|
640
|
|
|
613
|
# Disconnect from controlling tty if still connected.
|
|
641
|
# Disconnect from controlling tty. Harmless if not already connected.
|
|
|
|
|
642
|
try:
|
|
614
|
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
|
|
643
|
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
|
|
615
|
if fd >= 0:
|
|
644
|
if fd >= 0:
|
|
616
|
os.close(fd)
|
|
645
|
os.close(fd)
|
|
|
|
|
646
|
except:
|
|
|
|
|
647
|
# Already disconnected. This happens if running inside cron.
|
|
|
|
|
648
|
pass
|
|
617
|
|
|
649
|
|
|
618
|
os.setsid()
|
|
650
|
os.setsid()
|
|
619
|
|
|
651
|
|
|
620
|
# Verify we are disconnected from controlling tty
|
|
652
|
# Verify we are disconnected from controlling tty
|
|
|
|
|
653
|
# by attempting to open it again.
|
|
621
|
try:
|
|
654
|
try:
|
|
622
|
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
|
|
655
|
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
|
|
623
|
if fd >= 0:
|
|
656
|
if fd >= 0:
|
|
624
|
os.close(fd)
|
|
657
|
os.close(fd)
|
|
625
|
raise ExceptionPexpect, "Error! We are not disconnected from a controlling tty."
|
|
658
|
raise ExceptionPexpect, "Error! Failed to disconnect from controlling tty. It is still possible to open /dev/tty."
|
|
626
|
except:
|
|
659
|
except:
|
|
627
|
# Good! We are disconnected from a controlling tty.
|
|
660
|
# Good! We are disconnected from a controlling tty.
|
|
628
|
pass
|
|
661
|
pass
|
|
@@
-695,9
+728,8
b' class spawn (object):'
|
|
695
|
p.waitnoecho()
|
|
728
|
p.waitnoecho()
|
|
696
|
p.sendline(mypassword)
|
|
729
|
p.sendline(mypassword)
|
|
697
|
|
|
730
|
|
|
698
|
If timeout is None then this method to block forever until ECHO flag is
|
|
731
|
If timeout==-1 then this method will use the value in self.timeout.
|
|
699
|
False.
|
|
732
|
If timeout==None then this method to block until ECHO flag is False.
|
|
700
|
|
|
|
|
|
701
|
"""
|
|
733
|
"""
|
|
702
|
|
|
734
|
|
|
703
|
if timeout == -1:
|
|
735
|
if timeout == -1:
|
|
@@
-767,7
+799,7
b' class spawn (object):'
|
|
767
|
|
|
799
|
|
|
768
|
def read_nonblocking (self, size = 1, timeout = -1):
|
|
800
|
def read_nonblocking (self, size = 1, timeout = -1):
|
|
769
|
|
|
801
|
|
|
770
|
"""This reads at most size characters from the child application. It
|
|
802
|
"""This reads at most size bytes from the child application. It
|
|
771
|
includes a timeout. If the read does not complete within the timeout
|
|
803
|
includes a timeout. If the read does not complete within the timeout
|
|
772
|
period then a TIMEOUT exception is raised. If the end of file is read
|
|
804
|
period then a TIMEOUT exception is raised. If the end of file is read
|
|
773
|
then an EOF exception will be raised. If a log file was set using
|
|
805
|
then an EOF exception will be raised. If a log file was set using
|
|
@@
-832,11
+864,12
b' class spawn (object):'
|
|
832
|
self.flag_eof = True
|
|
864
|
self.flag_eof = True
|
|
833
|
raise EOF ('End Of File (EOF) in read_nonblocking(). Empty string style platform.')
|
|
865
|
raise EOF ('End Of File (EOF) in read_nonblocking(). Empty string style platform.')
|
|
834
|
|
|
866
|
|
|
|
|
|
867
|
s2 = self._cast_buffer_type(s)
|
|
835
|
if self.logfile is not None:
|
|
868
|
if self.logfile is not None:
|
|
836
|
self.logfile.write (s)
|
|
869
|
self.logfile.write(s2)
|
|
837
|
self.logfile.flush()
|
|
870
|
self.logfile.flush()
|
|
838
|
if self.logfile_read is not None:
|
|
871
|
if self.logfile_read is not None:
|
|
839
|
self.logfile_read.write (s)
|
|
872
|
self.logfile_read.write(s2)
|
|
840
|
self.logfile_read.flush()
|
|
873
|
self.logfile_read.flush()
|
|
841
|
|
|
874
|
|
|
842
|
return s
|
|
875
|
return s
|
|
@@
-844,7
+877,6
b' class spawn (object):'
|
|
844
|
raise ExceptionPexpect ('Reached an unexpected state in read_nonblocking().')
|
|
877
|
raise ExceptionPexpect ('Reached an unexpected state in read_nonblocking().')
|
|
845
|
|
|
878
|
|
|
846
|
def read (self, size = -1): # File-like object.
|
|
879
|
def read (self, size = -1): # File-like object.
|
|
847
|
|
|
|
|
|
848
|
"""This reads at most "size" bytes from the file (less if the read hits
|
|
880
|
"""This reads at most "size" bytes from the file (less if the read hits
|
|
849
|
EOF before obtaining size bytes). If the size argument is negative or
|
|
881
|
EOF before obtaining size bytes). If the size argument is negative or
|
|
850
|
omitted, read all data until EOF is reached. The bytes are returned as
|
|
882
|
omitted, read all data until EOF is reached. The bytes are returned as
|
|
@@
-852,7
+884,7
b' class spawn (object):'
|
|
852
|
immediately. """
|
|
884
|
immediately. """
|
|
853
|
|
|
885
|
|
|
854
|
if size == 0:
|
|
886
|
if size == 0:
|
|
855
|
return ''
|
|
887
|
return self._empty_buffer
|
|
856
|
if size < 0:
|
|
888
|
if size < 0:
|
|
857
|
self.expect (self.delimiter) # delimiter default is EOF
|
|
889
|
self.expect (self.delimiter) # delimiter default is EOF
|
|
858
|
return self.before
|
|
890
|
return self.before
|
|
@@
-864,14
+896,17
b' class spawn (object):'
|
|
864
|
# worry about if I have to later modify read() or expect().
|
|
896
|
# worry about if I have to later modify read() or expect().
|
|
865
|
# Note, it's OK if size==-1 in the regex. That just means it
|
|
897
|
# Note, it's OK if size==-1 in the regex. That just means it
|
|
866
|
# will never match anything in which case we stop only on EOF.
|
|
898
|
# will never match anything in which case we stop only on EOF.
|
|
867
|
cre = re.compile('.{%d}' % size, re.DOTALL)
|
|
899
|
if self._buffer_type is bytes:
|
|
|
|
|
900
|
pat = (u'.{%d}' % size).encode('ascii')
|
|
|
|
|
901
|
else:
|
|
|
|
|
902
|
pat = u'.{%d}' % size
|
|
|
|
|
903
|
cre = re.compile(pat, re.DOTALL)
|
|
868
|
index = self.expect ([cre, self.delimiter]) # delimiter default is EOF
|
|
904
|
index = self.expect ([cre, self.delimiter]) # delimiter default is EOF
|
|
869
|
if index == 0:
|
|
905
|
if index == 0:
|
|
870
|
return self.after ### self.before should be ''. Should I assert this?
|
|
906
|
return self.after ### self.before should be ''. Should I assert this?
|
|
871
|
return self.before
|
|
907
|
return self.before
|
|
872
|
|
|
908
|
|
|
873
|
def readline (self, size = -1): # File-like object.
|
|
909
|
def readline(self, size = -1):
|
|
874
|
|
|
|
|
|
875
|
"""This reads and returns one entire line. A trailing newline is kept
|
|
910
|
"""This reads and returns one entire line. A trailing newline is kept
|
|
876
|
in the string, but may be absent when a file ends with an incomplete
|
|
911
|
in the string, but may be absent when a file ends with an incomplete
|
|
877
|
line. Note: This readline() looks for a \\r\\n pair even on UNIX
|
|
912
|
line. Note: This readline() looks for a \\r\\n pair even on UNIX
|
|
@@
-882,11
+917,10
b' class spawn (object):'
|
|
882
|
object. If size is 0 then an empty string is returned. """
|
|
917
|
object. If size is 0 then an empty string is returned. """
|
|
883
|
|
|
918
|
|
|
884
|
if size == 0:
|
|
919
|
if size == 0:
|
|
885
|
return ''
|
|
920
|
return self._empty_buffer
|
|
886
|
index = self.expect (['\r\n', self.delimiter]) # delimiter default is EOF
|
|
921
|
index = self.expect ([self._pty_newline, self.delimiter]) # delimiter default is EOF
|
|
887
|
if index == 0:
|
|
922
|
if index == 0:
|
|
888
|
return self.before + '\r\n'
|
|
923
|
return self.before + self._pty_newline
|
|
889
|
else:
|
|
|
|
|
890
|
return self.before
|
|
924
|
return self.before
|
|
891
|
|
|
925
|
|
|
892
|
def __iter__ (self): # File-like object.
|
|
926
|
def __iter__ (self): # File-like object.
|
|
@@
-902,7
+936,7
b' class spawn (object):'
|
|
902
|
"""
|
|
936
|
"""
|
|
903
|
|
|
937
|
|
|
904
|
result = self.readline()
|
|
938
|
result = self.readline()
|
|
905
|
if result == "":
|
|
939
|
if result == self._empty_buffer:
|
|
906
|
raise StopIteration
|
|
940
|
raise StopIteration
|
|
907
|
return result
|
|
941
|
return result
|
|
908
|
|
|
942
|
|
|
@@
-936,22
+970,22
b' class spawn (object):'
|
|
936
|
for s in sequence:
|
|
970
|
for s in sequence:
|
|
937
|
self.write (s)
|
|
971
|
self.write (s)
|
|
938
|
|
|
972
|
|
|
939
|
def send(self, s, encoding='utf-8'):
|
|
973
|
def send(self, s):
|
|
940
|
|
|
974
|
|
|
941
|
"""This sends a string to the child process. This returns the number of
|
|
975
|
"""This sends a string to the child process. This returns the number of
|
|
942
|
bytes written. If a log file was set then the data is also written to
|
|
976
|
bytes written. If a log file was set then the data is also written to
|
|
943
|
the log. """
|
|
977
|
the log. """
|
|
944
|
|
|
978
|
|
|
945
|
if isinstance(s, unicode):
|
|
|
|
|
946
|
s = s.encode(encoding)
|
|
|
|
|
947
|
time.sleep(self.delaybeforesend)
|
|
979
|
time.sleep(self.delaybeforesend)
|
|
|
|
|
980
|
|
|
|
|
|
981
|
s2 = self._cast_buffer_type(s)
|
|
948
|
if self.logfile is not None:
|
|
982
|
if self.logfile is not None:
|
|
949
|
self.logfile.write (s)
|
|
983
|
self.logfile.write(s2)
|
|
950
|
self.logfile.flush()
|
|
984
|
self.logfile.flush()
|
|
951
|
if self.logfile_send is not None:
|
|
985
|
if self.logfile_send is not None:
|
|
952
|
self.logfile_send.write (s)
|
|
986
|
self.logfile_send.write(s2)
|
|
953
|
self.logfile_send.flush()
|
|
987
|
self.logfile_send.flush()
|
|
954
|
c = os.write(self.child_fd, s)
|
|
988
|
c = os.write (self.child_fd, _cast_bytes(s, self.encoding))
|
|
955
|
return c
|
|
989
|
return c
|
|
956
|
|
|
990
|
|
|
957
|
def sendline(self, s=''):
|
|
991
|
def sendline(self, s=''):
|
|
@@
-1131,8
+1165,8
b' class spawn (object):'
|
|
1131
|
|
|
1165
|
|
|
1132
|
try:
|
|
1166
|
try:
|
|
1133
|
pid, status = os.waitpid(self.pid, waitpid_options)
|
|
1167
|
pid, status = os.waitpid(self.pid, waitpid_options)
|
|
1134
|
except OSError, e: # No child processes
|
|
1168
|
except OSError as e: # No child processes
|
|
1135
|
if e[0] == errno.ECHILD:
|
|
1169
|
if e.errno == errno.ECHILD:
|
|
1136
|
raise ExceptionPexpect ('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?')
|
|
1170
|
raise ExceptionPexpect ('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?')
|
|
1137
|
else:
|
|
1171
|
else:
|
|
1138
|
raise e
|
|
1172
|
raise e
|
|
@@
-1218,20
+1252,28
b' class spawn (object):'
|
|
1218
|
compile_flags = compile_flags | re.IGNORECASE
|
|
1252
|
compile_flags = compile_flags | re.IGNORECASE
|
|
1219
|
compiled_pattern_list = []
|
|
1253
|
compiled_pattern_list = []
|
|
1220
|
for p in patterns:
|
|
1254
|
for p in patterns:
|
|
1221
|
if isinstance(p, basestring):
|
|
1255
|
if isinstance(p, (bytes, unicode)):
|
|
|
|
|
1256
|
p = self._cast_buffer_type(p)
|
|
1222
|
compiled_pattern_list.append(re.compile(p, compile_flags))
|
|
1257
|
compiled_pattern_list.append(re.compile(p, compile_flags))
|
|
1223
|
elif p is EOF:
|
|
1258
|
elif p is EOF:
|
|
1224
|
compiled_pattern_list.append(EOF)
|
|
1259
|
compiled_pattern_list.append(EOF)
|
|
1225
|
elif p is TIMEOUT:
|
|
1260
|
elif p is TIMEOUT:
|
|
1226
|
compiled_pattern_list.append(TIMEOUT)
|
|
1261
|
compiled_pattern_list.append(TIMEOUT)
|
|
1227
|
elif type(p) is type(re.compile('')):
|
|
1262
|
elif type(p) is re_type:
|
|
|
|
|
1263
|
p = self._prepare_regex_pattern(p)
|
|
1228
|
compiled_pattern_list.append(p)
|
|
1264
|
compiled_pattern_list.append(p)
|
|
1229
|
else:
|
|
1265
|
else:
|
|
1230
|
raise TypeError ('Argument must be one of StringTypes, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p)))
|
|
1266
|
raise TypeError ('Argument must be one of StringTypes, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p)))
|
|
1231
|
|
|
1267
|
|
|
1232
|
return compiled_pattern_list
|
|
1268
|
return compiled_pattern_list
|
|
1233
|
|
|
1269
|
|
|
1234
|
def expect(self, pattern, timeout = -1, searchwindowsize=None):
|
|
1270
|
def _prepare_regex_pattern(self, p):
|
|
|
|
|
1271
|
"Recompile unicode regexes as bytes regexes. Overridden in subclass."
|
|
|
|
|
1272
|
if isinstance(p.pattern, unicode):
|
|
|
|
|
1273
|
p = re.compile(p.pattern.encode('utf-8'), p.flags &~ re.UNICODE)
|
|
|
|
|
1274
|
return p
|
|
|
|
|
1275
|
|
|
|
|
|
1276
|
def expect(self, pattern, timeout = -1, searchwindowsize=-1):
|
|
1235
|
|
|
1277
|
|
|
1236
|
"""This seeks through the stream until a pattern is matched. The
|
|
1278
|
"""This seeks through the stream until a pattern is matched. The
|
|
1237
|
pattern is overloaded and may take several types. The pattern can be a
|
|
1279
|
pattern is overloaded and may take several types. The pattern can be a
|
|
@@
-1339,7
+1381,7
b' class spawn (object):'
|
|
1339
|
This method is also useful when you don't want to have to worry about
|
|
1381
|
This method is also useful when you don't want to have to worry about
|
|
1340
|
escaping regular expression characters that you want to match."""
|
|
1382
|
escaping regular expression characters that you want to match."""
|
|
1341
|
|
|
1383
|
|
|
1342
|
if isinstance(pattern_list, basestring) or pattern_list in (TIMEOUT, EOF):
|
|
1384
|
if isinstance(pattern_list, (bytes, unicode)) or pattern_list in (TIMEOUT, EOF):
|
|
1343
|
pattern_list = [pattern_list]
|
|
1385
|
pattern_list = [pattern_list]
|
|
1344
|
return self.expect_loop(searcher_string(pattern_list), timeout, searchwindowsize)
|
|
1386
|
return self.expect_loop(searcher_string(pattern_list), timeout, searchwindowsize)
|
|
1345
|
|
|
1387
|
|
|
@@
-1383,7
+1425,7
b' class spawn (object):'
|
|
1383
|
if timeout is not None:
|
|
1425
|
if timeout is not None:
|
|
1384
|
timeout = end_time - time.time()
|
|
1426
|
timeout = end_time - time.time()
|
|
1385
|
except EOF, e:
|
|
1427
|
except EOF, e:
|
|
1386
|
self.buffer = b''
|
|
1428
|
self.buffer = self._empty_buffer
|
|
1387
|
self.before = incoming
|
|
1429
|
self.before = incoming
|
|
1388
|
self.after = EOF
|
|
1430
|
self.after = EOF
|
|
1389
|
index = searcher.eof_index
|
|
1431
|
index = searcher.eof_index
|
|
@@
-1448,7
+1490,7
b' class spawn (object):'
|
|
1448
|
s = struct.pack('HHHH', r, c, 0, 0)
|
|
1490
|
s = struct.pack('HHHH', r, c, 0, 0)
|
|
1449
|
fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
|
|
1491
|
fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
|
|
1450
|
|
|
1492
|
|
|
1451
|
def interact(self, escape_character = chr(29), input_filter = None, output_filter = None):
|
|
1493
|
def interact(self, escape_character = b'\x1d', input_filter = None, output_filter = None):
|
|
1452
|
|
|
1494
|
|
|
1453
|
"""This gives control of the child process to the interactive user (the
|
|
1495
|
"""This gives control of the child process to the interactive user (the
|
|
1454
|
human at the keyboard). Keystrokes are sent to the child process, and
|
|
1496
|
human at the keyboard). Keystrokes are sent to the child process, and
|
|
@@
-1484,9
+1526,10
b' class spawn (object):'
|
|
1484
|
"""
|
|
1526
|
"""
|
|
1485
|
|
|
1527
|
|
|
1486
|
# Flush the buffer.
|
|
1528
|
# Flush the buffer.
|
|
1487
|
self.stdout.write (self.buffer)
|
|
1529
|
if PY3: self.stdout.write(_cast_unicode(self.buffer, self.encoding))
|
|
|
|
|
1530
|
else: self.stdout.write(self.buffer)
|
|
1488
|
self.stdout.flush()
|
|
1531
|
self.stdout.flush()
|
|
1489
|
self.buffer = b''
|
|
1532
|
self.buffer = self._empty_buffer
|
|
1490
|
mode = tty.tcgetattr(self.STDIN_FILENO)
|
|
1533
|
mode = tty.tcgetattr(self.STDIN_FILENO)
|
|
1491
|
tty.setraw(self.STDIN_FILENO)
|
|
1534
|
tty.setraw(self.STDIN_FILENO)
|
|
1492
|
try:
|
|
1535
|
try:
|
|
@@
-1499,7
+1542,7
b' class spawn (object):'
|
|
1499
|
"""This is used by the interact() method.
|
|
1542
|
"""This is used by the interact() method.
|
|
1500
|
"""
|
|
1543
|
"""
|
|
1501
|
|
|
1544
|
|
|
1502
|
while data != '' and self.isalive():
|
|
1545
|
while data != b'' and self.isalive():
|
|
1503
|
n = os.write(fd, data)
|
|
1546
|
n = os.write(fd, data)
|
|
1504
|
data = data[n:]
|
|
1547
|
data = data[n:]
|
|
1505
|
|
|
1548
|
|
|
@@
-1548,8
+1591,8
b' class spawn (object):'
|
|
1548
|
while True:
|
|
1591
|
while True:
|
|
1549
|
try:
|
|
1592
|
try:
|
|
1550
|
return select.select (iwtd, owtd, ewtd, timeout)
|
|
1593
|
return select.select (iwtd, owtd, ewtd, timeout)
|
|
1551
|
except select.error, e:
|
|
1594
|
except select.error as e:
|
|
1552
|
if e[0] == errno.EINTR:
|
|
1595
|
if e.args[0] == errno.EINTR:
|
|
1553
|
# if we loop back we have to subtract the amount of time we already waited.
|
|
1596
|
# if we loop back we have to subtract the amount of time we already waited.
|
|
1554
|
if timeout is not None:
|
|
1597
|
if timeout is not None:
|
|
1555
|
timeout = end_time - time.time()
|
|
1598
|
timeout = end_time - time.time()
|
|
@@
-1558,22
+1601,34
b' class spawn (object):'
|
|
1558
|
else: # something else caused the select.error, so this really is an exception
|
|
1601
|
else: # something else caused the select.error, so this really is an exception
|
|
1559
|
raise
|
|
1602
|
raise
|
|
1560
|
|
|
1603
|
|
|
1561
|
##############################################################################
|
|
1604
|
class spawn(spawnb):
|
|
1562
|
# The following methods are no longer supported or allowed.
|
|
1605
|
"""This is the main class interface for Pexpect. Use this class to start
|
|
|
|
|
1606
|
and control child applications."""
|
|
1563
|
|
|
1607
|
|
|
1564
|
def setmaxread (self, maxread):
|
|
1608
|
_buffer_type = unicode
|
|
|
|
|
1609
|
def _cast_buffer_type(self, s):
|
|
|
|
|
1610
|
return _cast_unicode(s, self.encoding)
|
|
|
|
|
1611
|
_empty_buffer = u''
|
|
|
|
|
1612
|
_pty_newline = u'\r\n'
|
|
1565
|
|
|
1613
|
|
|
1566
|
"""This method is no longer supported or allowed. I don't like getters
|
|
1614
|
def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None,
|
|
1567
|
and setters without a good reason. """
|
|
1615
|
logfile=None, cwd=None, env=None, encoding='utf-8'):
|
|
|
|
|
1616
|
super(spawn, self).__init__(command, args, timeout=timeout, maxread=maxread,
|
|
|
|
|
1617
|
searchwindowsize=searchwindowsize, logfile=logfile, cwd=cwd, env=env)
|
|
|
|
|
1618
|
self.encoding = encoding
|
|
1568
|
|
|
1619
|
|
|
1569
|
raise ExceptionPexpect ('This method is no longer supported or allowed. Just assign a value to the maxread member variable.')
|
|
1620
|
def _prepare_regex_pattern(self, p):
|
|
|
|
|
1621
|
"Recompile bytes regexes as unicode regexes."
|
|
|
|
|
1622
|
if isinstance(p.pattern, bytes):
|
|
|
|
|
1623
|
p = re.compile(p.pattern.decode(self.encoding), p.flags)
|
|
|
|
|
1624
|
return p
|
|
1570
|
|
|
1625
|
|
|
1571
|
def setlog (self, fileobject):
|
|
1626
|
def read_nonblocking(self, size=1, timeout=-1):
|
|
|
|
|
1627
|
return super(spawn, self).read_nonblocking(size=size, timeout=timeout)\
|
|
|
|
|
1628
|
.decode(self.encoding)
|
|
1572
|
|
|
1629
|
|
|
1573
|
"""This method is no longer supported or allowed.
|
|
1630
|
read_nonblocking.__doc__ = spawnb.read_nonblocking.__doc__
|
|
1574
|
"""
|
|
|
|
|
1575
|
|
|
1631
|
|
|
1576
|
raise ExceptionPexpect ('This method is no longer supported or allowed. Just assign a value to the logfile member variable.')
|
|
|
|
|
1577
|
|
|
1632
|
|
|
1578
|
##############################################################################
|
|
1633
|
##############################################################################
|
|
1579
|
# End of spawn class
|
|
1634
|
# End of spawn class
|
|
@@
-1582,6
+1637,8
b' class spawn (object):'
|
|
1582
|
class searcher_string (object):
|
|
1637
|
class searcher_string (object):
|
|
1583
|
|
|
1638
|
|
|
1584
|
"""This is a plain string search helper for the spawn.expect_any() method.
|
|
1639
|
"""This is a plain string search helper for the spawn.expect_any() method.
|
|
|
|
|
1640
|
This helper class is for speed. For more powerful regex patterns
|
|
|
|
|
1641
|
see the helper class, searcher_re.
|
|
1585
|
|
|
1642
|
|
|
1586
|
Attributes:
|
|
1643
|
Attributes:
|
|
1587
|
|
|
1644
|
|
|
@@
-1594,6
+1651,7
b' class searcher_string (object):'
|
|
1594
|
start - index into the buffer, first byte of match
|
|
1651
|
start - index into the buffer, first byte of match
|
|
1595
|
end - index into the buffer, first byte after match
|
|
1652
|
end - index into the buffer, first byte after match
|
|
1596
|
match - the matching string itself
|
|
1653
|
match - the matching string itself
|
|
|
|
|
1654
|
|
|
1597
|
"""
|
|
1655
|
"""
|
|
1598
|
|
|
1656
|
|
|
1599
|
def __init__(self, strings):
|
|
1657
|
def __init__(self, strings):
|
|
@@
-1604,7
+1662,7
b' class searcher_string (object):'
|
|
1604
|
self.eof_index = -1
|
|
1662
|
self.eof_index = -1
|
|
1605
|
self.timeout_index = -1
|
|
1663
|
self.timeout_index = -1
|
|
1606
|
self._strings = []
|
|
1664
|
self._strings = []
|
|
1607
|
for n, s in zip(range(len(strings)), strings):
|
|
1665
|
for n, s in enumerate(strings):
|
|
1608
|
if s is EOF:
|
|
1666
|
if s is EOF:
|
|
1609
|
self.eof_index = n
|
|
1667
|
self.eof_index = n
|
|
1610
|
continue
|
|
1668
|
continue
|
|
@@
-1625,8
+1683,7
b' class searcher_string (object):'
|
|
1625
|
if self.timeout_index >= 0:
|
|
1683
|
if self.timeout_index >= 0:
|
|
1626
|
ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
|
|
1684
|
ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
|
|
1627
|
ss.sort()
|
|
1685
|
ss.sort()
|
|
1628
|
ss = zip(*ss)[1]
|
|
1686
|
return '\n'.join(a[1] for a in ss)
|
|
1629
|
return '\n'.join(ss)
|
|
|
|
|
1630
|
|
|
1687
|
|
|
1631
|
def search(self, buffer, freshlen, searchwindowsize=None):
|
|
1688
|
def search(self, buffer, freshlen, searchwindowsize=None):
|
|
1632
|
|
|
1689
|
|
|
@@
-1677,7
+1734,8
b' class searcher_string (object):'
|
|
1677
|
class searcher_re (object):
|
|
1734
|
class searcher_re (object):
|
|
1678
|
|
|
1735
|
|
|
1679
|
"""This is regular expression string search helper for the
|
|
1736
|
"""This is regular expression string search helper for the
|
|
1680
|
spawn.expect_any() method.
|
|
1737
|
spawn.expect_any() method. This helper class is for powerful
|
|
|
|
|
1738
|
pattern matching. For speed, see the helper class, searcher_string.
|
|
1681
|
|
|
1739
|
|
|
1682
|
Attributes:
|
|
1740
|
Attributes:
|
|
1683
|
|
|
1741
|
|
|
@@
-1723,8
+1781,7
b' class searcher_re (object):'
|
|
1723
|
if self.timeout_index >= 0:
|
|
1781
|
if self.timeout_index >= 0:
|
|
1724
|
ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
|
|
1782
|
ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
|
|
1725
|
ss.sort()
|
|
1783
|
ss.sort()
|
|
1726
|
ss = [a[1] for a in ss]
|
|
1784
|
return '\n'.join(a[1] for a in ss)
|
|
1727
|
return '\n'.join(ss)
|
|
|
|
|
1728
|
|
|
1785
|
|
|
1729
|
def search(self, buffer, freshlen, searchwindowsize=None):
|
|
1786
|
def search(self, buffer, freshlen, searchwindowsize=None):
|
|
1730
|
|
|
1787
|
|
|
@@
-1777,8
+1834,6
b' def which (filename):'
|
|
1777
|
else:
|
|
1834
|
else:
|
|
1778
|
p = os.environ['PATH']
|
|
1835
|
p = os.environ['PATH']
|
|
1779
|
|
|
1836
|
|
|
1780
|
# Oddly enough this was the one line that made Pexpect
|
|
|
|
|
1781
|
# incompatible with Python 1.5.2.
|
|
|
|
|
1782
|
pathlist = p.split(os.pathsep)
|
|
1837
|
pathlist = p.split(os.pathsep)
|
|
1783
|
|
|
1838
|
|
|
1784
|
for path in pathlist:
|
|
1839
|
for path in pathlist:
|
|
@@
-1842,4
+1897,4
b' def split_command_line(command_line):'
|
|
1842
|
arg_list.append(arg)
|
|
1897
|
arg_list.append(arg)
|
|
1843
|
return arg_list
|
|
1898
|
return arg_list
|
|
1844
|
|
|
1899
|
|
|
1845
|
# vi:ts=4:sw=4:expandtab:ft=python:
|
|
1900
|
# vi:set sr et ts=4 sw=4 ft=python :
|