Merge lp:~mterry/duplicity/drop-pexpect into lp:duplicity/0.6

Proposed by Michael Terry
Status: Merged
Merged at revision: 974
Proposed branch: lp:~mterry/duplicity/drop-pexpect
Merge into: lp:duplicity/0.6
Prerequisite: lp:~mterry/duplicity/fix-drop-u1
Diff against target: 2000 lines (+13/-1853)
8 files modified
bin/duplicity.1 (+3/-0)
duplicity/backends/_ssh_pexpect.py (+2/-1)
duplicity/backends/~par2wrapperbackend.py (+5/-4)
duplicity/pexpect.py (+0/-1845)
po/POTFILES.in (+0/-1)
setup.py (+1/-1)
testing/helpers/helper.py (+1/-1)
tox.ini (+1/-0)
To merge this branch: bzr merge lp:~mterry/duplicity/drop-pexpect
Reviewer Review Type Date Requested Status
duplicity-team Pending
Review via email: mp+216389@code.launchpad.net

This proposal supersedes a proposal from 2014-04-17.

Description of the change

Drop our local copy of pexpect in favor of a system version.

It's only used by the pexpect ssh backend (and if you're opting into that, you probably can expect that you will need pexpect) and the tests.

I've done a quick smoketest (backed up and restored using --ssh-backend=pexpect) and it seemed to work fine with a modern version of pexpect.

To post a comment you must log in.
lp:~mterry/duplicity/drop-pexpect updated
975. By Michael Terry

fix typo

Revision history for this message
edso (ed.so) wrote :

Mike,

could you please check if the par backend still works, as it seems to be affected as well?

thx.. ede

Revision history for this message
Michael Terry (mterry) wrote :

Yes, it works, at least in a simple par2+file:/// test.

On 17 April 2014 16:52, edso <email address hidden> wrote:

