Show More
@@ -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 |
|
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 |
|
|
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, |
|
39 | Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey, | |
37 |
Perez, Corey Minyard, Jon Cohen, Guillaume |
|
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 |
|
|
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) 200 |
|
64 | Pexpect Copyright (c) 2010 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. |
|
88 | __version__ = '2.6.dev' | |
87 | __revision__ = '$Revision: 399 $' |
|
89 | version = __version__ | |
|
90 | version_info = (2,6,'dev') | |||
88 | __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run', 'which', |
|
91 | __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run', 'which', | |
89 |
'split_command_line', '__version__' |
|
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 | |
@@ -212,12 +230,14 b' def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None' | |||||
212 | the next event. A callback may also return a string which will be sent to |
|
230 | the next event. A callback may also return a string which will be sent to | |
213 | the child. 'extra_args' is not used by directly run(). It provides a way to |
|
231 | the child. 'extra_args' is not used by directly run(). It provides a way to | |
214 | pass data to a callback function through run() through the locals |
|
232 | pass data to a callback function through run() through the locals | |
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, |
|
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 |
|
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 = |
|
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 |
|
281 | class spawnb(object): | |
262 |
|
282 | """Use this class to start and control child applications with a pure-bytes | ||
263 | """This is the main class interface for Pexpect. Use this class to start |
|
283 | interface.""" | |
264 | and control child applications. """ |
|
284 | ||
265 |
|
285 | _buffer_type = bytes | ||
266 | def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None): |
|
286 | def _cast_buffer_type(self, s): | |
|
287 | return _cast_bytes(s, self.encoding) | |||
|
288 | _empty_buffer = b'' | |||
|
289 | _pty_newline = b'\r\n' | |||
|
290 | ||||
|
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 = |
|
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 |
|
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 |
|
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__ |
|
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 |
|
641 | # Disconnect from controlling tty. Harmless if not already connected. | |
614 | fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY); |
|
642 | try: | |
615 | if fd >= 0: |
|
643 | fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY); | |
616 | os.close(fd) |
|
644 | if fd >= 0: | |
|
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! |
|
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 |
|
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,19 +864,19 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 |
|
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 |
|
872 | self.logfile_read.write(s2) | |
840 | self.logfile_read.flush() |
|
873 | self.logfile_read.flush() | |
841 |
|
874 | |||
842 | return s |
|
875 | return s | |
843 |
|
876 | |||
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 |
|
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,12 +917,11 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 ([ |
|
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 + |
|
923 | return self.before + self._pty_newline | |
889 | else: |
|
924 | return self.before | |
890 | return self.before |
|
|||
891 |
|
925 | |||
892 | def __iter__ (self): # File-like object. |
|
926 | def __iter__ (self): # File-like object. | |
893 |
|
927 | |||
@@ -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 |
|
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 |
|
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 |
|
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=''): | |
@@ -959,7 +993,7 b' class spawn (object):' | |||||
959 | """This is like send(), but it adds a line feed (os.linesep). This |
|
993 | """This is like send(), but it adds a line feed (os.linesep). This | |
960 | returns the number of bytes written. """ |
|
994 | returns the number of bytes written. """ | |
961 |
|
995 | |||
962 | n = self.send(s) |
|
996 | n = self.send (s) | |
963 | n = n + self.send (os.linesep) |
|
997 | n = n + self.send (os.linesep) | |
964 | return n |
|
998 | return n | |
965 |
|
999 | |||
@@ -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 |
|
1168 | except OSError as e: # No child processes | |
1135 |
if e |
|
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, |
|
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 |
|
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 | |
|
1269 | ||||
|
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 | |||
1233 |
|
1275 | |||
1234 |
def expect(self, pattern, timeout = -1, searchwindowsize= |
|
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, |
|
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 = |
|
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 = |
|
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 |
|
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 = |
|
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 |
|
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 | |
1563 |
|
1606 | and control child applications.""" | ||
1564 | def setmaxread (self, maxread): |
|
1607 | ||
1565 |
|
1608 | _buffer_type = unicode | ||
1566 | """This method is no longer supported or allowed. I don't like getters |
|
1609 | def _cast_buffer_type(self, s): | |
1567 | and setters without a good reason. """ |
|
1610 | return _cast_unicode(s, self.encoding) | |
1568 |
|
1611 | _empty_buffer = u'' | ||
1569 | raise ExceptionPexpect ('This method is no longer supported or allowed. Just assign a value to the maxread member variable.') |
|
1612 | _pty_newline = u'\r\n' | |
1570 |
|
1613 | |||
1571 | def setlog (self, fileobject): |
|
1614 | def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None, | |
1572 |
|
1615 | logfile=None, cwd=None, env=None, encoding='utf-8'): | ||
1573 | """This method is no longer supported or allowed. |
|
1616 | super(spawn, self).__init__(command, args, timeout=timeout, maxread=maxread, | |
1574 | """ |
|
1617 | searchwindowsize=searchwindowsize, logfile=logfile, cwd=cwd, env=env) | |
1575 |
|
1618 | self.encoding = encoding | ||
1576 | raise ExceptionPexpect ('This method is no longer supported or allowed. Just assign a value to the logfile member variable.') |
|
1619 | ||
|
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 | |||
|
1625 | ||||
|
1626 | def read_nonblocking(self, size=1, timeout=-1): | |||
|
1627 | return super(spawn, self).read_nonblocking(size=size, timeout=timeout)\ | |||
|
1628 | .decode(self.encoding) | |||
|
1629 | ||||
|
1630 | read_nonblocking.__doc__ = spawnb.read_nonblocking.__doc__ | |||
|
1631 | ||||
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 |
|
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 |
|
|
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: |
|
1900 | # vi:set sr et ts=4 sw=4 ft=python : |
General Comments 0
You need to be logged in to leave comments.
Login now