Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(529)

Side by Side Diff: third_party/pexpect/doc/overview.rst

Issue 1398903002: Add third_party/pexpect (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@end-to-end-test
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/pexpect/doc/make.bat ('k') | third_party/pexpect/doc/requirements.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 API Overview
2 ============
3
4 Pexpect can be used for automating interactive applications such as ssh, ftp,
5 mencoder, passwd, etc. The Pexpect interface was designed to be easy to use.
6
7 Here is an example of Pexpect in action::
8
9 # This connects to the openbsd ftp site and
10 # downloads the recursive directory listing.
11 import pexpect
12 child = pexpect.spawn('ftp ftp.openbsd.org')
13 child.expect('Name .*: ')
14 child.sendline('anonymous')
15 child.expect('Password:')
16 child.sendline('noah@example.com')
17 child.expect('ftp> ')
18 child.sendline('lcd /tmp')
19 child.expect('ftp> ')
20 child.sendline('cd pub/OpenBSD')
21 child.expect('ftp> ')
22 child.sendline('get README')
23 child.expect('ftp> ')
24 child.sendline('bye')
25
26 Obviously you could write an ftp client using Python's own :mod:`ftplib` module,
27 but this is just a demonstration. You can use this technique with any applicatio n.
28 This is especially handy if you are writing automated test tools.
29
30 There are two important methods in Pexpect -- :meth:`~pexpect.spawn.expect` and
31 :meth:`~pexpect.spawn.send` (or :meth:`~pexpect.spawn.sendline` which is
32 like :meth:`~pexpect.spawn.send` with a linefeed). The :meth:`~pexpect.spawn.exp ect`
33 method waits for the child application to return a given string. The string you
34 specify is a regular expression, so you can match complicated patterns. The
35 :meth:`~pexpect.spawn.send` method writes a string to the child application.
36 From the child's point of view it looks just like someone typed the text from a
37 terminal. After each call to :meth:`~pexpect.spawn.expect` the ``before`` and `` after``
38 properties will be set to the text printed by child application. The ``before``
39 property will contain all text up to the expected string pattern. The ``after``
40 string will contain the text that was matched by the expected pattern.
41 The match property is set to the `re match object <http://docs.python.org/3/libr ary/re#match-objects>`_.
42
43 An example of Pexpect in action may make things more clear. This example uses
44 ftp to login to the OpenBSD site; list files in a directory; and then pass
45 interactive control of the ftp session to the human user::
46
47 import pexpect
48 child = pexpect.spawn ('ftp ftp.openbsd.org')
49 child.expect ('Name .*: ')
50 child.sendline ('anonymous')
51 child.expect ('Password:')
52 child.sendline ('noah@example.com')
53 child.expect ('ftp> ')
54 child.sendline ('ls /pub/OpenBSD/')
55 child.expect ('ftp> ')
56 print child.before # Print the result of the ls command.
57 child.interact() # Give control of the child to the user.
58
59 Special EOF and TIMEOUT patterns
60 --------------------------------
61
62 There are two special patterns to match the End Of File (:class:`~pexpect.EOF`)
63 or a Timeout condition (:class:`~pexpect.TIMEOUT`). You can pass these
64 patterns to :meth:`~pexpect.spawn.expect`. These patterns are not regular
65 expressions. Use them like predefined constants.
66
67 If the child has died and you have read all the child's output then ordinarily
68 :meth:`~pexpect.spawn.expect` will raise an :class:`~pexpect.EOF` exception.
69 You can read everything up to the EOF without generating an exception by using
70 the EOF pattern expect. In this case everything the child has output will be
71 available in the ``before`` property.
72
73 The pattern given to :meth:`~pexpect.spawn.expect` may be a regular expression
74 or it may also be a list of regular expressions. This allows you to match
75 multiple optional responses. The :meth:`~pexpect.spawn.expect` method returns
76 the index of the pattern that was matched. For example, say you wanted to login
77 to a server. After entering a password you could get various responses from the
78 server -- your password could be rejected; or you could be allowed in and asked
79 for your terminal type; or you could be let right in and given a command prompt.
80 The following code fragment gives an example of this::
81
82 child.expect('password:')
83 child.sendline(my_secret_password)
84 # We expect any of these three patterns...
85 i = child.expect (['Permission denied', 'Terminal type', '[#\$] '])
86 if i==0:
87 print('Permission denied on host. Can\'t login')
88 child.kill(0)
89 elif i==1:
90 print('Login OK... need to send terminal type.')
91 child.sendline('vt100')
92 child.expect('[#\$] ')
93 elif i==2:
94 print('Login OK.')
95 print('Shell command prompt', child.after)
96
97 If nothing matches an expected pattern then :meth:`~pexpect.spawn.expect` will
98 eventually raise a :class:`~pexpect.TIMEOUT` exception. The default time is 30
99 seconds, but you can change this by passing a timeout argument to
100 :meth:`~pexpect.spawn.expect`::
101
102 # Wait no more than 2 minutes (120 seconds) for password prompt.
103 child.expect('password:', timeout=120)
104
105 Find the end of line -- CR/LF conventions
106 -----------------------------------------
107
108 Pexpect matches regular expressions a little differently than what you might be
109 used to.
110
111 The :regexp:`$` pattern for end of line match is useless. The :regexp:`$`
112 matches the end of string, but Pexpect reads from the child one character at a
113 time, so each character looks like the end of a line. Pexpect can't do a
114 look-ahead into the child's output stream. In general you would have this
115 situation when using regular expressions with any stream.
116
117 .. note::
118
119 Pexpect does have an internal buffer, so reads are faster than one character
120 at a time, but from the user's perspective the regex patterns test happens
121 one character at a time.
122
123 The best way to match the end of a line is to look for the newline: ``"\r\n"``
124 (CR/LF). Yes, that does appear to be DOS-style. It may surprise some UNIX people
125 to learn that terminal TTY device drivers (dumb, vt100, ANSI, xterm, etc.) all
126 use the CR/LF combination to signify the end of line. Pexpect uses a Pseudo-TTY
127 device to talk to the child application, so when the child app prints ``"\n"``
128 you actually see ``"\r\n"``.
129
130 UNIX uses just linefeeds to end lines of text, but not when it comes to TTY
131 devices! TTY devices are more like the Windows world. Each line of text ends
132 with a CR/LF combination. When you intercept data from a UNIX command from a
133 TTY device you will find that the TTY device outputs a CR/LF combination. A
134 UNIX command may only write a linefeed (``\n``), but the TTY device driver
135 converts it to CR/LF. This means that your terminal will see lines end with
136 CR/LF (hex ``0D 0A``). Since Pexpect emulates a terminal, to match ends of
137 lines you have to expect the CR/LF combination::
138
139 child.expect('\r\n')
140
141 If you just need to skip past a new line then ``expect('\n')`` by itself will
142 work, but if you are expecting a specific pattern before the end of line then
143 you need to explicitly look for the ``\r``. For example the following expects a
144 word at the end of a line::
145
146 child.expect('\w+\r\n')
147
148 But the following would both fail::
149
150 child.expect('\w+\n')
151
152 And as explained before, trying to use :regexp:`$` to match the end of line
153 would not work either::
154
155 child.expect ('\w+$')
156
157 So if you need to explicitly look for the END OF LINE, you want to look for the
158 CR/LF combination -- not just the LF and not the $ pattern.
159
160 This problem is not limited to Pexpect. This problem happens any time you try
161 to perform a regular expression match on a stream. Regular expressions need to
162 look ahead. With a stream it is hard to look ahead because the process
163 generating the stream may not be finished. There is no way to know if the
164 process has paused momentarily or is finished and waiting for you. Pexpect must
165 implicitly always do a NON greedy match (minimal) at the end of a input.
166
167 Pexpect compiles all regular expressions with the :data:`re.DOTALL` flag.
168 With the :data:`~re.DOTALL` flag, a ``"."`` will match a newline.
169
170 Beware of + and * at the end of patterns
171 ----------------------------------------
172
173 Remember that any time you try to match a pattern that needs look-ahead that
174 you will always get a minimal match (non greedy). For example, the following
175 will always return just one character::
176
177 child.expect ('.+')
178
179 This example will match successfully, but will always return no characters::
180
181 child.expect ('.*')
182
183 Generally any star * expression will match as little as possible.
184
185 One thing you can do is to try to force a non-ambiguous character at the end of
186 your :regexp:`\\d+` pattern. Expect that character to delimit the string. For
187 example, you might try making the end of your pattern be :regexp:`\\D+` instead
188 of :regexp:`\\D*`. Number digits alone would not satisfy the :regexp:`(\\d+)\\D+ `
189 pattern. You would need some numbers and at least one non-number at the end.
190
191
192 Debugging
193 ---------
194
195 If you get the string value of a :class:`pexpect.spawn` object you will get lots
196 of useful debugging information. For debugging it's very useful to use the
197 following pattern::
198
199 try:
200 i = child.expect ([pattern1, pattern2, pattern3, etc])
201 except:
202 print("Exception was thrown")
203 print("debug information:")
204 print(str(child))
205
206 It is also useful to log the child's input and out to a file or the screen. The
207 following will turn on logging and send output to stdout (the screen)::
208
209 child = pexpect.spawn(foo)
210 child.logfile = sys.stdout
211
212 Exceptions
213 ----------
214
215 :class:`~pexpect.EOF`
216
217 Note that two flavors of EOF Exception may be thrown. They are virtually
218 identical except for the message string. For practical purposes you should have
219 no need to distinguish between them, but they do give a little extra information
220 about what type of platform you are running. The two messages are:
221
222 - "End Of File (EOF) in read(). Exception style platform."
223 - "End Of File (EOF) in read(). Empty string style platform."
224
225 Some UNIX platforms will throw an exception when you try to read from a file
226 descriptor in the EOF state. Other UNIX platforms instead quietly return an
227 empty string to indicate that the EOF state has been reached.
228
229 If you wish to read up to the end of the child's output without generating an
230 :class:`~pexpect.EOF` exception then use the ``expect(pexpect.EOF)`` method.
231
232 :class:`~pexpect.TIMEOUT`
233
234 The :meth:`~pexpect.spawn.expect` and :meth:`~pexpect.spawn.read` methods will
235 also timeout if the child does not generate any output for a given amount of
236 time. If this happens they will raise a :class:`~pexpect.TIMEOUT` exception.
237 You can have these methods ignore timeout and block indefinitely by passing
238 ``None`` for the timeout parameter::
239
240 child.expect(pexpect.EOF, timeout=None)
241
242 .. _windows:
243
244 Pexpect on Windows
245 ------------------
246
247 .. versionadded:: 4.0
248 Windows support
249
250 Pexpect can be used on Windows to wait for a pattern to be produced by a child
251 process, using :class:`pexpect.popen_spawn.PopenSpawn`, or a file descriptor,
252 using :class:`pexpect.fdpexpect.fdspawn`. This should be considered experimental
253 for now.
254
255 :class:`pexpect.spawn` and :func:`pexpect.run` are *not* available on Windows,
256 as they rely on Unix pseudoterminals (ptys). Cross platform code must not use
257 these.
OLDNEW
« no previous file with comments | « third_party/pexpect/doc/make.bat ('k') | third_party/pexpect/doc/requirements.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698