> Mike,
>
> could you please check if the par backend still works, as it seems to be
> affected as well?
>
> thx.. ede
> --
> https://code.launchpad.net/~mterry/duplicity/drop-pexpect/+merge/216389
> Your team duplicity-team is requested to review the proposed merge of
> lp:~mterry/duplicity/drop-pexpect into lp:duplicity.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~duplicity-team
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~duplicity-team
> More help : https://help.launchpad.net/ListHelp
>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/duplicity.1'
--- bin/duplicity.1 2014-04-17 17:58:17 +0000
+++ bin/duplicity.1 2014-04-17 19:53:39 +0000
@@ -120,6 +120,9 @@
120.B ssh pexpect backend120.B ssh pexpect backend
121.B sftp/scp client binaries121.B sftp/scp client binaries
122OpenSSH - http://www.openssh.com/122OpenSSH - http://www.openssh.com/
123.br
124.B Python pexpect module
125- http://pexpect.sourceforge.net/pexpect.html
123.TP126.TP
124.BR "swift backend (OpenStack Object Storage)"127.BR "swift backend (OpenStack Object Storage)"
125.B Python swiftclient module128.B Python swiftclient module
126129
=== modified file 'duplicity/backends/_ssh_pexpect.py'
--- duplicity/backends/_ssh_pexpect.py 2013-12-27 06:39:00 +0000
+++ duplicity/backends/_ssh_pexpect.py 2014-04-17 19:53:39 +0000
@@ -32,7 +32,6 @@
32import duplicity.backend32import duplicity.backend
33from duplicity import globals33from duplicity import globals
34from duplicity import log34from duplicity import log
35from duplicity import pexpect
36from duplicity.errors import * #@UnusedWildImport35from duplicity.errors import * #@UnusedWildImport
3736
38class SSHPExpectBackend(duplicity.backend.Backend):37class SSHPExpectBackend(duplicity.backend.Backend):
@@ -76,6 +75,7 @@
7675
77 def run_scp_command(self, commandline):76 def run_scp_command(self, commandline):
78 """ Run an scp command, responding to password prompts """77 """ Run an scp command, responding to password prompts """
78 import pexpect
79 for n in range(1, globals.num_retries+1):79 for n in range(1, globals.num_retries+1):
80 if n > 1:80 if n > 1:
81 # sleep before retry81 # sleep before retry
@@ -147,6 +147,7 @@
147147
148 def run_sftp_command(self, commandline, commands):148 def run_sftp_command(self, commandline, commands):
149 """ Run an sftp command, responding to password prompts, passing commands from list """149 """ Run an sftp command, responding to password prompts, passing commands from list """
150 import pexpect
150 maxread = 2000 # expected read buffer size151 maxread = 2000 # expected read buffer size
151 responses = [pexpect.EOF,152 responses = [pexpect.EOF,
152 "(?i)timeout, server not responding",153 "(?i)timeout, server not responding",
153154
=== modified file 'duplicity/backends/~par2wrapperbackend.py'
--- duplicity/backends/~par2wrapperbackend.py 2014-02-09 21:42:18 +0000
+++ duplicity/backends/~par2wrapperbackend.py 2014-04-17 19:53:39 +0000
@@ -20,7 +20,6 @@
20import re20import re
21from duplicity import backend21from duplicity import backend
22from duplicity.errors import UnsupportedBackendScheme, BackendException22from duplicity.errors import UnsupportedBackendScheme, BackendException
23from duplicity.pexpect import run
24from duplicity import log23from duplicity import log
25from duplicity import globals24from duplicity import globals
2625
@@ -52,6 +51,7 @@
52 temp-filename later on. So first of all create a tempdir and symlink51 temp-filename later on. So first of all create a tempdir and symlink
53 the soure_path with remote_filename into this. 52 the soure_path with remote_filename into this.
54 """53 """
54 import pexpect
55 if remote_filename is None:55 if remote_filename is None:
56 remote_filename = source_path.get_filename()56 remote_filename = source_path.get_filename()
5757
@@ -63,7 +63,7 @@
6363
64 log.Info("Create Par2 recovery files")64 log.Info("Create Par2 recovery files")
65 par2create = 'par2 c -r%d -n1 -q -q %s' % (self.redundancy, source_symlink.get_canonical())65 par2create = 'par2 c -r%d -n1 -q -q %s' % (self.redundancy, source_symlink.get_canonical())
66 out, returncode = run(par2create, -1, True)66 out, returncode = pexpect.run(par2create, -1, True)
67 source_symlink.delete()67 source_symlink.delete()
68 files_to_transfer = []68 files_to_transfer = []
69 if not returncode:69 if not returncode:
@@ -89,6 +89,7 @@
89 If "par2 verify" detect an error transfer the Par2-volumes into the89 If "par2 verify" detect an error transfer the Par2-volumes into the
90 temp-dir and try to repair.90 temp-dir and try to repair.
91 """91 """
92 import pexpect
92 par2temp = local_path.get_temp_in_same_dir()93 par2temp = local_path.get_temp_in_same_dir()
93 par2temp.mkdir()94 par2temp.mkdir()
94 local_path_temp = par2temp.append(remote_filename)95 local_path_temp = par2temp.append(remote_filename)
@@ -100,7 +101,7 @@
100 self.wrapped_backend.get(par2file.get_filename(), par2file)101 self.wrapped_backend.get(par2file.get_filename(), par2file)
101102
102 par2verify = 'par2 v -q -q %s %s' % (par2file.get_canonical(), local_path_temp.get_canonical())103 par2verify = 'par2 v -q -q %s %s' % (par2file.get_canonical(), local_path_temp.get_canonical())
103 out, returncode = run(par2verify, -1, True)104 out, returncode = pexpect.run(par2verify, -1, True)
104105
105 if returncode:106 if returncode:
106 log.Warn("File is corrupt. Try to repair %s" % remote_filename)107 log.Warn("File is corrupt. Try to repair %s" % remote_filename)
@@ -111,7 +112,7 @@
111 self.wrapped_backend.get(filename, file)112 self.wrapped_backend.get(filename, file)
112113
113 par2repair = 'par2 r -q -q %s %s' % (par2file.get_canonical(), local_path_temp.get_canonical())114 par2repair = 'par2 r -q -q %s %s' % (par2file.get_canonical(), local_path_temp.get_canonical())
114 out, returncode = run(par2repair, -1, True)115 out, returncode = pexpect.run(par2repair, -1, True)
115116
116 if returncode:117 if returncode:
117 log.Error("Failed to repair %s" % remote_filename)118 log.Error("Failed to repair %s" % remote_filename)
118119
=== removed file 'duplicity/pexpect.py'
--- duplicity/pexpect.py 2012-03-13 20:54:44 +0000
+++ duplicity/pexpect.py 1970-01-01 00:00:00 +0000
@@ -1,1845 +0,0 @@
1"""Pexpect is a Python module for spawning child applications and controlling
2them automatically. Pexpect can be used for automating interactive applications
3such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
4scripts for duplicating software package installations on different servers. It
5can be used for automated software testing. Pexpect is in the spirit of Don
6Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
7require TCL and Expect or require C extensions to be compiled. Pexpect does not
8use C, Expect, or TCL extensions. It should work on any platform that supports
9the standard Python pty module. The Pexpect interface focuses on ease of use so
10that simple tasks are easy.
11
12There are two main interfaces to Pexpect -- the function, run() and the class,
13spawn. You can call the run() function to execute a command and return the
14output. This is a handy replacement for os.system().
15
16For example::
17
18 pexpect.run('ls -la')
19
20The more powerful interface is the spawn class. You can use this to spawn an
21external child command and then interact with the child by sending lines and
22expecting responses.
23
24For example::
25
26 child = pexpect.spawn('scp foo myname@host.example.com:.')
27 child.expect ('Password:')
28 child.sendline (mypassword)
29
30This works even for commands that ask for passwords or other input outside of
31the normal stdio streams.
32
33Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
34Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
35vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
36Geoffrey Marshall, Francisco Lourenco, Glen Mabey, Karthik Gurusamy, Fernando
37Perez, Corey Minyard, Jon Cohen, Guillaume Chazarain, Andrew Ryan, Nick
38Craig-Wood, Andrew Stone, Jorgen Grahn (Let me know if I forgot anyone.)
39
40Free, open source, and all that good stuff.
41
42Permission is hereby granted, free of charge, to any person obtaining a copy of
43this software and associated documentation files (the "Software"), to deal in
44the Software without restriction, including without limitation the rights to
45use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
46of the Software, and to permit persons to whom the Software is furnished to do
47so, subject to the following conditions:
48
49The above copyright notice and this permission notice shall be included in all
50copies or substantial portions of the Software.
51
52THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
58SOFTWARE.
59
60Pexpect Copyright (c) 2008 Noah Spurrier
61http://pexpect.sourceforge.net/
62
63$Id: pexpect.py,v 1.1 2009/01/06 22:11:37 loafman Exp $
64"""
65
66try:
67 import os, sys, time
68 import select
69 import string
70 import re
71 import struct
72 import resource
73 import types
74 import pty
75 import tty
76 import termios
77 import fcntl
78 import errno
79 import traceback
80 import signal
81except ImportError, e:
82 raise ImportError (str(e) + """
83
84A critical module was not found. Probably this operating system does not
85support it. Pexpect is intended for UNIX-like operating systems.""")
86
87__version__ = '2.3'
88__revision__ = '$Revision: 1.1 $'
89__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run', 'which',
90 'split_command_line', '__version__', '__revision__']
91
92# Exception classes used by this module.
93class ExceptionPexpect(Exception):
94
95 """Base class for all exceptions raised by this module.
96 """
97
98 def __init__(self, value):
99
100 self.value = value
101
102 def __str__(self):
103
104 return str(self.value)
105
106 def get_trace(self):
107
108 """This returns an abbreviated stack trace with lines that only concern
109 the caller. In other words, the stack trace inside the Pexpect module
110 is not included. """
111
112 tblist = traceback.extract_tb(sys.exc_info()[2])
113 #tblist = filter(self.__filter_not_pexpect, tblist)
114 tblist = [item for item in tblist if self.__filter_not_pexpect(item)]
115 tblist = traceback.format_list(tblist)
116 return ''.join(tblist)
117
118 def __filter_not_pexpect(self, trace_list_item):
119
120 """This returns True if list item 0 the string 'pexpect.py' in it. """
121
122 if trace_list_item[0].find('pexpect.py') == -1:
123 return True
124 else:
125 return False
126
127class EOF(ExceptionPexpect):
128
129 """Raised when EOF is read from a child. This usually means the child has exited."""
130
131class TIMEOUT(ExceptionPexpect):
132
133 """Raised when a read time exceeds the timeout. """
134
135##class TIMEOUT_PATTERN(TIMEOUT):
136## """Raised when the pattern match time exceeds the timeout.
137## This is different than a read TIMEOUT because the child process may
138## give output, thus never give a TIMEOUT, but the output
139## may never match a pattern.
140## """
141##class MAXBUFFER(ExceptionPexpect):
142## """Raised when a scan buffer fills before matching an expected pattern."""
143
144def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None, logfile=None, cwd=None, env=None):
145
146 """
147 This function runs the given command; waits for it to finish; then
148 returns all output as a string. STDERR is included in output. If the full
149 path to the command is not given then the path is searched.
150
151 Note that lines are terminated by CR/LF (\\r\\n) combination even on
152 UNIX-like systems because this is the standard for pseudo ttys. If you set
153 'withexitstatus' to true, then run will return a tuple of (command_output,
154 exitstatus). If 'withexitstatus' is false then this returns just
155 command_output.
156
157 The run() function can often be used instead of creating a spawn instance.
158 For example, the following code uses spawn::
159
160 from pexpect import * #@UnusedWildImport
161 child = spawn('scp foo myname@host.example.com:.')
162 child.expect ('(?i)password')
163 child.sendline (mypassword)
164
165 The previous code can be replace with the following::
166
167 from pexpect import * #@UnusedWildImport
168 run ('scp foo myname@host.example.com:.', events={'(?i)password': mypassword})
169
170 Examples
171 ========
172
173 Start the apache daemon on the local machine::
174
175 from pexpect import * #@UnusedWildImport
176 run ("/usr/local/apache/bin/apachectl start")
177
178 Check in a file using SVN::
179
180 from pexpect import * #@UnusedWildImport
181 run ("svn ci -m 'automatic commit' my_file.py")
182
183 Run a command and capture exit status::
184
185 from pexpect import * #@UnusedWildImport
186 (command_output, exitstatus) = run ('ls -l /bin', withexitstatus=1)
187
188 Tricky Examples
189 ===============
190
191 The following will run SSH and execute 'ls -l' on the remote machine. The
192 password 'secret' will be sent if the '(?i)password' pattern is ever seen::
193
194 run ("ssh username@machine.example.com 'ls -l'", events={'(?i)password':'secret\\n'})
195
196 This will start mencoder to rip a video from DVD. This will also display
197 progress ticks every 5 seconds as it runs. For example::
198
199 from pexpect import * #@UnusedWildImport
200 def print_ticks(d):
201 print d['event_count'],
202 run ("mencoder dvd://1 -o video.avi -oac copy -ovc copy", events={TIMEOUT:print_ticks}, timeout=5)
203
204 The 'events' argument should be a dictionary of patterns and responses.
205 Whenever one of the patterns is seen in the command out run() will send the
206 associated response string. Note that you should put newlines in your
207 string if Enter is necessary. The responses may also contain callback
208 functions. Any callback is function that takes a dictionary as an argument.
209 The dictionary contains all the locals from the run() function, so you can
210 access the child spawn object or any other variable defined in run()
211 (event_count, child, and extra_args are the most useful). A callback may
212 return True to stop the current run process otherwise run() continues until
213 the next event. A callback may also return a string which will be sent to
214 the child. 'extra_args' is not used by directly run(). It provides a way to
215 pass data to a callback function through run() through the locals
216 dictionary passed to a callback. """
217
218 if timeout == -1:
219 child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env)
220 else:
221 child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, cwd=cwd, env=env)
222 if events is not None:
223 patterns = events.keys()
224 responses = events.values()
225 else:
226 patterns=None # We assume that EOF or TIMEOUT will save us.
227 responses=None
228 child_result_list = []
229 event_count = 0
230 while 1:
231 try:
232 index = child.expect (patterns)
233 if type(child.after) in types.StringTypes:
234 child_result_list.append(child.before + child.after)
235 else: # child.after may have been a TIMEOUT or EOF, so don't cat those.
236 child_result_list.append(child.before)
237 if type(responses[index]) in types.StringTypes:
238 child.send(responses[index])
239 elif type(responses[index]) is types.FunctionType:
240 callback_result = responses[index](locals())
241 sys.stdout.flush()
242 if type(callback_result) in types.StringTypes:
243 child.send(callback_result)
244 elif callback_result:
245 break
246 else:
247 raise TypeError ('The callback must be a string or function type.')
248 event_count = event_count + 1
249 except TIMEOUT, e:
250 child_result_list.append(child.before)
251 break
252 except EOF, e:
253 child_result_list.append(child.before)
254 break
255 child_result = ''.join(child_result_list)
256 if withexitstatus:
257 child.close()
258 return (child_result, child.exitstatus)
259 else:
260 return child_result
261
262class spawn (object):
263
264 """This is the main class interface for Pexpect. Use this class to start
265 and control child applications. """
266
267 def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None):
268
269 """This is the constructor. The command parameter may be a string that
270 includes a command and any arguments to the command. For example::
271
272 child = pexpect.spawn ('/usr/bin/ftp')
273 child = pexpect.spawn ('/usr/bin/ssh user@example.com')
274 child = pexpect.spawn ('ls -latr /tmp')
275
276 You may also construct it with a list of arguments like so::
277
278 child = pexpect.spawn ('/usr/bin/ftp', [])
279 child = pexpect.spawn ('/usr/bin/ssh', ['user@example.com'])
280 child = pexpect.spawn ('ls', ['-latr', '/tmp'])
281
282 After this the child application will be created and will be ready to
283 talk to. For normal use, see expect() and send() and sendline().
284
285 Remember that Pexpect does NOT interpret shell meta characters such as
286 redirect, pipe, or wild cards (>, |, or *). This is a common mistake.
287 If you want to run a command and pipe it through another command then
288 you must also start a shell. For example::
289
290 child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"')
291 child.expect(pexpect.EOF)
292
293 The second form of spawn (where you pass a list of arguments) is useful
294 in situations where you wish to spawn a command and pass it its own
295 argument list. This can make syntax more clear. For example, the
296 following is equivalent to the previous example::
297
298 shell_cmd = 'ls -l | grep LOG > log_list.txt'
299 child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
300 child.expect(pexpect.EOF)
301
302 The maxread attribute sets the read buffer size. This is maximum number
303 of bytes that Pexpect will try to read from a TTY at one time. Setting
304 the maxread size to 1 will turn off buffering. Setting the maxread
305 value higher may help performance in cases where large amounts of
306 output are read back from the child. This feature is useful in
307 conjunction with searchwindowsize.
308
309 The searchwindowsize attribute sets the how far back in the incomming
310 seach buffer Pexpect will search for pattern matches. Every time
311 Pexpect reads some data from the child it will append the data to the
312 incomming buffer. The default is to search from the beginning of the
313 imcomming buffer each time new data is read from the child. But this is
314 very inefficient if you are running a command that generates a large
315 amount of data where you want to match The searchwindowsize does not
316 effect the size of the incomming data buffer. You will still have
317 access to the full buffer after expect() returns.
318
319 The logfile member turns on or off logging. All input and output will
320 be copied to the given file object. Set logfile to None to stop
321 logging. This is the default. Set logfile to sys.stdout to echo
322 everything to standard output. The logfile is flushed after each write.
323
324 Example log input and output to a file::
325
326 child = pexpect.spawn('some_command')
327 fout = file('mylog.txt','w')
328 child.logfile = fout
329
330 Example log to stdout::
331
332 child = pexpect.spawn('some_command')
333 child.logfile = sys.stdout
334
335 The logfile_read and logfile_send members can be used to separately log
336 the input from the child and output sent to the child. Sometimes you
337 don't want to see everything you write to the child. You only want to
338 log what the child sends back. For example::
339
340 child = pexpect.spawn('some_command')
341 child.logfile_read = sys.stdout
342
343 To separately log output sent to the child use logfile_send::
344
345 self.logfile_send = fout
346
347 The delaybeforesend helps overcome a weird behavior that many users
348 were experiencing. The typical problem was that a user would expect() a
349 "Password:" prompt and then immediately call sendline() to send the
350 password. The user would then see that their password was echoed back
351 to them. Passwords don't normally echo. The problem is caused by the
352 fact that most applications print out the "Password" prompt and then
353 turn off stdin echo, but if you send your password before the
354 application turned off echo, then you get your password echoed.
355 Normally this wouldn't be a problem when interacting with a human at a
356 real keyboard. If you introduce a slight delay just before writing then
357 this seems to clear up the problem. This was such a common problem for
358 many users that I decided that the default pexpect behavior should be
359 to sleep just before writing to the child application. 1/20th of a
360 second (50 ms) seems to be enough to clear up the problem. You can set
361 delaybeforesend to 0 to return to the old behavior. Most Linux machines
362 don't like this to be below 0.03. I don't know why.
363
364 Note that spawn is clever about finding commands on your path.
365 It uses the same logic that "which" uses to find executables.
366
367 If you wish to get the exit status of the child you must call the
368 close() method. The exit or signal status of the child will be stored
369 in self.exitstatus or self.signalstatus. If the child exited normally
370 then exitstatus will store the exit return code and signalstatus will
371 be None. If the child was terminated abnormally with a signal then
372 signalstatus will store the signal value and exitstatus will be None.
373 If you need more detail you can also read the self.status member which
374 stores the status returned by os.waitpid. You can interpret this using
375 os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. """
376
377 self.STDIN_FILENO = pty.STDIN_FILENO
378 self.STDOUT_FILENO = pty.STDOUT_FILENO
379 self.STDERR_FILENO = pty.STDERR_FILENO
380 self.stdin = sys.stdin
381 self.stdout = sys.stdout
382 self.stderr = sys.stderr
383
384 self.searcher = None
385 self.ignorecase = False
386 self.before = None
387 self.after = None
388 self.match = None
389 self.match_index = None
390 self.terminated = True
391 self.exitstatus = None
392 self.signalstatus = None
393 self.status = None # status returned by os.waitpid
394 self.flag_eof = False
395 self.pid = None
396 self.child_fd = -1 # initially closed
397 self.timeout = timeout
398 self.delimiter = EOF
399 self.logfile = logfile
400 self.logfile_read = None # input from child (read_nonblocking)
401 self.logfile_send = None # output to send (send, sendline)
402 self.maxread = maxread # max bytes to read at one time into buffer
403 self.buffer = '' # This is the read buffer. See maxread.
404 self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched.
405 # Most Linux machines don't like delaybeforesend to be below 0.03 (30 ms).
406 self.delaybeforesend = 0.05 # Sets sleep time used just before sending data to child. Time in seconds.
407 self.delayafterclose = 0.1 # Sets delay in close() method to allow kernel time to update process status. Time in seconds.
408 self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds.
409 self.softspace = False # File-like object.
410 self.name = '<' + repr(self) + '>' # File-like object.
411 self.encoding = None # File-like object.
412 self.closed = True # File-like object.
413 self.cwd = cwd
414 self.env = env
415 self.__irix_hack = (sys.platform.lower().find('irix')>=0) # This flags if we are running on irix
416 # Solaris uses internal __fork_pty(). All others use pty.fork().
417 if (sys.platform.lower().find('solaris')>=0) or (sys.platform.lower().find('sunos5')>=0):
418 self.use_native_pty_fork = False
419 else:
420 self.use_native_pty_fork = True
421
422
423 # allow dummy instances for subclasses that may not use command or args.
424 if command is None:
425 self.command = None
426 self.args = None
427 self.name = '<pexpect factory incomplete>'
428 else:
429 self._spawn (command, args)
430
431 def __del__(self):
432
433 """This makes sure that no system resources are left open. Python only
434 garbage collects Python objects. OS file descriptors are not Python
435 objects, so they must be handled explicitly. If the child file
436 descriptor was opened outside of this class (passed to the constructor)
437 then this does not close it. """
438
439 if not self.closed:
440 # It is possible for __del__ methods to execute during the
441 # teardown of the Python VM itself. Thus self.close() may
442 # trigger an exception because os.close may be None.
443 # -- Fernando Perez
444 try:
445 self.close()
446 except AttributeError:
447 pass
448
449 def __str__(self):
450
451 """This returns a human-readable string that represents the state of
452 the object. """
453
454 s = []
455 s.append(repr(self))
456 s.append('version: ' + __version__ + ' (' + __revision__ + ')')
457 s.append('command: ' + str(self.command))
458 s.append('args: ' + str(self.args))
459 s.append('searcher: ' + str(self.searcher))
460 s.append('buffer (last 100 chars): ' + str(self.buffer)[-100:])
461 s.append('before (last 100 chars): ' + str(self.before)[-100:])
462 s.append('after: ' + str(self.after))
463 s.append('match: ' + str(self.match))
464 s.append('match_index: ' + str(self.match_index))
465 s.append('exitstatus: ' + str(self.exitstatus))
466 s.append('flag_eof: ' + str(self.flag_eof))
467 s.append('pid: ' + str(self.pid))
468 s.append('child_fd: ' + str(self.child_fd))
469 s.append('closed: ' + str(self.closed))
470 s.append('timeout: ' + str(self.timeout))
471 s.append('delimiter: ' + str(self.delimiter))
472 s.append('logfile: ' + str(self.logfile))
473 s.append('logfile_read: ' + str(self.logfile_read))
474 s.append('logfile_send: ' + str(self.logfile_send))
475 s.append('maxread: ' + str(self.maxread))
476 s.append('ignorecase: ' + str(self.ignorecase))
477 s.append('searchwindowsize: ' + str(self.searchwindowsize))
478 s.append('delaybeforesend: ' + str(self.delaybeforesend))
479 s.append('delayafterclose: ' + str(self.delayafterclose))
480 s.append('delayafterterminate: ' + str(self.delayafterterminate))
481 return '\n'.join(s)
482
483 def _spawn(self,command,args=[]):
484
485 """This starts the given command in a child process. This does all the
486 fork/exec type of stuff for a pty. This is called by __init__. If args
487 is empty then command will be parsed (split on spaces) and args will be
488 set to parsed arguments. """
489
490 # The pid and child_fd of this object get set by this method.
491 # Note that it is difficult for this method to fail.
492 # You cannot detect if the child process cannot start.
493 # So the only way you can tell if the child process started
494 # or not is to try to read from the file descriptor. If you get
495 # EOF immediately then it means that the child is already dead.
496 # That may not necessarily be bad because you may haved spawned a child
497 # that performs some task; creates no stdout output; and then dies.
498
499 # If command is an int type then it may represent a file descriptor.
500 if type(command) == type(0):
501 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.')
502
503 if type (args) != type([]):
504 raise TypeError ('The argument, args, must be a list.')
505
506 if args == []:
507 self.args = split_command_line(command)
508 self.command = self.args[0]
509 else:
510 self.args = args[:] # work with a copy
511 self.args.insert (0, command)
512 self.command = command
513
514 command_with_path = which(self.command)
515 if command_with_path is None:
516 raise ExceptionPexpect ('The command was not found or was not executable: %s.' % self.command)
517 self.command = command_with_path
518 self.args[0] = self.command
519
520 self.name = '<' + ' '.join (self.args) + '>'
521
522 assert self.pid is None, 'The pid member should be None.'
523 assert self.command is not None, 'The command member should not be None.'
524
525 if self.use_native_pty_fork:
526 try:
527 self.pid, self.child_fd = pty.fork()
528 except OSError, e:
529 raise ExceptionPexpect('Error! pty.fork() failed: ' + str(e))
530 else: # Use internal __fork_pty
531 self.pid, self.child_fd = self.__fork_pty()
532
533 if self.pid == 0: # Child
534 try:
535 self.child_fd = sys.stdout.fileno() # used by setwinsize()
536 self.setwinsize(24, 80)
537 except Exception:
538 # Some platforms do not like setwinsize (Cygwin).
539 # This will cause problem when running applications that
540 # are very picky about window size.
541 # This is a serious limitation, but not a show stopper.
542 pass
543 # Do not allow child to inherit open file descriptors from parent.
544 max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
545 for i in range (3, max_fd):
546 try:
547 os.close (i)
548 except OSError:
549 pass
550
551 # I don't know why this works, but ignoring SIGHUP fixes a
552 # problem when trying to start a Java daemon with sudo
553 # (specifically, Tomcat).
554 signal.signal(signal.SIGHUP, signal.SIG_IGN)
555
556 if self.cwd is not None:
557 os.chdir(self.cwd)
558 if self.env is None:
559 os.execv(self.command, self.args)
560 else:
561 os.execvpe(self.command, self.args, self.env)
562
563 # Parent
564 self.terminated = False
565 self.closed = False
566
567 def __fork_pty(self):
568
569 """This implements a substitute for the forkpty system call. This
570 should be more portable than the pty.fork() function. Specifically,
571 this should work on Solaris.
572
573 Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to
574 resolve the issue with Python's pty.fork() not supporting Solaris,
575 particularly ssh. Based on patch to posixmodule.c authored by Noah
576 Spurrier::
577
578 http://mail.python.org/pipermail/python-dev/2003-May/035281.html
579
580 """
581
582 parent_fd, child_fd = os.openpty()
583 if parent_fd < 0 or child_fd < 0:
584 raise ExceptionPexpect, "Error! Could not open pty with os.openpty()."
585
586 pid = os.fork()
587 if pid < 0:
588 raise ExceptionPexpect, "Error! Failed os.fork()."
589 elif pid == 0:
590 # Child.
591 os.close(parent_fd)
592 self.__pty_make_controlling_tty(child_fd)
593
594 os.dup2(child_fd, 0)
595 os.dup2(child_fd, 1)
596 os.dup2(child_fd, 2)
597
598 if child_fd > 2:
599 os.close(child_fd)
600 else:
601 # Parent.
602 os.close(child_fd)
603
604 return pid, parent_fd
605
606 def __pty_make_controlling_tty(self, tty_fd):
607
608 """This makes the pseudo-terminal the controlling tty. This should be
609 more portable than the pty.fork() function. Specifically, this should
610 work on Solaris. """
611
612 child_name = os.ttyname(tty_fd)
613
614 # Disconnect from controlling tty if still connected.
615 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
616 if fd >= 0:
617 os.close(fd)
618
619 os.setsid()
620
621 # Verify we are disconnected from controlling tty
622 try:
623 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
624 if fd >= 0:
625 os.close(fd)
626 raise ExceptionPexpect, "Error! We are not disconnected from a controlling tty."
627 except Exception:
628 # Good! We are disconnected from a controlling tty.
629 pass
630
631 # Verify we can open child pty.
632 fd = os.open(child_name, os.O_RDWR);
633 if fd < 0:
634 raise ExceptionPexpect, "Error! Could not open child pty, " + child_name
635 else:
636 os.close(fd)
637
638 # Verify we now have a controlling tty.
639 fd = os.open("/dev/tty", os.O_WRONLY)
640 if fd < 0:
641 raise ExceptionPexpect, "Error! Could not open controlling tty, /dev/tty"
642 else:
643 os.close(fd)
644
645 def fileno (self): # File-like object.
646
647 """This returns the file descriptor of the pty for the child.
648 """
649
650 return self.child_fd
651
652 def close (self, force=True): # File-like object.
653
654 """This closes the connection with the child application. Note that
655 calling close() more than once is valid. This emulates standard Python
656 behavior with files. Set force to True if you want to make sure that
657 the child is terminated (SIGKILL is sent if the child ignores SIGHUP
658 and SIGINT). """
659
660 if not self.closed:
661 self.flush()
662 os.close (self.child_fd)
663 time.sleep(self.delayafterclose) # Give kernel time to update process status.
664 if self.isalive():
665 if not self.terminate(force):
666 raise ExceptionPexpect ('close() could not terminate the child using terminate()')
667 self.child_fd = -1
668 self.closed = True
669 #self.pid = None
670
671 def flush (self): # File-like object.
672
673 """This does nothing. It is here to support the interface for a
674 File-like object. """
675
676 pass
677
678 def isatty (self): # File-like object.
679
680 """This returns True if the file descriptor is open and connected to a
681 tty(-like) device, else False. """
682
683 return os.isatty(self.child_fd)
684
685 def waitnoecho (self, timeout=-1):
686
687 """This waits until the terminal ECHO flag is set False. This returns
688 True if the echo mode is off. This returns False if the ECHO flag was
689 not set False before the timeout. This can be used to detect when the
690 child is waiting for a password. Usually a child application will turn
691 off echo mode when it is waiting for the user to enter a password. For
692 example, instead of expecting the "password:" prompt you can wait for
693 the child to set ECHO off::
694
695 p = pexpect.spawn ('ssh user@example.com')
696 p.waitnoecho()
697 p.sendline(mypassword)
698
699 If timeout is None then this method to block forever until ECHO flag is
700 False.
701
702 """
703
704 if timeout == -1:
705 timeout = self.timeout
706 if timeout is not None:
707 end_time = time.time() + timeout
708 while True:
709 if not self.getecho():
710 return True
711 if timeout < 0 and timeout is not None:
712 return False
713 if timeout is not None:
714 timeout = end_time - time.time()
715 time.sleep(0.1)
716
717 def getecho (self):
718
719 """This returns the terminal echo mode. This returns True if echo is
720 on or False if echo is off. Child applications that are expecting you
721 to enter a password often set ECHO False. See waitnoecho(). """
722
723 attr = termios.tcgetattr(self.child_fd)
724 if attr[3] & termios.ECHO:
725 return True
726 return False
727
728 def setecho (self, state):
729
730 """This sets the terminal echo mode on or off. Note that anything the
731 child sent before the echo will be lost, so you should be sure that
732 your input buffer is empty before you call setecho(). For example, the
733 following will work as expected::
734
735 p = pexpect.spawn('cat')
736 p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
737 p.expect (['1234'])
738 p.expect (['1234'])
739 p.setecho(False) # Turn off tty echo
740 p.sendline ('abcd') # We will set this only once (echoed by cat).
741 p.sendline ('wxyz') # We will set this only once (echoed by cat)
742 p.expect (['abcd'])
743 p.expect (['wxyz'])
744
745 The following WILL NOT WORK because the lines sent before the setecho
746 will be lost::
747
748 p = pexpect.spawn('cat')
749 p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
750 p.setecho(False) # Turn off tty echo
751 p.sendline ('abcd') # We will set this only once (echoed by cat).
752 p.sendline ('wxyz') # We will set this only once (echoed by cat)
753 p.expect (['1234'])
754 p.expect (['1234'])
755 p.expect (['abcd'])
756 p.expect (['wxyz'])
757 """
758
759 self.child_fd
760 attr = termios.tcgetattr(self.child_fd)
761 if state:
762 attr[3] = attr[3] | termios.ECHO
763 else:
764 attr[3] = attr[3] & ~termios.ECHO
765 # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent
766 # and blocked on some platforms. TCSADRAIN is probably ideal if it worked.
767 termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
768
769 def read_nonblocking (self, size = 1, timeout = -1):
770
771 """This reads at most size characters from the child application. It
772 includes a timeout. If the read does not complete within the timeout
773 period then a TIMEOUT exception is raised. If the end of file is read
774 then an EOF exception will be raised. If a log file was set using
775 setlog() then all data will also be written to the log file.
776
777 If timeout is None then the read may block indefinitely. If timeout is -1
778 then the self.timeout value is used. If timeout is 0 then the child is
779 polled and if there was no data immediately ready then this will raise
780 a TIMEOUT exception.
781
782 The timeout refers only to the amount of time to read at least one
783 character. This is not effected by the 'size' parameter, so if you call
784 read_nonblocking(size=100, timeout=30) and only one character is
785 available right away then one character will be returned immediately.
786 It will not wait for 30 seconds for another 99 characters to come in.
787
788 This is a wrapper around os.read(). It uses select.select() to
789 implement the timeout. """
790
791 if self.closed:
792 raise ValueError ('I/O operation on closed file in read_nonblocking().')
793
794 if timeout == -1:
795 timeout = self.timeout
796
797 # Note that some systems such as Solaris do not give an EOF when
798 # the child dies. In fact, you can still try to read
799 # from the child_fd -- it will block forever or until TIMEOUT.
800 # For this case, I test isalive() before doing any reading.
801 # If isalive() is false, then I pretend that this is the same as EOF.
802 if not self.isalive():
803 r,w,e = self.__select([self.child_fd], [], [], 0) # timeout of 0 means "poll" @UnusedVariable
804 if not r:
805 self.flag_eof = True
806 raise EOF ('End Of File (EOF) in read_nonblocking(). Braindead platform.')
807 elif self.__irix_hack:
808 # This is a hack for Irix. It seems that Irix requires a long delay before checking isalive.
809 # This adds a 2 second delay, but only when the child is terminated.
810 r, w, e = self.__select([self.child_fd], [], [], 2) #@UnusedVariable
811 if not r and not self.isalive():
812 self.flag_eof = True
813 raise EOF ('End Of File (EOF) in read_nonblocking(). Pokey platform.')
814
815 r,w,e = self.__select([self.child_fd], [], [], timeout) #@UnusedVariable
816
817 if not r:
818 if not self.isalive():
819 # Some platforms, such as Irix, will claim that their processes are alive;
820 # then timeout on the select; and then finally admit that they are not alive.
821 self.flag_eof = True
822 raise EOF ('End of File (EOF) in read_nonblocking(). Very pokey platform.')
823 else:
824 raise TIMEOUT ('Timeout exceeded in read_nonblocking().')
825
826 if self.child_fd in r:
827 try:
828 s = os.read(self.child_fd, size)
829 except OSError, e: # Linux does this
830 self.flag_eof = True
831 raise EOF ('End Of File (EOF) in read_nonblocking(). Exception style platform.')
832 if s == '': # BSD style
833 self.flag_eof = True
834 raise EOF ('End Of File (EOF) in read_nonblocking(). Empty string style platform.')
835
836 if self.logfile is not None:
837 self.logfile.write (s)
838 self.logfile.flush()
839 if self.logfile_read is not None:
840 self.logfile_read.write (s)
841 self.logfile_read.flush()
842
843 return s
844
845 raise ExceptionPexpect ('Reached an unexpected state in read_nonblocking().')
846
847 def read (self, size = -1): # File-like object.
848
849 """This reads at most "size" bytes from the file (less if the read hits
850 EOF before obtaining size bytes). If the size argument is negative or
851 omitted, read all data until EOF is reached. The bytes are returned as
852 a string object. An empty string is returned when EOF is encountered
853 immediately. """
854
855 if size == 0:
856 return ''
857 if size < 0:
858 self.expect (self.delimiter) # delimiter default is EOF
859 return self.before
860
861 # I could have done this more directly by not using expect(), but
862 # I deliberately decided to couple read() to expect() so that
863 # I would catch any bugs early and ensure consistant behavior.
864 # It's a little less efficient, but there is less for me to
865 # worry about if I have to later modify read() or expect().
866 # Note, it's OK if size==-1 in the regex. That just means it
867 # will never match anything in which case we stop only on EOF.
868 cre = re.compile('.{%d}' % size, re.DOTALL)
869 index = self.expect ([cre, self.delimiter]) # delimiter default is EOF
870 if index == 0:
871 return self.after ### self.before should be ''. Should I assert this?
872 return self.before
873
874 def readline (self, size = -1): # File-like object.
875
876 """This reads and returns one entire line. A trailing newline is kept
877 in the string, but may be absent when a file ends with an incomplete
878 line. Note: This readline() looks for a \\r\\n pair even on UNIX
879 because this is what the pseudo tty device returns. So contrary to what
880 you may expect you will receive the newline as \\r\\n. An empty string
881 is returned when EOF is hit immediately. Currently, the size argument is
882 mostly ignored, so this behavior is not standard for a file-like
883 object. If size is 0 then an empty string is returned. """
884
885 if size == 0:
886 return ''
887 index = self.expect (['\r\n', self.delimiter]) # delimiter default is EOF
888 if index == 0:
889 return self.before + '\r\n'
890 else:
891 return self.before
892
893 def __iter__ (self): # File-like object.
894
895 """This is to support iterators over a file-like object.
896 """
897
898 return self
899
900 def next (self): # File-like object.
901
902 """This is to support iterators over a file-like object.
903 """
904
905 result = self.readline()
906 if result == "":
907 raise StopIteration
908 return result
909
910 def readlines (self, sizehint = -1): # File-like object.
911
912 """This reads until EOF using readline() and returns a list containing
913 the lines thus read. The optional "sizehint" argument is ignored. """
914
915 lines = []
916 while True:
917 line = self.readline()
918 if not line:
919 break
920 lines.append(line)
921 return lines
922
923 def write(self, s): # File-like object.
924
925 """This is similar to send() except that there is no return value.
926 """
927
928 self.send (s)
929
930 def writelines (self, sequence): # File-like object.
931
932 """This calls write() for each element in the sequence. The sequence
933 can be any iterable object producing strings, typically a list of
934 strings. This does not add line separators There is no return value.
935 """
936
937 for s in sequence:
938 self.write (s)
939
940 def send(self, s):
941
942 """This sends a string to the child process. This returns the number of
943 bytes written. If a log file was set then the data is also written to
944 the log. """
945
946 time.sleep(self.delaybeforesend)
947 if self.logfile is not None:
948 self.logfile.write (s)
949 self.logfile.flush()
950 if self.logfile_send is not None:
951 self.logfile_send.write (s)
952 self.logfile_send.flush()
953 c = os.write(self.child_fd, s)
954 return c
955
956 def sendline(self, s=''):
957
958 """This is like send(), but it adds a line feed (os.linesep). This
959 returns the number of bytes written. """
960
961 n = self.send(s)
962 n = n + self.send (os.linesep)
963 return n
964
965 def sendcontrol(self, char):
966
967 """This sends a control character to the child such as Ctrl-C or
968 Ctrl-D. For example, to send a Ctrl-G (ASCII 7)::
969
970 child.sendcontrol('g')
971
972 See also, sendintr() and sendeof().
973 """
974
975 char = char.lower()
976 a = ord(char)
977 if a>=97 and a<=122:
978 a = a - ord('a') + 1
979 return self.send (chr(a))
980 d = {'@':0, '`':0,
981 '[':27, '{':27,
982 '\\':28, '|':28,
983 ']':29, '}': 29,
984 '^':30, '~':30,
985 '_':31,
986 '?':127}
987 if char not in d:
988 return 0
989 return self.send (chr(d[char]))
990
991 def sendeof(self):
992
993 """This sends an EOF to the child. This sends a character which causes
994 the pending parent output buffer to be sent to the waiting child
995 program without waiting for end-of-line. If it is the first character
996 of the line, the read() in the user program returns 0, which signifies
997 end-of-file. This means to work as expected a sendeof() has to be
998 called at the beginning of a line. This method does not send a newline.
999 It is the responsibility of the caller to ensure the eof is sent at the
1000 beginning of a line. """
1001
1002 ### Hmmm... how do I send an EOF?
1003 ###C if ((m = write(pty, *buf, p - *buf)) < 0)
1004 ###C return (errno == EWOULDBLOCK) ? n : -1;
1005 #fd = sys.stdin.fileno()
1006 #old = termios.tcgetattr(fd) # remember current state
1007 #attr = termios.tcgetattr(fd)
1008 #attr[3] = attr[3] | termios.ICANON # ICANON must be set to recognize EOF
1009 #try: # use try/finally to ensure state gets restored
1010 # termios.tcsetattr(fd, termios.TCSADRAIN, attr)
1011 # if hasattr(termios, 'CEOF'):
1012 # os.write (self.child_fd, '%c' % termios.CEOF)
1013 # else:
1014 # # Silly platform does not define CEOF so assume CTRL-D
1015 # os.write (self.child_fd, '%c' % 4)
1016 #finally: # restore state
1017 # termios.tcsetattr(fd, termios.TCSADRAIN, old)
1018 if hasattr(termios, 'VEOF'):
1019 char = termios.tcgetattr(self.child_fd)[6][termios.VEOF]
1020 else:
1021 # platform does not define VEOF so assume CTRL-D
1022 char = chr(4)
1023 self.send(char)
1024
1025 def sendintr(self):
1026
1027 """This sends a SIGINT to the child. It does not require
1028 the SIGINT to be the first character on a line. """
1029
1030 if hasattr(termios, 'VINTR'):
1031 char = termios.tcgetattr(self.child_fd)[6][termios.VINTR]
1032 else:
1033 # platform does not define VINTR so assume CTRL-C
1034 char = chr(3)
1035 self.send (char)
1036
1037 def eof (self):
1038
1039 """This returns True if the EOF exception was ever raised.
1040 """
1041
1042 return self.flag_eof
1043
1044 def terminate(self, force=False):
1045
1046 """This forces a child process to terminate. It starts nicely with
1047 SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This
1048 returns True if the child was terminated. This returns False if the
1049 child could not be terminated. """
1050
1051 if not self.isalive():
1052 return True
1053 try:
1054 self.kill(signal.SIGHUP)
1055 time.sleep(self.delayafterterminate)
1056 if not self.isalive():
1057 return True
1058 self.kill(signal.SIGCONT)
1059 time.sleep(self.delayafterterminate)
1060 if not self.isalive():
1061 return True
1062 self.kill(signal.SIGINT)
1063 time.sleep(self.delayafterterminate)
1064 if not self.isalive():
1065 return True
1066 if force:
1067 self.kill(signal.SIGKILL)
1068 time.sleep(self.delayafterterminate)
1069 if not self.isalive():
1070 return True
1071 else:
1072 return False
1073 return False
1074 except OSError, e:
1075 # I think there are kernel timing issues that sometimes cause
1076 # this to happen. I think isalive() reports True, but the
1077 # process is dead to the kernel.
1078 # Make one last attempt to see if the kernel is up to date.
1079 time.sleep(self.delayafterterminate)
1080 if not self.isalive():
1081 return True
1082 else:
1083 return False
1084
1085 def wait(self):
1086
1087 """This waits until the child exits. This is a blocking call. This will
1088 not read any data from the child, so this will block forever if the
1089 child has unread output and has terminated. In other words, the child
1090 may have printed output then called exit(); but, technically, the child
1091 is still alive until its output is read. """
1092
1093 if self.isalive():
1094 pid, status = os.waitpid(self.pid, 0) #@UnusedVariable
1095 else:
1096 raise ExceptionPexpect ('Cannot wait for dead child process.')
1097 self.exitstatus = os.WEXITSTATUS(status)
1098 if os.WIFEXITED (status):
1099 self.status = status
1100 self.exitstatus = os.WEXITSTATUS(status)
1101 self.signalstatus = None
1102 self.terminated = True
1103 elif os.WIFSIGNALED (status):
1104 self.status = status
1105 self.exitstatus = None
1106 self.signalstatus = os.WTERMSIG(status)
1107 self.terminated = True
1108 elif os.WIFSTOPPED (status):
1109 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?')
1110 return self.exitstatus
1111
1112 def isalive(self):
1113
1114 """This tests if the child process is running or not. This is
1115 non-blocking. If the child was terminated then this will read the
1116 exitstatus or signalstatus of the child. This returns True if the child
1117 process appears to be running or False if not. It can take literally
1118 SECONDS for Solaris to return the right status. """
1119
1120 if self.terminated:
1121 return False
1122
1123 if self.flag_eof:
1124 # This is for Linux, which requires the blocking form of waitpid to get
1125 # status of a defunct process. This is super-lame. The flag_eof would have
1126 # been set in read_nonblocking(), so this should be safe.
1127 waitpid_options = 0
1128 else:
1129 waitpid_options = os.WNOHANG
1130
1131 try:
1132 pid, status = os.waitpid(self.pid, waitpid_options)
1133 except OSError, e: # No child processes
1134 if e[0] == errno.ECHILD:
1135 raise ExceptionPexpect ('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?')
1136 else:
1137 raise e
1138
1139 # I have to do this twice for Solaris. I can't even believe that I figured this out...
1140 # If waitpid() returns 0 it means that no child process wishes to
1141 # report, and the value of status is undefined.
1142 if pid == 0:
1143 try:
1144 pid, status = os.waitpid(self.pid, waitpid_options) ### os.WNOHANG) # Solaris!
1145 except OSError, e: # This should never happen...
1146 if e[0] == errno.ECHILD:
1147 raise ExceptionPexpect ('isalive() encountered condition that should never happen. There was no child process. Did someone else call waitpid() on our process?')
1148 else:
1149 raise e
1150
1151 # If pid is still 0 after two calls to waitpid() then
1152 # the process really is alive. This seems to work on all platforms, except
1153 # for Irix which seems to require a blocking call on waitpid or select, so I let read_nonblocking
1154 # take care of this situation (unfortunately, this requires waiting through the timeout).
1155 if pid == 0:
1156 return True
1157
1158 if pid == 0:
1159 return True
1160
1161 if os.WIFEXITED (status):
1162 self.status = status
1163 self.exitstatus = os.WEXITSTATUS(status)
1164 self.signalstatus = None
1165 self.terminated = True
1166 elif os.WIFSIGNALED (status):
1167 self.status = status
1168 self.exitstatus = None
1169 self.signalstatus = os.WTERMSIG(status)
1170 self.terminated = True
1171 elif os.WIFSTOPPED (status):
1172 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?')
1173 return False
1174
1175 def kill(self, sig):
1176
1177 """This sends the given signal to the child application. In keeping
1178 with UNIX tradition it has a misleading name. It does not necessarily
1179 kill the child unless you send the right signal. """
1180
1181 # Same as os.kill, but the pid is given for you.
1182 if self.isalive():
1183 os.kill(self.pid, sig)
1184
1185 def compile_pattern_list(self, patterns):
1186
1187 """This compiles a pattern-string or a list of pattern-strings.
1188 Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of
1189 those. Patterns may also be None which results in an empty list (you
1190 might do this if waiting for an EOF or TIMEOUT condition without
1191 expecting any pattern).
1192
1193 This is used by expect() when calling expect_list(). Thus expect() is
1194 nothing more than::
1195
1196 cpl = self.compile_pattern_list(pl)
1197 return self.expect_list(cpl, timeout)
1198
1199 If you are using expect() within a loop it may be more
1200 efficient to compile the patterns first and then call expect_list().
1201 This avoid calls in a loop to compile_pattern_list()::
1202
1203 cpl = self.compile_pattern_list(my_pattern)
1204 while some_condition:
1205 ...
1206 i = self.expect_list(clp, timeout)
1207 ...
1208 """
1209
1210 if patterns is None:
1211 return []
1212 if type(patterns) is not types.ListType:
1213 patterns = [patterns]
1214
1215 compile_flags = re.DOTALL # Allow dot to match \n
1216 if self.ignorecase:
1217 compile_flags = compile_flags | re.IGNORECASE
1218 compiled_pattern_list = []
1219 for p in patterns:
1220 if type(p) in types.StringTypes:
1221 compiled_pattern_list.append(re.compile(p, compile_flags))
1222 elif p is EOF:
1223 compiled_pattern_list.append(EOF)
1224 elif p is TIMEOUT:
1225 compiled_pattern_list.append(TIMEOUT)
1226 elif type(p) is type(re.compile('')):
1227 compiled_pattern_list.append(p)
1228 else:
1229 raise TypeError ('Argument must be one of StringTypes, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p)))
1230
1231 return compiled_pattern_list
1232
1233 def expect(self, pattern, timeout = -1, searchwindowsize=None):
1234
1235 """This seeks through the stream until a pattern is matched. The
1236 pattern is overloaded and may take several types. The pattern can be a
1237 StringType, EOF, a compiled re, or a list of any of those types.
1238 Strings will be compiled to re types. This returns the index into the
1239 pattern list. If the pattern was not a list this returns index 0 on a
1240 successful match. This may raise exceptions for EOF or TIMEOUT. To
1241 avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern
1242 list. That will cause expect to match an EOF or TIMEOUT condition
1243 instead of raising an exception.
1244
1245 If you pass a list of patterns and more than one matches, the first match
1246 in the stream is chosen. If more than one pattern matches at that point,
1247 the leftmost in the pattern list is chosen. For example::
1248
1249 # the input is 'foobar'
1250 index = p.expect (['bar', 'foo', 'foobar'])
1251 # returns 1 ('foo') even though 'foobar' is a "better" match
1252
1253 Please note, however, that buffering can affect this behavior, since
1254 input arrives in unpredictable chunks. For example::
1255
1256 # the input is 'foobar'
1257 index = p.expect (['foobar', 'foo'])
1258 # returns 0 ('foobar') if all input is available at once,
1259 # but returs 1 ('foo') if parts of the final 'bar' arrive late
1260
1261 After a match is found the instance attributes 'before', 'after' and
1262 'match' will be set. You can see all the data read before the match in
1263 'before'. You can see the data that was matched in 'after'. The
1264 re.MatchObject used in the re match will be in 'match'. If an error
1265 occurred then 'before' will be set to all the data read so far and
1266 'after' and 'match' will be None.
1267
1268 If timeout is -1 then timeout will be set to the self.timeout value.
1269
1270 A list entry may be EOF or TIMEOUT instead of a string. This will
1271 catch these exceptions and return the index of the list entry instead
1272 of raising the exception. The attribute 'after' will be set to the
1273 exception type. The attribute 'match' will be None. This allows you to
1274 write code like this::
1275
1276 index = p.expect (['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
1277 if index == 0:
1278 do_something()
1279 elif index == 1:
1280 do_something_else()
1281 elif index == 2:
1282 do_some_other_thing()
1283 elif index == 3:
1284 do_something_completely_different()
1285
1286 instead of code like this::
1287
1288 try:
1289 index = p.expect (['good', 'bad'])
1290 if index == 0:
1291 do_something()
1292 elif index == 1:
1293 do_something_else()
1294 except EOF:
1295 do_some_other_thing()
1296 except TIMEOUT:
1297 do_something_completely_different()
1298
1299 These two forms are equivalent. It all depends on what you want. You
1300 can also just expect the EOF if you are waiting for all output of a
1301 child to finish. For example::
1302
1303 p = pexpect.spawn('/bin/ls')
1304 p.expect (pexpect.EOF)
1305 print p.before
1306
1307 If you are trying to optimize for speed then see expect_list().
1308 """
1309
1310 compiled_pattern_list = self.compile_pattern_list(pattern)
1311 return self.expect_list(compiled_pattern_list, timeout, searchwindowsize)
1312
1313 def expect_list(self, pattern_list, timeout = -1, searchwindowsize = -1):
1314
1315 """This takes a list of compiled regular expressions and returns the
1316 index into the pattern_list that matched the child output. The list may
1317 also contain EOF or TIMEOUT (which are not compiled regular
1318 expressions). This method is similar to the expect() method except that
1319 expect_list() does not recompile the pattern list on every call. This
1320 may help if you are trying to optimize for speed, otherwise just use
1321 the expect() method. This is called by expect(). If timeout==-1 then
1322 the self.timeout value is used. If searchwindowsize==-1 then the
1323 self.searchwindowsize value is used. """
1324
1325 return self.expect_loop(searcher_re(pattern_list), timeout, searchwindowsize)
1326
1327 def expect_exact(self, pattern_list, timeout = -1, searchwindowsize = -1):
1328
1329 """This is similar to expect(), but uses plain string matching instead
1330 of compiled regular expressions in 'pattern_list'. The 'pattern_list'
1331 may be a string; a list or other sequence of strings; or TIMEOUT and
1332 EOF.
1333
1334 This call might be faster than expect() for two reasons: string
1335 searching is faster than RE matching and it is possible to limit the
1336 search to just the end of the input buffer.
1337
1338 This method is also useful when you don't want to have to worry about
1339 escaping regular expression characters that you want to match."""
1340
1341 if type(pattern_list) in types.StringTypes or pattern_list in (TIMEOUT, EOF):
1342 pattern_list = [pattern_list]
1343 return self.expect_loop(searcher_string(pattern_list), timeout, searchwindowsize)
1344
1345 def expect_loop(self, searcher, timeout = -1, searchwindowsize = -1):
1346
1347 """This is the common loop used inside expect. The 'searcher' should be
1348 an instance of searcher_re or searcher_string, which describes how and what
1349 to search for in the input.
1350
1351 See expect() for other arguments, return value and exceptions. """
1352
1353 self.searcher = searcher
1354
1355 if timeout == -1:
1356 timeout = self.timeout
1357 if timeout is not None:
1358 end_time = time.time() + timeout
1359 if searchwindowsize == -1:
1360 searchwindowsize = self.searchwindowsize
1361
1362 try:
1363 incoming = self.buffer
1364 freshlen = len(incoming)
1365 while True: # Keep reading until exception or return.
1366 index = searcher.search(incoming, freshlen, searchwindowsize)
1367 if index >= 0:
1368 self.buffer = incoming[searcher.end : ]
1369 self.before = incoming[ : searcher.start]
1370 self.after = incoming[searcher.start : searcher.end]
1371 self.match = searcher.match
1372 self.match_index = index
1373 return self.match_index
1374 # No match at this point
1375 if timeout < 0 and timeout is not None:
1376 raise TIMEOUT ('Timeout exceeded in expect_any().')
1377 # Still have time left, so read more data
1378 c = self.read_nonblocking (self.maxread, timeout)
1379 freshlen = len(c)
1380 time.sleep (0.0001)
1381 incoming = incoming + c
1382 if timeout is not None:
1383 timeout = end_time - time.time()
1384 except EOF, e:
1385 self.buffer = ''
1386 self.before = incoming
1387 self.after = EOF
1388 index = searcher.eof_index
1389 if index >= 0:
1390 self.match = EOF
1391 self.match_index = index
1392 return self.match_index
1393 else:
1394 self.match = None
1395 self.match_index = None
1396 raise EOF (str(e) + '\n' + str(self))
1397 except TIMEOUT, e:
1398 self.buffer = incoming
1399 self.before = incoming
1400 self.after = TIMEOUT
1401 index = searcher.timeout_index
1402 if index >= 0:
1403 self.match = TIMEOUT
1404 self.match_index = index
1405 return self.match_index
1406 else:
1407 self.match = None
1408 self.match_index = None
1409 raise TIMEOUT (str(e) + '\n' + str(self))
1410 except Exception:
1411 self.before = incoming
1412 self.after = None
1413 self.match = None
1414 self.match_index = None
1415 raise
1416
1417 def getwinsize(self):
1418
1419 """This returns the terminal window size of the child tty. The return
1420 value is a tuple of (rows, cols). """
1421
1422 TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912L)
1423 s = struct.pack('HHHH', 0, 0, 0, 0)
1424 x = fcntl.ioctl(self.fileno(), TIOCGWINSZ, s)
1425 return struct.unpack('HHHH', x)[0:2]
1426
1427 def setwinsize(self, r, c):
1428
1429 """This sets the terminal window size of the child tty. This will cause
1430 a SIGWINCH signal to be sent to the child. This does not change the
1431 physical window size. It changes the size reported to TTY-aware
1432 applications like vi or curses -- applications that respond to the
1433 SIGWINCH signal. """
1434
1435 # Check for buggy platforms. Some Python versions on some platforms
1436 # (notably OSF1 Alpha and RedHat 7.1) truncate the value for
1437 # termios.TIOCSWINSZ. It is not clear why this happens.
1438 # These platforms don't seem to handle the signed int very well;
1439 # yet other platforms like OpenBSD have a large negative value for
1440 # TIOCSWINSZ and they don't have a truncate problem.
1441 # Newer versions of Linux have totally different values for TIOCSWINSZ.
1442 # Note that this fix is a hack.
1443 TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561)
1444 if TIOCSWINSZ == 2148037735L: # L is not required in Python >= 2.2.
1445 TIOCSWINSZ = -2146929561 # Same bits, but with sign.
1446 # Note, assume ws_xpixel and ws_ypixel are zero.
1447 s = struct.pack('HHHH', r, c, 0, 0)
1448 fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
1449
1450 def interact(self, escape_character = chr(29), input_filter = None, output_filter = None):
1451
1452 """This gives control of the child process to the interactive user (the
1453 human at the keyboard). Keystrokes are sent to the child process, and
1454 the stdout and stderr output of the child process is printed. This
1455 simply echos the child stdout and child stderr to the real stdout and
1456 it echos the real stdin to the child stdin. When the user types the
1457 escape_character this method will stop. The default for
1458 escape_character is ^]. This should not be confused with ASCII 27 --
1459 the ESC character. ASCII 29 was chosen for historical merit because
1460 this is the character used by 'telnet' as the escape character. The
1461 escape_character will not be sent to the child process.
1462
1463 You may pass in optional input and output filter functions. These
1464 functions should take a string and return a string. The output_filter
1465 will be passed all the output from the child process. The input_filter
1466 will be passed all the keyboard input from the user. The input_filter
1467 is run BEFORE the check for the escape_character.
1468
1469 Note that if you change the window size of the parent the SIGWINCH
1470 signal will not be passed through to the child. If you want the child
1471 window size to change when the parent's window size changes then do
1472 something like the following example::
1473
1474 import pexpect, struct, fcntl, termios, signal, sys
1475 def sigwinch_passthrough (sig, data):
1476 s = struct.pack("HHHH", 0, 0, 0, 0)
1477 a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s))
1478 global p
1479 p.setwinsize(a[0],a[1])
1480 p = pexpect.spawn('/bin/bash') # Note this is global and used in sigwinch_passthrough.
1481 signal.signal(signal.SIGWINCH, sigwinch_passthrough)
1482 p.interact()
1483 """
1484
1485 # Flush the buffer.
1486 self.stdout.write (self.buffer)
1487 self.stdout.flush()
1488 self.buffer = ''
1489 mode = tty.tcgetattr(self.STDIN_FILENO)
1490 tty.setraw(self.STDIN_FILENO)
1491 try:
1492 self.__interact_copy(escape_character, input_filter, output_filter)
1493 finally:
1494 tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
1495
1496 def __interact_writen(self, fd, data):
1497
1498 """This is used by the interact() method.
1499 """
1500
1501 while data != '' and self.isalive():
1502 n = os.write(fd, data)
1503 data = data[n:]
1504
1505 def __interact_read(self, fd):
1506
1507 """This is used by the interact() method.
1508 """
1509
1510 return os.read(fd, 1000)
1511
1512 def __interact_copy(self, escape_character = None, input_filter = None, output_filter = None):
1513
1514 """This is used by the interact() method.
1515 """
1516
1517 while self.isalive():
1518 r,w,e = self.__select([self.child_fd, self.STDIN_FILENO], [], []) #@UnusedVariable
1519 if self.child_fd in r:
1520 data = self.__interact_read(self.child_fd)
1521 if output_filter: data = output_filter(data)
1522 if self.logfile is not None:
1523 self.logfile.write (data)
1524 self.logfile.flush()
1525 os.write(self.STDOUT_FILENO, data)
1526 if self.STDIN_FILENO in r:
1527 data = self.__interact_read(self.STDIN_FILENO)
1528 if input_filter: data = input_filter(data)
1529 i = data.rfind(escape_character)
1530 if i != -1:
1531 data = data[:i]
1532 self.__interact_writen(self.child_fd, data)
1533 break
1534 self.__interact_writen(self.child_fd, data)
1535
1536 def __select (self, iwtd, owtd, ewtd, timeout=None):
1537
1538 """This is a wrapper around select.select() that ignores signals. If
1539 select.select raises a select.error exception and errno is an EINTR
1540 error then it is ignored. Mainly this is used to ignore sigwinch
1541 (terminal resize). """
1542
1543 # if select() is interrupted by a signal (errno==EINTR) then
1544 # we loop back and enter the select() again.
1545 if timeout is not None:
1546 end_time = time.time() + timeout
1547 while True:
1548 try:
1549 return select.select (iwtd, owtd, ewtd, timeout)
1550 except select.error, e:
1551 if e[0] == errno.EINTR:
1552 # if we loop back we have to subtract the amount of time we already waited.
1553 if timeout is not None:
1554 timeout = end_time - time.time()
1555 if timeout < 0:
1556 return ([],[],[])
1557 else: # something else caused the select.error, so this really is an exception
1558 raise
1559
1560##############################################################################
1561# The following methods are no longer supported or allowed.
1562
1563 def setmaxread (self, maxread):
1564
1565 """This method is no longer supported or allowed. I don't like getters
1566 and setters without a good reason. """
1567
1568 raise ExceptionPexpect ('This method is no longer supported or allowed. Just assign a value to the maxread member variable.')
1569
1570 def setlog (self, fileobject):
1571
1572 """This method is no longer supported or allowed.
1573 """
1574
1575 raise ExceptionPexpect ('This method is no longer supported or allowed. Just assign a value to the logfile member variable.')
1576
1577##############################################################################
1578# End of spawn class
1579##############################################################################
1580
1581class searcher_string (object):
1582
1583 """This is a plain string search helper for the spawn.expect_any() method.
1584
1585 Attributes:
1586
1587 eof_index - index of EOF, or -1
1588 timeout_index - index of TIMEOUT, or -1
1589
1590 After a successful match by the search() method the following attributes
1591 are available:
1592
1593 start - index into the buffer, first byte of match
1594 end - index into the buffer, first byte after match
1595 match - the matching string itself
1596 """
1597
1598 def __init__(self, strings):
1599
1600 """This creates an instance of searcher_string. This argument 'strings'
1601 may be a list; a sequence of strings; or the EOF or TIMEOUT types. """
1602
1603 self.eof_index = -1
1604 self.timeout_index = -1
1605 self._strings = []
1606 for n, s in zip(range(len(strings)), strings):
1607 if s is EOF:
1608 self.eof_index = n
1609 continue
1610 if s is TIMEOUT:
1611 self.timeout_index = n
1612 continue
1613 self._strings.append((n, s))
1614
1615 def __str__(self):
1616
1617 """This returns a human-readable string that represents the state of
1618 the object."""
1619
1620 ss = [ (ns[0],' %d: "%s"' % ns) for ns in self._strings ]
1621 ss.append((-1,'searcher_string:'))
1622 if self.eof_index >= 0:
1623 ss.append ((self.eof_index,' %d: EOF' % self.eof_index))
1624 if self.timeout_index >= 0:
1625 ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
1626 ss.sort()
1627 ss = zip(*ss)[1]
1628 return '\n'.join(ss)
1629
1630 def search(self, buffer, freshlen, searchwindowsize=None):
1631
1632 """This searches 'buffer' for the first occurence of one of the search
1633 strings. 'freshlen' must indicate the number of bytes at the end of
1634 'buffer' which have not been searched before. It helps to avoid
1635 searching the same, possibly big, buffer over and over again.
1636
1637 See class spawn for the 'searchwindowsize' argument.
1638
1639 If there is a match this returns the index of that string, and sets
1640 'start', 'end' and 'match'. Otherwise, this returns -1. """
1641
1642 absurd_match = len(buffer)
1643 first_match = absurd_match
1644
1645 # 'freshlen' helps a lot here. Further optimizations could
1646 # possibly include:
1647 #
1648 # using something like the Boyer-Moore Fast String Searching
1649 # Algorithm; pre-compiling the search through a list of
1650 # strings into something that can scan the input once to
1651 # search for all N strings; realize that if we search for
1652 # ['bar', 'baz'] and the input is '...foo' we need not bother
1653 # rescanning until we've read three more bytes.
1654 #
1655 # Sadly, I don't know enough about this interesting topic. /grahn
1656
1657 for index, s in self._strings:
1658 if searchwindowsize is None:
1659 # the match, if any, can only be in the fresh data,
1660 # or at the very end of the old data
1661 offset = -(freshlen+len(s))
1662 else:
1663 # better obey searchwindowsize
1664 offset = -searchwindowsize
1665 n = buffer.find(s, offset)
1666 if n >= 0 and n < first_match:
1667 first_match = n
1668 best_index, best_match = index, s
1669 if first_match == absurd_match:
1670 return -1
1671 self.match = best_match
1672 self.start = first_match
1673 self.end = self.start + len(self.match)
1674 return best_index
1675
1676class searcher_re (object):
1677
1678 """This is regular expression string search helper for the
1679 spawn.expect_any() method.
1680
1681 Attributes:
1682
1683 eof_index - index of EOF, or -1
1684 timeout_index - index of TIMEOUT, or -1
1685
1686 After a successful match by the search() method the following attributes
1687 are available:
1688
1689 start - index into the buffer, first byte of match
1690 end - index into the buffer, first byte after match
1691 match - the re.match object returned by a succesful re.search
1692
1693 """
1694
1695 def __init__(self, patterns):
1696
1697 """This creates an instance that searches for 'patterns' Where
1698 'patterns' may be a list or other sequence of compiled regular
1699 expressions, or the EOF or TIMEOUT types."""
1700
1701 self.eof_index = -1
1702 self.timeout_index = -1
1703 self._searches = []
1704 for n, s in zip(range(len(patterns)), patterns):
1705 if s is EOF:
1706 self.eof_index = n
1707 continue
1708 if s is TIMEOUT:
1709 self.timeout_index = n
1710 continue
1711 self._searches.append((n, s))
1712
1713 def __str__(self):
1714
1715 """This returns a human-readable string that represents the state of
1716 the object."""
1717
1718 ss = [ (n,' %d: re.compile("%s")' % (n,str(s.pattern))) for n,s in self._searches]
1719 ss.append((-1,'searcher_re:'))
1720 if self.eof_index >= 0:
1721 ss.append ((self.eof_index,' %d: EOF' % self.eof_index))
1722 if self.timeout_index >= 0:
1723 ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
1724 ss.sort()
1725 ss = zip(*ss)[1]
1726 return '\n'.join(ss)
1727
1728 def search(self, buffer, freshlen, searchwindowsize=None):
1729
1730 """This searches 'buffer' for the first occurence of one of the regular
1731 expressions. 'freshlen' must indicate the number of bytes at the end of
1732 'buffer' which have not been searched before.
1733
1734 See class spawn for the 'searchwindowsize' argument.
1735
1736 If there is a match this returns the index of that string, and sets
1737 'start', 'end' and 'match'. Otherwise, returns -1."""
1738
1739 absurd_match = len(buffer)
1740 first_match = absurd_match
1741 # 'freshlen' doesn't help here -- we cannot predict the
1742 # length of a match, and the re module provides no help.
1743 if searchwindowsize is None:
1744 searchstart = 0
1745 else:
1746 searchstart = max(0, len(buffer)-searchwindowsize)
1747 for index, s in self._searches:
1748 match = s.search(buffer, searchstart)
1749 if match is None:
1750 continue
1751 n = match.start()
1752 if n < first_match:
1753 first_match = n
1754 the_match = match
1755 best_index = index
1756 if first_match == absurd_match:
1757 return -1
1758 self.start = first_match
1759 self.match = the_match
1760 self.end = self.match.end()
1761 return best_index
1762
1763def which (filename):
1764
1765 """This takes a given filename; tries to find it in the environment path;
1766 then checks if it is executable. This returns the full path to the filename
1767 if found and executable. Otherwise this returns None."""
1768
1769 # Special case where filename already contains a path.
1770 if os.path.dirname(filename) != '':
1771 if os.access (filename, os.X_OK):
1772 return filename
1773
1774 if not os.environ.has_key('PATH') or os.environ['PATH'] == '':
1775 p = os.defpath
1776 else:
1777 p = os.environ['PATH']
1778
1779 # Oddly enough this was the one line that made Pexpect
1780 # incompatible with Python 1.5.2.
1781 #pathlist = p.split (os.pathsep)
1782 pathlist = string.split (p, os.pathsep)
1783
1784 for path in pathlist:
1785 f = os.path.join(path, filename)
1786 if os.access(f, os.X_OK):
1787 return f
1788 return None
1789
1790def split_command_line(command_line):
1791
1792 """This splits a command line into a list of arguments. It splits arguments
1793 on spaces, but handles embedded quotes, doublequotes, and escaped
1794 characters. It's impossible to do this with a regular expression, so I
1795 wrote a little state machine to parse the command line. """
1796
1797 arg_list = []
1798 arg = ''
1799
1800 # Constants to name the states we can be in.
1801 state_basic = 0
1802 state_esc = 1
1803 state_singlequote = 2
1804 state_doublequote = 3
1805 state_whitespace = 4 # The state of consuming whitespace between commands.
1806 state = state_basic
1807
1808 for c in command_line:
1809 if state == state_basic or state == state_whitespace:
1810 if c == '\\': # Escape the next character
1811 state = state_esc
1812 elif c == r"'": # Handle single quote
1813 state = state_singlequote
1814 elif c == r'"': # Handle double quote
1815 state = state_doublequote
1816 elif c.isspace():
1817 # Add arg to arg_list if we aren't in the middle of whitespace.
1818 if state == state_whitespace:
1819 None # Do nothing.
1820 else:
1821 arg_list.append(arg)
1822 arg = ''
1823 state = state_whitespace
1824 else:
1825 arg = arg + c
1826 state = state_basic
1827 elif state == state_esc:
1828 arg = arg + c
1829 state = state_basic
1830 elif state == state_singlequote:
1831 if c == r"'":
1832 state = state_basic
1833 else:
1834 arg = arg + c
1835 elif state == state_doublequote:
1836 if c == r'"':
1837 state = state_basic
1838 else:
1839 arg = arg + c
1840
1841 if arg != '':
1842 arg_list.append(arg)
1843 return arg_list
1844
1845# vi:ts=4:sw=4:expandtab:ft=python:
18460
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2014-04-17 19:53:39 +0000
+++ po/POTFILES.in 2014-04-17 19:53:39 +0000
@@ -51,7 +51,6 @@
51duplicity/filechunkio.py51duplicity/filechunkio.py
52duplicity/dup_threading.py52duplicity/dup_threading.py
53duplicity/path.py53duplicity/path.py
54duplicity/pexpect.py
55duplicity/gpginterface.py54duplicity/gpginterface.py
56duplicity/dup_time.py55duplicity/dup_time.py
57duplicity/gpg.py56duplicity/gpg.py
5857
=== modified file 'setup.py'
--- setup.py 2014-04-16 20:45:09 +0000
+++ setup.py 2014-04-17 19:53:39 +0000
@@ -144,7 +144,7 @@
144 libraries=["rsync"])],144 libraries=["rsync"])],
145 scripts = ['bin/rdiffdir', 'bin/duplicity'],145 scripts = ['bin/rdiffdir', 'bin/duplicity'],
146 data_files = data_files,146 data_files = data_files,
147 tests_require = ['lockfile', 'mock', 'nose'],147 tests_require = ['lockfile', 'mock', 'nose', 'pexpect'],
148 test_suite = 'nose.collector',148 test_suite = 'nose.collector',
149 cmdclass={'test': TestCommand,149 cmdclass={'test': TestCommand,
150 'install': InstallCommand,150 'install': InstallCommand,
151151
=== modified file 'testing/helpers/helper.py'
--- testing/helpers/helper.py 2014-04-16 02:43:43 +0000
+++ testing/helpers/helper.py 2014-04-17 19:53:39 +0000
@@ -20,13 +20,13 @@
20# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA20# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2121
22import os22import os
23import pexpect
23import time24import time
24import unittest25import unittest
2526
26from duplicity import backend27from duplicity import backend
27from duplicity import globals28from duplicity import globals
28from duplicity import log29from duplicity import log
29from duplicity import pexpect
3030
31sign_key = '56538CCF'31sign_key = '56538CCF'
32sign_passphrase = 'test'32sign_passphrase = 'test'
3333
=== modified file 'tox.ini'
--- tox.ini 2014-04-16 18:37:39 +0000
+++ tox.ini 2014-04-17 19:53:39 +0000
@@ -5,4 +5,5 @@
5deps=lockfile5deps=lockfile
6 mock6 mock
7 nose7 nose
8 pexpect
8commands=nosetests9commands=nosetests

Subscribers

People subscribed via source and target branches

to all changes: