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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/pexpect/doc/overview.rst
diff --git a/third_party/pexpect/doc/overview.rst b/third_party/pexpect/doc/overview.rst
new file mode 100644
index 0000000000000000000000000000000000000000..d394ef16f8179872f2cfa996e4dd0a18e4fc48d7
--- /dev/null
+++ b/third_party/pexpect/doc/overview.rst
@@ -0,0 +1,257 @@
+API Overview
+============
+
+Pexpect can be used for automating interactive applications such as ssh, ftp,
+mencoder, passwd, etc. The Pexpect interface was designed to be easy to use.
+
+Here is an example of Pexpect in action::
+
+ # This connects to the openbsd ftp site and
+ # downloads the recursive directory listing.
+ import pexpect
+ child = pexpect.spawn('ftp ftp.openbsd.org')
+ child.expect('Name .*: ')
+ child.sendline('anonymous')
+ child.expect('Password:')
+ child.sendline('noah@example.com')
+ child.expect('ftp> ')
+ child.sendline('lcd /tmp')
+ child.expect('ftp> ')
+ child.sendline('cd pub/OpenBSD')
+ child.expect('ftp> ')
+ child.sendline('get README')
+ child.expect('ftp> ')
+ child.sendline('bye')
+
+Obviously you could write an ftp client using Python's own :mod:`ftplib` module,
+but this is just a demonstration. You can use this technique with any application.
+This is especially handy if you are writing automated test tools.
+
+There are two important methods in Pexpect -- :meth:`~pexpect.spawn.expect` and
+:meth:`~pexpect.spawn.send` (or :meth:`~pexpect.spawn.sendline` which is
+like :meth:`~pexpect.spawn.send` with a linefeed). The :meth:`~pexpect.spawn.expect`
+method waits for the child application to return a given string. The string you
+specify is a regular expression, so you can match complicated patterns. The
+:meth:`~pexpect.spawn.send` method writes a string to the child application.
+From the child's point of view it looks just like someone typed the text from a
+terminal. After each call to :meth:`~pexpect.spawn.expect` the ``before`` and ``after``
+properties will be set to the text printed by child application. The ``before``
+property will contain all text up to the expected string pattern. The ``after``
+string will contain the text that was matched by the expected pattern.
+The match property is set to the `re match object <http://docs.python.org/3/library/re#match-objects>`_.
+
+An example of Pexpect in action may make things more clear. This example uses
+ftp to login to the OpenBSD site; list files in a directory; and then pass
+interactive control of the ftp session to the human user::
+
+ import pexpect
+ child = pexpect.spawn ('ftp ftp.openbsd.org')
+ child.expect ('Name .*: ')
+ child.sendline ('anonymous')
+ child.expect ('Password:')
+ child.sendline ('noah@example.com')
+ child.expect ('ftp> ')
+ child.sendline ('ls /pub/OpenBSD/')
+ child.expect ('ftp> ')
+ print child.before # Print the result of the ls command.
+ child.interact() # Give control of the child to the user.
+
+Special EOF and TIMEOUT patterns
+--------------------------------
+
+There are two special patterns to match the End Of File (:class:`~pexpect.EOF`)
+or a Timeout condition (:class:`~pexpect.TIMEOUT`). You can pass these
+patterns to :meth:`~pexpect.spawn.expect`. These patterns are not regular
+expressions. Use them like predefined constants.
+
+If the child has died and you have read all the child's output then ordinarily
+:meth:`~pexpect.spawn.expect` will raise an :class:`~pexpect.EOF` exception.
+You can read everything up to the EOF without generating an exception by using
+the EOF pattern expect. In this case everything the child has output will be
+available in the ``before`` property.
+
+The pattern given to :meth:`~pexpect.spawn.expect` may be a regular expression
+or it may also be a list of regular expressions. This allows you to match
+multiple optional responses. The :meth:`~pexpect.spawn.expect` method returns
+the index of the pattern that was matched. For example, say you wanted to login
+to a server. After entering a password you could get various responses from the
+server -- your password could be rejected; or you could be allowed in and asked
+for your terminal type; or you could be let right in and given a command prompt.
+The following code fragment gives an example of this::
+
+ child.expect('password:')
+ child.sendline(my_secret_password)
+ # We expect any of these three patterns...
+ i = child.expect (['Permission denied', 'Terminal type', '[#\$] '])
+ if i==0:
+ print('Permission denied on host. Can\'t login')
+ child.kill(0)
+ elif i==1:
+ print('Login OK... need to send terminal type.')
+ child.sendline('vt100')
+ child.expect('[#\$] ')
+ elif i==2:
+ print('Login OK.')
+ print('Shell command prompt', child.after)
+
+If nothing matches an expected pattern then :meth:`~pexpect.spawn.expect` will
+eventually raise a :class:`~pexpect.TIMEOUT` exception. The default time is 30
+seconds, but you can change this by passing a timeout argument to
+:meth:`~pexpect.spawn.expect`::
+
+ # Wait no more than 2 minutes (120 seconds) for password prompt.
+ child.expect('password:', timeout=120)
+
+Find the end of line -- CR/LF conventions
+-----------------------------------------
+
+Pexpect matches regular expressions a little differently than what you might be
+used to.
+
+The :regexp:`$` pattern for end of line match is useless. The :regexp:`$`
+matches the end of string, but Pexpect reads from the child one character at a
+time, so each character looks like the end of a line. Pexpect can't do a
+look-ahead into the child's output stream. In general you would have this
+situation when using regular expressions with any stream.
+
+.. note::
+
+ Pexpect does have an internal buffer, so reads are faster than one character
+ at a time, but from the user's perspective the regex patterns test happens
+ one character at a time.
+
+The best way to match the end of a line is to look for the newline: ``"\r\n"``
+(CR/LF). Yes, that does appear to be DOS-style. It may surprise some UNIX people
+to learn that terminal TTY device drivers (dumb, vt100, ANSI, xterm, etc.) all
+use the CR/LF combination to signify the end of line. Pexpect uses a Pseudo-TTY
+device to talk to the child application, so when the child app prints ``"\n"``
+you actually see ``"\r\n"``.
+
+UNIX uses just linefeeds to end lines of text, but not when it comes to TTY
+devices! TTY devices are more like the Windows world. Each line of text ends
+with a CR/LF combination. When you intercept data from a UNIX command from a
+TTY device you will find that the TTY device outputs a CR/LF combination. A
+UNIX command may only write a linefeed (``\n``), but the TTY device driver
+converts it to CR/LF. This means that your terminal will see lines end with
+CR/LF (hex ``0D 0A``). Since Pexpect emulates a terminal, to match ends of
+lines you have to expect the CR/LF combination::
+
+ child.expect('\r\n')
+
+If you just need to skip past a new line then ``expect('\n')`` by itself will
+work, but if you are expecting a specific pattern before the end of line then
+you need to explicitly look for the ``\r``. For example the following expects a
+word at the end of a line::
+
+ child.expect('\w+\r\n')
+
+But the following would both fail::
+
+ child.expect('\w+\n')
+
+And as explained before, trying to use :regexp:`$` to match the end of line
+would not work either::
+
+ child.expect ('\w+$')
+
+So if you need to explicitly look for the END OF LINE, you want to look for the
+CR/LF combination -- not just the LF and not the $ pattern.
+
+This problem is not limited to Pexpect. This problem happens any time you try
+to perform a regular expression match on a stream. Regular expressions need to
+look ahead. With a stream it is hard to look ahead because the process
+generating the stream may not be finished. There is no way to know if the
+process has paused momentarily or is finished and waiting for you. Pexpect must
+implicitly always do a NON greedy match (minimal) at the end of a input.
+
+Pexpect compiles all regular expressions with the :data:`re.DOTALL` flag.
+With the :data:`~re.DOTALL` flag, a ``"."`` will match a newline.
+
+Beware of + and * at the end of patterns
+----------------------------------------
+
+Remember that any time you try to match a pattern that needs look-ahead that
+you will always get a minimal match (non greedy). For example, the following
+will always return just one character::
+
+ child.expect ('.+')
+
+This example will match successfully, but will always return no characters::
+
+ child.expect ('.*')
+
+Generally any star * expression will match as little as possible.
+
+One thing you can do is to try to force a non-ambiguous character at the end of
+your :regexp:`\\d+` pattern. Expect that character to delimit the string. For
+example, you might try making the end of your pattern be :regexp:`\\D+` instead
+of :regexp:`\\D*`. Number digits alone would not satisfy the :regexp:`(\\d+)\\D+`
+pattern. You would need some numbers and at least one non-number at the end.
+
+
+Debugging
+---------
+
+If you get the string value of a :class:`pexpect.spawn` object you will get lots
+of useful debugging information. For debugging it's very useful to use the
+following pattern::
+
+ try:
+ i = child.expect ([pattern1, pattern2, pattern3, etc])
+ except:
+ print("Exception was thrown")
+ print("debug information:")
+ print(str(child))
+
+It is also useful to log the child's input and out to a file or the screen. The
+following will turn on logging and send output to stdout (the screen)::
+
+ child = pexpect.spawn(foo)
+ child.logfile = sys.stdout
+
+Exceptions
+----------
+
+:class:`~pexpect.EOF`
+
+Note that two flavors of EOF Exception may be thrown. They are virtually
+identical except for the message string. For practical purposes you should have
+no need to distinguish between them, but they do give a little extra information
+about what type of platform you are running. The two messages are:
+
+- "End Of File (EOF) in read(). Exception style platform."
+- "End Of File (EOF) in read(). Empty string style platform."
+
+Some UNIX platforms will throw an exception when you try to read from a file
+descriptor in the EOF state. Other UNIX platforms instead quietly return an
+empty string to indicate that the EOF state has been reached.
+
+If you wish to read up to the end of the child's output without generating an
+:class:`~pexpect.EOF` exception then use the ``expect(pexpect.EOF)`` method.
+
+:class:`~pexpect.TIMEOUT`
+
+The :meth:`~pexpect.spawn.expect` and :meth:`~pexpect.spawn.read` methods will
+also timeout if the child does not generate any output for a given amount of
+time. If this happens they will raise a :class:`~pexpect.TIMEOUT` exception.
+You can have these methods ignore timeout and block indefinitely by passing
+``None`` for the timeout parameter::
+
+ child.expect(pexpect.EOF, timeout=None)
+
+.. _windows:
+
+Pexpect on Windows
+------------------
+
+.. versionadded:: 4.0
+ Windows support
+
+Pexpect can be used on Windows to wait for a pattern to be produced by a child
+process, using :class:`pexpect.popen_spawn.PopenSpawn`, or a file descriptor,
+using :class:`pexpect.fdpexpect.fdspawn`. This should be considered experimental
+for now.
+
+:class:`pexpect.spawn` and :func:`pexpect.run` are *not* available on Windows,
+as they rely on Unix pseudoterminals (ptys). Cross platform code must not use
+these.
« 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