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

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

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

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