| Index: third_party/pexpect/pexpect.py
|
| diff --git a/third_party/pexpect/pexpect.py b/third_party/pexpect/pexpect.py
|
| index 67c6389faa1cddcac5ea6b5b8c00360a7b810e4f..ade20b23dac113ab114463be68dffa8d7080f882 100644
|
| --- a/third_party/pexpect/pexpect.py
|
| +++ b/third_party/pexpect/pexpect.py
|
| @@ -9,62 +9,64 @@ use C, Expect, or TCL extensions. It should work on any platform that supports
|
| the standard Python pty module. The Pexpect interface focuses on ease of use so
|
| that simple tasks are easy.
|
|
|
| -There are two main interfaces to Pexpect -- the function, run() and the class,
|
| -spawn. You can call the run() function to execute a command and return the
|
| +There are two main interfaces to the Pexpect system; these are the function,
|
| +run() and the class, spawn. The spawn class is more powerful. The run()
|
| +function is simpler than spawn, and is good for quickly calling program. When
|
| +you call the run() function it executes a given program and then returns the
|
| output. This is a handy replacement for os.system().
|
|
|
| For example::
|
|
|
| pexpect.run('ls -la')
|
|
|
| -The more powerful interface is the spawn class. You can use this to spawn an
|
| -external child command and then interact with the child by sending lines and
|
| -expecting responses.
|
| +The spawn class is the more powerful interface to the Pexpect system. You can
|
| +use this to spawn a child program then interact with it by sending input and
|
| +expecting responses (waiting for patterns in the child's output).
|
|
|
| For example::
|
|
|
| - child = pexpect.spawn('scp foo myname@host.example.com:.')
|
| - child.expect ('Password:')
|
| - child.sendline (mypassword)
|
| + child = pexpect.spawn('scp foo user@example.com:.')
|
| + child.expect('Password:')
|
| + child.sendline(mypassword)
|
|
|
| This works even for commands that ask for passwords or other input outside of
|
| -the normal stdio streams.
|
| +the normal stdio streams. For example, ssh reads input directly from the TTY
|
| +device which bypasses stdin.
|
|
|
| Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
|
| Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
|
| vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
|
| -Geoffrey Marshall, Francisco Lourenco, Glen Mabey, Karthik Gurusamy, Fernando
|
| -Perez, Corey Minyard, Jon Cohen, Guillaume Chazarain, Andrew Ryan, Nick
|
| -Craig-Wood, Andrew Stone, Jorgen Grahn (Let me know if I forgot anyone.)
|
| -
|
| -Free, open source, and all that good stuff.
|
| -
|
| -Permission is hereby granted, free of charge, to any person obtaining a copy of
|
| -this software and associated documentation files (the "Software"), to deal in
|
| -the Software without restriction, including without limitation the rights to
|
| -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
| -of the Software, and to permit persons to whom the Software is furnished to do
|
| -so, subject to the following conditions:
|
| -
|
| -The above copyright notice and this permission notice shall be included in all
|
| -copies or substantial portions of the Software.
|
| -
|
| -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| -SOFTWARE.
|
| -
|
| -Pexpect Copyright (c) 2008 Noah Spurrier
|
| +Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey,
|
| +Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume
|
| +Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John
|
| +Spiegel, Jan Grant, and Shane Kerr. Let me know if I forgot anyone.
|
| +
|
| +Pexpect is free, open source, and all that good stuff.
|
| http://pexpect.sourceforge.net/
|
|
|
| -$Id: pexpect.py 507 2007-12-27 02:40:52Z noah $
|
| +PEXPECT LICENSE
|
| +
|
| + This license is approved by the OSI and FSF as GPL-compatible.
|
| + http://opensource.org/licenses/isc-license.txt
|
| +
|
| + Copyright (c) 2012, Noah Spurrier <noah@noah.org>
|
| + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
|
| + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
|
| + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
|
| + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
| + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
| + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
| + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
| + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
| + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
| + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
| +
|
| """
|
|
|
| try:
|
| - import os, sys, time
|
| + import os
|
| + import sys
|
| + import time
|
| import select
|
| import string
|
| import re
|
| @@ -78,17 +80,18 @@ try:
|
| import errno
|
| import traceback
|
| import signal
|
| -except ImportError, e:
|
| - raise ImportError (str(e) + """
|
| +except ImportError as e:
|
| + raise ImportError(str(e) + """
|
|
|
| A critical module was not found. Probably this operating system does not
|
| support it. Pexpect is intended for UNIX-like operating systems.""")
|
|
|
| -__version__ = '2.3'
|
| -__revision__ = '$Revision: 399 $'
|
| +__version__ = '2.6'
|
| +__revision__ = '1'
|
| __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run', 'which',
|
| 'split_command_line', '__version__', '__revision__']
|
|
|
| +
|
| # Exception classes used by this module.
|
| class ExceptionPexpect(Exception):
|
|
|
| @@ -124,9 +127,12 @@ class ExceptionPexpect(Exception):
|
| else:
|
| return False
|
|
|
| +
|
| class EOF(ExceptionPexpect):
|
|
|
| - """Raised when EOF is read from a child. This usually means the child has exited."""
|
| + """Raised when EOF is read from a child.
|
| + This usually means the child has exited."""
|
| +
|
|
|
| class TIMEOUT(ExceptionPexpect):
|
|
|
| @@ -139,9 +145,11 @@ class TIMEOUT(ExceptionPexpect):
|
| ## may never match a pattern.
|
| ## """
|
| ##class MAXBUFFER(ExceptionPexpect):
|
| -## """Raised when a scan buffer fills before matching an expected pattern."""
|
| +## """Raised when a buffer fills before matching an expected pattern."""
|
| +
|
|
|
| -def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None, logfile=None, cwd=None, env=None):
|
| +def run(command, timeout=-1, withexitstatus=False, events=None,
|
| + extra_args=None, logfile=None, cwd=None, env=None):
|
|
|
| """
|
| This function runs the given command; waits for it to finish; then
|
| @@ -149,7 +157,7 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
| path to the command is not given then the path is searched.
|
|
|
| Note that lines are terminated by CR/LF (\\r\\n) combination even on
|
| - UNIX-like systems because this is the standard for pseudo ttys. If you set
|
| + UNIX-like systems because this is the standard for pseudottys. If you set
|
| 'withexitstatus' to true, then run will return a tuple of (command_output,
|
| exitstatus). If 'withexitstatus' is false then this returns just
|
| command_output.
|
| @@ -158,14 +166,14 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
| For example, the following code uses spawn::
|
|
|
| from pexpect import *
|
| - child = spawn('scp foo myname@host.example.com:.')
|
| - child.expect ('(?i)password')
|
| - child.sendline (mypassword)
|
| + child = spawn('scp foo user@example.com:.')
|
| + child.expect('(?i)password')
|
| + child.sendline(mypassword)
|
|
|
| The previous code can be replace with the following::
|
|
|
| from pexpect import *
|
| - run ('scp foo myname@host.example.com:.', events={'(?i)password': mypassword})
|
| + run('scp foo user@example.com:.', events={'(?i)password': mypassword})
|
|
|
| Examples
|
| ========
|
| @@ -173,17 +181,17 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
| Start the apache daemon on the local machine::
|
|
|
| from pexpect import *
|
| - run ("/usr/local/apache/bin/apachectl start")
|
| + run("/usr/local/apache/bin/apachectl start")
|
|
|
| Check in a file using SVN::
|
|
|
| from pexpect import *
|
| - run ("svn ci -m 'automatic commit' my_file.py")
|
| + run("svn ci -m 'automatic commit' my_file.py")
|
|
|
| Run a command and capture exit status::
|
|
|
| from pexpect import *
|
| - (command_output, exitstatus) = run ('ls -l /bin', withexitstatus=1)
|
| + (command_output, exitstatus) = run('ls -l /bin', withexitstatus=1)
|
|
|
| Tricky Examples
|
| ===============
|
| @@ -191,7 +199,8 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
| The following will run SSH and execute 'ls -l' on the remote machine. The
|
| password 'secret' will be sent if the '(?i)password' pattern is ever seen::
|
|
|
| - run ("ssh username@machine.example.com 'ls -l'", events={'(?i)password':'secret\\n'})
|
| + run("ssh username@machine.example.com 'ls -l'",
|
| + events={'(?i)password':'secret\\n'})
|
|
|
| This will start mencoder to rip a video from DVD. This will also display
|
| progress ticks every 5 seconds as it runs. For example::
|
| @@ -199,7 +208,8 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
| from pexpect import *
|
| def print_ticks(d):
|
| print d['event_count'],
|
| - run ("mencoder dvd://1 -o video.avi -oac copy -ovc copy", events={TIMEOUT:print_ticks}, timeout=5)
|
| + run("mencoder dvd://1 -o video.avi -oac copy -ovc copy",
|
| + events={TIMEOUT:print_ticks}, timeout=5)
|
|
|
| The 'events' argument should be a dictionary of patterns and responses.
|
| Whenever one of the patterns is seen in the command out run() will send the
|
| @@ -218,25 +228,29 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
| if timeout == -1:
|
| child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env)
|
| else:
|
| - child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, cwd=cwd, env=env)
|
| + child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile,
|
| + cwd=cwd, env=env)
|
| if events is not None:
|
| - patterns = events.keys()
|
| - responses = events.values()
|
| + patterns = list(events.keys())
|
| + responses = list(events.values())
|
| else:
|
| - patterns=None # We assume that EOF or TIMEOUT will save us.
|
| - responses=None
|
| + # This assumes EOF or TIMEOUT will eventually cause run to terminate.
|
| + patterns = None
|
| + responses = None
|
| child_result_list = []
|
| event_count = 0
|
| - while 1:
|
| + while True:
|
| try:
|
| - index = child.expect (patterns)
|
| + index = child.expect(patterns)
|
| if type(child.after) in types.StringTypes:
|
| child_result_list.append(child.before + child.after)
|
| - else: # child.after may have been a TIMEOUT or EOF, so don't cat those.
|
| + else:
|
| + # child.after may have been a TIMEOUT or EOF,
|
| + # which we don't want appended to the list.
|
| child_result_list.append(child.before)
|
| if type(responses[index]) in types.StringTypes:
|
| child.send(responses[index])
|
| - elif type(responses[index]) is types.FunctionType:
|
| + elif isinstance(responses[index], types.FunctionType):
|
| callback_result = responses[index](locals())
|
| sys.stdout.flush()
|
| if type(callback_result) in types.StringTypes:
|
| @@ -244,12 +258,12 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
| elif callback_result:
|
| break
|
| else:
|
| - raise TypeError ('The callback must be a string or function type.')
|
| + raise TypeError('The callback must be a string or function.')
|
| event_count = event_count + 1
|
| - except TIMEOUT, e:
|
| + except TIMEOUT as e:
|
| child_result_list.append(child.before)
|
| break
|
| - except EOF, e:
|
| + except EOF as e:
|
| child_result_list.append(child.before)
|
| break
|
| child_result = ''.join(child_result_list)
|
| @@ -259,25 +273,27 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
| else:
|
| return child_result
|
|
|
| -class spawn (object):
|
| +
|
| +class spawn(object):
|
|
|
| """This is the main class interface for Pexpect. Use this class to start
|
| and control child applications. """
|
|
|
| - def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None):
|
| + def __init__(self, command, args=[], timeout=30, maxread=2000,
|
| + searchwindowsize=None, logfile=None, cwd=None, env=None):
|
|
|
| """This is the constructor. The command parameter may be a string that
|
| includes a command and any arguments to the command. For example::
|
|
|
| - child = pexpect.spawn ('/usr/bin/ftp')
|
| - child = pexpect.spawn ('/usr/bin/ssh user@example.com')
|
| - child = pexpect.spawn ('ls -latr /tmp')
|
| + child = pexpect.spawn('/usr/bin/ftp')
|
| + child = pexpect.spawn('/usr/bin/ssh user@example.com')
|
| + child = pexpect.spawn('ls -latr /tmp')
|
|
|
| You may also construct it with a list of arguments like so::
|
|
|
| - child = pexpect.spawn ('/usr/bin/ftp', [])
|
| - child = pexpect.spawn ('/usr/bin/ssh', ['user@example.com'])
|
| - child = pexpect.spawn ('ls', ['-latr', '/tmp'])
|
| + child = pexpect.spawn('/usr/bin/ftp', [])
|
| + child = pexpect.spawn('/usr/bin/ssh', ['user@example.com'])
|
| + child = pexpect.spawn('ls', ['-latr', '/tmp'])
|
|
|
| After this the child application will be created and will be ready to
|
| talk to. For normal use, see expect() and send() and sendline().
|
| @@ -287,7 +303,7 @@ class spawn (object):
|
| If you want to run a command and pipe it through another command then
|
| you must also start a shell. For example::
|
|
|
| - child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"')
|
| + child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"')
|
| child.expect(pexpect.EOF)
|
|
|
| The second form of spawn (where you pass a list of arguments) is useful
|
| @@ -295,7 +311,7 @@ class spawn (object):
|
| argument list. This can make syntax more clear. For example, the
|
| following is equivalent to the previous example::
|
|
|
| - shell_cmd = 'ls -l | grep LOG > log_list.txt'
|
| + shell_cmd = 'ls -l | grep LOG > logs.txt'
|
| child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
|
| child.expect(pexpect.EOF)
|
|
|
| @@ -336,12 +352,12 @@ class spawn (object):
|
| the input from the child and output sent to the child. Sometimes you
|
| don't want to see everything you write to the child. You only want to
|
| log what the child sends back. For example::
|
| -
|
| +
|
| child = pexpect.spawn('some_command')
|
| child.logfile_read = sys.stdout
|
|
|
| To separately log output sent to the child use logfile_send::
|
| -
|
| +
|
| self.logfile_send = fout
|
|
|
| The delaybeforesend helps overcome a weird behavior that many users
|
| @@ -390,43 +406,56 @@ class spawn (object):
|
| self.terminated = True
|
| self.exitstatus = None
|
| self.signalstatus = None
|
| - self.status = None # status returned by os.waitpid
|
| + # status returned by os.waitpid
|
| + self.status = None
|
| self.flag_eof = False
|
| self.pid = None
|
| - self.child_fd = -1 # initially closed
|
| + # the chile filedescriptor is initially closed
|
| + self.child_fd = -1
|
| self.timeout = timeout
|
| self.delimiter = EOF
|
| self.logfile = logfile
|
| - self.logfile_read = None # input from child (read_nonblocking)
|
| - self.logfile_send = None # output to send (send, sendline)
|
| - self.maxread = maxread # max bytes to read at one time into buffer
|
| - self.buffer = '' # This is the read buffer. See maxread.
|
| - self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched.
|
| - # Most Linux machines don't like delaybeforesend to be below 0.03 (30 ms).
|
| - self.delaybeforesend = 0.05 # Sets sleep time used just before sending data to child. Time in seconds.
|
| - self.delayafterclose = 0.1 # Sets delay in close() method to allow kernel time to update process status. Time in seconds.
|
| - self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds.
|
| - self.softspace = False # File-like object.
|
| - self.name = '<' + repr(self) + '>' # File-like object.
|
| - self.encoding = None # File-like object.
|
| - self.closed = True # File-like object.
|
| + # input from child (read_nonblocking)
|
| + self.logfile_read = None
|
| + # output to send (send, sendline)
|
| + self.logfile_send = None
|
| + # max bytes to read at one time into buffer
|
| + self.maxread = maxread
|
| + # This is the read buffer. See maxread.
|
| + self.buffer = ''
|
| + # Data before searchwindowsize point is preserved, but not searched.
|
| + self.searchwindowsize = searchwindowsize
|
| + # Delay used before sending data to child. Time in seconds.
|
| + # Most Linux machines don't like this to be below 0.03 (30 ms).
|
| + self.delaybeforesend = 0.05
|
| + # Used by close() to give kernel time to update process status.
|
| + # Time in seconds.
|
| + self.delayafterclose = 0.1
|
| + # Used by terminate() to give kernel time to update process status.
|
| + # Time in seconds.
|
| + self.delayafterterminate = 0.1
|
| + self.softspace = False
|
| + self.name = '<' + repr(self) + '>'
|
| + self.encoding = None
|
| + self.closed = True
|
| self.cwd = cwd
|
| self.env = env
|
| - self.__irix_hack = (sys.platform.lower().find('irix')>=0) # This flags if we are running on irix
|
| + # This flags if we are running on irix
|
| + self.__irix_hack = (sys.platform.lower().find('irix') >= 0)
|
| # Solaris uses internal __fork_pty(). All others use pty.fork().
|
| - if (sys.platform.lower().find('solaris')>=0) or (sys.platform.lower().find('sunos5')>=0):
|
| + if ((sys.platform.lower().find('solaris') >= 0)
|
| + or (sys.platform.lower().find('sunos5') >= 0)):
|
| self.use_native_pty_fork = False
|
| else:
|
| self.use_native_pty_fork = True
|
|
|
| -
|
| - # allow dummy instances for subclasses that may not use command or args.
|
| + # Support subclasses that do not use command or args.
|
| if command is None:
|
| self.command = None
|
| self.args = None
|
| self.name = '<pexpect factory incomplete>'
|
| else:
|
| - self._spawn (command, args)
|
| + self._spawn(command, args)
|
|
|
| def __del__(self):
|
|
|
| @@ -443,7 +472,7 @@ class spawn (object):
|
| # -- Fernando Perez
|
| try:
|
| self.close()
|
| - except AttributeError:
|
| + except:
|
| pass
|
|
|
| def __str__(self):
|
| @@ -480,7 +509,7 @@ class spawn (object):
|
| s.append('delayafterterminate: ' + str(self.delayafterterminate))
|
| return '\n'.join(s)
|
|
|
| - def _spawn(self,command,args=[]):
|
| + def _spawn(self, command, args=[]):
|
|
|
| """This starts the given command in a child process. This does all the
|
| fork/exec type of stuff for a pty. This is called by __init__. If args
|
| @@ -493,46 +522,54 @@ class spawn (object):
|
| # So the only way you can tell if the child process started
|
| # or not is to try to read from the file descriptor. If you get
|
| # EOF immediately then it means that the child is already dead.
|
| - # That may not necessarily be bad because you may haved spawned a child
|
| + # That may not necessarily be bad because you may have spawned a child
|
| # that performs some task; creates no stdout output; and then dies.
|
|
|
| # If command is an int type then it may represent a file descriptor.
|
| - if type(command) == type(0):
|
| - raise ExceptionPexpect ('Command is an int type. If this is a file descriptor then maybe you want to use fdpexpect.fdspawn which takes an existing file descriptor instead of a command string.')
|
| + if isinstance(command, type(0)):
|
| + raise ExceptionPexpect('Command is an int type. ' +
|
| + 'If this is a file descriptor then maybe you want to ' +
|
| + 'use fdpexpect.fdspawn which takes an existing ' +
|
| + 'file descriptor instead of a command string.')
|
|
|
| - if type (args) != type([]):
|
| - raise TypeError ('The argument, args, must be a list.')
|
| + if not isinstance(args, type([])):
|
| + raise TypeError('The argument, args, must be a list.')
|
|
|
| if args == []:
|
| self.args = split_command_line(command)
|
| self.command = self.args[0]
|
| else:
|
| - self.args = args[:] # work with a copy
|
| - self.args.insert (0, command)
|
| + # Make a shallow copy of the args list.
|
| + self.args = args[:]
|
| + self.args.insert(0, command)
|
| self.command = command
|
|
|
| command_with_path = which(self.command)
|
| if command_with_path is None:
|
| - raise ExceptionPexpect ('The command was not found or was not executable: %s.' % self.command)
|
| + raise ExceptionPexpect('The command was not found or was not ' +
|
| + 'executable: %s.' % self.command)
|
| self.command = command_with_path
|
| self.args[0] = self.command
|
|
|
| - self.name = '<' + ' '.join (self.args) + '>'
|
| + self.name = '<' + ' '.join(self.args) + '>'
|
|
|
| - assert self.pid is None, 'The pid member should be None.'
|
| - assert self.command is not None, 'The command member should not be None.'
|
| + assert self.pid is None, 'The pid member must be None.'
|
| + assert self.command is not None, 'The command member must not be None.'
|
|
|
| if self.use_native_pty_fork:
|
| try:
|
| self.pid, self.child_fd = pty.fork()
|
| - except OSError, e:
|
| - raise ExceptionPexpect('Error! pty.fork() failed: ' + str(e))
|
| - else: # Use internal __fork_pty
|
| + except OSError as e:
|
| + raise ExceptionPexpect('pty.fork() failed: ' + str(e))
|
| + else:
|
| + # Use internal __fork_pty
|
| self.pid, self.child_fd = self.__fork_pty()
|
|
|
| - if self.pid == 0: # Child
|
| + if self.pid == 0:
|
| + # Child
|
| try:
|
| - self.child_fd = sys.stdout.fileno() # used by setwinsize()
|
| + # used by setwinsize()
|
| + self.child_fd = sys.stdout.fileno()
|
| self.setwinsize(24, 80)
|
| except:
|
| # Some platforms do not like setwinsize (Cygwin).
|
| @@ -542,9 +579,9 @@ class spawn (object):
|
| pass
|
| # Do not allow child to inherit open file descriptors from parent.
|
| max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
|
| - for i in range (3, max_fd):
|
| + for i in range(3, max_fd):
|
| try:
|
| - os.close (i)
|
| + os.close(i)
|
| except OSError:
|
| pass
|
|
|
| @@ -581,11 +618,11 @@ class spawn (object):
|
|
|
| parent_fd, child_fd = os.openpty()
|
| if parent_fd < 0 or child_fd < 0:
|
| - raise ExceptionPexpect, "Error! Could not open pty with os.openpty()."
|
| + raise ExceptionPexpect("Could not open with os.openpty().")
|
|
|
| pid = os.fork()
|
| if pid < 0:
|
| - raise ExceptionPexpect, "Error! Failed os.fork()."
|
| + raise ExceptionPexpect("Failed os.fork().")
|
| elif pid == 0:
|
| # Child.
|
| os.close(parent_fd)
|
| @@ -611,45 +648,51 @@ class spawn (object):
|
|
|
| child_name = os.ttyname(tty_fd)
|
|
|
| - # Disconnect from controlling tty if still connected.
|
| - fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
|
| - if fd >= 0:
|
| - os.close(fd)
|
| + # Disconnect from controlling tty. Harmless if not already connected.
|
| + try:
|
| + fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
|
| + if fd >= 0:
|
| + os.close(fd)
|
| + except:
|
| + # Already disconnected. This happens if running inside cron.
|
| + pass
|
|
|
| os.setsid()
|
|
|
| # Verify we are disconnected from controlling tty
|
| + # by attempting to open it again.
|
| try:
|
| - fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
|
| + fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
|
| if fd >= 0:
|
| os.close(fd)
|
| - raise ExceptionPexpect, "Error! We are not disconnected from a controlling tty."
|
| + raise ExceptionPexpect('Failed to disconnect from ' +
|
| + 'controlling tty. It is still possible to open /dev/tty.')
|
| except:
|
| # Good! We are disconnected from a controlling tty.
|
| pass
|
|
|
| # Verify we can open child pty.
|
| - fd = os.open(child_name, os.O_RDWR);
|
| + fd = os.open(child_name, os.O_RDWR)
|
| if fd < 0:
|
| - raise ExceptionPexpect, "Error! Could not open child pty, " + child_name
|
| + raise ExceptionPexpect("Could not open child pty, " + child_name)
|
| else:
|
| os.close(fd)
|
|
|
| # Verify we now have a controlling tty.
|
| fd = os.open("/dev/tty", os.O_WRONLY)
|
| if fd < 0:
|
| - raise ExceptionPexpect, "Error! Could not open controlling tty, /dev/tty"
|
| + raise ExceptionPexpect("Could not open controlling tty, /dev/tty")
|
| else:
|
| os.close(fd)
|
|
|
| - def fileno (self): # File-like object.
|
| + def fileno(self):
|
|
|
| """This returns the file descriptor of the pty for the child.
|
| """
|
|
|
| return self.child_fd
|
|
|
| - def close (self, force=True): # File-like object.
|
| + def close(self, force=True):
|
|
|
| """This closes the connection with the child application. Note that
|
| calling close() more than once is valid. This emulates standard Python
|
| @@ -659,30 +702,31 @@ class spawn (object):
|
|
|
| if not self.closed:
|
| self.flush()
|
| - os.close (self.child_fd)
|
| - time.sleep(self.delayafterclose) # Give kernel time to update process status.
|
| + os.close(self.child_fd)
|
| + # Give kernel time to update process status.
|
| + time.sleep(self.delayafterclose)
|
| if self.isalive():
|
| if not self.terminate(force):
|
| - raise ExceptionPexpect ('close() could not terminate the child using terminate()')
|
| + raise ExceptionPexpect('Could not terminate the child.')
|
| self.child_fd = -1
|
| self.closed = True
|
| #self.pid = None
|
|
|
| - def flush (self): # File-like object.
|
| + def flush(self):
|
|
|
| """This does nothing. It is here to support the interface for a
|
| File-like object. """
|
|
|
| pass
|
|
|
| - def isatty (self): # File-like object.
|
| + def isatty(self):
|
|
|
| """This returns True if the file descriptor is open and connected to a
|
| tty(-like) device, else False. """
|
|
|
| return os.isatty(self.child_fd)
|
|
|
| - def waitnoecho (self, timeout=-1):
|
| + def waitnoecho(self, timeout=-1):
|
|
|
| """This waits until the terminal ECHO flag is set False. This returns
|
| True if the echo mode is off. This returns False if the ECHO flag was
|
| @@ -692,19 +736,18 @@ class spawn (object):
|
| example, instead of expecting the "password:" prompt you can wait for
|
| the child to set ECHO off::
|
|
|
| - p = pexpect.spawn ('ssh user@example.com')
|
| + p = pexpect.spawn('ssh user@example.com')
|
| p.waitnoecho()
|
| p.sendline(mypassword)
|
|
|
| - If timeout is None then this method to block forever until ECHO flag is
|
| - False.
|
| -
|
| + If timeout==-1 then this method will use the value in self.timeout.
|
| + If timeout==None then this method to block until ECHO flag is False.
|
| """
|
|
|
| if timeout == -1:
|
| timeout = self.timeout
|
| if timeout is not None:
|
| - end_time = time.time() + timeout
|
| + end_time = time.time() + timeout
|
| while True:
|
| if not self.getecho():
|
| return True
|
| @@ -714,7 +757,7 @@ class spawn (object):
|
| timeout = end_time - time.time()
|
| time.sleep(0.1)
|
|
|
| - def getecho (self):
|
| + def getecho(self):
|
|
|
| """This returns the terminal echo mode. This returns True if echo is
|
| on or False if echo is off. Child applications that are expecting you
|
| @@ -725,35 +768,35 @@ class spawn (object):
|
| return True
|
| return False
|
|
|
| - def setecho (self, state):
|
| + def setecho(self, state):
|
|
|
| """This sets the terminal echo mode on or off. Note that anything the
|
| child sent before the echo will be lost, so you should be sure that
|
| your input buffer is empty before you call setecho(). For example, the
|
| following will work as expected::
|
|
|
| - p = pexpect.spawn('cat')
|
| - p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
|
| - p.expect (['1234'])
|
| - p.expect (['1234'])
|
| + p = pexpect.spawn('cat') # Echo is on by default.
|
| + p.sendline('1234') # We expect see this twice from the child...
|
| + p.expect(['1234']) # ... once from the tty echo...
|
| + p.expect(['1234']) # ... and again from cat itself.
|
| p.setecho(False) # Turn off tty echo
|
| - p.sendline ('abcd') # We will set this only once (echoed by cat).
|
| - p.sendline ('wxyz') # We will set this only once (echoed by cat)
|
| - p.expect (['abcd'])
|
| - p.expect (['wxyz'])
|
| + p.sendline('abcd') # We will set this only once (echoed by cat).
|
| + p.sendline('wxyz') # We will set this only once (echoed by cat)
|
| + p.expect(['abcd'])
|
| + p.expect(['wxyz'])
|
|
|
| The following WILL NOT WORK because the lines sent before the setecho
|
| will be lost::
|
|
|
| p = pexpect.spawn('cat')
|
| - p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
|
| + p.sendline('1234')
|
| p.setecho(False) # Turn off tty echo
|
| - p.sendline ('abcd') # We will set this only once (echoed by cat).
|
| - p.sendline ('wxyz') # We will set this only once (echoed by cat)
|
| - p.expect (['1234'])
|
| - p.expect (['1234'])
|
| - p.expect (['abcd'])
|
| - p.expect (['wxyz'])
|
| + p.sendline('abcd') # We will set this only once (echoed by cat).
|
| + p.sendline('wxyz') # We will set this only once (echoed by cat)
|
| + p.expect(['1234'])
|
| + p.expect(['1234'])
|
| + p.expect(['abcd'])
|
| + p.expect(['wxyz'])
|
| """
|
|
|
| self.child_fd
|
| @@ -762,11 +805,12 @@ class spawn (object):
|
| attr[3] = attr[3] | termios.ECHO
|
| else:
|
| attr[3] = attr[3] & ~termios.ECHO
|
| - # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent
|
| - # and blocked on some platforms. TCSADRAIN is probably ideal if it worked.
|
| + # I tried TCSADRAIN and TCSAFLUSH, but
|
| + # these were inconsistent and blocked on some platforms.
|
| + # TCSADRAIN would probably be ideal if it worked.
|
| termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
|
|
|
| - def read_nonblocking (self, size = 1, timeout = -1):
|
| + def read_nonblocking(self, size=1, timeout=-1):
|
|
|
| """This reads at most size characters from the child application. It
|
| includes a timeout. If the read does not complete within the timeout
|
| @@ -774,10 +818,10 @@ class spawn (object):
|
| then an EOF exception will be raised. If a log file was set using
|
| setlog() then all data will also be written to the log file.
|
|
|
| - If timeout is None then the read may block indefinitely. If timeout is -1
|
| - then the self.timeout value is used. If timeout is 0 then the child is
|
| - polled and if there was no data immediately ready then this will raise
|
| - a TIMEOUT exception.
|
| + If timeout is None then the read may block indefinitely.
|
| + If timeout is -1 then the self.timeout value is used. If timeout is 0
|
| + then the child is polled and if there is no data immediately ready
|
| + then this will raise a TIMEOUT exception.
|
|
|
| The timeout refers only to the amount of time to read at least one
|
| character. This is not effected by the 'size' parameter, so if you call
|
| @@ -789,7 +833,7 @@ class spawn (object):
|
| implement the timeout. """
|
|
|
| if self.closed:
|
| - raise ValueError ('I/O operation on closed file in read_nonblocking().')
|
| + raise ValueError('I/O operation on closed file.')
|
|
|
| if timeout == -1:
|
| timeout = self.timeout
|
| @@ -800,51 +844,54 @@ class spawn (object):
|
| # For this case, I test isalive() before doing any reading.
|
| # If isalive() is false, then I pretend that this is the same as EOF.
|
| if not self.isalive():
|
| - r,w,e = self.__select([self.child_fd], [], [], 0) # timeout of 0 means "poll"
|
| + # timeout of 0 means "poll"
|
| + r, w, e = self.__select([self.child_fd], [], [], 0)
|
| if not r:
|
| self.flag_eof = True
|
| - raise EOF ('End Of File (EOF) in read_nonblocking(). Braindead platform.')
|
| + raise EOF('End Of File (EOF). Braindead platform.')
|
| elif self.__irix_hack:
|
| - # This is a hack for Irix. It seems that Irix requires a long delay before checking isalive.
|
| - # This adds a 2 second delay, but only when the child is terminated.
|
| + # Irix takes a long time before it realizes a child was terminated.
|
| + # FIXME So does this mean Irix systems are forced to always have
|
| + # FIXME a 2 second delay when calling read_nonblocking? That sucks.
|
| r, w, e = self.__select([self.child_fd], [], [], 2)
|
| if not r and not self.isalive():
|
| self.flag_eof = True
|
| - raise EOF ('End Of File (EOF) in read_nonblocking(). Pokey platform.')
|
| + raise EOF('End Of File (EOF). Slow platform.')
|
|
|
| - r,w,e = self.__select([self.child_fd], [], [], timeout)
|
| + r, w, e = self.__select([self.child_fd], [], [], timeout)
|
|
|
| if not r:
|
| if not self.isalive():
|
| - # Some platforms, such as Irix, will claim that their processes are alive;
|
| - # then timeout on the select; and then finally admit that they are not alive.
|
| + # Some platforms, such as Irix, will claim that their
|
| + # processes are alive; timeout on the select; and
|
| + # then finally admit that they are not alive.
|
| self.flag_eof = True
|
| - raise EOF ('End of File (EOF) in read_nonblocking(). Very pokey platform.')
|
| + raise EOF('End of File (EOF). Very slow platform.')
|
| else:
|
| - raise TIMEOUT ('Timeout exceeded in read_nonblocking().')
|
| + raise TIMEOUT('Timeout exceeded.')
|
|
|
| if self.child_fd in r:
|
| try:
|
| s = os.read(self.child_fd, size)
|
| - except OSError, e: # Linux does this
|
| + except OSError as e:
|
| + # Linux does this
|
| self.flag_eof = True
|
| - raise EOF ('End Of File (EOF) in read_nonblocking(). Exception style platform.')
|
| - if s == '': # BSD style
|
| + raise EOF('End Of File (EOF). Exception style platform.')
|
| + if s == '':
|
| + # BSD style
|
| self.flag_eof = True
|
| - raise EOF ('End Of File (EOF) in read_nonblocking(). Empty string style platform.')
|
| -
|
| + raise EOF('End Of File (EOF). Empty string style platform.')
|
| if self.logfile is not None:
|
| - self.logfile.write (s)
|
| + self.logfile.write(s)
|
| self.logfile.flush()
|
| if self.logfile_read is not None:
|
| - self.logfile_read.write (s)
|
| + self.logfile_read.write(s)
|
| self.logfile_read.flush()
|
| -
|
| return s
|
|
|
| - raise ExceptionPexpect ('Reached an unexpected state in read_nonblocking().')
|
| + raise ExceptionPexpect('Reached an unexpected state.')
|
|
|
| - def read (self, size = -1): # File-like object.
|
| + def read(self, size=-1):
|
|
|
| """This reads at most "size" bytes from the file (less if the read hits
|
| EOF before obtaining size bytes). If the size argument is negative or
|
| @@ -855,7 +902,8 @@ class spawn (object):
|
| if size == 0:
|
| return ''
|
| if size < 0:
|
| - self.expect (self.delimiter) # delimiter default is EOF
|
| + # delimiter default is EOF
|
| + self.expect(self.delimiter)
|
| return self.before
|
|
|
| # I could have done this more directly by not using expect(), but
|
| @@ -866,38 +914,43 @@ class spawn (object):
|
| # Note, it's OK if size==-1 in the regex. That just means it
|
| # will never match anything in which case we stop only on EOF.
|
| cre = re.compile('.{%d}' % size, re.DOTALL)
|
| - index = self.expect ([cre, self.delimiter]) # delimiter default is EOF
|
| + # delimiter default is EOF
|
| + index = self.expect([cre, self.delimiter])
|
| if index == 0:
|
| - return self.after ### self.before should be ''. Should I assert this?
|
| + ### FIXME self.before should be ''. Should I assert this?
|
| + return self.after
|
| return self.before
|
|
|
| - def readline (self, size = -1): # File-like object.
|
| + def readline(self, size=-1):
|
| +
|
| + """This reads and returns one entire line. The newline at the end of
|
| + line is returned as part of the string, unless the file ends without a
|
| + newline. An empty string is returned if EOF is encountered immediately.
|
| + This looks for a newline as a CR/LF pair (\\r\\n) even on UNIX because
|
| + this is what the pseudotty device returns. So contrary to what you may
|
| + expect you will receive newlines as \\r\\n.
|
|
|
| - """This reads and returns one entire line. A trailing newline is kept
|
| - in the string, but may be absent when a file ends with an incomplete
|
| - line. Note: This readline() looks for a \\r\\n pair even on UNIX
|
| - because this is what the pseudo tty device returns. So contrary to what
|
| - you may expect you will receive the newline as \\r\\n. An empty string
|
| - is returned when EOF is hit immediately. Currently, the size argument is
|
| - mostly ignored, so this behavior is not standard for a file-like
|
| - object. If size is 0 then an empty string is returned. """
|
| + If the size argument is 0 then an empty string is returned. In all
|
| + other cases the size argument is ignored, which is not standard
|
| + behavior for a file-like object. """
|
|
|
| if size == 0:
|
| return ''
|
| - index = self.expect (['\r\n', self.delimiter]) # delimiter default is EOF
|
| + # delimiter default is EOF
|
| + index = self.expect(['\r\n', self.delimiter])
|
| if index == 0:
|
| return self.before + '\r\n'
|
| else:
|
| return self.before
|
|
|
| - def __iter__ (self): # File-like object.
|
| + def __iter__(self):
|
|
|
| """This is to support iterators over a file-like object.
|
| """
|
|
|
| return self
|
|
|
| - def next (self): # File-like object.
|
| + def __next__(self):
|
|
|
| """This is to support iterators over a file-like object.
|
| """
|
| @@ -907,10 +960,10 @@ class spawn (object):
|
| raise StopIteration
|
| return result
|
|
|
| - def readlines (self, sizehint = -1): # File-like object.
|
| + def readlines(self, sizehint=-1):
|
|
|
| """This reads until EOF using readline() and returns a list containing
|
| - the lines thus read. The optional "sizehint" argument is ignored. """
|
| + the lines thus read. The optional 'sizehint' argument is ignored. """
|
|
|
| lines = []
|
| while True:
|
| @@ -920,14 +973,14 @@ class spawn (object):
|
| lines.append(line)
|
| return lines
|
|
|
| - def write(self, s): # File-like object.
|
| + def write(self, s):
|
|
|
| """This is similar to send() except that there is no return value.
|
| """
|
|
|
| - self.send (s)
|
| + self.send(s)
|
|
|
| - def writelines (self, sequence): # File-like object.
|
| + def writelines(self, sequence):
|
|
|
| """This calls write() for each element in the sequence. The sequence
|
| can be any iterable object producing strings, typically a list of
|
| @@ -935,7 +988,7 @@ class spawn (object):
|
| """
|
|
|
| for s in sequence:
|
| - self.write (s)
|
| + self.write(s)
|
|
|
| def send(self, s):
|
|
|
| @@ -945,21 +998,21 @@ class spawn (object):
|
|
|
| time.sleep(self.delaybeforesend)
|
| if self.logfile is not None:
|
| - self.logfile.write (s)
|
| + self.logfile.write(s)
|
| self.logfile.flush()
|
| if self.logfile_send is not None:
|
| - self.logfile_send.write (s)
|
| + self.logfile_send.write(s)
|
| self.logfile_send.flush()
|
| - c = os.write(self.child_fd, s)
|
| + c = os.write(self.child_fd, s.encode("utf-8"))
|
| return c
|
|
|
| def sendline(self, s=''):
|
|
|
| - """This is like send(), but it adds a line feed (os.linesep). This
|
| + """This is like send(), but it adds a linefeed (os.linesep). This
|
| returns the number of bytes written. """
|
|
|
| n = self.send(s)
|
| - n = n + self.send (os.linesep)
|
| + n = n + self.send(os.linesep)
|
| return n
|
|
|
| def sendcontrol(self, char):
|
| @@ -974,19 +1027,19 @@ class spawn (object):
|
|
|
| char = char.lower()
|
| a = ord(char)
|
| - if a>=97 and a<=122:
|
| + if a >= 97 and a <= 122:
|
| a = a - ord('a') + 1
|
| - return self.send (chr(a))
|
| - d = {'@':0, '`':0,
|
| - '[':27, '{':27,
|
| - '\\':28, '|':28,
|
| - ']':29, '}': 29,
|
| - '^':30, '~':30,
|
| - '_':31,
|
| - '?':127}
|
| + return self.send(chr(a))
|
| + d = {'@': 0, '`': 0,
|
| + '[': 27, '{': 27,
|
| + '\\': 28, '|': 28,
|
| + ']': 29, '}': 29,
|
| + '^': 30, '~': 30,
|
| + '_': 31,
|
| + '?': 127}
|
| if char not in d:
|
| return 0
|
| - return self.send (chr(d[char]))
|
| + return self.send(chr(d[char]))
|
|
|
| def sendeof(self):
|
|
|
| @@ -1005,14 +1058,14 @@ class spawn (object):
|
| #fd = sys.stdin.fileno()
|
| #old = termios.tcgetattr(fd) # remember current state
|
| #attr = termios.tcgetattr(fd)
|
| - #attr[3] = attr[3] | termios.ICANON # ICANON must be set to recognize EOF
|
| + #attr[3] = attr[3] | termios.ICANON # ICANON must be set to see EOF
|
| #try: # use try/finally to ensure state gets restored
|
| # termios.tcsetattr(fd, termios.TCSADRAIN, attr)
|
| # if hasattr(termios, 'CEOF'):
|
| - # os.write (self.child_fd, '%c' % termios.CEOF)
|
| + # os.write(self.child_fd, '%c' % termios.CEOF)
|
| # else:
|
| # # Silly platform does not define CEOF so assume CTRL-D
|
| - # os.write (self.child_fd, '%c' % 4)
|
| + # os.write(self.child_fd, '%c' % 4)
|
| #finally: # restore state
|
| # termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
| if hasattr(termios, 'VEOF'):
|
| @@ -1032,9 +1085,9 @@ class spawn (object):
|
| else:
|
| # platform does not define VINTR so assume CTRL-C
|
| char = chr(3)
|
| - self.send (char)
|
| + self.send(char)
|
|
|
| - def eof (self):
|
| + def eof(self):
|
|
|
| """This returns True if the EOF exception was ever raised.
|
| """
|
| @@ -1071,7 +1124,7 @@ class spawn (object):
|
| else:
|
| return False
|
| return False
|
| - except OSError, e:
|
| + except OSError as e:
|
| # I think there are kernel timing issues that sometimes cause
|
| # this to happen. I think isalive() reports True, but the
|
| # process is dead to the kernel.
|
| @@ -1087,26 +1140,29 @@ class spawn (object):
|
| """This waits until the child exits. This is a blocking call. This will
|
| not read any data from the child, so this will block forever if the
|
| child has unread output and has terminated. In other words, the child
|
| - may have printed output then called exit(); but, technically, the child
|
| - is still alive until its output is read. """
|
| + may have printed output then called exit(), but, the child is
|
| + technically still alive until its output is read by the parent. """
|
|
|
| if self.isalive():
|
| pid, status = os.waitpid(self.pid, 0)
|
| else:
|
| - raise ExceptionPexpect ('Cannot wait for dead child process.')
|
| + raise ExceptionPexpect('Cannot wait for dead child process.')
|
| self.exitstatus = os.WEXITSTATUS(status)
|
| - if os.WIFEXITED (status):
|
| + if os.WIFEXITED(status):
|
| self.status = status
|
| self.exitstatus = os.WEXITSTATUS(status)
|
| self.signalstatus = None
|
| self.terminated = True
|
| - elif os.WIFSIGNALED (status):
|
| + elif os.WIFSIGNALED(status):
|
| self.status = status
|
| self.exitstatus = None
|
| self.signalstatus = os.WTERMSIG(status)
|
| self.terminated = True
|
| - elif os.WIFSTOPPED (status):
|
| - raise ExceptionPexpect ('Wait was called for a child process that is stopped. This is not supported. Is some other process attempting job control with our child pid?')
|
| + elif os.WIFSTOPPED(status):
|
| + # You can't call wait() on a child process in the stopped state.
|
| + raise ExceptionPexpect('Called wait() on a stopped child ' +
|
| + 'process. This is not supported. Is some other ' +
|
| + 'process attempting job control with our child pid?')
|
| return self.exitstatus
|
|
|
| def isalive(self):
|
| @@ -1121,55 +1177,70 @@ class spawn (object):
|
| return False
|
|
|
| if self.flag_eof:
|
| - # This is for Linux, which requires the blocking form of waitpid to get
|
| - # status of a defunct process. This is super-lame. The flag_eof would have
|
| - # been set in read_nonblocking(), so this should be safe.
|
| + # This is for Linux, which requires the blocking form
|
| + # of waitpid to # get status of a defunct process.
|
| + # This is super-lame. The flag_eof would have been set
|
| + # in read_nonblocking(), so this should be safe.
|
| waitpid_options = 0
|
| else:
|
| waitpid_options = os.WNOHANG
|
|
|
| try:
|
| pid, status = os.waitpid(self.pid, waitpid_options)
|
| - except OSError, e: # No child processes
|
| + except OSError as e:
|
| + # No child processes
|
| if e[0] == errno.ECHILD:
|
| - raise ExceptionPexpect ('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?')
|
| + raise ExceptionPexpect('isalive() encountered condition ' +
|
| + 'where "terminated" is 0, but there was no child ' +
|
| + 'process. Did someone else call waitpid() ' +
|
| + 'on our process?')
|
| else:
|
| raise e
|
|
|
| - # I have to do this twice for Solaris. I can't even believe that I figured this out...
|
| - # If waitpid() returns 0 it means that no child process wishes to
|
| - # report, and the value of status is undefined.
|
| + # I have to do this twice for Solaris.
|
| + # I can't even believe that I figured this out...
|
| + # If waitpid() returns 0 it means that no child process
|
| + # wishes to report, and the value of status is undefined.
|
| if pid == 0:
|
| try:
|
| - pid, status = os.waitpid(self.pid, waitpid_options) ### os.WNOHANG) # Solaris!
|
| - except OSError, e: # This should never happen...
|
| + ### os.WNOHANG) # Solaris!
|
| + pid, status = os.waitpid(self.pid, waitpid_options)
|
| + except OSError as e:
|
| + # This should never happen...
|
| if e[0] == errno.ECHILD:
|
| - raise ExceptionPexpect ('isalive() encountered condition that should never happen. There was no child process. Did someone else call waitpid() on our process?')
|
| + raise ExceptionPexpect('isalive() encountered condition ' +
|
| + 'that should never happen. There was no child ' +
|
| + 'process. Did someone else call waitpid() ' +
|
| + 'on our process?')
|
| else:
|
| raise e
|
|
|
| - # If pid is still 0 after two calls to waitpid() then
|
| - # the process really is alive. This seems to work on all platforms, except
|
| - # for Irix which seems to require a blocking call on waitpid or select, so I let read_nonblocking
|
| - # take care of this situation (unfortunately, this requires waiting through the timeout).
|
| + # If pid is still 0 after two calls to waitpid() then the process
|
| + # really is alive. This seems to work on all platforms, except for
|
| + # Irix which seems to require a blocking call on waitpid or select,
|
| + # so I let read_nonblocking take care of this situation
|
| + # (unfortunately, this requires waiting through the timeout).
|
| if pid == 0:
|
| return True
|
|
|
| if pid == 0:
|
| return True
|
|
|
| - if os.WIFEXITED (status):
|
| + if os.WIFEXITED(status):
|
| self.status = status
|
| self.exitstatus = os.WEXITSTATUS(status)
|
| self.signalstatus = None
|
| self.terminated = True
|
| - elif os.WIFSIGNALED (status):
|
| + elif os.WIFSIGNALED(status):
|
| self.status = status
|
| self.exitstatus = None
|
| self.signalstatus = os.WTERMSIG(status)
|
| self.terminated = True
|
| - elif os.WIFSTOPPED (status):
|
| - raise ExceptionPexpect ('isalive() encountered condition where child process is stopped. This is not supported. Is some other process attempting job control with our child pid?')
|
| + elif os.WIFSTOPPED(status):
|
| + raise ExceptionPexpect('isalive() encountered condition ' +
|
| + 'where child process is stopped. This is not ' +
|
| + 'supported. Is some other process attempting ' +
|
| + 'job control with our child pid?')
|
| return False
|
|
|
| def kill(self, sig):
|
| @@ -1209,10 +1280,11 @@ class spawn (object):
|
|
|
| if patterns is None:
|
| return []
|
| - if type(patterns) is not types.ListType:
|
| + if not isinstance(patterns, list):
|
| patterns = [patterns]
|
|
|
| - compile_flags = re.DOTALL # Allow dot to match \n
|
| + # Allow dot to match \n
|
| + compile_flags = re.DOTALL
|
| if self.ignorecase:
|
| compile_flags = compile_flags | re.IGNORECASE
|
| compiled_pattern_list = []
|
| @@ -1223,14 +1295,16 @@ class spawn (object):
|
| compiled_pattern_list.append(EOF)
|
| elif p is TIMEOUT:
|
| compiled_pattern_list.append(TIMEOUT)
|
| - elif type(p) is type(re.compile('')):
|
| + elif isinstance(p, type(re.compile(''))):
|
| compiled_pattern_list.append(p)
|
| else:
|
| - raise TypeError ('Argument must be one of StringTypes, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p)))
|
| + raise TypeError('Argument must be one of StringTypes, ' +
|
| + 'EOF, TIMEOUT, SRE_Pattern, or a list of those ' +
|
| + 'type. %s' % str(type(p)))
|
|
|
| return compiled_pattern_list
|
|
|
| - def expect(self, pattern, timeout = -1, searchwindowsize=None):
|
| + def expect(self, pattern, timeout=-1, searchwindowsize=-1):
|
|
|
| """This seeks through the stream until a pattern is matched. The
|
| pattern is overloaded and may take several types. The pattern can be a
|
| @@ -1242,21 +1316,21 @@ class spawn (object):
|
| list. That will cause expect to match an EOF or TIMEOUT condition
|
| instead of raising an exception.
|
|
|
| - If you pass a list of patterns and more than one matches, the first match
|
| - in the stream is chosen. If more than one pattern matches at that point,
|
| - the leftmost in the pattern list is chosen. For example::
|
| + If you pass a list of patterns and more than one matches, the first
|
| + match in the stream is chosen. If more than one pattern matches at that
|
| + point, the leftmost in the pattern list is chosen. For example::
|
|
|
| # the input is 'foobar'
|
| - index = p.expect (['bar', 'foo', 'foobar'])
|
| - # returns 1 ('foo') even though 'foobar' is a "better" match
|
| + index = p.expect(['bar', 'foo', 'foobar'])
|
| + # returns 1('foo') even though 'foobar' is a "better" match
|
|
|
| Please note, however, that buffering can affect this behavior, since
|
| input arrives in unpredictable chunks. For example::
|
|
|
| # the input is 'foobar'
|
| - index = p.expect (['foobar', 'foo'])
|
| - # returns 0 ('foobar') if all input is available at once,
|
| - # but returs 1 ('foo') if parts of the final 'bar' arrive late
|
| + index = p.expect(['foobar', 'foo'])
|
| + # returns 0('foobar') if all input is available at once,
|
| + # but returs 1('foo') if parts of the final 'bar' arrive late
|
|
|
| After a match is found the instance attributes 'before', 'after' and
|
| 'match' will be set. You can see all the data read before the match in
|
| @@ -1273,7 +1347,7 @@ class spawn (object):
|
| exception type. The attribute 'match' will be None. This allows you to
|
| write code like this::
|
|
|
| - index = p.expect (['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
|
| + index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
|
| if index == 0:
|
| do_something()
|
| elif index == 1:
|
| @@ -1286,7 +1360,7 @@ class spawn (object):
|
| instead of code like this::
|
|
|
| try:
|
| - index = p.expect (['good', 'bad'])
|
| + index = p.expect(['good', 'bad'])
|
| if index == 0:
|
| do_something()
|
| elif index == 1:
|
| @@ -1301,20 +1375,21 @@ class spawn (object):
|
| child to finish. For example::
|
|
|
| p = pexpect.spawn('/bin/ls')
|
| - p.expect (pexpect.EOF)
|
| + p.expect(pexpect.EOF)
|
| print p.before
|
|
|
| If you are trying to optimize for speed then see expect_list().
|
| """
|
|
|
| compiled_pattern_list = self.compile_pattern_list(pattern)
|
| - return self.expect_list(compiled_pattern_list, timeout, searchwindowsize)
|
| + return self.expect_list(compiled_pattern_list,
|
| + timeout, searchwindowsize)
|
|
|
| - def expect_list(self, pattern_list, timeout = -1, searchwindowsize = -1):
|
| + def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1):
|
|
|
| """This takes a list of compiled regular expressions and returns the
|
| index into the pattern_list that matched the child output. The list may
|
| - also contain EOF or TIMEOUT (which are not compiled regular
|
| + also contain EOF or TIMEOUT(which are not compiled regular
|
| expressions). This method is similar to the expect() method except that
|
| expect_list() does not recompile the pattern list on every call. This
|
| may help if you are trying to optimize for speed, otherwise just use
|
| @@ -1322,9 +1397,10 @@ class spawn (object):
|
| the self.timeout value is used. If searchwindowsize==-1 then the
|
| self.searchwindowsize value is used. """
|
|
|
| - return self.expect_loop(searcher_re(pattern_list), timeout, searchwindowsize)
|
| + return self.expect_loop(searcher_re(pattern_list),
|
| + timeout, searchwindowsize)
|
|
|
| - def expect_exact(self, pattern_list, timeout = -1, searchwindowsize = -1):
|
| + def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1):
|
|
|
| """This is similar to expect(), but uses plain string matching instead
|
| of compiled regular expressions in 'pattern_list'. The 'pattern_list'
|
| @@ -1338,15 +1414,17 @@ class spawn (object):
|
| This method is also useful when you don't want to have to worry about
|
| escaping regular expression characters that you want to match."""
|
|
|
| - if type(pattern_list) in types.StringTypes or pattern_list in (TIMEOUT, EOF):
|
| + if (type(pattern_list) in types.StringTypes or
|
| + pattern_list in (TIMEOUT, EOF)):
|
| pattern_list = [pattern_list]
|
| - return self.expect_loop(searcher_string(pattern_list), timeout, searchwindowsize)
|
| + return self.expect_loop(searcher_string(pattern_list),
|
| + timeout, searchwindowsize)
|
|
|
| - def expect_loop(self, searcher, timeout = -1, searchwindowsize = -1):
|
| + def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1):
|
|
|
| """This is the common loop used inside expect. The 'searcher' should be
|
| - an instance of searcher_re or searcher_string, which describes how and what
|
| - to search for in the input.
|
| + an instance of searcher_re or searcher_string, which describes how and
|
| + what to search for in the input.
|
|
|
| See expect() for other arguments, return value and exceptions. """
|
|
|
| @@ -1355,33 +1433,34 @@ class spawn (object):
|
| if timeout == -1:
|
| timeout = self.timeout
|
| if timeout is not None:
|
| - end_time = time.time() + timeout
|
| + end_time = time.time() + timeout
|
| if searchwindowsize == -1:
|
| searchwindowsize = self.searchwindowsize
|
|
|
| try:
|
| incoming = self.buffer
|
| freshlen = len(incoming)
|
| - while True: # Keep reading until exception or return.
|
| + while True:
|
| + # Keep reading until exception or return.
|
| index = searcher.search(incoming, freshlen, searchwindowsize)
|
| if index >= 0:
|
| - self.buffer = incoming[searcher.end : ]
|
| - self.before = incoming[ : searcher.start]
|
| - self.after = incoming[searcher.start : searcher.end]
|
| + self.buffer = incoming[searcher.end:]
|
| + self.before = incoming[: searcher.start]
|
| + self.after = incoming[searcher.start: searcher.end]
|
| self.match = searcher.match
|
| self.match_index = index
|
| return self.match_index
|
| # No match at this point
|
| if timeout < 0 and timeout is not None:
|
| - raise TIMEOUT ('Timeout exceeded in expect_any().')
|
| + raise TIMEOUT('Timeout exceeded in expect_any().')
|
| # Still have time left, so read more data
|
| - c = self.read_nonblocking (self.maxread, timeout)
|
| + c = self.read_nonblocking(self.maxread, timeout)
|
| freshlen = len(c)
|
| - time.sleep (0.0001)
|
| + time.sleep(0.0001)
|
| incoming = incoming + c
|
| if timeout is not None:
|
| timeout = end_time - time.time()
|
| - except EOF, e:
|
| + except EOF as e:
|
| self.buffer = ''
|
| self.before = incoming
|
| self.after = EOF
|
| @@ -1393,8 +1472,8 @@ class spawn (object):
|
| else:
|
| self.match = None
|
| self.match_index = None
|
| - raise EOF (str(e) + '\n' + str(self))
|
| - except TIMEOUT, e:
|
| + raise EOF(str(e) + '\n' + str(self))
|
| + except TIMEOUT as e:
|
| self.buffer = incoming
|
| self.before = incoming
|
| self.after = TIMEOUT
|
| @@ -1406,7 +1485,7 @@ class spawn (object):
|
| else:
|
| self.match = None
|
| self.match_index = None
|
| - raise TIMEOUT (str(e) + '\n' + str(self))
|
| + raise TIMEOUT(str(e) + '\n' + str(self))
|
| except:
|
| self.before = incoming
|
| self.after = None
|
| @@ -1419,12 +1498,12 @@ class spawn (object):
|
| """This returns the terminal window size of the child tty. The return
|
| value is a tuple of (rows, cols). """
|
|
|
| - TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912L)
|
| + TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912)
|
| s = struct.pack('HHHH', 0, 0, 0, 0)
|
| x = fcntl.ioctl(self.fileno(), TIOCGWINSZ, s)
|
| return struct.unpack('HHHH', x)[0:2]
|
|
|
| - def setwinsize(self, r, c):
|
| + def setwinsize(self, rows, cols):
|
|
|
| """This sets the terminal window size of the child tty. This will cause
|
| a SIGWINCH signal to be sent to the child. This does not change the
|
| @@ -1441,13 +1520,15 @@ class spawn (object):
|
| # Newer versions of Linux have totally different values for TIOCSWINSZ.
|
| # Note that this fix is a hack.
|
| TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561)
|
| - if TIOCSWINSZ == 2148037735L: # L is not required in Python >= 2.2.
|
| - TIOCSWINSZ = -2146929561 # Same bits, but with sign.
|
| + if TIOCSWINSZ == 2148037735:
|
| + # Same bits, but with sign.
|
| + TIOCSWINSZ = -2146929561
|
| # Note, assume ws_xpixel and ws_ypixel are zero.
|
| - s = struct.pack('HHHH', r, c, 0, 0)
|
| + s = struct.pack('HHHH', rows, cols, 0, 0)
|
| fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
|
|
|
| - def interact(self, escape_character = chr(29), input_filter = None, output_filter = None):
|
| + def interact(self, escape_character=chr(29),
|
| + input_filter=None, output_filter=None):
|
|
|
| """This gives control of the child process to the interactive user (the
|
| human at the keyboard). Keystrokes are sent to the child process, and
|
| @@ -1474,16 +1555,18 @@ class spawn (object):
|
| import pexpect, struct, fcntl, termios, signal, sys
|
| def sigwinch_passthrough (sig, data):
|
| s = struct.pack("HHHH", 0, 0, 0, 0)
|
| - a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s))
|
| + a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(),
|
| + termios.TIOCGWINSZ , s))
|
| global p
|
| p.setwinsize(a[0],a[1])
|
| - p = pexpect.spawn('/bin/bash') # Note this is global and used in sigwinch_passthrough.
|
| + # Note this 'p' global and used in sigwinch_passthrough.
|
| + p = pexpect.spawn('/bin/bash')
|
| signal.signal(signal.SIGWINCH, sigwinch_passthrough)
|
| p.interact()
|
| """
|
|
|
| # Flush the buffer.
|
| - self.stdout.write (self.buffer)
|
| + self.stdout.write(self.buffer)
|
| self.stdout.flush()
|
| self.buffer = ''
|
| mode = tty.tcgetattr(self.STDIN_FILENO)
|
| @@ -1509,23 +1592,26 @@ class spawn (object):
|
|
|
| return os.read(fd, 1000)
|
|
|
| - def __interact_copy(self, escape_character = None, input_filter = None, output_filter = None):
|
| + def __interact_copy(self, escape_character=None,
|
| + input_filter=None, output_filter=None):
|
|
|
| """This is used by the interact() method.
|
| """
|
|
|
| while self.isalive():
|
| - r,w,e = self.__select([self.child_fd, self.STDIN_FILENO], [], [])
|
| + r, w, e = self.__select([self.child_fd, self.STDIN_FILENO], [], [])
|
| if self.child_fd in r:
|
| data = self.__interact_read(self.child_fd)
|
| - if output_filter: data = output_filter(data)
|
| + if output_filter:
|
| + data = output_filter(data)
|
| if self.logfile is not None:
|
| - self.logfile.write (data)
|
| + self.logfile.write(data)
|
| self.logfile.flush()
|
| os.write(self.STDOUT_FILENO, data)
|
| if self.STDIN_FILENO in r:
|
| data = self.__interact_read(self.STDIN_FILENO)
|
| - if input_filter: data = input_filter(data)
|
| + if input_filter:
|
| + data = input_filter(data)
|
| i = data.rfind(escape_character)
|
| if i != -1:
|
| data = data[:i]
|
| @@ -1533,7 +1619,7 @@ class spawn (object):
|
| break
|
| self.__interact_writen(self.child_fd, data)
|
|
|
| - def __select (self, iwtd, owtd, ewtd, timeout=None):
|
| + def __select(self, iwtd, owtd, ewtd, timeout=None):
|
|
|
| """This is a wrapper around select.select() that ignores signals. If
|
| select.select raises a select.error exception and errno is an EINTR
|
| @@ -1546,41 +1632,51 @@ class spawn (object):
|
| end_time = time.time() + timeout
|
| while True:
|
| try:
|
| - return select.select (iwtd, owtd, ewtd, timeout)
|
| - except select.error, e:
|
| + return select.select(iwtd, owtd, ewtd, timeout)
|
| + except select.error as e:
|
| if e[0] == errno.EINTR:
|
| - # if we loop back we have to subtract the amount of time we already waited.
|
| + # if we loop back we have to subtract the
|
| + # amount of time we already waited.
|
| if timeout is not None:
|
| timeout = end_time - time.time()
|
| if timeout < 0:
|
| - return ([],[],[])
|
| - else: # something else caused the select.error, so this really is an exception
|
| + return([], [], [])
|
| + else:
|
| + # something else caused the select.error, so
|
| + # this actually is an exception.
|
| raise
|
|
|
| ##############################################################################
|
| # The following methods are no longer supported or allowed.
|
|
|
| - def setmaxread (self, maxread):
|
| + def setmaxread(self, maxread):
|
|
|
| """This method is no longer supported or allowed. I don't like getters
|
| and setters without a good reason. """
|
|
|
| - raise ExceptionPexpect ('This method is no longer supported or allowed. Just assign a value to the maxread member variable.')
|
| + raise ExceptionPexpect('This method is no longer supported ' +
|
| + 'or allowed. Just assign a value to the ' +
|
| + 'maxread member variable.')
|
|
|
| - def setlog (self, fileobject):
|
| + def setlog(self, fileobject):
|
|
|
| """This method is no longer supported or allowed.
|
| """
|
|
|
| - raise ExceptionPexpect ('This method is no longer supported or allowed. Just assign a value to the logfile member variable.')
|
| + raise ExceptionPexpect('This method is no longer supported ' +
|
| + 'or allowed. Just assign a value to the logfile ' +
|
| + 'member variable.')
|
|
|
| ##############################################################################
|
| # End of spawn class
|
| ##############################################################################
|
|
|
| -class searcher_string (object):
|
| +
|
| +class searcher_string(object):
|
|
|
| """This is a plain string search helper for the spawn.expect_any() method.
|
| + This helper class is for speed. For more powerful regex patterns
|
| + see the helper class, searcher_re.
|
|
|
| Attributes:
|
|
|
| @@ -1593,6 +1689,7 @@ class searcher_string (object):
|
| start - index into the buffer, first byte of match
|
| end - index into the buffer, first byte after match
|
| match - the matching string itself
|
| +
|
| """
|
|
|
| def __init__(self, strings):
|
| @@ -1603,7 +1700,7 @@ class searcher_string (object):
|
| self.eof_index = -1
|
| self.timeout_index = -1
|
| self._strings = []
|
| - for n, s in zip(range(len(strings)), strings):
|
| + for n, s in zip(list(range(len(strings))), strings):
|
| if s is EOF:
|
| self.eof_index = n
|
| continue
|
| @@ -1617,12 +1714,13 @@ class searcher_string (object):
|
| """This returns a human-readable string that represents the state of
|
| the object."""
|
|
|
| - ss = [ (ns[0],' %d: "%s"' % ns) for ns in self._strings ]
|
| - ss.append((-1,'searcher_string:'))
|
| + ss = [(ns[0], ' %d: "%s"' % ns) for ns in self._strings]
|
| + ss.append((-1, 'searcher_string:'))
|
| if self.eof_index >= 0:
|
| - ss.append ((self.eof_index,' %d: EOF' % self.eof_index))
|
| + ss.append((self.eof_index, ' %d: EOF' % self.eof_index))
|
| if self.timeout_index >= 0:
|
| - ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
|
| + ss.append((self.timeout_index,
|
| + ' %d: TIMEOUT' % self.timeout_index))
|
| ss.sort()
|
| ss = zip(*ss)[1]
|
| return '\n'.join(ss)
|
| @@ -1653,12 +1751,12 @@ class searcher_string (object):
|
| # rescanning until we've read three more bytes.
|
| #
|
| # Sadly, I don't know enough about this interesting topic. /grahn
|
| -
|
| +
|
| for index, s in self._strings:
|
| if searchwindowsize is None:
|
| # the match, if any, can only be in the fresh data,
|
| # or at the very end of the old data
|
| - offset = -(freshlen+len(s))
|
| + offset = -(freshlen + len(s))
|
| else:
|
| # better obey searchwindowsize
|
| offset = -searchwindowsize
|
| @@ -1673,10 +1771,12 @@ class searcher_string (object):
|
| self.end = self.start + len(self.match)
|
| return best_index
|
|
|
| -class searcher_re (object):
|
| +
|
| +class searcher_re(object):
|
|
|
| """This is regular expression string search helper for the
|
| - spawn.expect_any() method.
|
| + spawn.expect_any() method. This helper class is for powerful
|
| + pattern matching. For speed, see the helper class, searcher_string.
|
|
|
| Attributes:
|
|
|
| @@ -1701,7 +1801,7 @@ class searcher_re (object):
|
| self.eof_index = -1
|
| self.timeout_index = -1
|
| self._searches = []
|
| - for n, s in zip(range(len(patterns)), patterns):
|
| + for n, s in zip(list(range(len(patterns))), patterns):
|
| if s is EOF:
|
| self.eof_index = n
|
| continue
|
| @@ -1715,12 +1815,14 @@ class searcher_re (object):
|
| """This returns a human-readable string that represents the state of
|
| the object."""
|
|
|
| - ss = [ (n,' %d: re.compile("%s")' % (n,str(s.pattern))) for n,s in self._searches]
|
| - ss.append((-1,'searcher_re:'))
|
| + ss = [(n, ' %d: re.compile("%s")' %
|
| + (n, str(s.pattern))) for n, s in self._searches]
|
| + ss.append((-1, 'searcher_re:'))
|
| if self.eof_index >= 0:
|
| - ss.append ((self.eof_index,' %d: EOF' % self.eof_index))
|
| + ss.append((self.eof_index, ' %d: EOF' % self.eof_index))
|
| if self.timeout_index >= 0:
|
| - ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
|
| + ss.append((self.timeout_index, ' %d: TIMEOUT' %
|
| + self.timeout_index))
|
| ss.sort()
|
| ss = zip(*ss)[1]
|
| return '\n'.join(ss)
|
| @@ -1732,7 +1834,7 @@ class searcher_re (object):
|
| 'buffer' which have not been searched before.
|
|
|
| See class spawn for the 'searchwindowsize' argument.
|
| -
|
| +
|
| If there is a match this returns the index of that string, and sets
|
| 'start', 'end' and 'match'. Otherwise, returns -1."""
|
|
|
| @@ -1743,7 +1845,7 @@ class searcher_re (object):
|
| if searchwindowsize is None:
|
| searchstart = 0
|
| else:
|
| - searchstart = max(0, len(buffer)-searchwindowsize)
|
| + searchstart = max(0, len(buffer) - searchwindowsize)
|
| for index, s in self._searches:
|
| match = s.search(buffer, searchstart)
|
| if match is None:
|
| @@ -1760,33 +1862,29 @@ class searcher_re (object):
|
| self.end = self.match.end()
|
| return best_index
|
|
|
| -def which (filename):
|
| +
|
| +def which(filename):
|
|
|
| """This takes a given filename; tries to find it in the environment path;
|
| then checks if it is executable. This returns the full path to the filename
|
| if found and executable. Otherwise this returns None."""
|
|
|
| - # Special case where filename already contains a path.
|
| + # Special case where filename contains an explicit path.
|
| if os.path.dirname(filename) != '':
|
| - if os.access (filename, os.X_OK):
|
| + if os.access(filename, os.X_OK):
|
| return filename
|
| -
|
| - if not os.environ.has_key('PATH') or os.environ['PATH'] == '':
|
| + if 'PATH' not in os.environ or os.environ['PATH'] == '':
|
| p = os.defpath
|
| else:
|
| p = os.environ['PATH']
|
| -
|
| - # Oddly enough this was the one line that made Pexpect
|
| - # incompatible with Python 1.5.2.
|
| - #pathlist = p.split (os.pathsep)
|
| - pathlist = string.split (p, os.pathsep)
|
| -
|
| + pathlist = string.split(p, os.pathsep)
|
| for path in pathlist:
|
| - f = os.path.join(path, filename)
|
| - if os.access(f, os.X_OK):
|
| - return f
|
| + ff = os.path.join(path, filename)
|
| + if os.access(ff, os.X_OK):
|
| + return ff
|
| return None
|
|
|
| +
|
| def split_command_line(command_line):
|
|
|
| """This splits a command line into a list of arguments. It splits arguments
|
| @@ -1802,21 +1900,26 @@ def split_command_line(command_line):
|
| state_esc = 1
|
| state_singlequote = 2
|
| state_doublequote = 3
|
| - state_whitespace = 4 # The state of consuming whitespace between commands.
|
| + # The state when consuming whitespace between commands.
|
| + state_whitespace = 4
|
| state = state_basic
|
|
|
| for c in command_line:
|
| if state == state_basic or state == state_whitespace:
|
| - if c == '\\': # Escape the next character
|
| + if c == '\\':
|
| + # Escape the next character
|
| state = state_esc
|
| - elif c == r"'": # Handle single quote
|
| + elif c == r"'":
|
| + # Handle single quote
|
| state = state_singlequote
|
| - elif c == r'"': # Handle double quote
|
| + elif c == r'"':
|
| + # Handle double quote
|
| state = state_doublequote
|
| elif c.isspace():
|
| # Add arg to arg_list if we aren't in the middle of whitespace.
|
| if state == state_whitespace:
|
| - None # Do nothing.
|
| + # Do nothing.
|
| + None
|
| else:
|
| arg_list.append(arg)
|
| arg = ''
|
| @@ -1842,4 +1945,4 @@ def split_command_line(command_line):
|
| arg_list.append(arg)
|
| return arg_list
|
|
|
| -# vi:ts=4:sw=4:expandtab:ft=python:
|
| +# vi:set sr et ts=4 sw=4 ft=python :
|
|
|