source: soft/build_system/build_system/repsys/tags/V1_5_7/RepSys/pexpect.py @ 1

Last change on this file since 1 was 1, checked in by fasma, 12 years ago

Initial Import from Mandriva's soft revision 224062 and package revision 45733

File size: 41.0 KB
Line 
1"""
2Pexpect is a Python module for spawning child applications;
3controlling them; and responding to expected patterns in their output.
4Pexpect can be used for automating interactive applications such as
5ssh, ftp, passwd, telnet, etc. It can be used to a automate setup scripts
6for duplicating software package installations on different servers.
7It can be used for automated software testing. Pexpect is in the spirit of
8Don Libes' Expect, but Pexpect is pure Python. Other Expect-like
9modules for Python require TCL and Expect or require C extensions to
10be compiled. Pexpect does not use C, Expect, or TCL extensions. It
11should work on any platform that supports the standard Python pty
12module. The Pexpect interface focuses on ease of use so that simple
13tasks are easy.
14
15Pexpect is Open Source, Free, and all Good that stuff.
16License: Python Software Foundation License
17         http://www.opensource.org/licenses/PythonSoftFoundation.html
18
19Noah Spurrier
20
21$Revision: 965 $
22$Date: 2006-07-12 18:16:33 +0000 (Qua, 12 Jul 2006) $
23"""
24
25
26try:
27    import os, sys
28    import select
29    import string
30    import re
31    import struct
32    import resource
33    from types import *
34    import pty
35    import tty
36    import termios
37    import fcntl
38except ImportError, e:
39    raise ImportError, str(e) + """
40A critical module was not found. Probably this OS does not support it.
41Currently pexpect is intended for UNIX operating systems."""
42
43
44
45__version__ = '0.99'
46__revision__ = '$Revision: 965 $'
47__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run',
48    '__version__', '__revision__']
49
50
51
52# Exception classes used by this module.
53class ExceptionPexpect(Exception):
54    """Base class for all exceptions raised by this module."""
55    def __init__(self, value):
56        self.value = value
57    def __str__(self):
58        return `self.value`
59class EOF(ExceptionPexpect):
60    """Raised when EOF is read from a child."""
61class TIMEOUT(ExceptionPexpect):
62    """Raised when a read time exceeds the timeout."""
63##class MAXBUFFER(ExceptionPexpect):
64##    """Raised when a scan buffer fills before matching an expected pattern."""
65
66
67
68def run (command, args=[], timeout=30):
69    """This runs a command; waits for it to finish; then returns
70        all output as a string. This is a utility interface around
71        the spawn class.
72    """
73    child = spawn(command, args, timeout)
74    child.expect (EOF)
75    return child.before
76
77class spawn:
78    """This is the main class interface for Pexpect. Use this class to
79    start and control child applications.
80    """
81
82    def __init__(self, command, args=[], timeout=30):
83        """This is the constructor. The command parameter may be a string
84        that includes a command and any arguments to the command. For example:
85            p = pexpect.spawn ('/usr/bin/ftp')
86            p = pexpect.spawn ('/usr/bin/ssh user@example.com')
87            p = pexpect.spawn ('ls -latr /tmp')
88        You may also construct it with a list of arguments like so:
89            p = pexpect.spawn ('/usr/bin/ftp', [])
90            p = pexpect.spawn ('/usr/bin/ssh', ['user@example.com'])
91            p = pexpect.spawn ('ls', ['-latr', '/tmp'])
92        After this the child application will be created and
93        will be ready to talk to. For normal use, see expect() and
94        send() and sendline().
95
96        If the command parameter is an integer AND a valid file descriptor
97        then spawn will talk to the file descriptor instead. This can be
98        used to act expect features to any file descriptor. For example:
99            fd = os.open ('somefile.txt', os.O_RDONLY)
100            s = pexpect.spawn (fd)
101        The original creator of the file descriptor is responsible
102        for closing it. Spawn will not try to close it and spawn will
103        raise an exception if you try to call spawn.close().
104        """
105
106        self.STDIN_FILENO = sys.stdin.fileno()
107        self.STDOUT_FILENO = sys.stdout.fileno()
108        self.STDERR_FILENO = sys.stderr.fileno()
109
110        self.stdin = sys.stdin
111        self.stdout = sys.stdout
112        self.stderr = sys.stderr
113
114        self.timeout = timeout
115        self.child_fd = -1 # initially closed
116        self.__child_fd_owner = None
117        self.exitstatus = None
118        self.pid = None
119        self.log_file = None   
120        self.before = None
121        self.after = None
122        self.match = None
123        self.softspace = 0 # File-like object.
124        self.name = '' # File-like object.
125        self.flag_eof = 0
126
127        # NEW -- to support buffering -- the ability to read more than one
128        # byte from a TTY at a time. See setmaxread() method.
129        self.buffer = ''
130        self.maxread = 1 # Maximum to read at a time
131        ### IMPLEMENT THIS FEATURE!!!
132        # anything before maxsearchsize point is preserved, but not searched.
133        #self.maxsearchsize = 1000
134       
135        # If command is an int type then it must represent an open file descriptor.
136        if type (command) == type(0):
137            try: # Command is an int, so now check if it is a file descriptor.
138                os.fstat(command)
139            except OSError:
140                raise ExceptionPexpect, 'Command is an int type, yet is not a valid file descriptor.'
141            self.pid = -1 
142            self.child_fd = command
143            self.__child_fd_owner = 0 # Sets who is reponsible for the child_fd
144            self.args = None
145            self.command = None
146            self.name = '<file descriptor>'
147            return
148
149        if type (args) != type([]):
150            raise TypeError, 'The second argument, args, must be a list.'
151
152        if args == []:
153            self.args = _split_command_line(command)
154            self.command = self.args[0]
155        else:
156            self.args = args
157            self.args.insert (0, command)
158            self.command = command
159        self.name = '<' + reduce(lambda x, y: x+' '+y, self.args) + '>'
160
161        self.__spawn()
162
163    def __del__(self):
164        """This makes sure that no system resources are left open.
165        Python only garbage collects Python objects. OS file descriptors
166        are not Python objects, so they must be handled explicitly.
167        If the child file descriptor was opened outside of this class
168        (passed to the constructor) then this does not close it.
169        """
170        try: # CNC:2003-09-23
171            if self.__child_fd_owner:
172                self.close()
173        except OSError:
174            pass
175
176    def __spawn(self):
177        """This starts the given command in a child process. This does
178        all the fork/exec type of stuff for a pty. This is called by
179        __init__. The args parameter is a list, command is a string.
180        """
181        # The pid and child_fd of this object get set by this method.
182        # Note that it is difficult for this method to fail.
183        # You cannot detect if the child process cannot start.
184        # So the only way you can tell if the child process started
185        # or not is to try to read from the file descriptor. If you get
186        # EOF immediately then it means that the child is already dead.
187        # That may not necessarily be bad, because you may haved spawned a child
188        # that performs some task; creates no stdout output; and then dies.
189        # It is a fuzzy edge case. Any child process that you are likely to
190        # want to interact with Pexpect would probably not fall into this
191        # category.
192        # FYI, This essentially does a fork/exec operation.
193
194        assert self.pid == None, 'The pid member is not None.'
195        assert self.command != None, 'The command member is None.'
196
197        if _which(self.command) == None:
198            raise ExceptionPexpect ('The command was not found or was not executable: %s.' % self.command)
199
200        try:
201            self.pid, self.child_fd = pty.fork()
202        except OSError, e:
203            raise ExceptionPexpect('Pexpect: pty.fork() failed: ' + str(e))
204
205        if self.pid == 0: # Child
206            try: # Some platforms do not like setwinsize (Cygwin).
207                self.child_fd = sys.stdout.fileno()
208                self.setwinsize(24, 80)
209            except:
210                pass
211            # Do not allow child to inherit open file descriptors from parent.
212            max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
213            for i in range (3, max_fd):
214                try:
215                    os.close (i)
216                except OSError:
217                    pass
218
219            os.environ["LANG"] = "C"
220            os.environ["LANGUAGE"] = "C"
221            os.environ["LC_ALL"] = "C"
222            os.execvp(self.command, self.args)
223
224        # Parent
225        self.__child_fd_owner = 1
226
227    def fileno (self):   # File-like object.
228        """This returns the file descriptor of the pty for the child."""
229        return self.child_fd
230
231    def close (self, wait=1):   # File-like object.
232        """ This closes the connection with the child application.
233        It makes no attempt to actually kill the child or wait for its status.
234        If the file descriptor was set by passing a file descriptor
235        to the constructor then this method raises an exception.
236        Note that calling close() more than once is valid.
237        This emulates standard Python behavior with files.
238        If wait is set to True then close will wait
239        for the exit status of the process. Doing a wait is a blocking call,
240        but this usually takes almost no time at all. Generally,
241        you don't have to worry about this. If you are
242        creating lots of children then you usually want to call wait.
243        Only set wait to false if you know the child will
244        continue to run after closing the controlling TTY.
245        Otherwise you will end up with defunct (zombie) processes.
246        """
247        if self.child_fd != -1:
248            if not self.__child_fd_owner:
249                raise ExceptionPexpect ('This file descriptor cannot be closed because it was not created by spawn. The original creator is responsible for closing it.')
250            self.flush()
251            os.close (self.child_fd)
252            if wait:
253                os.waitpid (self.pid, 0)
254            self.child_fd = -1
255            self.__child_fd_owner = None
256
257    def flush (self):   # File-like object.
258        """This does nothing. It is here to support the interface for a File-like object.
259        """
260        pass
261
262    def isatty (self):   # File-like object.
263        """This returns 1 if the file descriptor is open and
264        connected to a tty(-like) device, else 0.
265        """
266        return os.isatty(self.child_fd)
267
268    def setecho (self, on):
269        """This sets the terminal echo mode on or off."""
270        new = termios.tcgetattr(self.child_fd)
271        if on:
272            new[3] = new[3] | termios.ECHO # lflags
273        else:
274            new[3] = new[3] & ~termios.ECHO # lflags
275        termios.tcsetattr(self.child_fd, termios.TCSADRAIN, new)
276
277    def setlog (self, fileobject):
278        """This sets logging output to go to the given fileobject.
279        Set fileobject to None to stop logging.
280        Example:
281            child = pexpect.spawn('some_command')
282            fout = file('mylog.txt','w')
283            child.setlog (fout)
284            ...
285        """
286        self.log_file = fileobject
287
288    def setmaxread (self, maxread):
289        """This sets the maximum number of bytes to read from a TTY at one time.
290        This is used to change the read buffer size. When a pexpect.spawn
291        object is created the default maxread is 1 (unbuffered).
292        Set this value higher to turn on buffer. This should help performance
293        in cases where large amounts of output are read back from the child.
294        """
295        self.maxread = maxread
296
297    def read_nonblocking (self, size = 1, timeout = None):
298        """
299        This reads at most size characters from the child application.
300        It includes a timeout. If the read does not complete within the
301        timeout period then a TIMEOUT exception is raised.
302        If the end of file is read then an EOF exception will be raised.
303        If a log file was set using setlog() then all data will
304        also be written to the log file.
305
306        Notice that if this method is called with timeout=None
307        then it actually may block.
308
309        This is a non-blocking wrapper around os.read().
310        It uses select.select() to implement a timeout.
311        """
312       
313        if self.child_fd == -1:
314            raise ValueError ('I/O operation on closed file')
315
316        # Note that some systems like Solaris don't seem to ever give
317        # an EOF when the child dies. In fact, you can still try to read
318        # from the child_fd -- it will block forever or until TIMEOUT.
319        # For this case, I test isalive() before doing any reading.
320        # If isalive() is false, then I pretend that this is the same as EOF.
321        if not self.isalive():
322            r, w, e = select.select([self.child_fd], [], [], 0)
323            if not r:
324                self.flag_eof = 1
325                raise EOF ('End Of File (EOF) in read(). Braindead platform.')
326       
327        r, w, e = select.select([self.child_fd], [], [], timeout)
328        if not r:
329            raise TIMEOUT('Timeout exceeded in read().')
330
331        if self.child_fd in r:
332            try:
333                s = os.read(self.child_fd, size)
334            except OSError, e:
335                self.flag_eof = 1
336                raise EOF('End Of File (EOF) in read(). Exception style platform.')
337            if s == '':
338                self.flag_eof = 1
339                raise EOF('End Of File (EOF) in read(). Empty string style platform.')
340           
341            if self.log_file != None:
342                self.log_file.write (s)
343                self.log_file.flush()
344               
345            return s
346
347        raise ExceptionPexpect('Reached an unexpected state in read().')
348
349    def read (self, size = -1):   # File-like object.
350        """This reads at most size bytes from the file
351        (less if the read hits EOF before obtaining size bytes).
352        If the size argument is negative or omitted,
353        read all data until EOF is reached.
354        The bytes are returned as a string object.
355        An empty string is returned when EOF is encountered immediately.
356        """
357        if size == 0:
358            return ''
359        if size < 0:
360            self.expect (EOF)
361            return self.before
362
363        # I could have done this more directly by not using expect(), but
364        # I deliberately decided to couple read() to expect() so that
365        # I would catch any bugs early and ensure consistant behavior.
366        # It's a little less efficient, but there is less for me to
367        # worry about if I have to later modify read() or expect().
368        cre = re.compile('.{%d}' % size, re.DOTALL) 
369        index = self.expect ([cre, EOF])
370        if index == 0:
371            return self.after ### self.before should be ''. Should I assert this?
372        return self.before
373       
374    def readline (self, size = -1):    # File-like object.
375        """This reads and returns one entire line. A trailing newline is kept in
376        the string, but may be absent when a file ends with an incomplete line.
377        Note: This readline() looks for a \r\n pair even on UNIX because this is
378        what the pseudo tty device returns. So contrary to what you may be used to
379        you will get a newline as \r\n.
380        An empty string is returned when EOF is hit immediately.
381        Currently, the size agument is mostly ignored, so this behavior is not
382        standard for a file-like object.
383        """
384        if size == 0:
385            return ''
386        index = self.expect (['\r\n', EOF])
387        if index == 0:
388            return self.before + '\r\n'
389        else:
390            return self.before
391
392    def __iter__ (self):
393        """This is to support interators over a file-like object.
394        """
395        return self
396    def next (self):
397        """This is to support iterators over a file-like object.
398        """
399        result = self.readline()
400        if result == "":
401            raise StopIteration
402        return result
403
404    def readlines (self, sizehint = -1):    # File-like object.
405        """This reads until EOF using readline() and returns a list containing
406        the lines thus read. The optional sizehint argument is ignored.
407        """       
408        lines = []
409        while 1:
410            line = self.readline()
411            if not line:
412                break
413            lines.append(line)
414        return lines
415
416    def write(self, str):   # File-like object.
417        """This is similar to send() except that there is no return value.
418        """
419        self.send (str)
420
421    def writelines (self, sequence):   # File-like object.
422        """This calls write() for each element in the sequence.
423        The sequence can be any iterable object producing strings,
424        typically a list of strings. This does not add line separators
425        There is no return value.
426        """
427        for str in sequence:
428            self.write (str)
429
430    def send(self, str):
431        """This sends a string to the child process.
432        This returns the number of bytes written.
433        """
434        return os.write(self.child_fd, str)
435
436    def sendline(self, str=''):
437        """This is like send(), but it adds a line feed (os.linesep).
438        This returns the number of bytes written.
439        """
440        n = self.send(str)
441        n = n + self.send (os.linesep)
442        return n
443
444    def sendeof(self):
445        """This sends an EOF to the child.
446        This sends a character which causes the pending parent output
447        buffer to be sent to the waiting child program without
448        waiting for end-of-line. If it is the first character of the
449        line, the read() in the user program returns 0, which
450        signifies end-of-file. This means to work as expected
451        a sendeof() has to be called at the begining of a line.
452        This method does not send a newline. It is the responsibility
453        of the caller to ensure the eof is sent at the beginning of a line.
454        """
455        ### Hmmm... how do I send an EOF?
456        ###C  if ((m = write(pty, *buf, p - *buf)) < 0)
457        ###C      return (errno == EWOULDBLOCK) ? n : -1;
458        fd = sys.stdin.fileno()
459        old = termios.tcgetattr(fd) # remember current state
460        new = termios.tcgetattr(fd)
461        new[3] = new[3] | termios.ICANON # lflags
462        # use try/finally to ensure state gets restored
463        try:
464            # EOF is recognized when ICANON is set, so make sure it is set.
465            termios.tcsetattr(fd, termios.TCSADRAIN, new)
466            os.write (self.child_fd, '%c' % termios.CEOF)
467        finally:
468            termios.tcsetattr(fd, termios.TCSADRAIN, old) # restore state
469
470    def eof (self):
471        """This returns 1 if the EOF exception was raised at some point.
472        """
473        return self.flag_eof
474
475    def isalive(self):
476        """This tests if the child process is running or not.
477        This returns 1 if the child process appears to be running or 0 if not.
478        This also sets the exitstatus attribute.
479        It can take literally SECONDS for Solaris to return the right status.
480        This is the most wiggly part of Pexpect, but I think I've almost got
481        it nailed down.
482        """
483        # I can't use signals. Signals on UNIX suck and they
484        # mess up Python pipes (setting SIGCHLD to SIGIGNORE).
485
486        # If this class was created from an existing file descriptor then
487        # I just check to see if the file descriptor is still valid.
488        if self.pid == -1 and not self.__child_fd_owner: 
489            try:
490                os.fstat(self.child_fd)
491                return 1
492            except:
493                return 0
494
495        try:
496            pid, status = os.waitpid(self.pid, os.WNOHANG)
497        except OSError:
498            return 0
499
500        # I have to do this twice for Solaris.
501        # I can't even believe that I figured this out...
502        if pid == 0 and status == 0:
503            try:
504                pid, status = os.waitpid(self.pid, os.WNOHANG)
505                #print 'Solaris sucks'
506            except OSError: # This is crufty. When does this happen?
507                return 0
508            # If pid and status is still 0 after two calls to waitpid() then
509            # the process really is alive. This seems to work on all platforms.
510            if pid == 0 and status == 0:
511                return 1
512
513        # I do not OR this together because I want hooks for debugging.
514        if os.WIFEXITED (status):
515            self.exitstatus = os.WEXITSTATUS(status)
516            return 0
517        elif os.WIFSTOPPED (status):
518            return 0
519        elif os.WIFSIGNALED (status):
520            return 0
521        else:
522            return 0 # Can I ever get here?
523
524    def kill(self, sig):
525        """This sends the given signal to the child application.
526        In keeping with UNIX tradition it has a misleading name.
527        It does not necessarily kill the child unless
528        you send the right signal.
529        """
530        # Same as os.kill, but the pid is given for you.
531        if self.isalive():
532            os.kill(self.pid, sig)
533
534    def compile_pattern_list(self, patterns):
535        """This compiles a pattern-string or a list of pattern-strings.
536        Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or
537        a list of those.
538
539        This is used by expect() when calling expect_list().
540        Thus expect() is nothing more than::
541             cpl = self.compile_pattern_list(pl)
542             return self.expect_list(clp, timeout)
543
544        If you are using expect() within a loop it may be more
545        efficient to compile the patterns first and then call expect_list().
546        This avoid calls in a loop to compile_pattern_list():
547             cpl = self.compile_pattern_list(my_pattern)
548             while some_condition:
549                ...
550                i = self.expect_list(clp, timeout)
551                ...
552        """
553        if type(patterns) is not ListType:
554            patterns = [patterns]
555
556        compiled_pattern_list = []
557        for p in patterns:
558            if type(p) is StringType:
559                compiled_pattern_list.append(re.compile(p, re.DOTALL))
560            elif p is EOF:
561                compiled_pattern_list.append(EOF)
562            elif p is TIMEOUT:
563                compiled_pattern_list.append(TIMEOUT)
564            elif type(p) is type(re.compile('')):
565                compiled_pattern_list.append(p)
566            else:
567                raise TypeError, 'Argument must be one of StringType, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p))
568
569        return compiled_pattern_list
570 
571    def expect(self, pattern, timeout = -1):
572        """This seeks through the stream until a pattern is matched.
573        The pattern is overloaded and may take several types including a list.
574        The pattern can be a StringType, EOF, a compiled re, or
575        a list of those types. Strings will be compiled to re types.
576        This returns the index into the pattern list. If the pattern was
577        not a list this returns index 0 on a successful match.
578        This may raise exceptions for EOF or TIMEOUT.
579        To avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to
580        the pattern list.
581
582        After a match is found the instance attributes
583        'before', 'after' and 'match' will be set.
584        You can see all the data read before the match in 'before'.
585        You can see the data that was matched in 'after'.
586        The re.MatchObject used in the re match will be in 'match'.
587        If an error occured then 'before' will be set to all the
588        data read so far and 'after' and 'match' will be None.
589
590        If timeout is -1 then timeout will be set to the self.timeout value.
591
592        Note: A list entry may be EOF or TIMEOUT instead of a string.
593        This will catch these exceptions and return the index
594        of the list entry instead of raising the exception.
595        The attribute 'after' will be set to the exception type.
596        The attribute 'match' will be None.
597        This allows you to write code like this:
598                index = p.expect (['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
599                if index == 0:
600                    do_something()
601                elif index == 1:
602                    do_something_else()
603                elif index == 2:
604                    do_some_other_thing()
605                elif index == 3:
606                    do_something_completely_different()
607        instead of code like this:
608                try:
609                    index = p.expect (['good', 'bad'])
610                    if index == 0:
611                        do_something()
612                    elif index == 1:
613                        do_something_else()
614                except EOF:
615                    do_some_other_thing()
616                except TIMEOUT:
617                    do_something_completely_different()
618        These two forms are equivalent. It all depends on what you want.
619        You can also just expect the EOF if you are waiting for all output
620        of a child to finish. For example:
621                p = pexpect.spawn('/bin/ls')
622                p.expect (pexpect.EOF)
623                print p.before
624        """
625        compiled_pattern_list = self.compile_pattern_list(pattern)
626        return self.expect_list(compiled_pattern_list, timeout)
627
628    def expect_exact (self, pattern_list, timeout = -1):
629        """This is similar to expect() except that it takes
630        list of plain strings instead of regular expressions.
631        The idea is that this should be much faster. It could also be
632        useful when you don't want to have to worry about escaping
633        regular expression characters that you want to match.
634        You may also pass just a string without a list and the single
635        string will be converted to a list.
636        If timeout is -1 then timeout will be set to the self.timeout value.
637        """
638        ### This is dumb. It shares most of the code with expect_list.
639        ### The only different is the comparison method and that
640        ### self.match is always None after calling this.
641        if timeout == -1:
642            timeout = self.timeout
643
644        if type(pattern_list) is StringType:
645            pattern_list = [pattern_list]
646
647        try:
648            #ED# incoming = ''
649            incoming = self.buffer
650            while 1: # Keep reading until exception or return.
651                #ED# c = self.read_nonblocking (1, timeout)
652                #ED# incoming = incoming + c
653
654                # Sequence through the list of patterns and look for a match.
655                index = -1
656                for str_target in pattern_list:
657                    index = index + 1
658                    if str_target is EOF or str_target is TIMEOUT: 
659                        continue # The Exception patterns are handled differently.
660                    match_index = incoming.find (str_target)
661                    if match_index >= 0:
662                        self.before = incoming [ : match_index]
663                        self.after = incoming [match_index : ]
664                        self.buffer = incoming [match_index + len(str_target):]
665                        self.match = None
666                        return index
667                c = self.read_nonblocking (self.maxread, timeout) 
668                incoming = incoming + c
669               
670        except EOF:
671            if EOF in pattern_list:
672                self.before = incoming
673                self.after = EOF
674                self.buffer = ''
675                return pattern_list.index(EOF)
676            else:
677                raise
678        except TIMEOUT:
679            if TIMEOUT in pattern_list:
680                self.before = incoming
681                self.after = TIMEOUT
682                self.buffer = ''
683                return pattern_list.index(TIMEOUT)
684            else:
685                raise
686        except Exception:
687            self.before = incoming
688            self.after = None
689            self.match = None
690            self.buffer = ''
691            raise
692           
693    def expect_list(self, pattern_list, timeout = -1):
694        """
695        This takes a list of compiled regular expressions and returns
696        the index into the pattern_list that matched the child's output.
697        This is called by expect(). It is similar to the expect() method
698        except that expect_list() is not overloaded. You must not pass
699        anything except a list of compiled regular expressions.
700        If timeout is -1 then timeout will be set to the self.timeout value.
701        """
702
703        if timeout == -1:
704            timeout = self.timeout
705       
706        try:
707            #ED# incoming = ''
708            incoming = self.buffer
709            while 1: # Keep reading until exception or return.
710                #ED# c = self.read_nonblocking (1, timeout)
711                #ED# incoming = incoming + c
712
713                # Sequence through the list of patterns and look for a match.
714                index = -1
715                for cre in pattern_list:
716                    index = index + 1
717                    if cre is EOF or cre is TIMEOUT: 
718                        continue # The patterns for PexpectExceptions are handled differently.
719                    match = cre.search(incoming)
720                    if match is not None:
721                        self.before = incoming[ : match.start()]
722                        self.after = incoming[match.start() : ]
723                        self.match = match
724                        self.buffer = incoming[match.end() : ]
725                        return index
726                # Read more data
727                c = self.read_nonblocking (self.maxread, timeout)
728                incoming = incoming + c
729               
730        except EOF:
731            if EOF in pattern_list:
732                self.before = incoming
733                self.after = EOF
734                self.buffer = ''
735                return pattern_list.index(EOF)
736            else:
737                raise
738        except TIMEOUT:
739            if TIMEOUT in pattern_list:
740                self.before = incoming
741                self.after = TIMEOUT
742                self.buffer = ''
743                return pattern_list.index(TIMEOUT)
744            else:
745                raise
746        except Exception:
747            self.before = incoming
748            self.after = None
749            self.match = None
750            self.buffer = ''
751            raise
752
753    def getwinsize(self):
754        """
755        This returns the window size of the child tty.
756        The return value is a tuple of (rows, cols).
757        """
758
759        s = struct.pack('HHHH', 0, 0, 0, 0)
760        x = fcntl.ioctl(self.fileno(), termios.TIOCGWINSZ, s)
761        return struct.unpack('HHHH', x)[0:2]
762
763    def setwinsize(self, r, c):
764        """
765        This sets the windowsize of the child tty.
766        This will cause a SIGWINCH signal to be sent to the child.
767        This does not change the physical window size.
768        It changes the size reported to TTY-aware applications like
769        vi or curses -- applications that respond to the SIGWINCH signal.
770        """
771        # Check for buggy platforms. Some Python versions on some platforms
772        # (notably OSF1 Alpha and RedHat 7.1) truncate the value for
773        # termios.TIOCSWINSZ. It is not clear why this happens.
774        # These platforms don't seem to handle the signed int very well;
775        # yet other platforms like OpenBSD have a large negative value for
776        # TIOCSWINSZ and they don't have a truncate problem.
777        # Newer versions of Linux have totally different values for TIOCSWINSZ.
778        #
779        # Note that this fix is a hack.
780        TIOCSWINSZ = termios.TIOCSWINSZ
781        if TIOCSWINSZ == 2148037735L: # L is not required in Python >= 2.2.
782            TIOCSWINSZ = -2146929561 # Same bits, but with sign.
783
784        # Note, assume ws_xpixel and ws_ypixel are zero.
785        s = struct.pack('HHHH', r, c, 0, 0)
786        fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
787
788    def interact(self, escape_character = chr(29)):
789        """This gives control of the child process to the interactive user
790        (the human at the keyboard).
791        Keystrokes are sent to the child process, and the stdout and stderr
792        output of the child process is printed.
793        When the user types the escape_character this method will stop.
794        The default for escape_character is ^] (ASCII 29).
795        This simply echos the child stdout and child stderr to the real
796        stdout and it echos the real stdin to the child stdin.
797        """
798        # Flush the buffer.
799        self.stdout.write (self.buffer)
800        self.buffer = ''
801        self.stdout.flush()
802        mode = tty.tcgetattr(self.STDIN_FILENO)
803        tty.setraw(self.STDIN_FILENO)
804        try:
805            self.__interact_copy(escape_character)
806        finally:
807            tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
808
809    def __interact_writen(self, fd, data):
810        """This is used by the interact() method.
811        """
812        while data != '' and self.isalive():
813            n = os.write(fd, data)
814            data = data[n:]
815    def __interact_read(self, fd):
816        """This is used by the interact() method.
817        """
818        return os.read(fd, 1000)
819    def __interact_copy(self, escape_character = None):
820        """This is used by the interact() method.
821        """
822        while self.isalive():
823            r, w, e = select.select([self.child_fd, self.STDIN_FILENO], [], [])
824            if self.child_fd in r:
825                data = self.__interact_read(self.child_fd)
826                os.write(self.STDOUT_FILENO, data)
827            if self.STDIN_FILENO in r:
828                data = self.__interact_read(self.STDIN_FILENO)
829                self.__interact_writen(self.child_fd, data)
830                if escape_character in data:
831                    break
832
833##############################################################################
834# End of Spawn
835##############################################################################
836
837def _which (filename):
838    """This takes a given filename; tries to find it in the
839    environment path; then checks if it is executable.
840    """
841
842    # Special case where filename already contains a path.
843    if os.path.dirname(filename) != '':
844        if os.access (filename, os.X_OK):
845            return filename
846
847    if not os.environ.has_key('PATH') or os.environ['PATH'] == '':
848        p = os.defpath
849    else:
850        p = os.environ['PATH']
851
852    # Oddly enough this was the one line that made Pexpect
853    # incompatible with Python 1.5.2.
854    #pathlist = p.split (os.pathsep)
855    pathlist = string.split (p, os.pathsep)
856
857    for path in pathlist:
858        f = os.path.join(path, filename)
859        if os.access(f, os.X_OK):
860            return f
861    return None
862
863def _split_command_line(command_line):
864    """This splits a command line into a list of arguments.
865    It splits arguments on spaces, but handles
866    embedded quotes, doublequotes, and escaped characters.
867    It's impossible to do this with a regular expression, so
868    I wrote a little state machine to parse the command line.
869    """
870    arg_list = []
871    arg = ''
872    state_quote = 0
873    state_doublequote = 0
874    state_esc = 0
875    for c in command_line:
876        if c == '\\': # Escape the next character
877            state_esc = 1
878        elif c == r"'": # Handle single quote
879            if state_esc:
880                state_esc = 0
881            elif not state_quote:
882                state_quote = 1
883            else:
884                state_quote = 0
885        elif c == r'"': # Handle double quote
886            if state_esc:
887                state_esc = 0
888            elif not state_doublequote:
889                state_doublequote = 1
890            else:
891                state_doublequote = 0
892
893        # Add arg to arg_list unless in some other state.
894        elif c == ' 'and not state_quote and not state_doublequote and not state_esc:
895            arg_list.append(arg)
896            arg = ''
897        else:
898            arg = arg + c
899            if c != '\\'and state_esc: # escape mode lasts for one character.
900                state_esc = 0
901
902    # Handle last argument.       
903    if arg != '':
904        arg_list.append(arg)
905    return arg_list
906
907import shlex
908def _split_command_line(command_line):
909    return shlex.split(command_line)
910
911
912####################
913#
914#        NOTES
915#
916####################
917
918##    def send_human(self, text, delay_min = 0, delay_max = 1):
919##        pass
920##    def spawn2(self, command, args):
921##        """return pid, fd_stdio, fd_stderr
922##        """
923##        pass
924
925
926# Reason for double fork:
927# http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC15
928# Reason for ptys:
929# http://www.erlenstar.demon.co.uk/unix/faq_4.html#SEC52
930
931# Nonblocking on Win32?
932# Reasearch this as a way to maybe make pipe work for Win32.
933# http://groups.google.com/groups?q=setraw+tty&hl=en&selm=uvgpvisvk.fsf%40roundpoint.com&rnum=7
934#
935#    if istty:
936#        if os.name=='posix':
937#            import tty
938#            tty.setraw(sys.stdin.fileno())
939#        elif os.name=='nt':
940#            import win32file, win32con
941#            hstdin = win32file._get_osfhandle(sys.stdin.fileno())
942#            modes = (win32file.GetConsoleMode(hstdin)
943#                     & ~(win32con.ENABLE_LINE_INPUT
944#                         |win32con.ENABLE_ECHO_INPUT))
945#            win32file.SetConsoleMode(hstdin, modes)
946
947# Basic documentation:
948#       Explain use of lists of patterns and return index.
949#       Explain exceptions for non-handled special cases like EOF
950
951# Test bad fork
952# Test ENOENT. In other words, no more TTY devices.
953
954#GLOBAL_SIGCHLD_RECEIVED = 0
955#def childdied (signum, frame):
956#    print 'Signal handler called with signal', signum
957#    frame.f_globals['pexpect'].GLOBAL_SIGCHLD_RECEIVED = 1
958#    print str(frame.f_globals['pexpect'].GLOBAL_SIGCHLD_RECEIVED)
959#    GLOBAL_SIGCHLD_RECEIVED = 1
960
961### Weird bug. If you read too fast after doing a sendline()
962# Sometimes you will read the data back that you just sent even if
963# the child did not echo the data. This is particularly a problem if
964# you send a password.
965
966# This was previously used to implement a look-ahead in reads.
967# if the lookahead failed then Pexpect would "push-back" the data
968# that was read. The idea was to allow read() to read blocks of data.
969# What I do now is just read one character at a time and then try a
970# match. This is not as efficient, but it works well enough for the
971# output of most applications and it makes program logic much simpler.
972##class PushbackReader:
973##    """This class is a wrapper around os.read. It adds the features of buffering
974##        to allow push-back of data and to provide a timeout on a read.
975##    """
976##    def __init__(self, file_descriptor):
977##        self.fd = file_descriptor
978##        self.buffer = ''
979##
980##    def read(self, n, timeout = None):
981##        """This does a read restricted by a timeout and
982##        it includes any cached data from previous calls.
983##            This is a non-blocking wrapper around os.read.
984##        it uses select.select to supply a timeout.
985##        Note that if this is called with timeout=None (the default)
986##        then this actually MAY block.
987##        """
988##        # The read() call is a problem.
989##        # Some platforms return an empty string '' at EOF.
990##        # Whereas other platforms raise an Input/output exception.
991##
992##        avail = len(self.buffer)
993##        if n > avail:
994##            result = self.buffer
995##            n = n-avail
996##        else:
997##            result = self.buffer[: n]
998##            self.buffer = self.buffer[n:]
999##
1000##        r, w, e = select.select([self.fd], [], [], timeout)
1001##        if not r:
1002##            self.flag_timeout = 1
1003##            raise TIMEOUT('Read exceeded time: %d'%timeout)
1004##
1005##        if self.fd in r:
1006##            try:
1007##                s = os.read(self.fd, n)
1008##            except OSError, e:
1009##                self.flag_eof = 1
1010##                raise EOF('Read reached End Of File (EOF). Exception platform.')
1011##            if s == '':
1012##                self.flag_eof = 1
1013##                raise EOF('Read reached End Of File (EOF). Empty string platform.')
1014##            return s
1015##
1016##        self.flag_error = 1
1017##        raise ExceptionPexpect('PushbackReader.read() reached an unexpected state.'+
1018##        ' There is a logic error in the Pexpect source code.')
1019##
1020##    def pushback(self, data):
1021##        self.buffer = piece+self.buffer
1022
1023
1024#def _setwinsize(r, c):
1025#    """This sets the windowsize of the tty for stdout.
1026#    This does not change the physical window size.
1027#    It changes the size reported to TTY-aware applications like
1028#    vi or curses -- applications that respond to the SIGWINCH signal.
1029#    This is used by __spawn to set the tty window size of the child.
1030#    """
1031#    # Check for buggy platforms. Some Pythons on some platforms
1032#    # (notably OSF1 Alpha and RedHat 7.1) truncate the value for
1033#    # termios.TIOCSWINSZ. It is not clear why this happens.
1034#    # These platforms don't seem to handle the signed int very well;
1035#    # yet other platforms like OpenBSD have a large negative value for
1036#    # TIOCSWINSZ and they don't truncate.
1037#    # Newer versions of Linux have totally different values for TIOCSWINSZ.
1038#    #
1039#    # Note that this fix is a hack.
1040#    TIOCSWINSZ = termios.TIOCSWINSZ
1041#    if TIOCSWINSZ == 2148037735L: # L is not required in Python 2.2.
1042#        TIOCSWINSZ = -2146929561 # Same number in binary, but with sign.
1043#
1044#    # Assume ws_xpixel and ws_ypixel are zero.
1045#    s = struct.pack("HHHH", r, c, 0, 0)
1046#    fcntl.ioctl(sys.stdout.fileno(), TIOCSWINSZ, s)
1047#
1048#def _getwinsize():
1049#    s = struct.pack("HHHH", 0, 0, 0, 0)
1050#    x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, s)
1051#    return struct.unpack("HHHH", x)
1052
Note: See TracBrowser for help on using the repository browser.