diff options
author | Davide Italiano <davide@freebsd.org> | 2019-03-12 20:41:24 +0000 |
---|---|---|
committer | Davide Italiano <davide@freebsd.org> | 2019-03-12 20:41:24 +0000 |
commit | 205fd03a27dcf1649f4facaf8d80d219e2937d9d (patch) | |
tree | 59e5ddf3f860f20b05a9b4b043b26c0eabb5840b /lldb/third_party/Python/module/pexpect-4.6 | |
parent | e2b8c40a7726806557fb17666478e60ada1c7439 (diff) | |
download | bcm5719-llvm-205fd03a27dcf1649f4facaf8d80d219e2937d9d.tar.gz bcm5719-llvm-205fd03a27dcf1649f4facaf8d80d219e2937d9d.zip |
[third-party] Update pexpect to 4.6.
Reviewers: labath, jdevlieghere
Subscribers: lldb-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59159
llvm-svn: 355967
Diffstat (limited to 'lldb/third_party/Python/module/pexpect-4.6')
136 files changed, 17049 insertions, 0 deletions
diff --git a/lldb/third_party/Python/module/pexpect-4.6/.gitignore b/lldb/third_party/Python/module/pexpect-4.6/.gitignore new file mode 100644 index 00000000000..22cd4785f71 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/.gitignore @@ -0,0 +1,11 @@ +*.pyc +doc/_build +tests/log +build/ +dist/ +MANIFEST +*~ +.coverage* +htmlcov +*.egg-info/ +.cache/ diff --git a/lldb/third_party/Python/module/pexpect-4.6/.travis.yml b/lldb/third_party/Python/module/pexpect-4.6/.travis.yml new file mode 100644 index 00000000000..40d96229501 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/.travis.yml @@ -0,0 +1,31 @@ +language: python + +python: + - 2.7 + - 3.3 + - 3.4 + - 3.5 + - 3.6 + - pypy + - nightly + +matrix: + allow_failures: + # PyPy on Travis is currently incompatible with Cryptography. + - python: pypy + +install: + - export PYTHONIOENCODING=UTF8 + - pip install coveralls pytest-cov ptyprocess + +script: + - ./tools/display-sighandlers.py + - ./tools/display-terminalinfo.py + - py.test --cov pexpect --cov-config .coveragerc + +after_success: + - coverage combine + - coveralls + +# Use new Travis stack, should be faster +sudo: false diff --git a/lldb/third_party/Python/module/pexpect-4.6/DEVELOPERS.rst b/lldb/third_party/Python/module/pexpect-4.6/DEVELOPERS.rst new file mode 100644 index 00000000000..bf2bb9f30f8 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/DEVELOPERS.rst @@ -0,0 +1,12 @@ +To run the tests, use `py.test <http://pytest.org/latest/>`_:: + + py.test tests + +The tests are all located in the tests/ directory. To add a new unit +test all you have to do is create the file in the tests/ directory with a +filename in this format:: + + test_*.py + +New test case classes may wish to inherit from ``PexpectTestCase.PexpectTestCase`` +in the tests directory, which sets up some convenient functionality. diff --git a/lldb/third_party/Python/module/pexpect-4.6/LICENSE b/lldb/third_party/Python/module/pexpect-4.6/LICENSE new file mode 100644 index 00000000000..754db5afcb8 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/LICENSE @@ -0,0 +1,20 @@ +ISC LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2013-2014, Pexpect development team + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/lldb/third_party/Python/module/pexpect-4.6/MANIFEST.in b/lldb/third_party/Python/module/pexpect-4.6/MANIFEST.in new file mode 100644 index 00000000000..32c72ba1712 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/MANIFEST.in @@ -0,0 +1,6 @@ +recursive-include doc * +prune doc/_build +recursive-include examples * +include .coveragerc README.rst LICENSE pexpect/bashrc.sh +recursive-include tests * +global-exclude __pycache__ *.pyc *~ diff --git a/lldb/third_party/Python/module/pexpect-4.6/README.rst b/lldb/third_party/Python/module/pexpect-4.6/README.rst new file mode 100644 index 00000000000..0f5cb98ceb9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/README.rst @@ -0,0 +1,55 @@ +.. image:: https://travis-ci.org/pexpect/pexpect.svg?branch=master + :target: https://travis-ci.org/pexpect/pexpect + :align: right + :alt: Build status + +Pexpect is a Pure Python Expect-like module + +Pexpect makes Python a better tool for controlling other applications. + +Pexpect is a pure Python module for spawning child applications; controlling +them; and responding to expected patterns in their output. Pexpect works like +Don Libes' Expect. Pexpect allows your script to spawn a child application and +control it as if a human were typing commands. + +Pexpect can be used for automating interactive applications such as ssh, ftp, +passwd, telnet, etc. It can be used to a automate setup scripts for duplicating +software package installations on different servers. It can be used for +automated software testing. Pexpect is in the spirit of Don Libes' Expect, but +Pexpect is pure Python. + +The main features of Pexpect require the pty module in the Python standard +library, which is only available on Unix-like systems. Some features—waiting +for patterns from file descriptors or subprocesses—are also available on +Windows. + +If you want to work with the development version of the source code then please +read the DEVELOPERS.rst document in the root of the source code tree. + +Free, open source, and all that good stuff. + +You can install Pexpect using pip:: + + pip install pexpect + +`Docs on ReadTheDocs <https://pexpect.readthedocs.io/>`_ + +PEXPECT LICENSE:: + + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2013-2016, Pexpect development team + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +This license is approved by the OSI and FSF as GPL-compatible. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/FAQ.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/FAQ.rst new file mode 100644 index 00000000000..1964b12002a --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/FAQ.rst @@ -0,0 +1,145 @@ +FAQ +=== + +**Q: Where can I get help with pexpect? Is there a mailing list?** + +A: You can use the `pexpect tag on Stackoverflow <http://stackoverflow.com/questions/tagged/pexpect>`__ +to ask questions specifically related to Pexpect. For more general Python +support, there's the python-list_ mailing list, and the `#python`_ +IRC channel. Please refrain from using github for general +python or systems scripting support. + +.. _python-list: https://mail.python.org/mailman/listinfo/python-list +.. _#python: https://www.python.org/community/irc/ + +**Q: Why don't shell pipe and redirect (| and >) work when I spawn a command?** + +A: Remember that Pexpect does NOT interpret shell meta characters such as +redirect, pipe, or wild cards (``>``, ``|``, or ``*``). That's done by a shell not +the command you are spawning. This is a common mistake. If you want to run a +command and pipe it through another command then you must also start a shell. +For example:: + + child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"') + child.expect(pexpect.EOF) + +The second form of spawn (where you pass a list of arguments) is useful in +situations where you wish to spawn a command and pass it its own argument list. +This can make syntax more clear. For example, the following is equivalent to the +previous example:: + + shell_cmd = 'ls -l | grep LOG > log_list.txt' + child = pexpect.spawn('/bin/bash', ['-c', shell_cmd]) + child.expect(pexpect.EOF) + +**Q: The `before` and `after` properties sound weird.** + +A: This is how the -B and -A options in grep works, so that made it +easier for me to remember. Whatever makes my life easier is what's best. +Originally I was going to model Pexpect after Expect, but then I found +that I didn't actually like the way Expect did some things. It was more +confusing. The `after` property can be a little confusing at first, +because it will actually include the matched string. The `after` means +after the point of match, not after the matched string. + +**Q: Why not just use Expect?** + +A: I love it. It's great. I has bailed me out of some real jams, but I +wanted something that would do 90% of what I need from Expect; be 10% of +the size; and allow me to write my code in Python instead of TCL. +Pexpect is not nearly as big as Expect, but Pexpect does everything I +have ever used Expect for. + +.. _whynotpipe: + +**Q: Why not just use a pipe (popen())?** + +A: A pipe works fine for getting the output to non-interactive programs. +If you just want to get the output from ls, uname, or ping then this +works. Pipes do not work very well for interactive programs and pipes +will almost certainly fail for most applications that ask for passwords +such as telnet, ftp, or ssh. + +There are two reasons for this. + +* First an application may bypass stdout and print directly to its + controlling TTY. Something like SSH will do this when it asks you for + a password. This is why you cannot redirect the password prompt because + it does not go through stdout or stderr. + +* The second reason is because most applications are built using the C + Standard IO Library (anything that uses ``#include <stdio.h>``). One + of the features of the stdio library is that it buffers all input and + output. Normally output is line buffered when a program is printing to + a TTY (your terminal screen). Everytime the program prints a line-feed + the currently buffered data will get printed to your screen. The + problem comes when you connect a pipe. The stdio library is smart and + can tell that it is printing to a pipe instead of a TTY. In that case + it switches from line buffer mode to block buffered. In this mode the + currently buffered data is flushed when the buffer is full. This + causes most interactive programs to deadlock. Block buffering is more + efficient when writing to disks and pipes. Take the situation where a + program prints a message ``"Enter your user name:\n"`` and then waits + for you type type something. In block buffered mode, the stdio library + will not put the message into the pipe even though a linefeed is + printed. The result is that you never receive the message, yet the + child application will sit and wait for you to type a response. Don't + confuse the stdio lib's buffer with the pipe's buffer. The pipe buffer + is another area that can cause problems. You could flush the input + side of a pipe, whereas you have no control over the stdio library buffer. + +More information: the Standard IO library has three states for a +``FILE *``. These are: _IOFBF for block buffered; _IOLBF for line buffered; +and _IONBF for unbuffered. The STDIO lib will use block buffering when +talking to a block file descriptor such as a pipe. This is usually not +helpful for interactive programs. Short of recompiling your program to +include fflush() everywhere or recompiling a custom stdio library there +is not much a controlling application can do about this if talking over +a pipe. + +The program may have put data in its output that remains unflushed +because the output buffer is not full; then the program will go and +deadlock while waiting for input -- because you never send it any +because you are still waiting for its output (still stuck in the STDIO's +output buffer). + +The answer is to use a pseudo-tty. A TTY device will force line +buffering (as opposed to block buffering). Line buffering means that you +will get each line when the child program sends a line feed. This +corresponds to the way most interactive programs operate -- send a line +of output then wait for a line of input. + +I put "answer" in quotes because it's ugly solution and because there is +no POSIX standard for pseudo-TTY devices (even though they have a TTY +standard...). What would make more sense to me would be to have some way +to set a mode on a file descriptor so that it will tell the STDIO to be +line-buffered. I have investigated, and I don't think there is a way to +set the buffered state of a child process. The STDIO Library does not +maintain any external state in the kernel or whatnot, so I don't think +there is any way for you to alter it. I'm not quite sure how this +line-buffered/block-buffered state change happens internally in the +STDIO library. I think the STDIO lib looks at the file descriptor and +decides to change behavior based on whether it's a TTY or a block file +(see isatty()). + +I hope that this qualifies as helpful. Don't use a pipe to control +another application. + +**Q: Can I do screen scraping with this thing?** + +A: That depends. If your application just does line-oriented output then +this is easy. If a program emits many terminal sequences, from video +attributes to screen addressing, such as programs using curses, then +it may become very difficult to ascertain what text is displayed on a screen. + +We suggest using the `pyte <https://github.com/selectel/pyte>`_ library to +screen-scrape. The module :mod:`pexpect.ANSI` released with previous versions +of pexpect is now marked deprecated and may be removed in the future. + +**Q: I get strange behavior with pexect and gevent** + +A: Pexpect uses fork(2), exec(2), select(2), waitpid(2), and implements its +own selector in expect family of calls. pexpect has been known to misbehave +when paired with gevent. A solution might be to isolate your pexpect +dependent code from any frameworks that manipulate event selection behavior +by running it in an another process entirely. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/Makefile b/lldb/third_party/Python/module/pexpect-4.6/doc/Makefile new file mode 100644 index 00000000000..ced8a685263 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/Makefile @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pexpect.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pexpect.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Pexpect" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Pexpect" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/api/fdpexpect.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/api/fdpexpect.rst new file mode 100644 index 00000000000..3ddf2cdb228 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/api/fdpexpect.rst @@ -0,0 +1,20 @@ +fdpexpect - use pexpect with a file descriptor +============================================== + +.. automodule:: pexpect.fdpexpect + +fdspawn class +------------- + +.. autoclass:: fdspawn + :show-inheritance: + + .. automethod:: __init__ + .. automethod:: isalive + .. automethod:: close + + .. method:: expect + expect_exact + expect_list + + As :class:`pexpect.spawn`. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/api/index.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/api/index.rst new file mode 100644 index 00000000000..5277d1cd00a --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/api/index.rst @@ -0,0 +1,18 @@ +API documentation +================= + +.. toctree:: + :maxdepth: 2 + + pexpect + fdpexpect + popen_spawn + replwrap + pxssh + +The modules ``pexpect.screen`` and ``pexpect.ANSI`` have been deprecated in +Pexpect version 4. They were separate from the main use cases for Pexpect, and +there are better maintained Python terminal emulator packages, such as +`pyte <https://pypi.python.org/pypi/pyte>`__. +These modules are still present for now, but we don't advise using them in new +code. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/api/pexpect.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/api/pexpect.rst new file mode 100644 index 00000000000..79bbcefffc5 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/api/pexpect.rst @@ -0,0 +1,115 @@ +Core pexpect components +======================= + +.. automodule:: pexpect + +spawn class +----------- + +.. autoclass:: spawn + + .. automethod:: __init__ + .. automethod:: expect + .. automethod:: expect_exact + .. automethod:: expect_list + .. automethod:: compile_pattern_list + .. automethod:: send + .. automethod:: sendline + .. automethod:: write + .. automethod:: writelines + .. automethod:: sendcontrol + .. automethod:: sendeof + .. automethod:: sendintr + .. automethod:: read + .. automethod:: readline + .. automethod:: read_nonblocking + .. automethod:: eof + .. automethod:: interact + + .. attribute:: logfile + logfile_read + logfile_send + + Set these to a Python file object (or :data:`sys.stdout`) to log all + communication, data read from the child process, or data sent to the child + process. + + .. note:: + + With :class:`spawn` in bytes mode, the log files should be open for + writing binary data. In unicode mode, they should + be open for writing unicode text. See :ref:`unicode`. + +Controlling the child process +````````````````````````````` + +.. class:: spawn + + .. automethod:: kill + .. automethod:: terminate + .. automethod:: isalive + .. automethod:: wait + .. automethod:: close + .. automethod:: getwinsize + .. automethod:: setwinsize + .. automethod:: getecho + .. automethod:: setecho + .. automethod:: waitnoecho + + .. attribute:: pid + + The process ID of the child process. + + .. attribute:: child_fd + + The file descriptor used to communicate with the child process. + +.. _unicode: + +Handling unicode +```````````````` + +By default, :class:`spawn` is a bytes interface: its read methods return bytes, +and its write/send and expect methods expect bytes. If you pass the *encoding* +parameter to the constructor, it will instead act as a unicode interface: +strings you send will be encoded using that encoding, and bytes received will +be decoded before returning them to you. In this mode, patterns for +:meth:`~spawn.expect` and :meth:`~spawn.expect_exact` should also be unicode. + +.. versionchanged:: 4.0 + + :class:`spawn` provides both the bytes and unicode interfaces. In Pexpect + 3.x, the unicode interface was provided by a separate ``spawnu`` class. + +For backwards compatibility, some Unicode is allowed in bytes mode: the +send methods will encode arbitrary unicode as UTF-8 before sending it to the +child process, and its expect methods can accept ascii-only unicode strings. + +.. note:: + + Unicode handling with pexpect works the same way on Python 2 and 3, despite + the difference in names. I.e.: + + - Bytes mode works with ``str`` on Python 2, and :class:`bytes` on Python 3, + - Unicode mode works with ``unicode`` on Python 2, and :class:`str` on Python 3. + +run function +------------ + +.. autofunction:: run + +Exceptions +---------- + +.. autoclass:: EOF + +.. autoclass:: TIMEOUT + +.. autoclass:: ExceptionPexpect + +Utility functions +----------------- + +.. autofunction:: which + +.. autofunction:: split_command_line diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/api/popen_spawn.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/api/popen_spawn.rst new file mode 100644 index 00000000000..64cae1561ea --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/api/popen_spawn.rst @@ -0,0 +1,24 @@ +popen_spawn - use pexpect with a piped subprocess +================================================= + +.. automodule:: pexpect.popen_spawn + +PopenSpawn class +---------------- + +.. autoclass:: PopenSpawn + + .. automethod:: __init__ + .. automethod:: send + .. automethod:: sendline + .. automethod:: write + .. automethod:: writelines + .. automethod:: kill + .. automethod:: sendeof + .. automethod:: wait + + .. method:: expect + expect_exact + expect_list + + As :class:`pexpect.spawn`. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/api/pxssh.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/api/pxssh.rst new file mode 100644 index 00000000000..b947f4b5ace --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/api/pxssh.rst @@ -0,0 +1,34 @@ +pxssh - control an SSH session +============================== + +.. automodule:: pexpect.pxssh + +.. autoclass:: ExceptionPxssh + +pxssh class +----------- + +.. autoclass:: pxssh + + .. automethod:: __init__ + + .. attribute:: PROMPT + + The regex pattern to search for to find the prompt. If you call :meth:`login` + with ``auto_prompt_reset=False``, you must set this attribute manually. + + .. attribute:: force_password + + If this is set to True, public key authentication is disabled, forcing the + server to ask for a password. Note that the sysadmin can disable password + logins, in which case this won't work. + + .. attribute:: options + + The dictionary of user specified SSH options, eg, ``options = dict(StrictHostKeyChecking="no", UserKnownHostsFile="/dev/null")`` + + .. automethod:: login + .. automethod:: logout + .. automethod:: prompt + .. automethod:: sync_original_prompt + .. automethod:: set_unique_prompt diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/api/replwrap.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/api/replwrap.rst new file mode 100644 index 00000000000..bf44a948db8 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/api/replwrap.rst @@ -0,0 +1,26 @@ +replwrap - Control read-eval-print-loops +======================================== + +.. automodule:: pexpect.replwrap + +.. versionadded:: 3.3 + +.. autoclass:: REPLWrapper + + .. automethod:: run_command + +.. data:: PEXPECT_PROMPT + + A string that can be used as a prompt, and is unlikely to be found in output. + +Using the objects above, it is easy to wrap a REPL. For instance, to use a +Python shell:: + + py = REPLWrapper("python", ">>> ", "import sys; sys.ps1={!r}; sys.ps2={!r}") + py.run_command("4+7") + +Convenience functions are provided for Python and bash shells: + +.. autofunction:: python + +.. autofunction:: bash diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/clean.css b/lldb/third_party/Python/module/pexpect-4.6/doc/clean.css new file mode 100644 index 00000000000..e8d98ddb2e5 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/clean.css @@ -0,0 +1,103 @@ + +body { + margin:0px; + padding:0px; + font-family:verdana, arial, helvetica, sans-serif; + color:#333; + background-color:white; + } +pre { + background: #eeeeee; + border: 1px solid #888888; + color: black; + padding: 1em; + white-space: pre; +} +h1 { + margin:5px 0px 5px 0px; + padding:0px; + font-size:20px; + line-height:28px; + font-weight:900; + color:#44f; + } +h2 { + margin:5px 0px 5px 0px; + padding:0px; + font-size:17px; + line-height:28px; + font-weight:900; + color:#226; + } +h3 { + margin:5px 0px 5px 0px; + padding:0px; + font-size:15px; + line-height:28px; + font-weight:900; + } +p +{ + margin:0px 0px 16px 0px; + font:11px/20px verdana, arial, helvetica, sans-serif; + padding:0px; +} +table +{ + font-size: 10pt; + color: #000000; +} +td{border:1px solid #999;} + +table.pymenu {color: #000000; background-color: #99ccff} +th.pymenu {color: #ffffff; background-color: #003366} + +.code +{ + font-family: "Lucida Console", monospace; font-weight: bold; + color: #007700; background-color: #eeeeee +} + +#Content>p {margin:0px;} +#Content>p+p {text-indent:30px;} + +a { + text-decoration:none; + font-weight:600; + font-family:verdana, arial, helvetica, sans-serif; + color: #900; +} +//a:link {color:#09c;} +//a x:visited {color:#07a;} +a:hover {background-color:#ee0;} + +#Header { + margin:10px 0px 10px 0px; + padding:10px 0px 10px 20px; + /* For IE5/Win's benefit height = [correct height] + [top padding] + [top and bottom border widths] */ + height:33px; /* 14px + 17px + 2px = 33px */ + border-style:solid; + border-color:black; + border-width:1px 0px; /* top and bottom borders: 1px; left and right borders: 0px */ + line-height:33px; + background-color:#eee; + height:66px; /* the correct height */ + } + +#Content { + margin:0px 210px 50px 10px; + padding:10px; + } + +#Menu { + position:absolute; + top:100px; + right:20px; + width:172px; + padding:10px; + background-color:#eee; + border:1px solid #999; // dashed #999; + line-height:17px; + width:150px; + font-size:11px; + } diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/commonissues.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/commonissues.rst new file mode 100644 index 00000000000..f60085e2aaa --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/commonissues.rst @@ -0,0 +1,101 @@ +Common problems +=============== + +Threads +------- + +On Linux (RH 8) you cannot spawn a child from a different thread and pass the +handle back to a worker thread. The child is successfully spawned but you can't +interact with it. The only way to make it work is to spawn and interact with the +child all in the same thread. [Adam Kerrison] + +Timing issue with send() and sendline() +--------------------------------------- + +This problem has been addressed and should not affect most users. + +It is sometimes possible to read an echo of the string sent with +:meth:`~pexpect.spawn.send` and :meth:`~pexpect.spawn.sendline`. If you call +:meth:`~pexpect.spawn.send` and then immediately call :meth:`~pexpect.spawn.readline`, +you may get part of your output echoed back. You may read back what you just +wrote even if the child application does not explicitly echo it. Timing is +critical. This could be a security issue when talking to an application that +asks for a password; otherwise, this does not seem like a big deal. But why do +TTYs do this? + +People usually report this when they are trying to control SSH or some other +login. For example, if your code looks something like this:: + + child.expect ('[pP]assword:') + child.sendline (my_password) + + +1. SSH prints "password:" prompt to the user. +2. SSH turns off echo on the TTY device. +3. SSH waits for user to enter a password. + +When scripting with Pexpect what can happen is that Pexpect will respond to the +"password:" prompt before SSH has had time to turn off TTY echo. In other words, +Pexpect sends the password between steps 1. and 2., so the password gets echoed +back to the TTY. I would call this an SSH bug. + +Pexpect now automatically adds a short delay before sending data to a child +process. This more closely mimics what happens in the usual human-to-app +interaction. The delay can be tuned with the ``delaybeforesend`` attribute of the +spawn class. In general, this fixes the problem for everyone and so this should +not be an issue for most users. For some applications you might with to turn it +off:: + + child = pexpect.spawn ("ssh user@example.com") + child.delaybeforesend = None + +Truncated output just before child exits +---------------------------------------- + +So far I have seen this only on older versions of Apple's MacOS X. If the child +application quits it may not flush its output buffer. This means that your +Pexpect application will receive an EOF even though it should have received a +little more data before the child died. This is not generally a problem when +talking to interactive child applications. One example where it is a problem is +when trying to read output from a program like *ls*. You may receive most of the +directory listing, but the last few lines will get lost before you receive an EOF. +The reason for this is that *ls* runs; completes its task; and then exits. The +buffer is not flushed before exit so the last few lines are lost. The following +example demonstrates the problem:: + + child = pexpect.spawn('ls -l') + child.expect(pexpect.EOF) + print child.before + +Controlling SSH on Solaris +-------------------------- + +Pexpect does not yet work perfectly on Solaris. One common problem is that SSH +sometimes will not allow TTY password authentication. For example, you may +expect SSH to ask you for a password using code like this:: + + child = pexpect.spawn('ssh user@example.com') + child.expect('password') + child.sendline('mypassword') + +You may see the following error come back from a spawned child SSH:: + + Permission denied (publickey,keyboard-interactive). + +This means that SSH thinks it can't access the TTY to ask you for your password. +The only solution I have found is to use public key authentication with SSH. +This bypasses the need for a password. I'm not happy with this solution. The +problem is due to poor support for Solaris Pseudo TTYs in the Python Standard +Library. + +child does not receive full input, emits BEL +-------------------------------------------- + +You may notice when running for example cat(1) or base64(1), when sending a +very long input line, that it is not fully received, and the BEL ('\a') may +be found in output. + +By default the child terminal matches the parent, which is often in "canonical +mode processing". You may wish to disable this mode. The exact limit of a line +varies by operating system, and details of disabling canonical mode may be +found in the docstring of :meth:`~pexpect.spawn.send`. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/conf.py b/lldb/third_party/Python/module/pexpect-4.6/doc/conf.py new file mode 100644 index 00000000000..a7341473b69 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/conf.py @@ -0,0 +1,250 @@ +# -*- coding: utf-8 -*- +# +# Pexpect documentation build configuration file, created by +# sphinx-quickstart on Tue Sep 17 11:05:11 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('sphinxext')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', + 'sphinx.ext.viewcode', 'github', # for easy GitHub links + ] + +github_project_url = "https://github.com/pexpect/pexpect" + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Pexpect' +copyright = u'2013, Noah Spurrier and contributors' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '4.6' +# The full version, including alpha/beta/rc tags. +release = version + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Pexpectdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'Pexpect.tex', u'Pexpect Documentation', + u'Noah Spurrier and contributors', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'pexpect', u'Pexpect Documentation', + [u'Noah Spurrier and contributors'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Pexpect', u'Pexpect Documentation', + u'Noah Spurrier and contributors', 'Pexpect', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/3/': None} diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/examples.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/examples.rst new file mode 100644 index 00000000000..6338b5c01cd --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/examples.rst @@ -0,0 +1,63 @@ +Examples +======== + +Under the distribution tarball directory you should find an "examples" directory. +This is the best way to learn to use Pexpect. See the descriptions of Pexpect +Examples. + +`topip.py <https://github.com/pexpect/pexpect/blob/master/examples/topip.py>`_ + This runs `netstat` on a local or remote server. It calculates some simple + statistical information on the number of external inet connections. This can + be used to detect if one IP address is taking up an excessive number of + connections. It can also send an email alert if a given IP address exceeds a + threshold between runs of the script. This script can be used as a drop-in + Munin plugin or it can be used stand-alone from cron. I used this on a busy + web server that would sometimes get hit with denial of service attacks. This + made it easy to see if a script was opening many multiple connections. A + typical browser would open fewer than 10 connections at once. A script might + open over 100 simultaneous connections. + +`hive.py <https://github.com/pexpect/pexpect/blob/master/examples/hive.py>`_ + This script creates SSH connections to a list of hosts that you provide. + Then you are given a command line prompt. Each shell command that you + enter is sent to all the hosts. The response from each host is collected + and printed. For example, you could connect to a dozen different + machines and reboot them all at once. + +`script.py <https://github.com/pexpect/pexpect/blob/master/examples/script.py>`_ + This implements a command similar to the classic BSD "script" command. + This will start a subshell and log all input and output to a file. + This demonstrates the :meth:`~pexpect.spawn.interact` method of Pexpect. + +`ftp.py <https://github.com/pexpect/pexpect/blob/master/examples/ftp.py>`_ + This demonstrates an FTP "bookmark". This connects to an ftp site; + does a few ftp tasks; and then gives the user interactive control over + the session. In this case the "bookmark" is to a directory on the + OpenBSD ftp server. It puts you in the i386 packages directory. You + can easily modify this for other sites. This demonstrates the + :meth:`~pexpect.spawn.interact` method of Pexpect. + +`monitor.py <https://github.com/pexpect/pexpect/blob/master/examples/monitor.py>`_ + This runs a sequence of commands on a remote host using SSH. It runs a + simple system checks such as uptime and free to monitor the state of + the remote host. + +`passmass.py <https://github.com/pexpect/pexpect/blob/master/examples/passmass.py>`_ + This will login to each given server and change the password of the + given user. This demonstrates scripting logins and passwords. + +`python.py <https://github.com/pexpect/pexpect/blob/master/examples/python.py>`_ + This starts the python interpreter and prints the greeting message + backwards. It then gives the user iteractive control of Python. It's + pretty useless! + +`ssh_tunnel.py <https://github.com/pexpect/pexpect/blob/master/examples/ssh_tunnel.py>`_ + This starts an SSH tunnel to a remote machine. It monitors the + connection and restarts the tunnel if it goes down. + +`uptime.py <https://github.com/pexpect/pexpect/blob/master/examples/uptime.py>`_ + This will run the uptime command and parse the output into variables. + This demonstrates using a single regular expression to match the + output of a command and capturing different variable in match groups. + The grouping regular expression handles a wide variety of different + uptime formats. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/history.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/history.rst new file mode 100644 index 00000000000..41a591819b3 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/history.rst @@ -0,0 +1,338 @@ +History +======= + +Releases +-------- + +Version 4.6 +``````````` + +* The :meth:`.pxssh.login` method now supports an ``ssh_config`` parameter, + which can be used to specify a file path to an SSH config file + (:ghpull:`490`). +* Improved compatability for the ``crlf`` parameter of :class:`~.PopenSpawn` + (:ghpull:`493`) +* Fixed an issue in read timeout handling when using :class:`~.spawn` and + :class:`~.fdspawn` with the ``use_poll`` parameter (:ghpull:`492`). + +Version 4.5 +``````````` + +* :class:`~.spawn` and :class:`~.fdspawn` now have a ``use_poll`` parameter. + If this is True, they will use :func:`select.poll` instead of :func:`select.select`. + ``poll()`` allows file descriptors above 1024, but it must be explicitly + enabled due to compatibility concerns (:ghpull:`474`). +* The :meth:`.pxssh.login` method has several new and changed options: + + * The option ``password_regex`` allows changing + the password prompt regex, for servers that include ``password:`` in a banner + before reaching a prompt (:ghpull:`468`). + * :meth:`~.pxssh.login` now allows for setting up SSH tunnels to be requested once + logged in to the remote server. This option is ``ssh_tunnels`` (:ghpull:`473`). + The structure should be like this:: + + { + 'local': ['2424:localhost:22'], # Local SSH tunnels + 'remote': ['2525:localhost:22'], # Remote SSH tunnels + 'dynamic': [8888], # Dynamic/SOCKS tunnels + } + + * The option ``spawn_local_ssh=False`` allows subsequent logins from the + remote session and treats the session as if it was local (:ghpull:`472`). + * Setting ``sync_original_prompt=False`` will prevent changing the prompt to + something unique, in case the remote server is sensitive to new lines at login + (:ghpull:`468`). + * If ``ssh_key=True`` is passed, the SSH client forces forwarding the authentication + agent to the remote server instead of providing a key (:ghpull:`473`). + +Version 4.4 +``````````` + +* :class:`~.PopenSpawn` now has a ``preexec_fn`` parameter, like :class:`~.spawn` + and :class:`subprocess.Popen`, for a function to be called in the child + process before executing the new command. Like in ``Popen``, this works only + in POSIX, and can cause issues if your application also uses threads + (:ghpull:`460`). +* Significant performance improvements when processing large amounts of data + (:ghpull:`464`). +* Ensure that ``spawn.closed`` gets set by :meth:`~.spawn.close`, and improve + an example for passing ``SIGWINCH`` through to a child process (:ghpull:`466`). + +Version 4.3.1 +````````````` + +* When launching bash for :mod:`pexpect.replwrap`, load the system ``bashrc`` + from a couple of different common locations (:ghpull:`457`), and then unset + the ``PROMPT_COMMAND`` environment variable, which can interfere with the + prompt we're expecting (:ghpull:`459`). + +Version 4.3 +``````````` + +* The ``async=`` parameter to integrate with asyncio has become ``async_=`` + (:ghpull:`431`), as *async* is becoming a Python keyword from Python 3.6. + Pexpect will still recognise ``async`` as an alternative spelling. +* Similarly, the module ``pexpect.async`` became ``pexpect._async`` + (:ghpull:`450`). This module is not part of the public API. +* Fix problems with asyncio objects closing file descriptors during garbage + collection (:ghissue:`347`, :ghpull:`376`). +* Set the ``.pid`` attribute of a :class:`~.PopenSpawn` object (:ghpull:`417`). +* Fix passing Windows paths to :class:`~.PopenSpawn` (:ghpull:`446`). +* :class:`~.PopenSpawn` on Windows can pass string commands through to ``Popen`` + without splitting them into a list (:ghpull:`447`). +* Stop ``shlex`` trying to read from stdin when :class:`~.PopenSpawn` is + passed ``cmd=None`` (:ghissue:`433`, :ghpull:`434`). +* Ensure that an error closing a Pexpect spawn object raises a Pexpect error, + rather than a Ptyprocess error (:ghissue:`383`, :ghpull:`386`). +* Cleaned up invalid backslash escape sequences in strings (:ghpull:`430`, + :ghpull:`445`). +* The pattern for a password prompt in :mod:`pexpect.pxssh` changed from + ``password`` to ``password:`` (:ghpull:`452`). +* Correct docstring for using unicode with spawn (:ghpull:`395`). +* Various other improvements to documentation. + +Version 4.2.1 +````````````` + +* Fix to allow running ``env`` in replwrap-ed bash. +* Raise more informative exception from pxssh if it fails to connect. +* Change ``passmass`` example to not log passwords entered. + +Version 4.2 +``````````` + +* Change: When an ``env`` parameter is specified to the :class:`~.spawn` or + :class:`~.run` family of calls containing a value for ``PATH``, its value is + used to discover the target executable from a relative path, rather than the + current process's environment ``PATH``. This mirrors the behavior of + :func:`subprocess.Popen` in the standard library (:ghissue:`348`). + +* Regression: Re-introduce capability for :meth:`read_nonblocking` in class + :class:`fdspawn` as previously supported in version 3.3 (:ghissue:`359`). + +Version 4.0 +``````````` + +* Integration with :mod:`asyncio`: passing ``async=True`` to :meth:`~.spawn.expect`, + :meth:`~.spawn.expect_exact` or :meth:`~.spawn.expect_list` will make them return a + coroutine. You can get the result using ``yield from``, or wrap it in an + :class:`asyncio.Task`. This allows the event loop to do other things while + waiting for output that matches a pattern. +* Experimental support for Windows (with some caveats)—see :ref:`windows`. +* Enhancement: allow method as callbacks of argument ``events`` for + :func:`pexpect.run` (:ghissue:`176`). +* It is now possible to call :meth:`~.spawn.wait` multiple times, or after a process + is already determined to be terminated without raising an exception + (:ghpull:`211`). +* New :class:`pexpect.spawn` keyword argument, ``dimensions=(rows, columns)`` + allows setting terminal screen dimensions before launching a program + (:ghissue:`122`). +* Fix regression that prevented executable, but unreadable files from + being found when not specified by absolute path -- such as + /usr/bin/sudo (:ghissue:`104`). +* Fixed regression when executing pexpect with some prior releases of + the multiprocessing module where stdin has been closed (:ghissue:`86`). + +Backwards incompatible changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Deprecated ``pexpect.screen`` and ``pexpect.ANSI``. Please use other packages + such as `pyte <https://pypi.python.org/pypi/pyte>`__ to emulate a terminal. +* Removed the independent top-level modules (``pxssh fdpexpect FSM screen ANSI``) + which were installed alongside Pexpect. These were moved into the Pexpect + package in 3.0, but the old names were left as aliases. +* Child processes created by Pexpect no longer ignore SIGHUP by default: the + ``ignore_sighup`` parameter of :class:`pexpect.spawn` defaults to False. To + get the old behaviour, pass ``ignore_sighup=True``. + +Version 3.3 +``````````` + +* Added a mechanism to wrap REPLs, or shells, in an object which can conveniently + be used to send commands and wait for the output (:mod:`pexpect.replwrap`). +* Fixed issue where pexpect would attempt to execute a directory because + it has the 'execute' bit set (:ghissue:`37`). +* Removed the ``pexpect.psh`` module. This was never documented, and we found + no evidence that people use it. The new :mod:`pexpect.replwrap` module + provides a more flexible alternative. +* Fixed ``TypeError: got <type 'str'> ('\r\n') as pattern`` in :meth:`spawnu.readline` + method (:ghissue:`67`). +* Fixed issue where EOF was not correctly detected in :meth:`~.interact`, causing + a repeating loop of output on Linux, and blocking before EOF on BSD and + Solaris (:ghissue:`49`). +* Several Solaris (SmartOS) bugfixes, preventing :exc:`IOError` exceptions, especially + when used with cron(1) (:ghissue:`44`). +* Added new keyword argument ``echo=True`` for :class:`spawn`. On SVR4-like + systems, the method :meth:`~.isatty` will always return *False*: the child pty + does not appear as a terminal. Therefore, :meth:`~.setecho`, :meth:`~.getwinsize`, + :meth:`~.setwinsize`, and :meth:`~.waitnoecho` are not supported on those platforms. + +After this, we intend to start working on a bigger refactoring of the code, to +be released as Pexpect 4. There may be more bugfix 3.x releases, however. + +Version 3.2 +``````````` + +* Fix exception handling from :func:`select.select` on Python 2 (:ghpull:`38`). + This was accidentally broken in the previous release when it was fixed for + Python 3. +* Removed a workaround for ``TIOCSWINSZ`` on very old systems, which was causing + issues on some BSD systems (:ghpull:`40`). +* Fixed an issue with exception handling in :mod:`~pexpect.pxssh` (:ghpull:`43`) + +The documentation for :mod:`~pexpect.pxssh` was improved. + +Version 3.1 +``````````` + +* Fix an issue that prevented importing pexpect on Python 3 when ``sys.stdout`` + was reassigned (:ghissue:`30`). +* Improve prompt synchronisation in :mod:`~pexpect.pxssh` (:ghpull:`28`). +* Fix pickling exception instances (:ghpull:`34`). +* Fix handling exceptions from :func:`select.select` on Python 3 (:ghpull:`33`). + +The examples have also been cleaned up somewhat - this will continue in future +releases. + +Version 3.0 +``````````` + +The new major version number doesn't indicate any deliberate API incompatibility. +We have endeavoured to avoid breaking existing APIs. However, pexpect is under +new maintenance after a long dormancy, so some caution is warranted. + +* A new :ref:`unicode API <unicode>` was introduced. +* Python 3 is now supported, using a single codebase. +* Pexpect now requires at least Python 2.6 or 3.2. +* The modules other than pexpect, such as :mod:`pexpect.fdpexpect` and + :mod:`pexpect.pxssh`, were moved into the pexpect package. For now, wrapper + modules are installed to the old locations for backwards compatibility (e.g. + ``import pxssh`` will still work), but these will be removed at some point in + the future. +* Ignoring ``SIGHUP`` is now optional - thanks to Kimmo Parviainen-Jalanko for + the patch. + +We also now have `docs on ReadTheDocs <https://pexpect.readthedocs.io/>`_, +and `continuous integration on Travis CI <https://travis-ci.org/pexpect/pexpect>`_. + +Version 2.4 +``````````` + +* Fix a bug regarding making the pty the controlling terminal when the process + spawning it is not, actually, a terminal (such as from cron) + +Version 2.3 +``````````` + +* Fixed OSError exception when a pexpect object is cleaned up. Previously, you + might have seen this exception:: + + Exception exceptions.OSError: (10, 'No child processes') + in <bound method spawn.__del__ of <pexpect.spawn instance at 0xd248c>> ignored + + You should not see that anymore. Thanks to Michael Surette. +* Added support for buffering reads. This greatly improves speed when trying to + match long output from a child process. When you create an instance of the spawn + object you can then set a buffer size. For now you MUST do the following to turn + on buffering -- it may be on by default in future version:: + + child = pexpect.spawn ('my_command') + child.maxread=1000 # Sets buffer to 1000 characters. + +* I made a subtle change to the way TIMEOUT and EOF exceptions behave. + Previously you could either expect these states in which case pexpect + will not raise an exception, or you could just let pexpect raise an + exception when these states were encountered. If you expected the + states then the ``before`` property was set to everything before the + state was encountered, but if you let pexpect raise the exception then + ``before`` was not set. Now, the ``before`` property will get set either + way you choose to handle these states. +* The spawn object now provides iterators for a *file-like interface*. + This makes Pexpect a more complete file-like object. You can now write + code like this:: + + child = pexpect.spawn ('ls -l') + for line in child: + print line + +* write and writelines() no longer return a value. Use send() if you need that + functionality. I did this to make the Spawn object more closely match a + file-like object. +* Added the attribute ``exitstatus``. This will give the exit code returned + by the child process. This will be set to ``None`` while the child is still + alive. When ``isalive()`` returns 0 then ``exitstatus`` will be set. +* Made a few more tweaks to ``isalive()`` so that it will operate more + consistently on different platforms. Solaris is the most difficult to support. +* You can now put ``TIMEOUT`` in a list of expected patterns. This is just like + putting ``EOF`` in the pattern list. Expecting for a ``TIMEOUT`` may not be + used as often as ``EOF``, but this makes Pexpect more consistent. +* Thanks to a suggestion and sample code from Chad J. Schroeder I added the ability + for Pexpect to operate on a file descriptor that is already open. This means that + Pexpect can be used to control streams such as those from serial port devices. Now, + you just pass the integer file descriptor as the "command" when constructing a + spawn open. For example on a Linux box with a modem on ttyS1:: + + fd = os.open("/dev/ttyS1", os.O_RDWR|os.O_NONBLOCK|os.O_NOCTTY) + m = pexpect.spawn(fd) # Note integer fd is used instead of usual string. + m.send("+++") # Escape sequence + m.send("ATZ0\r") # Reset modem to profile 0 + rval = m.expect(["OK", "ERROR"]) + +* ``read()`` was renamed to ``read_nonblocking()``. Added new ``read()`` method + that matches file-like object interface. In general, you should not notice + the difference except that ``read()`` no longer allows you to directly set the + timeout value. I hope this will not effect any existing code. Switching to + ``read_nonblocking()`` should fix existing code. +* Changed the name of ``set_echo()`` to ``setecho()``. +* Changed the name of ``send_eof()`` to ``sendeof()``. +* Modified ``kill()`` so that it checks to make sure the pid ``isalive()``. +* modified ``spawn()`` (really called from ``__spawn()``) so that it does not + raise an exception if ``setwinsize()`` fails. Some platforms such as Cygwin + do not like setwinsize. This was a constant problem and since it is not a + critical feature I decided to just silence the error. Normally I don't like + to do that, but in this case I'm making an exception. +* Added a method ``close()`` that does what you think. It closes the file + descriptor of the child application. It makes no attempt to actually kill the + child or wait for its status. +* Add variables ``__version__`` and ``__revision__`` (from cvs) to the pexpect + modules. This is mainly helpful to me so that I can make sure that I'm testing + with the right version instead of one already installed. +* ``log_open()`` and ``log_close(`` have been removed. Now use ``setlog()``. + The ``setlog()`` method takes a file object. This is far more flexible than + the previous log method. Each time data is written to the file object it will + be flushed. To turn logging off simply call ``setlog()`` with None. +* renamed the ``isAlive()`` method to ``isalive()`` to match the more typical + naming style in Python. Also the technique used to detect child process + status has been drastically modified. Previously I did some funky stuff + with signals which caused indigestion in other Python modules on some + platforms. It was a big headache. It still is, but I think it works + better now. +* attribute ``matched`` renamed to ``after`` +* new attribute ``match`` +* The ``expect_eof()`` method is gone. You can now simply use the + ``expect()`` method to look for EOF. +* **Pexpect works on OS X**, but the nature of the quirks cause many of the + tests to fail. See bugs. (Incomplete Child Output). The problem is more + than minor, but Pexpect is still more than useful for most tasks. +* **Solaris**: For some reason, the *second* time a pty file descriptor is created and + deleted it never gets returned for use. It does not effect the first time + or the third time or any time after that. It's only the second time. This + is weird... This could be a file descriptor leak, or it could be some + peculiarity of how Solaris recycles them. I thought it was a UNIX requirement + for the OS to give you the lowest available filedescriptor number. In any case, + this should not be a problem unless you create hundreds of pexpect instances... + It may also be a pty module bug. + + +Moves and forks +--------------- + +* Pexpect development used to be hosted on Sourceforge. +* In 2011, Thomas Kluyver forked pexpect as 'pexpect-u', to support + Python 3. He later decided he had taken the wrong approach with this. +* In 2012, Noah Spurrier, the original author of Pexpect, moved the + project to Github, but was still too busy to develop it much. +* In 2013, Thomas Kluyver and Jeff Quast forked Pexpect again, intending + to call the new fork Pexpected. Noah Spurrier agreed to let them use + the name Pexpect, so Pexpect versions 3 and above are based on this + fork, which now lives `here on Github <https://github.com/pexpect/pexpect>`_. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/index.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/index.rst new file mode 100644 index 00000000000..0bcf862dd4d --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/index.rst @@ -0,0 +1,50 @@ +Pexpect version |version| +========================= + +.. image:: https://travis-ci.org/pexpect/pexpect.png?branch=master + :target: https://travis-ci.org/pexpect/pexpect + :align: right + :alt: Build status + +Pexpect makes Python a better tool for controlling other +applications. + +Pexpect is a pure Python module for spawning child applications; +controlling them; and responding to expected patterns in their output. +Pexpect works like Don Libes' Expect. Pexpect allows your script to +spawn a child application and control it as if a human were typing +commands. + +Pexpect can be used for automating interactive applications such as +ssh, ftp, passwd, telnet, etc. It can be used to a automate setup +scripts for duplicating software package installations on different +servers. It can be used for automated software testing. Pexpect is in +the spirit of Don Libes' Expect, but Pexpect is pure Python. Unlike +other Expect-like modules for Python, Pexpect does not require TCL or +Expect nor does it require C extensions to be compiled. It should work +on any platform that supports the standard Python pty module. The +Pexpect interface was designed to be easy to use. + +Contents: + +.. toctree:: + :maxdepth: 2 + + install + overview + api/index + examples + FAQ + commonissues + history + +Pexpect is developed `on Github <http://github.com/pexpect/pexpect>`_. Please +report `issues <https://github.com/pexpect/pexpect/issues>`_ there as well. + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/install.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/install.rst new file mode 100644 index 00000000000..6f7e36af62d --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/install.rst @@ -0,0 +1,20 @@ +Installation +============ + +Pexpect is on PyPI, and can be installed with standard tools:: + + pip install pexpect + +Or:: + + easy_install pexpect + +Requirements +------------ + +This version of Pexpect requires Python 3.3 or above, or Python 2.7. + +As of version 4.0, Pexpect can be used on Windows and POSIX systems. However, +:class:`pexpect.spawn` and :func:`pexpect.run` are only available on POSIX, +where the :mod:`pty` module is present in the standard library. See +:ref:`windows` for more information. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/make.bat b/lldb/third_party/Python/module/pexpect-4.6/doc/make.bat new file mode 100644 index 00000000000..448f1470824 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^<target^>` where ^<target^> is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Pexpect.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Pexpect.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/overview.rst b/lldb/third_party/Python/module/pexpect-4.6/doc/overview.rst new file mode 100644 index 00000000000..e52809cdc68 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/overview.rst @@ -0,0 +1,266 @@ +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`. + +: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. + +``PopenSpawn`` is not a direct replacement for ``spawn``. Many programs only +offer interactive behaviour if they detect that they are running in a terminal. +When run by ``PopenSpawn``, they may behave differently. + +.. seealso:: + + `winpexpect <https://pypi.python.org/pypi/winpexpect>`__ and `wexpect <https://gist.github.com/anthonyeden/8488763>`__ + Two unmaintained pexpect-like modules for Windows, which work with a + hidden console. diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/requirements.txt b/lldb/third_party/Python/module/pexpect-4.6/doc/requirements.txt new file mode 100644 index 00000000000..57ebb2d6bdd --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/requirements.txt @@ -0,0 +1 @@ +ptyprocess diff --git a/lldb/third_party/Python/module/pexpect-4.6/doc/sphinxext/github.py b/lldb/third_party/Python/module/pexpect-4.6/doc/sphinxext/github.py new file mode 100644 index 00000000000..519e146d198 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/doc/sphinxext/github.py @@ -0,0 +1,155 @@ +"""Define text roles for GitHub + +* ghissue - Issue +* ghpull - Pull Request +* ghuser - User + +Adapted from bitbucket example here: +https://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/bitbucket/sphinxcontrib/bitbucket.py + +Authors +------- + +* Doug Hellmann +* Min RK +""" +# +# Original Copyright (c) 2010 Doug Hellmann. All rights reserved. +# + +from docutils import nodes, utils +from docutils.parsers.rst.roles import set_classes + +def make_link_node(rawtext, app, type, slug, options): + """Create a link to a github resource. + + :param rawtext: Text being replaced with link node. + :param app: Sphinx application context + :param type: Link type (issues, changeset, etc.) + :param slug: ID of the thing to link to + :param options: Options dictionary passed to role func. + """ + + try: + base = app.config.github_project_url + if not base: + raise AttributeError + if not base.endswith('/'): + base += '/' + except AttributeError as err: + raise ValueError('github_project_url configuration value is not set (%s)' % str(err)) + + ref = base + type + '/' + slug + '/' + set_classes(options) + prefix = "#" + if type == 'pull': + prefix = "PR " + prefix + node = nodes.reference(rawtext, prefix + utils.unescape(slug), refuri=ref, + **options) + return node + +def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): + """Link to a GitHub issue. + + Returns 2 part tuple containing list of nodes to insert into the + document and a list of system messages. Both are allowed to be + empty. + + :param name: The role name used in the document. + :param rawtext: The entire markup snippet, with role. + :param text: The text marked with the role. + :param lineno: The line number where rawtext appears in the input. + :param inliner: The inliner instance that called us. + :param options: Directive options for customization. + :param content: The directive content for customization. + """ + + try: + issue_num = int(text) + if issue_num <= 0: + raise ValueError + except ValueError: + msg = inliner.reporter.error( + 'GitHub issue number must be a number greater than or equal to 1; ' + '"%s" is invalid.' % text, line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + app = inliner.document.settings.env.app + #app.info('issue %r' % text) + if 'pull' in name.lower(): + category = 'pull' + elif 'issue' in name.lower(): + category = 'issues' + else: + msg = inliner.reporter.error( + 'GitHub roles include "ghpull" and "ghissue", ' + '"%s" is invalid.' % name, line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + node = make_link_node(rawtext, app, category, str(issue_num), options) + return [node], [] + +def ghuser_role(name, rawtext, text, lineno, inliner, options={}, content=[]): + """Link to a GitHub user. + + Returns 2 part tuple containing list of nodes to insert into the + document and a list of system messages. Both are allowed to be + empty. + + :param name: The role name used in the document. + :param rawtext: The entire markup snippet, with role. + :param text: The text marked with the role. + :param lineno: The line number where rawtext appears in the input. + :param inliner: The inliner instance that called us. + :param options: Directive options for customization. + :param content: The directive content for customization. + """ + app = inliner.document.settings.env.app + #app.info('user link %r' % text) + ref = 'https://www.github.com/' + text + node = nodes.reference(rawtext, text, refuri=ref, **options) + return [node], [] + +def ghcommit_role(name, rawtext, text, lineno, inliner, options={}, content=[]): + """Link to a GitHub commit. + + Returns 2 part tuple containing list of nodes to insert into the + document and a list of system messages. Both are allowed to be + empty. + + :param name: The role name used in the document. + :param rawtext: The entire markup snippet, with role. + :param text: The text marked with the role. + :param lineno: The line number where rawtext appears in the input. + :param inliner: The inliner instance that called us. + :param options: Directive options for customization. + :param content: The directive content for customization. + """ + app = inliner.document.settings.env.app + #app.info('user link %r' % text) + try: + base = app.config.github_project_url + if not base: + raise AttributeError + if not base.endswith('/'): + base += '/' + except AttributeError as err: + raise ValueError('github_project_url configuration value is not set (%s)' % str(err)) + + ref = base + text + node = nodes.reference(rawtext, text[:6], refuri=ref, **options) + return [node], [] + + +def setup(app): + """Install the plugin. + + :param app: Sphinx application context. + """ + app.info('Initializing GitHub plugin') + app.add_role('ghissue', ghissue_role) + app.add_role('ghpull', ghissue_role) + app.add_role('ghuser', ghuser_role) + app.add_role('ghcommit', ghcommit_role) + app.add_config_value('github_project_url', None, 'env') + return diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/README b/lldb/third_party/Python/module/pexpect-4.6/examples/README new file mode 100644 index 00000000000..823cc6335a9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/README @@ -0,0 +1,86 @@ +This directory contains scripts that give examples of using Pexpect. + +hive.py + This script creates SSH connections to a list of hosts that + you provide. Then you are given a command line prompt. Each + shell command that you enter is sent to all the hosts. The + response from each host is collected and printed. For example, + you could connect to a dozen different machines and reboot + them all at once. + +script.py + This implements a command similar to the classic BSD "script" command. + This will start a subshell and log all input and output to a file. + This demonstrates the interact() method of Pexpect. + +fix_cvs_files.py + This is for cleaning up binary files improperly added to + CVS. This script scans the given path to find binary files; + checks with CVS to see if the sticky options are set to -kb; + finally if sticky options are not -kb then uses 'cvs admin' + to set the -kb option. + +ftp.py + This demonstrates an FTP "bookmark". + This connects to an ftp site; does a few ftp commands; and then gives the user + interactive control over the session. In this case the "bookmark" is to a + directory on the OpenBSD ftp server. It puts you in the i386 packages + directory. You can easily modify this for other sites. + This demonstrates the interact() method of Pexpect. + +monitor.py + This runs a sequence of system status commands on a remote host using SSH. + It runs a simple system checks such as uptime and free to monitor + the state of the remote host. + +passmass.py + This will login to a list of hosts and change the password of the + given user. This demonstrates scripting logins; although, you could + more easily do this using the pxssh subclass of Pexpect. + See also the "hive.py" example script for a more general example + of scripting a collection of servers. + +python.py + This starts the python interpreter and prints the greeting message backwards. + It then gives the user interactive control of Python. It's pretty useless! + +rippy.py + This is a wizard for mencoder. It greatly simplifies the process of + ripping a DVD to mpeg4 format (XviD, DivX). It can transcode from any + video file to another. It has options for resampling the audio stream; + removing interlace artifacts, fitting to a target file size, etc. + There are lots of options, but the process is simple and easy to use. + +ssh_tunnel.py + This starts an SSH tunnel to a remote machine. It monitors the connection + and restarts the tunnel if it goes down. + +uptime.py + This will run the uptime command and parse the output into python variables. + This demonstrates using a single regular expression to match the output + of a command and capturing different variable in match groups. + The regular expression takes into account a wide variety of different + formats for uptime output. + +df.py + This collects filesystem capacity info using the 'df' command. + Tuples of filesystem name and percentage are stored in a list. + A simple report is printed. Filesystems over 95% capacity are highlighted. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/astat.py b/lldb/third_party/Python/module/pexpect-4.6/examples/astat.py new file mode 100755 index 00000000000..abba1be22b9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/astat.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python + +'''This runs Apache Status on the remote host and returns the number of requests per second. + +./astat.py [-s server_hostname] [-u username] [-p password] + -s : hostname of the remote server to login to. + -u : username to user for login. + -p : Password to user for login. + +Example: + This will print information about the given host: + ./astat.py -s www.example.com -u mylogin -p mypassword + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import os +import sys +import getopt +import getpass +import pxssh + + +try: + raw_input +except NameError: + raw_input = input + + +def exit_with_usage(): + + print(globals()['__doc__']) + os._exit(1) + + +def main(): + + ###################################################################### + ## Parse the options, arguments, get ready, etc. + ###################################################################### + try: + optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?']) + except Exception as e: + print(str(e)) + exit_with_usage() + options = dict(optlist) + if len(args) > 1: + exit_with_usage() + + if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]: + print("Help:") + exit_with_usage() + + if '-s' in options: + hostname = options['-s'] + else: + hostname = raw_input('hostname: ') + if '-u' in options: + username = options['-u'] + else: + username = raw_input('username: ') + if '-p' in options: + password = options['-p'] + else: + password = getpass.getpass('password: ') + + # + # Login via SSH + # + p = pxssh.pxssh() + p.login(hostname, username, password) + p.sendline('apachectl status') + p.expect(r'([0-9]+\.[0-9]+)\s*requests/sec') + requests_per_second = p.match.groups()[0] + p.logout() + print(requests_per_second) + +if __name__ == "__main__": + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/cgishell.cgi b/lldb/third_party/Python/module/pexpect-4.6/examples/cgishell.cgi new file mode 100755 index 00000000000..57d8667eb91 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/cgishell.cgi @@ -0,0 +1,766 @@ +#!/usr/bin/python +##!/usr/bin/env python +"""CGI shell server + +This exposes a shell terminal on a web page. +It uses AJAX to send keys and receive screen updates. +The client web browser needs nothing but CSS and Javascript. + + --hostname : sets the remote host name to open an ssh connection to. + --username : sets the user name to login with + --password : (optional) sets the password to login with + --port : set the local port for the server to listen on + --watch : show the virtual screen after each client request + +This project is probably not the most security conscious thing I've ever built. +This should be considered an experimental tool -- at best. +""" + +from __future__ import absolute_import +from __future__ import print_function + +import sys,os +sys.path.insert (0,os.getcwd()) # let local modules precede any installed modules +import socket, random, string, traceback, cgi, time, getopt, getpass, threading, resource, signal +import pxssh, pexpect, ANSI + +def exit_with_usage(exit_code=1): + print(globals()['__doc__']) + os._exit(exit_code) + +def client (command, host='localhost', port=-1): + """This sends a request to the server and returns the response. + If port <= 0 then host is assumed to be the filename of a Unix domain socket. + If port > 0 then host is an inet hostname. + """ + if port <= 0: + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(host) + else: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((host, port)) + s.send(command) + data = s.recv (2500) + s.close() + return data + +def server (hostname, username, password, socket_filename='/tmp/server_sock', daemon_mode = True, verbose=False): + """This starts and services requests from a client. + If daemon_mode is True then this forks off a separate daemon process and returns the daemon's pid. + If daemon_mode is False then this does not return until the server is done. + """ + if daemon_mode: + mypid_name = '/tmp/%d.pid' % os.getpid() + daemon_pid = daemonize(daemon_pid_filename=mypid_name) + time.sleep(1) + if daemon_pid != 0: + os.unlink(mypid_name) + return daemon_pid + + virtual_screen = ANSI.ANSI (24,80) + child = pxssh.pxssh() + try: + child.login (hostname, username, password, login_naked=True) + except: + return + if verbose: print('login OK') + virtual_screen.write (child.before) + virtual_screen.write (child.after) + + if os.path.exists(socket_filename): os.remove(socket_filename) + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.bind(socket_filename) + os.chmod(socket_filename, 0o777) + if verbose: print('Listen') + s.listen(1) + + r = roller (endless_poll, (child, child.PROMPT, virtual_screen)) + r.start() + if verbose: print("started screen-poll-updater in background thread") + sys.stdout.flush() + try: + while True: + conn, addr = s.accept() + if verbose: print('Connected by', addr) + data = conn.recv(1024) + request = data.split(' ', 1) + if len(request)>1: + cmd = request[0].strip() + arg = request[1].strip() + else: + cmd = request[0].strip() + arg = '' + + if cmd == 'exit': + r.cancel() + break + elif cmd == 'sendline': + child.sendline (arg) + time.sleep(0.1) + shell_window = str(virtual_screen) + elif cmd == 'send' or cmd=='xsend': + if cmd=='xsend': + arg = arg.decode("hex") + child.send (arg) + time.sleep(0.1) + shell_window = str(virtual_screen) + elif cmd == 'cursor': + shell_window = '%x,%x' % (virtual_screen.cur_r, virtual_screen.cur_c) + elif cmd == 'refresh': + shell_window = str(virtual_screen) + elif cmd == 'hash': + shell_window = str(hash(str(virtual_screen))) + + response = [] + response.append (shell_window) + if verbose: print('\n'.join(response)) + sent = conn.send('\n'.join(response)) + if sent < len (response): + if verbose: print("Sent is too short. Some data was cut off.") + conn.close() + except e: + pass + r.cancel() + if verbose: print("cleaning up socket") + s.close() + if os.path.exists(socket_filename): os.remove(socket_filename) + if verbose: print("server done!") + +class roller (threading.Thread): + """This class continuously loops a function in a thread. + This is basically a thin layer around Thread with a + while loop and a cancel. + """ + def __init__(self, function, args=[], kwargs={}): + threading.Thread.__init__(self) + self.function = function + self.args = args + self.kwargs = kwargs + self.finished = threading.Event() + def cancel(self): + """Stop the roller.""" + self.finished.set() + def run(self): + while not self.finished.isSet(): + self.function(*self.args, **self.kwargs) + +def endless_poll (child, prompt, screen, refresh_timeout=0.1): + """This keeps the screen updated with the output of the child. + This will be run in a separate thread. See roller class. + """ + #child.logfile_read = screen + try: + s = child.read_nonblocking(4000, 0.1) + screen.write(s) + except: + pass + +def daemonize (stdin=None, stdout=None, stderr=None, daemon_pid_filename=None): + """This runs the current process in the background as a daemon. + The arguments stdin, stdout, stderr allow you to set the filename that the daemon reads and writes to. + If they are set to None then all stdio for the daemon will be directed to /dev/null. + If daemon_pid_filename is set then the pid of the daemon will be written to it as plain text + and the pid will be returned. If daemon_pid_filename is None then this will return None. + """ + UMASK = 0 + WORKINGDIR = "/" + MAXFD = 1024 + + # The stdio file descriptors are redirected to /dev/null by default. + if hasattr(os, "devnull"): + DEVNULL = os.devnull + else: + DEVNULL = "/dev/null" + if stdin is None: stdin = DEVNULL + if stdout is None: stdout = DEVNULL + if stderr is None: stderr = DEVNULL + + try: + pid = os.fork() # fork first child + except OSError as e: + raise Exception("%s [%d]" % (e.strerror, e.errno)) + + if pid != 0: + os.waitpid(pid,0) + if daemon_pid_filename is not None: + daemon_pid = int(file(daemon_pid_filename,'r').read()) + return daemon_pid + else: + return None + + # first child + os.setsid() + signal.signal(signal.SIGHUP, signal.SIG_IGN) + + try: + pid = os.fork() # fork second child + except OSError as e: + raise Exception("%s [%d]" % (e.strerror, e.errno)) + + if pid != 0: + if daemon_pid_filename is not None: + file(daemon_pid_filename,'w').write(str(pid)) + os._exit(0) # exit parent (the first child) of the second child. + + # second child + os.chdir(WORKINGDIR) + os.umask(UMASK) + + maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] + if maxfd == resource.RLIM_INFINITY: + maxfd = MAXFD + + # close all file descriptors + for fd in range(0, maxfd): + try: + os.close(fd) + except OSError: # fd wasn't open to begin with (ignored) + pass + + os.open (DEVNULL, os.O_RDWR) # standard input + + # redirect standard file descriptors + si = open(stdin, 'r') + so = open(stdout, 'a+') + se = open(stderr, 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + + return 0 + +def client_cgi (): + """This handles the request if this script was called as a cgi. + """ + sys.stderr = sys.stdout + ajax_mode = False + TITLE="Shell" + SHELL_OUTPUT="" + SID="NOT" + print("Content-type: text/html;charset=utf-8\r\n") + try: + form = cgi.FieldStorage() + if 'ajax' in form: + ajax_mode = True + ajax_cmd = form['ajax'].value + SID=form['sid'].value + if ajax_cmd == 'send': + command = 'xsend' + arg = form['arg'].value.encode('hex') + result = client (command + ' ' + arg, '/tmp/'+SID) + print(result) + elif ajax_cmd == 'refresh': + command = 'refresh' + result = client (command, '/tmp/'+SID) + print(result) + elif ajax_cmd == 'cursor': + command = 'cursor' + result = client (command, '/tmp/'+SID) + print(result) + elif ajax_cmd == 'exit': + command = 'exit' + result = client (command, '/tmp/'+SID) + print(result) + elif ajax_cmd == 'hash': + command = 'hash' + result = client (command, '/tmp/'+SID) + print(result) + elif 'sid' not in form: + SID=random_sid() + print(LOGIN_HTML % locals()); + else: + SID=form['sid'].value + if 'start_server' in form: + USERNAME = form['username'].value + PASSWORD = form['password'].value + dpid = server ('127.0.0.1', USERNAME, PASSWORD, '/tmp/'+SID) + SHELL_OUTPUT="daemon pid: " + str(dpid) + else: + if 'cli' in form: + command = 'sendline ' + form['cli'].value + else: + command = 'sendline' + SHELL_OUTPUT = client (command, '/tmp/'+SID) + print(CGISH_HTML % locals()) + except: + tb_dump = traceback.format_exc() + if ajax_mode: + print(str(tb_dump)) + else: + SHELL_OUTPUT=str(tb_dump) + print(CGISH_HTML % locals()) + +def server_cli(): + """This is the command line interface to starting the server. + This handles things if the script was not called as a CGI + (if you run it from the command line). + """ + try: + optlist, args = getopt.getopt(sys.argv[1:], 'h?d', ['help','h','?', 'hostname=', 'username=', 'password=', 'port=', 'watch']) + except Exception as e: + print(str(e)) + exit_with_usage() + + command_line_options = dict(optlist) + options = dict(optlist) + # There are a million ways to cry for help. These are but a few of them. + if [elem for elem in command_line_options if elem in ['-h','--h','-?','--?','--help']]: + exit_with_usage(0) + + hostname = "127.0.0.1" + #port = 1664 + username = os.getenv('USER') + password = "" + daemon_mode = False + if '-d' in options: + daemon_mode = True + if '--watch' in options: + watch_mode = True + else: + watch_mode = False + if '--hostname' in options: + hostname = options['--hostname'] + if '--port' in options: + port = int(options['--port']) + if '--username' in options: + username = options['--username'] + if '--password' in options: + password = options['--password'] + else: + password = getpass.getpass('password: ') + + server (hostname, username, password, '/tmp/mysock', daemon_mode) + +def random_sid (): + a=random.randint(0,65535) + b=random.randint(0,65535) + return '%04x%04x.sid' % (a,b) + +def parse_host_connect_string (hcs): + """This parses a host connection string in the form + username:password@hostname:port. All fields are options expcet hostname. A + dictionary is returned with all four keys. Keys that were not included are + set to empty strings ''. Note that if your password has the '@' character + then you must backslash escape it. + """ + if '@' in hcs: + p = re.compile (r'(?P<username>[^@:]*)(:?)(?P<password>.*)(?!\\)@(?P<hostname>[^:]*):?(?P<port>[0-9]*)') + else: + p = re.compile (r'(?P<username>)(?P<password>)(?P<hostname>[^:]*):?(?P<port>[0-9]*)') + m = p.search (hcs) + d = m.groupdict() + d['password'] = d['password'].replace('\\@','@') + return d + +def pretty_box (s, rows=24, cols=80): + """This puts an ASCII text box around the given string. + """ + top_bot = '+' + '-'*cols + '+\n' + return top_bot + '\n'.join(['|'+line+'|' for line in s.split('\n')]) + '\n' + top_bot + +def main (): + if os.getenv('REQUEST_METHOD') is None: + server_cli() + else: + client_cgi() + +# It's mostly HTML and Javascript from here on out. +CGISH_HTML="""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>%(TITLE)s %(SID)s</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<style type=text/css> +a {color: #9f9; text-decoration: none} +a:hover {color: #0f0} +hr {color: #0f0} +html,body,textarea,input,form +{ +font-family: "Courier New", Courier, mono; +font-size: 8pt; +color: #0c0; +background-color: #020; +margin:0; +padding:0; +border:0; +} +input { background-color: #010; } +textarea { +border-width:1; +border-style:solid; +border-color:#0c0; +padding:3; +margin:3; +} +</style> + +<script language="JavaScript"> +function focus_first() +{if (document.forms.length > 0) +{var TForm = document.forms[0]; +for (i=0;i<TForm.length;i++){ +if ((TForm.elements[i].type=="text")|| +(TForm.elements[i].type=="textarea")|| +(TForm.elements[i].type.toString().charAt(0)=="s")) +{document.forms[0].elements[i].focus();break;}}}} + +// JavaScript Virtual Keyboard +// If you like this code then buy me a sandwich. +// Noah Spurrier <noah@noah.org> +var flag_shift=0; +var flag_shiftlock=0; +var flag_ctrl=0; +var ButtonOnColor="#ee0"; + +function init () +{ + // hack to set quote key to show both single quote and double quote + document.form['quote'].value = "'" + ' "'; + //refresh_screen(); + poll(); + document.form["cli"].focus(); +} +function get_password () +{ + var username = prompt("username?",""); + var password = prompt("password?",""); + start_server (username, password); +} +function multibrowser_ajax () +{ + var xmlHttp = false; +/*@cc_on @*/ +/*@if (@_jscript_version >= 5) + try + { + xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); + } + catch (e) + { + try + { + xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); + } + catch (e2) + { + xmlHttp = false; + } + } +@end @*/ + + if (!xmlHttp && typeof XMLHttpRequest != 'undefined') + { + xmlHttp = new XMLHttpRequest(); + } + return xmlHttp; +} +function load_url_to_screen(url) +{ + xmlhttp = multibrowser_ajax(); + //window.XMLHttpRequest?new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP"); + xmlhttp.onreadystatechange = update_virtual_screen; + xmlhttp.open("GET", url); + xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"); + xmlhttp.send(null); +} +function update_virtual_screen() +{ + if ((xmlhttp.readyState == 4) && (xmlhttp.status == 200)) + { + var screen_text = xmlhttp.responseText; + document.form["screen_text"].value = screen_text; + //var json_data = json_parse(xmlhttp.responseText); + } +} +function poll() +{ + refresh_screen(); + timerID = setTimeout("poll()", 2000); + // clearTimeout(timerID); +} +//function start_server (username, password) +//{ +// load_url_to_screen('cgishell.cgi?ajax=serverstart&username=' + escape(username) + '&password=' + escape(password); +//} +function refresh_screen() +{ + load_url_to_screen('cgishell.cgi?ajax=refresh&sid=%(SID)s'); +} +function query_hash() +{ + load_url_to_screen('cgishell.cgi?ajax=hash&sid=%(SID)s'); +} +function query_cursor() +{ + load_url_to_screen('cgishell.cgi?ajax=cursor&sid=%(SID)s'); +} +function exit_server() +{ + load_url_to_screen('cgishell.cgi?ajax=exit&sid=%(SID)s'); +} +function type_key (chars) +{ + var ch = '?'; + if (flag_shiftlock || flag_shift) + { + ch = chars.substr(1,1); + } + else if (flag_ctrl) + { + ch = chars.substr(2,1); + } + else + { + ch = chars.substr(0,1); + } + load_url_to_screen('cgishell.cgi?ajax=send&sid=%(SID)s&arg=' + escape(ch)); + if (flag_shift || flag_ctrl) + { + flag_shift = 0; + flag_ctrl = 0; + } + update_button_colors(); +} + +function key_shiftlock() +{ + flag_ctrl = 0; + flag_shift = 0; + if (flag_shiftlock) + { + flag_shiftlock = 0; + } + else + { + flag_shiftlock = 1; + } + update_button_colors(); +} + +function key_shift() +{ + if (flag_shift) + { + flag_shift = 0; + } + else + { + flag_ctrl = 0; + flag_shiftlock = 0; + flag_shift = 1; + } + update_button_colors(); +} +function key_ctrl () +{ + if (flag_ctrl) + { + flag_ctrl = 0; + } + else + { + flag_ctrl = 1; + flag_shiftlock = 0; + flag_shift = 0; + } + + update_button_colors(); +} +function update_button_colors () +{ + if (flag_ctrl) + { + document.form['Ctrl'].style.backgroundColor = ButtonOnColor; + document.form['Ctrl2'].style.backgroundColor = ButtonOnColor; + } + else + { + document.form['Ctrl'].style.backgroundColor = document.form.style.backgroundColor; + document.form['Ctrl2'].style.backgroundColor = document.form.style.backgroundColor; + } + if (flag_shift) + { + document.form['Shift'].style.backgroundColor = ButtonOnColor; + document.form['Shift2'].style.backgroundColor = ButtonOnColor; + } + else + { + document.form['Shift'].style.backgroundColor = document.form.style.backgroundColor; + document.form['Shift2'].style.backgroundColor = document.form.style.backgroundColor; + } + if (flag_shiftlock) + { + document.form['ShiftLock'].style.backgroundColor = ButtonOnColor; + } + else + { + document.form['ShiftLock'].style.backgroundColor = document.form.style.backgroundColor; + } + +} +function keyHandler(e) +{ + var pressedKey; + if (document.all) { e = window.event; } + if (document.layers) { pressedKey = e.which; } + if (document.all) { pressedKey = e.keyCode; } + pressedCharacter = String.fromCharCode(pressedKey); + type_key(pressedCharacter+pressedCharacter+pressedCharacter); + alert(pressedCharacter); +// alert(' Character = ' + pressedCharacter + ' [Decimal value = ' + pressedKey + ']'); +} +//document.onkeypress = keyHandler; +//if (document.layers) +// document.captureEvents(Event.KEYPRESS); +//http://sniptools.com/jskeys +//document.onkeyup = KeyCheck; +function KeyCheck(e) +{ + var KeyID = (window.event) ? event.keyCode : e.keyCode; + type_key(String.fromCharCode(KeyID)); + e.cancelBubble = true; + window.event.cancelBubble = true; +} +</script> + +</head> + +<body onload="init()"> +<form id="form" name="form" action="/cgi-bin/cgishell.cgi" method="POST"> +<input name="sid" value="%(SID)s" type="hidden"> +<textarea name="screen_text" cols="81" rows="25">%(SHELL_OUTPUT)s</textarea> +<hr noshade="1"> + <input name="cli" id="cli" type="text" size="80"><br> +<table border="0" align="left"> +<tr> +<td width="86%%" align="center"> + <input name="submit" type="submit" value="Submit"> + <input name="refresh" type="button" value="REFRESH" onclick="refresh_screen()"> + <input name="refresh" type="button" value="CURSOR" onclick="query_cursor()"> + <input name="hash" type="button" value="HASH" onclick="query_hash()"> + <input name="exit" type="button" value="EXIT" onclick="exit_server()"> + <br> + <input type="button" value="Esc" onclick="type_key('\\x1b\\x1b')" /> + <input type="button" value="` ~" onclick="type_key('`~')" /> + <input type="button" value="1!" onclick="type_key('1!')" /> + <input type="button" value="2@" onclick="type_key('2@\\x00')" /> + <input type="button" value="3#" onclick="type_key('3#')" /> + <input type="button" value="4$" onclick="type_key('4$')" /> + <input type="button" value="5%%" onclick="type_key('5%%')" /> + <input type="button" value="6^" onclick="type_key('6^\\x1E')" /> + <input type="button" value="7&" onclick="type_key('7&')" /> + <input type="button" value="8*" onclick="type_key('8*')" /> + <input type="button" value="9(" onclick="type_key('9(')" /> + <input type="button" value="0)" onclick="type_key('0)')" /> + <input type="button" value="-_" onclick="type_key('-_\\x1F')" /> + <input type="button" value="=+" onclick="type_key('=+')" /> + <input type="button" value="BkSp" onclick="type_key('\\x08\\x08\\x08')" /> + <br> + <input type="button" value="Tab" onclick="type_key('\\t\\t')" /> + <input type="button" value="Q" onclick="type_key('qQ\\x11')" /> + <input type="button" value="W" onclick="type_key('wW\\x17')" /> + <input type="button" value="E" onclick="type_key('eE\\x05')" /> + <input type="button" value="R" onclick="type_key('rR\\x12')" /> + <input type="button" value="T" onclick="type_key('tT\\x14')" /> + <input type="button" value="Y" onclick="type_key('yY\\x19')" /> + <input type="button" value="U" onclick="type_key('uU\\x15')" /> + <input type="button" value="I" onclick="type_key('iI\\x09')" /> + <input type="button" value="O" onclick="type_key('oO\\x0F')" /> + <input type="button" value="P" onclick="type_key('pP\\x10')" /> + <input type="button" value="[ {" onclick="type_key('[{\\x1b')" /> + <input type="button" value="] }" onclick="type_key(']}\\x1d')" /> + <input type="button" value="\\ |" onclick="type_key('\\\\|\\x1c')" /> + <br> + <input type="button" id="Ctrl" value="Ctrl" onclick="key_ctrl()" /> + <input type="button" value="A" onclick="type_key('aA\\x01')" /> + <input type="button" value="S" onclick="type_key('sS\\x13')" /> + <input type="button" value="D" onclick="type_key('dD\\x04')" /> + <input type="button" value="F" onclick="type_key('fF\\x06')" /> + <input type="button" value="G" onclick="type_key('gG\\x07')" /> + <input type="button" value="H" onclick="type_key('hH\\x08')" /> + <input type="button" value="J" onclick="type_key('jJ\\x0A')" /> + <input type="button" value="K" onclick="type_key('kK\\x0B')" /> + <input type="button" value="L" onclick="type_key('lL\\x0C')" /> + <input type="button" value="; :" onclick="type_key(';:')" /> + <input type="button" id="quote" value="'" onclick="type_key('\\x27\\x22')" /> + <input type="button" value="Enter" onclick="type_key('\\n\\n')" /> + <br> + <input type="button" id="ShiftLock" value="Caps Lock" onclick="key_shiftlock()" /> + <input type="button" id="Shift" value="Shift" onclick="key_shift()" /> + <input type="button" value="Z" onclick="type_key('zZ\\x1A')" /> + <input type="button" value="X" onclick="type_key('xX\\x18')" /> + <input type="button" value="C" onclick="type_key('cC\\x03')" /> + <input type="button" value="V" onclick="type_key('vV\\x16')" /> + <input type="button" value="B" onclick="type_key('bB\\x02')" /> + <input type="button" value="N" onclick="type_key('nN\\x0E')" /> + <input type="button" value="M" onclick="type_key('mM\\x0D')" /> + <input type="button" value=", <" onclick="type_key(',<')" /> + <input type="button" value=". >" onclick="type_key('.>')" /> + <input type="button" value="/ ?" onclick="type_key('/?')" /> + <input type="button" id="Shift2" value="Shift" onclick="key_shift()" /> + <input type="button" id="Ctrl2" value="Ctrl" onclick="key_ctrl()" /> + <br> + <input type="button" value=" FINAL FRONTIER " onclick="type_key(' ')" /> +</td> +</tr> +</table> +</form> +</body> +</html> +""" + +LOGIN_HTML="""<html> +<head> +<title>Shell Login</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<style type=text/css> +a {color: #9f9; text-decoration: none} +a:hover {color: #0f0} +hr {color: #0f0} +html,body,textarea,input,form +{ +font-family: "Courier New", Courier, mono; +font-size: 8pt; +color: #0c0; +background-color: #020; +margin:3; +padding:0; +border:0; +} +input { background-color: #010; } +input,textarea { +border-width:1; +border-style:solid; +border-color:#0c0; +padding:3; +margin:3; +} +</style> +<script language="JavaScript"> +function init () +{ + document.login_form["username"].focus(); +} +</script> +</head> +<body onload="init()"> +<form name="login_form" method="POST"> +<input name="start_server" value="1" type="hidden"> +<input name="sid" value="%(SID)s" type="hidden"> +username: <input name="username" type="text" size="30"><br> +password: <input name="password" type="password" size="30"><br> +<input name="submit" type="submit" value="enter"> +</form> +<br> +</body> +</html> +""" + +if __name__ == "__main__": + try: + main() + except Exception as e: + print(str(e)) + tb_dump = traceback.format_exc() + print(str(tb_dump)) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/chess.py b/lldb/third_party/Python/module/pexpect-4.6/examples/chess.py new file mode 100755 index 00000000000..f97a3a9ef26 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/chess.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python + +'''This demonstrates controlling a screen oriented application (curses). +It starts two instances of gnuchess and then pits them against each other. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import pexpect +import ANSI + +REGEX_MOVE = r'(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)' +REGEX_MOVE_PART = r'(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)' + +class Chess: + + def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"): + self.child = pexpect.spawn (engine) + self.term = ANSI.ANSI () + + self.child.expect ('Chess') + if self.child.after != 'Chess': + raise IOError('incompatible chess program') + self.term.process_list (self.before) + self.term.process_list (self.after) + self.last_computer_move = '' + + def read_until_cursor (self, r,c): + while 1: + self.child.read(1, 60) + self.term.process (c) + if self.term.cur_r == r and self.term.cur_c == c: + return 1 + + def do_first_move (self, move): + self.child.expect ('Your move is') + self.child.sendline (move) + self.term.process_list (self.before) + self.term.process_list (self.after) + return move + + def do_move (self, move): + self.read_until_cursor (19,60) + self.child.sendline (move) + return move + + def get_first_computer_move (self): + self.child.expect ('My move is') + self.child.expect (REGEX_MOVE) + return self.child.after + + def get_computer_move (self): + print('Here') + i = self.child.expect ([r'\[17;59H', r'\[17;58H']) + print(i) + if i == 0: + self.child.expect (REGEX_MOVE) + if len(self.child.after) < 4: + self.child.after = self.child.after + self.last_computer_move[3] + if i == 1: + self.child.expect (REGEX_MOVE_PART) + self.child.after = self.last_computer_move[0] + self.child.after + print('', self.child.after) + self.last_computer_move = self.child.after + return self.child.after + + def switch (self): + self.child.sendline ('switch') + + def set_depth (self, depth): + self.child.sendline ('depth') + self.child.expect ('depth=') + self.child.sendline ('%d' % depth) + + def quit(self): + self.child.sendline ('quit') +import sys +print('Starting...') +white = Chess() +white.child.echo = 1 +white.child.expect ('Your move is') +white.set_depth(2) +white.switch() + +move_white = white.get_first_computer_move() +print('first move white:', move_white) + +white.do_move ('e7e5') +move_white = white.get_computer_move() +print('move white:', move_white) +white.do_move ('f8c5') +move_white = white.get_computer_move() +print('move white:', move_white) +white.do_move ('b8a6') +move_white = white.get_computer_move() +print('move white:', move_white) + +sys.exit(1) + + + +black = Chess() +white = Chess() +white.child.expect ('Your move is') +white.switch() + +move_white = white.get_first_computer_move() +print('first move white:', move_white) + +black.do_first_move (move_white) +move_black = black.get_first_computer_move() +print('first move black:', move_black) + +white.do_move (move_black) + +done = 0 +while not done: + move_white = white.get_computer_move() + print('move white:', move_white) + + black.do_move (move_white) + move_black = black.get_computer_move() + print('move black:', move_black) + + white.do_move (move_black) + print('tail of loop') + +g.quit() diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/chess2.py b/lldb/third_party/Python/module/pexpect-4.6/examples/chess2.py new file mode 100755 index 00000000000..b92509e776f --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/chess2.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python + +'''This demonstrates controlling a screen oriented application (curses). +It starts two instances of gnuchess and then pits them against each other. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import pexpect +import ANSI +import sys +import time + +class Chess: + + def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"): + self.child = pexpect.spawn (engine) + self.term = ANSI.ANSI () + + #self.child.expect ('Chess') + #if self.child.after != 'Chess': + # raise IOError, 'incompatible chess program' + #self.term.process_list (self.child.before) + #self.term.process_list (self.child.after) + + self.last_computer_move = '' + + def read_until_cursor (self, r,c, e=0): + '''Eventually something like this should move into the screen class or + a subclass. Maybe a combination of pexpect and screen... + ''' + fout = open ('log','a') + while self.term.cur_r != r or self.term.cur_c != c: + try: + k = self.child.read(1, 10) + except Exception as e: + print('EXCEPTION, (r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c)) + sys.stdout.flush() + self.term.process (k) + fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c)) + fout.flush() + if e: + sys.stdout.write (k) + sys.stdout.flush() + if self.term.cur_r == r and self.term.cur_c == c: + fout.close() + return 1 + print('DIDNT EVEN HIT.') + fout.close() + return 1 + + def expect_region (self): + '''This is another method that would be moved into the + screen class. + ''' + pass + def do_scan (self): + fout = open ('log','a') + while 1: + c = self.child.read(1,10) + self.term.process (c) + fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c)) + fout.flush() + sys.stdout.write (c) + sys.stdout.flush() + + def do_move (self, move, e = 0): + time.sleep(1) + self.read_until_cursor (19,60, e) + self.child.sendline (move) + + def wait (self, color): + while 1: + r = self.term.get_region (14,50,14,60)[0] + r = r.strip() + if r == color: + return + time.sleep (1) + + def parse_computer_move (self, s): + i = s.find ('is: ') + cm = s[i+3:i+9] + return cm + def get_computer_move (self, e = 0): + time.sleep(1) + self.read_until_cursor (19,60, e) + time.sleep(1) + r = self.term.get_region (17,50,17,62)[0] + cm = self.parse_computer_move (r) + return cm + + def switch (self): + print('switching') + self.child.sendline ('switch') + + def set_depth (self, depth): + self.child.sendline ('depth') + self.child.expect ('depth=') + self.child.sendline ('%d' % depth) + + def quit(self): + self.child.sendline ('quit') + +def LOG (s): + print(s) + sys.stdout.flush () + fout = open ('moves.log', 'a') + fout.write (s + '\n') + fout.close() + +print('Starting...') + +black = Chess() +white = Chess() +white.read_until_cursor (19,60,1) +white.switch() + +done = 0 +while not done: + white.wait ('Black') + move_white = white.get_computer_move(1) + LOG ( 'move white:'+ move_white ) + + black.do_move (move_white) + black.wait ('White') + move_black = black.get_computer_move() + LOG ( 'move black:'+ move_black ) + + white.do_move (move_black, 1) + +g.quit() + + diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/chess3.py b/lldb/third_party/Python/module/pexpect-4.6/examples/chess3.py new file mode 100755 index 00000000000..2c087b039d9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/chess3.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + +'''This demonstrates controlling a screen oriented application (curses). +It starts two instances of gnuchess and then pits them against each other. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import pexpect +import ANSI + +REGEX_MOVE = r'(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)' +REGEX_MOVE_PART = r'(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)' + +class Chess: + + def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"): + self.child = pexpect.spawn (engine) + self.term = ANSI.ANSI () + +# self.child.expect ('Chess') + # if self.child.after != 'Chess': + # raise IOError, 'incompatible chess program' + # self.term.process_list (self.before) + # self.term.process_list (self.after) + self.last_computer_move = '' + def read_until_cursor (self, r,c): + fout = open ('log','a') + while 1: + k = self.child.read(1, 10) + self.term.process (k) + fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c)) + fout.flush() + if self.term.cur_r == r and self.term.cur_c == c: + fout.close() + return 1 + sys.stdout.write (k) + sys.stdout.flush() + + def do_scan (self): + fout = open ('log','a') + while 1: + c = self.child.read(1,10) + self.term.process (c) + fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c)) + fout.flush() + sys.stdout.write (c) + sys.stdout.flush() + + def do_move (self, move): + self.read_until_cursor (19,60) + self.child.sendline (move) + return move + + def get_computer_move (self): + print('Here') + i = self.child.expect ([r'\[17;59H', r'\[17;58H']) + print(i) + if i == 0: + self.child.expect (REGEX_MOVE) + if len(self.child.after) < 4: + self.child.after = self.child.after + self.last_computer_move[3] + if i == 1: + self.child.expect (REGEX_MOVE_PART) + self.child.after = self.last_computer_move[0] + self.child.after + print('', self.child.after) + self.last_computer_move = self.child.after + return self.child.after + + def switch (self): + self.child.sendline ('switch') + + def set_depth (self, depth): + self.child.sendline ('depth') + self.child.expect ('depth=') + self.child.sendline ('%d' % depth) + + def quit(self): + self.child.sendline ('quit') +import sys +print('Starting...') +white = Chess() +white.do_move('b2b4') +white.read_until_cursor (19,60) +c1 = white.term.get_abs(17,58) +c2 = white.term.get_abs(17,59) +c3 = white.term.get_abs(17,60) +c4 = white.term.get_abs(17,61) +fout = open ('log','a') +fout.write ('Computer:%s%s%s%s\n' %(c1,c2,c3,c4)) +fout.close() +white.do_move('c2c4') +white.read_until_cursor (19,60) +c1 = white.term.get_abs(17,58) +c2 = white.term.get_abs(17,59) +c3 = white.term.get_abs(17,60) +c4 = white.term.get_abs(17,61) +fout = open ('log','a') +fout.write ('Computer:%s%s%s%s\n' %(c1,c2,c3,c4)) +fout.close() +white.do_scan () + +#white.do_move ('b8a6') +#move_white = white.get_computer_move() +#print 'move white:', move_white + +sys.exit(1) + + + +black = Chess() +white = Chess() +white.child.expect ('Your move is') +white.switch() + +move_white = white.get_first_computer_move() +print('first move white:', move_white) + +black.do_first_move (move_white) +move_black = black.get_first_computer_move() +print('first move black:', move_black) + +white.do_move (move_black) + +done = 0 +while not done: + move_white = white.get_computer_move() + print('move white:', move_white) + + black.do_move (move_white) + move_black = black.get_computer_move() + print('move black:', move_black) + + white.do_move (move_black) + print('tail of loop') + +g.quit() diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/df.py b/lldb/third_party/Python/module/pexpect-4.6/examples/df.py new file mode 100755 index 00000000000..f8e3fc3989b --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/df.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +'''This collects filesystem capacity info using the 'df' command. Tuples of +filesystem name and percentage are stored in a list. A simple report is +printed. Filesystems over 95% capacity are highlighted. Note that this does not +parse filesystem names after the first space, so names with spaces in them will +be truncated. This will produce ambiguous results for automount filesystems on +Apple OSX. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import pexpect + +child = pexpect.spawn ('df') + +# parse 'df' output into a list. +pattern = r"\n(\S+).*?([0-9]+)%" +filesystem_list = [] +for dummy in range (0, 1000): + i = child.expect ([pattern, pexpect.EOF]) + if i == 0: + filesystem_list.append (child.match.groups()) + else: + break + +# Print report +print() +for m in filesystem_list: + s = "Filesystem %s is at %s%%" % (m[0], m[1]) + # highlight filesystems over 95% capacity + if int(m[1]) > 95: + s = '! ' + s + else: + s = ' ' + s + print(s) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/ftp.py b/lldb/third_party/Python/module/pexpect-4.6/examples/ftp.py new file mode 100755 index 00000000000..a1c1343a7de --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/ftp.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +'''This demonstrates an FTP "bookmark". This connects to an ftp site; does a +few ftp stuff; and then gives the user interactive control over the session. In +this case the "bookmark" is to a directory on the OpenBSD ftp server. It puts +you in the i386 packages directory. You can easily modify this for other sites. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import pexpect +import sys + +# Note that, for Python 3 compatibility reasons, we are using spawnu and +# importing unicode_literals (above). spawnu accepts Unicode input and +# unicode_literals makes all string literals in this script Unicode by default. +child = pexpect.spawnu('ftp ftp.openbsd.org') + +child.expect('(?i)name .*: ') +child.sendline('anonymous') +child.expect('(?i)password') +child.sendline('pexpect@sourceforge.net') +child.expect('ftp> ') +child.sendline('cd /pub/OpenBSD/3.7/packages/i386') +child.expect('ftp> ') +child.sendline('bin') +child.expect('ftp> ') +child.sendline('prompt') +child.expect('ftp> ') +child.sendline('pwd') +child.expect('ftp> ') +print("Escape character is '^]'.\n") +sys.stdout.write (child.after) +sys.stdout.flush() +child.interact() # Escape character defaults to ^] +# At this point this script blocks until the user presses the escape character +# or until the child exits. The human user and the child should be talking +# to each other now. + +# At this point the script is running again. +print('Left interactve mode.') + +# The rest is not strictly necessary. This just demonstrates a few functions. +# This makes sure the child is dead; although it would be killed when Python exits. +if child.isalive(): + child.sendline('bye') # Try to ask ftp child to exit. + child.close() +# Print the final state of the child. Normally isalive() should be FALSE. +if child.isalive(): + print('Child did not exit gracefully.') +else: + print('Child exited gracefully.') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/hive.py b/lldb/third_party/Python/module/pexpect-4.6/examples/hive.py new file mode 100755 index 00000000000..1b7bcbf2416 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/hive.py @@ -0,0 +1,466 @@ +#!/usr/bin/env python + +'''hive -- Hive Shell + +This lets you ssh to a group of servers and control them as if they were one. +Each command you enter is sent to each host in parallel. The response of each +host is collected and printed. In normal synchronous mode Hive will wait for +each host to return the shell command line prompt. The shell prompt is used to +sync output. + +Example: + + $ hive.py --sameuser --samepass host1.example.com host2.example.net + username: myusername + password: + connecting to host1.example.com - OK + connecting to host2.example.net - OK + targeting hosts: 192.168.1.104 192.168.1.107 + CMD (? for help) > uptime + ======================================================================= + host1.example.com + ----------------------------------------------------------------------- + uptime + 23:49:55 up 74 days, 5:14, 2 users, load average: 0.15, 0.05, 0.01 + ======================================================================= + host2.example.net + ----------------------------------------------------------------------- + uptime + 23:53:02 up 1 day, 13:36, 2 users, load average: 0.50, 0.40, 0.46 + ======================================================================= + +Other Usage Examples: + +1. You will be asked for your username and password for each host. + + hive.py host1 host2 host3 ... hostN + +2. You will be asked once for your username and password. + This will be used for each host. + + hive.py --sameuser --samepass host1 host2 host3 ... hostN + +3. Give a username and password on the command-line: + + hive.py user1:pass2@host1 user2:pass2@host2 ... userN:passN@hostN + +You can use an extended host notation to specify username, password, and host +instead of entering auth information interactively. Where you would enter a +host name use this format: + + username:password@host + +This assumes that ':' is not part of the password. If your password contains a +':' then you can use '\\:' to indicate a ':' and '\\\\' to indicate a single +'\\'. Remember that this information will appear in the process listing. Anyone +on your machine can see this auth information. This is not secure. + +This is a crude script that begs to be multithreaded. But it serves its +purpose. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +# TODO add feature to support username:password@host combination +# TODO add feature to log each host output in separate file + +import sys +import os +import re +import optparse +import time +import getpass +import readline +import atexit +try: + import pexpect + import pxssh +except ImportError: + sys.stderr.write("You do not have 'pexpect' installed.\n") + sys.stderr.write("On Ubuntu you need the 'python-pexpect' package.\n") + sys.stderr.write(" aptitude -y install python-pexpect\n") + exit(1) + + +try: + raw_input +except NameError: + raw_input = input + + +histfile = os.path.join(os.environ["HOME"], ".hive_history") +try: + readline.read_history_file(histfile) +except IOError: + pass +atexit.register(readline.write_history_file, histfile) + +CMD_HELP='''Hive commands are preceded by a colon : (just think of vi). + +:target name1 name2 name3 ... + + set list of hosts to target commands + +:target all + + reset list of hosts to target all hosts in the hive. + +:to name command + + send a command line to the named host. This is similar to :target, but + sends only one command and does not change the list of targets for future + commands. + +:sync + + set mode to wait for shell prompts after commands are run. This is the + default. When Hive first logs into a host it sets a special shell prompt + pattern that it can later look for to synchronize output of the hosts. If + you 'su' to another user then it can upset the synchronization. If you need + to run something like 'su' then use the following pattern: + + CMD (? for help) > :async + CMD (? for help) > sudo su - root + CMD (? for help) > :prompt + CMD (? for help) > :sync + +:async + + set mode to not expect command line prompts (see :sync). Afterwards + commands are send to target hosts, but their responses are not read back + until :sync is run. This is useful to run before commands that will not + return with the special shell prompt pattern that Hive uses to synchronize. + +:refresh + + refresh the display. This shows the last few lines of output from all hosts. + This is similar to resync, but does not expect the promt. This is useful + for seeing what hosts are doing during long running commands. + +:resync + + This is similar to :sync, but it does not change the mode. It looks for the + prompt and thus consumes all input from all targeted hosts. + +:prompt + + force each host to reset command line prompt to the special pattern used to + synchronize all the hosts. This is useful if you 'su' to a different user + where Hive would not know the prompt to match. + +:send my text + + This will send the 'my text' wihtout a line feed to the targeted hosts. + This output of the hosts is not automatically synchronized. + +:control X + + This will send the given control character to the targeted hosts. + For example, ":control c" will send ASCII 3. + +:exit + + This will exit the hive shell. + +''' + +def login (args, cli_username=None, cli_password=None): + + # I have to keep a separate list of host names because Python dicts are not ordered. + # I want to keep the same order as in the args list. + host_names = [] + hive_connect_info = {} + hive = {} + # build up the list of connection information (hostname, username, password, port) + for host_connect_string in args: + hcd = parse_host_connect_string (host_connect_string) + hostname = hcd['hostname'] + port = hcd['port'] + if port == '': + port = None + if len(hcd['username']) > 0: + username = hcd['username'] + elif cli_username is not None: + username = cli_username + else: + username = raw_input('%s username: ' % hostname) + if len(hcd['password']) > 0: + password = hcd['password'] + elif cli_password is not None: + password = cli_password + else: + password = getpass.getpass('%s password: ' % hostname) + host_names.append(hostname) + hive_connect_info[hostname] = (hostname, username, password, port) + # build up the list of hive connections using the connection information. + for hostname in host_names: + print('connecting to', hostname) + try: + fout = file("log_"+hostname, "w") + hive[hostname] = pxssh.pxssh() + # Disable host key checking. + hive[hostname].SSH_OPTS = (hive[hostname].SSH_OPTS + + " -o 'StrictHostKeyChecking=no'" + + " -o 'UserKnownHostsFile /dev/null' ") + hive[hostname].force_password = True + hive[hostname].login(*hive_connect_info[hostname]) + print(hive[hostname].before) + hive[hostname].logfile = fout + print('- OK') + except Exception as e: + print('- ERROR', end=' ') + print(str(e)) + print('Skipping', hostname) + hive[hostname] = None + return host_names, hive + +def main (): + + global options, args, CMD_HELP + + rows = 24 + cols = 80 + + if options.sameuser: + cli_username = raw_input('username: ') + else: + cli_username = None + + if options.samepass: + cli_password = getpass.getpass('password: ') + else: + cli_password = None + + host_names, hive = login(args, cli_username, cli_password) + + synchronous_mode = True + target_hostnames = host_names[:] + print('targeting hosts:', ' '.join(target_hostnames)) + while True: + cmd = raw_input('CMD (? for help) > ') + cmd = cmd.strip() + if cmd=='?' or cmd==':help' or cmd==':h': + print(CMD_HELP) + continue + elif cmd==':refresh': + refresh (hive, target_hostnames, timeout=0.5) + for hostname in target_hostnames: + print('/' + '=' * (cols - 2)) + print('| ' + hostname) + print('\\' + '-' * (cols - 2)) + if hive[hostname] is None: + print('# DEAD: %s' % hostname) + else: + print(hive[hostname].before) + print('#' * 79) + continue + elif cmd==':resync': + resync (hive, target_hostnames, timeout=0.5) + for hostname in target_hostnames: + print('/' + '=' * (cols - 2)) + print('| ' + hostname) + print('\\' + '-' * (cols - 2)) + if hive[hostname] is None: + print('# DEAD: %s' % hostname) + else: + print(hive[hostname].before) + print('#' * 79) + continue + elif cmd==':sync': + synchronous_mode = True + resync (hive, target_hostnames, timeout=0.5) + continue + elif cmd==':async': + synchronous_mode = False + continue + elif cmd==':prompt': + for hostname in target_hostnames: + try: + if hive[hostname] is not None: + hive[hostname].set_unique_prompt() + except Exception as e: + print("Had trouble communicating with %s, so removing it from the target list." % hostname) + print(str(e)) + hive[hostname] = None + continue + elif cmd[:5] == ':send': + cmd, txt = cmd.split(None,1) + for hostname in target_hostnames: + try: + if hive[hostname] is not None: + hive[hostname].send(txt) + except Exception as e: + print("Had trouble communicating with %s, so removing it from the target list." % hostname) + print(str(e)) + hive[hostname] = None + continue + elif cmd[:3] == ':to': + cmd, hostname, txt = cmd.split(None,2) + print('/' + '=' * (cols - 2)) + print('| ' + hostname) + print('\\' + '-' * (cols - 2)) + if hive[hostname] is None: + print('# DEAD: %s' % hostname) + continue + try: + hive[hostname].sendline (txt) + hive[hostname].prompt(timeout=2) + print(hive[hostname].before) + except Exception as e: + print("Had trouble communicating with %s, so removing it from the target list." % hostname) + print(str(e)) + hive[hostname] = None + continue + elif cmd[:7] == ':expect': + cmd, pattern = cmd.split(None,1) + print('looking for', pattern) + try: + for hostname in target_hostnames: + if hive[hostname] is not None: + hive[hostname].expect(pattern) + print(hive[hostname].before) + except Exception as e: + print("Had trouble communicating with %s, so removing it from the target list." % hostname) + print(str(e)) + hive[hostname] = None + continue + elif cmd[:7] == ':target': + target_hostnames = cmd.split()[1:] + if len(target_hostnames) == 0 or target_hostnames[0] == all: + target_hostnames = host_names[:] + print('targeting hosts:', ' '.join(target_hostnames)) + continue + elif cmd == ':exit' or cmd == ':q' or cmd == ':quit': + break + elif cmd[:8] == ':control' or cmd[:5] == ':ctrl' : + cmd, c = cmd.split(None,1) + if ord(c)-96 < 0 or ord(c)-96 > 255: + print('/' + '=' * (cols - 2)) + print('| Invalid character. Must be [a-zA-Z], @, [, ], \\, ^, _, or ?') + print('\\' + '-' * (cols - 2)) + continue + for hostname in target_hostnames: + try: + if hive[hostname] is not None: + hive[hostname].sendcontrol(c) + except Exception as e: + print("Had trouble communicating with %s, so removing it from the target list." % hostname) + print(str(e)) + hive[hostname] = None + continue + elif cmd == ':esc': + for hostname in target_hostnames: + if hive[hostname] is not None: + hive[hostname].send(chr(27)) + continue + # + # Run the command on all targets in parallel + # + for hostname in target_hostnames: + try: + if hive[hostname] is not None: + hive[hostname].sendline (cmd) + except Exception as e: + print("Had trouble communicating with %s, so removing it from the target list." % hostname) + print(str(e)) + hive[hostname] = None + + # + # print the response for each targeted host. + # + if synchronous_mode: + for hostname in target_hostnames: + try: + print('/' + '=' * (cols - 2)) + print('| ' + hostname) + print('\\' + '-' * (cols - 2)) + if hive[hostname] is None: + print('# DEAD: %s' % hostname) + else: + hive[hostname].prompt(timeout=2) + print(hive[hostname].before) + except Exception as e: + print("Had trouble communicating with %s, so removing it from the target list." % hostname) + print(str(e)) + hive[hostname] = None + print('#' * 79) + +def refresh (hive, hive_names, timeout=0.5): + + '''This waits for the TIMEOUT on each host. + ''' + + # TODO This is ideal for threading. + for hostname in hive_names: + if hive[hostname] is not None: + hive[hostname].expect([pexpect.TIMEOUT,pexpect.EOF],timeout=timeout) + +def resync (hive, hive_names, timeout=2, max_attempts=5): + + '''This waits for the shell prompt for each host in an effort to try to get + them all to the same state. The timeout is set low so that hosts that are + already at the prompt will not slow things down too much. If a prompt match + is made for a hosts then keep asking until it stops matching. This is a + best effort to consume all input if it printed more than one prompt. It's + kind of kludgy. Note that this will always introduce a delay equal to the + timeout for each machine. So for 10 machines with a 2 second delay you will + get AT LEAST a 20 second delay if not more. ''' + + # TODO This is ideal for threading. + for hostname in hive_names: + if hive[hostname] is not None: + for attempts in range(0, max_attempts): + if not hive[hostname].prompt(timeout=timeout): + break + +def parse_host_connect_string (hcs): + + '''This parses a host connection string in the form + username:password@hostname:port. All fields are options expcet hostname. A + dictionary is returned with all four keys. Keys that were not included are + set to empty strings ''. Note that if your password has the '@' character + then you must backslash escape it. ''' + + if '@' in hcs: + p = re.compile (r'(?P<username>[^@:]*)(:?)(?P<password>.*)(?!\\)@(?P<hostname>[^:]*):?(?P<port>[0-9]*)') + else: + p = re.compile (r'(?P<username>)(?P<password>)(?P<hostname>[^:]*):?(?P<port>[0-9]*)') + m = p.search (hcs) + d = m.groupdict() + d['password'] = d['password'].replace('\\@','@') + return d + +if __name__ == '__main__': + start_time = time.time() + parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter(), usage=globals()['__doc__'], version='$Id: hive.py 533 2012-10-20 02:19:33Z noah $',conflict_handler="resolve") + parser.add_option ('-v', '--verbose', action='store_true', default=False, help='verbose output') + parser.add_option ('--samepass', action='store_true', default=False, help='Use same password for each login.') + parser.add_option ('--sameuser', action='store_true', default=False, help='Use same username for each login.') + (options, args) = parser.parse_args() + if len(args) < 1: + parser.error ('missing argument') + if options.verbose: print(time.asctime()) + main() + if options.verbose: print(time.asctime()) + if options.verbose: print('TOTAL TIME IN MINUTES:', end=' ') + if options.verbose: print((time.time() - start_time) / 60.0) diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/monitor.py b/lldb/third_party/Python/module/pexpect-4.6/examples/monitor.py new file mode 100755 index 00000000000..c030d3a493d --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/monitor.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python + +''' This runs a sequence of commands on a remote host using SSH. It runs a +simple system checks such as uptime and free to monitor the state of the remote +host. + +./monitor.py [-s server_hostname] [-u username] [-p password] + -s : hostname of the remote server to login to. + -u : username to user for login. + -p : Password to user for login. + +Example: + This will print information about the given host: + ./monitor.py -s www.example.com -u mylogin -p mypassword + +It works like this: + Login via SSH (This is the hardest part). + Run and parse 'uptime'. + Run 'iostat'. + Run 'vmstat'. + Run 'netstat' + Run 'free'. + Exit the remote host. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import os, sys, re, getopt, getpass +import pexpect + + +try: + raw_input +except NameError: + raw_input = input + + +# +# Some constants. +# +COMMAND_PROMPT = '[#$] ' ### This is way too simple for industrial use -- we will change is ASAP. +TERMINAL_PROMPT = r'(?i)terminal type\?' +TERMINAL_TYPE = 'vt100' +# This is the prompt we get if SSH does not have the remote host's public key stored in the cache. +SSH_NEWKEY = '(?i)are you sure you want to continue connecting' + +def exit_with_usage(): + + print(globals()['__doc__']) + os._exit(1) + +def main(): + + global COMMAND_PROMPT, TERMINAL_PROMPT, TERMINAL_TYPE, SSH_NEWKEY + ###################################################################### + ## Parse the options, arguments, get ready, etc. + ###################################################################### + try: + optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?']) + except Exception as e: + print(str(e)) + exit_with_usage() + options = dict(optlist) + if len(args) > 1: + exit_with_usage() + + if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]: + print("Help:") + exit_with_usage() + + if '-s' in options: + host = options['-s'] + else: + host = raw_input('hostname: ') + if '-u' in options: + user = options['-u'] + else: + user = raw_input('username: ') + if '-p' in options: + password = options['-p'] + else: + password = getpass.getpass('password: ') + + # + # Login via SSH + # + child = pexpect.spawn('ssh -l %s %s'%(user, host)) + i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, COMMAND_PROMPT, '(?i)password']) + if i == 0: # Timeout + print('ERROR! could not login with SSH. Here is what SSH said:') + print(child.before, child.after) + print(str(child)) + sys.exit (1) + if i == 1: # In this case SSH does not have the public key cached. + child.sendline ('yes') + child.expect ('(?i)password') + if i == 2: + # This may happen if a public key was setup to automatically login. + # But beware, the COMMAND_PROMPT at this point is very trivial and + # could be fooled by some output in the MOTD or login message. + pass + if i == 3: + child.sendline(password) + # Now we are either at the command prompt or + # the login process is asking for our terminal type. + i = child.expect ([COMMAND_PROMPT, TERMINAL_PROMPT]) + if i == 1: + child.sendline (TERMINAL_TYPE) + child.expect (COMMAND_PROMPT) + # + # Set command prompt to something more unique. + # + COMMAND_PROMPT = r"\[PEXPECT\]\$ " + child.sendline (r"PS1='[PEXPECT]\$ '") # In case of sh-style + i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10) + if i == 0: + print("# Couldn't set sh-style prompt -- trying csh-style.") + child.sendline (r"set prompt='[PEXPECT]\$ '") + i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10) + if i == 0: + print("Failed to set command prompt using sh or csh style.") + print("Response was:") + print(child.before) + sys.exit (1) + + # Now we should be at the command prompt and ready to run some commands. + print('---------------------------------------') + print('Report of commands run on remote host.') + print('---------------------------------------') + + # Run uname. + child.sendline ('uname -a') + child.expect (COMMAND_PROMPT) + print(child.before) + if 'linux' in child.before.lower(): + LINUX_MODE = 1 + else: + LINUX_MODE = 0 + + # Run and parse 'uptime'. + child.sendline ('uptime') + child.expect(r'up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])') + duration, users, av1, av5, av15 = child.match.groups() + days = '0' + hours = '0' + mins = '0' + if 'day' in duration: + child.match = re.search(r'([0-9]+)\s+day',duration) + days = str(int(child.match.group(1))) + if ':' in duration: + child.match = re.search('([0-9]+):([0-9]+)',duration) + hours = str(int(child.match.group(1))) + mins = str(int(child.match.group(2))) + if 'min' in duration: + child.match = re.search(r'([0-9]+)\s+min',duration) + mins = str(int(child.match.group(1))) + print() + print('Uptime: %s days, %s users, %s (1 min), %s (5 min), %s (15 min)' % ( + duration, users, av1, av5, av15)) + child.expect (COMMAND_PROMPT) + + # Run iostat. + child.sendline ('iostat') + child.expect (COMMAND_PROMPT) + print(child.before) + + # Run vmstat. + child.sendline ('vmstat') + child.expect (COMMAND_PROMPT) + print(child.before) + + # Run free. + if LINUX_MODE: + child.sendline ('free') # Linux systems only. + child.expect (COMMAND_PROMPT) + print(child.before) + + # Run df. + child.sendline ('df') + child.expect (COMMAND_PROMPT) + print(child.before) + + # Run lsof. + child.sendline ('lsof') + child.expect (COMMAND_PROMPT) + print(child.before) + +# # Run netstat +# child.sendline ('netstat') +# child.expect (COMMAND_PROMPT) +# print child.before + +# # Run MySQL show status. +# child.sendline ('mysql -p -e "SHOW STATUS;"') +# child.expect (PASSWORD_PROMPT_MYSQL) +# child.sendline (password_mysql) +# child.expect (COMMAND_PROMPT) +# print +# print child.before + + # Now exit the remote host. + child.sendline ('exit') + index = child.expect([pexpect.EOF, "(?i)there are stopped jobs"]) + if index==1: + child.sendline("exit") + child.expect(EOF) + +if __name__ == "__main__": + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/passmass.py b/lldb/third_party/Python/module/pexpect-4.6/examples/passmass.py new file mode 100755 index 00000000000..c1ec4d0b326 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/passmass.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python + +'''Change passwords on the named machines. passmass host1 host2 host3 . . . +Note that login shell prompt on remote machine must end in # or $. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import pexpect +import sys, getpass + + +try: + raw_input +except NameError: + raw_input = input + + +USAGE = '''passmass host1 host2 host3 . . .''' +COMMAND_PROMPT = '[$#] ' +TERMINAL_PROMPT = r'Terminal type\?' +TERMINAL_TYPE = 'vt100' +SSH_NEWKEY = r'Are you sure you want to continue connecting \(yes/no\)\?' + +def login(host, user, password): + + child = pexpect.spawn('ssh -l %s %s'%(user, host)) + fout = file ("LOG.TXT","wb") + child.logfile_read = fout #use child.logfile to also log writes (passwords!) + + i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, '[Pp]assword: ']) + if i == 0: # Timeout + print('ERROR!') + print('SSH could not login. Here is what SSH said:') + print(child.before, child.after) + sys.exit (1) + if i == 1: # SSH does not have the public key. Just accept it. + child.sendline ('yes') + child.expect ('[Pp]assword: ') + child.sendline(password) + # Now we are either at the command prompt or + # the login process is asking for our terminal type. + i = child.expect (['Permission denied', TERMINAL_PROMPT, COMMAND_PROMPT]) + if i == 0: + print('Permission denied on host:', host) + sys.exit (1) + if i == 1: + child.sendline (TERMINAL_TYPE) + child.expect (COMMAND_PROMPT) + return child + +# (current) UNIX password: +def change_password(child, user, oldpassword, newpassword): + + child.sendline('passwd') + i = child.expect(['[Oo]ld [Pp]assword', '.current.*password', '[Nn]ew [Pp]assword']) + # Root does not require old password, so it gets to bypass the next step. + if i == 0 or i == 1: + child.sendline(oldpassword) + child.expect('[Nn]ew [Pp]assword') + child.sendline(newpassword) + i = child.expect(['[Nn]ew [Pp]assword', '[Rr]etype', '[Rr]e-enter']) + if i == 0: + print('Host did not like new password. Here is what it said...') + print(child.before) + child.send (chr(3)) # Ctrl-C + child.sendline('') # This should tell remote passwd command to quit. + return + child.sendline(newpassword) + +def main(): + + if len(sys.argv) <= 1: + print(USAGE) + return 1 + + user = raw_input('Username: ') + password = getpass.getpass('Current Password: ') + newpassword = getpass.getpass('New Password: ') + newpasswordconfirm = getpass.getpass('Confirm New Password: ') + if newpassword != newpasswordconfirm: + print('New Passwords do not match.') + return 1 + + for host in sys.argv[1:]: + child = login(host, user, password) + if child == None: + print('Could not login to host:', host) + continue + print('Changing password on host:', host) + change_password(child, user, password, newpassword) + child.expect(COMMAND_PROMPT) + child.sendline('exit') + +if __name__ == '__main__': + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/python.py b/lldb/third_party/Python/module/pexpect-4.6/examples/python.py new file mode 100755 index 00000000000..44c15e1da95 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/python.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +'''This starts the python interpreter; captures the startup message; then gives +the user interactive control over the session. Why? For fun... + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import pexpect + +# Don't do this unless you like being John Malkovich +# c = pexpect.spawnu('/usr/bin/env python ./python.py') + +# Note that, for Python 3 compatibility reasons, we are using spawnu and +# importing unicode_literals (above). spawnu accepts Unicode input and +# unicode_literals makes all string literals in this script Unicode by default. +c = pexpect.spawnu('/usr/bin/env python') + +c.expect('>>>') +print('And now for something completely different...') +print(''.join(reversed((c.before)))) +print('Yes, it\'s python, but it\'s backwards.') +print() +print('Escape character is \'^]\'.') +print(c.after, end=' ') +c.interact() +c.kill(1) +print('is alive:', c.isalive()) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/script.py b/lldb/third_party/Python/module/pexpect-4.6/examples/script.py new file mode 100755 index 00000000000..c8b94961de6 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/script.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +'''This spawns a sub-shell (bash) and gives the user interactive control. The +entire shell session is logged to a file called script.log. This behaves much +like the classic BSD command 'script'. + +./script.py [-a] [-c command] {logfilename} + + logfilename : This is the name of the log file. Default is script.log. + -a : Append to log file. Default is to overwrite log file. + -c : spawn command. Default is to spawn the sh shell. + +Example: + + This will start a bash shell and append to the log named my_session.log: + + ./script.py -a -c bash my_session.log + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import os, sys, time, getopt +import signal, fcntl, termios, struct +import pexpect + +global_pexpect_instance = None # Used by signal handler + +def exit_with_usage(): + + print(globals()['__doc__']) + os._exit(1) + +def main(): + + ###################################################################### + # Parse the options, arguments, get ready, etc. + ###################################################################### + try: + optlist, args = getopt.getopt(sys.argv[1:], 'h?ac:', ['help','h','?']) + except Exception as e: + print(str(e)) + exit_with_usage() + options = dict(optlist) + if len(args) > 1: + exit_with_usage() + + if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]: + print("Help:") + exit_with_usage() + + if len(args) == 1: + script_filename = args[0] + else: + script_filename = "script.log" + if '-a' in options: + fout = open(script_filename, "ab") + else: + fout = open(script_filename, "wb") + if '-c' in options: + command = options['-c'] + else: + command = "sh" + + # Begin log with date/time in the form CCCCyymm.hhmmss + fout.write ('# %4d%02d%02d.%02d%02d%02d \n' % time.localtime()[:-3]) + + ###################################################################### + # Start the interactive session + ###################################################################### + p = pexpect.spawn(command) + p.logfile = fout + global global_pexpect_instance + global_pexpect_instance = p + signal.signal(signal.SIGWINCH, sigwinch_passthrough) + + print("Script recording started. Type ^] (ASCII 29) to escape from the script shell.") + p.interact(chr(29)) + fout.close() + return 0 + +def sigwinch_passthrough (sig, data): + + # Check for buggy platforms (see pexpect.setwinsize()). + if 'TIOCGWINSZ' in dir(termios): + TIOCGWINSZ = termios.TIOCGWINSZ + else: + TIOCGWINSZ = 1074295912 # assume + s = struct.pack ("HHHH", 0, 0, 0, 0) + a = struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s)) + global global_pexpect_instance + global_pexpect_instance.setwinsize(a[0],a[1]) + +if __name__ == "__main__": + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/ssh_tunnel.py b/lldb/third_party/Python/module/pexpect-4.6/examples/ssh_tunnel.py new file mode 100755 index 00000000000..d7619118e08 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/ssh_tunnel.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +'''This starts an SSH tunnel to a given host. If the SSH process ever dies then +this script will detect that and restart it. I use this under Cygwin to keep +open encrypted tunnels to port 25 (SMTP), port 143 (IMAP4), and port 110 +(POP3). I set my mail client to talk to localhost and I keep this script +running in the background. + +Note that this is a rather stupid script at the moment because it just looks to +see if any ssh process is running. It should really make sure that our specific +ssh process is running. The problem is that ssh is missing a very useful +feature. It has no way to report the process id of the background daemon that +it creates with the -f command. This would be a really useful script if I could +figure a way around this problem. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +from __future__ import absolute_import + +import pexpect +import getpass +import time + + +try: + raw_input +except NameError: + raw_input = input + + +# SMTP:25 IMAP4:143 POP3:110 +tunnel_command = 'ssh -C -N -f -L 25:127.0.0.1:25 -L 143:127.0.0.1:143 -L 110:127.0.0.1:110 %(user)@%(host)' +host = raw_input('Hostname: ') +user = raw_input('Username: ') +X = getpass.getpass('Password: ') + +def get_process_info (): + + # This seems to work on both Linux and BSD, but should otherwise be considered highly UNportable. + + ps = pexpect.run ('ps ax -O ppid') + pass + +def start_tunnel (): + + try: + ssh_tunnel = pexpect.spawn (tunnel_command % globals()) + ssh_tunnel.expect ('password:') + time.sleep (0.1) + ssh_tunnel.sendline (X) + time.sleep (60) # Cygwin is slow to update process status. + ssh_tunnel.expect (pexpect.EOF) + + except Exception as e: + print(str(e)) + +def main (): + + while True: + ps = pexpect.spawn ('ps') + time.sleep (1) + index = ps.expect (['/usr/bin/ssh', pexpect.EOF, pexpect.TIMEOUT]) + if index == 2: + print('TIMEOUT in ps command...') + print(str(ps)) + time.sleep (13) + if index == 1: + print(time.asctime(), end=' ') + print('restarting tunnel') + start_tunnel () + time.sleep (11) + print('tunnel OK') + else: + # print 'tunnel OK' + time.sleep (7) + +if __name__ == '__main__': + + main () + +# This was for older SSH versions that didn't have -f option +#tunnel_command = 'ssh -C -n -L 25:%(host)s:25 -L 110:%(host)s:110 %(user)s@%(host)s -f nothing.sh' +#nothing_script = '''#!/bin/sh +#while true; do sleep 53; done +#''' + diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/table_test.html b/lldb/third_party/Python/module/pexpect-4.6/examples/table_test.html new file mode 100644 index 00000000000..5dba0ecf0c8 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/table_test.html @@ -0,0 +1,106 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<title>TEST</title> +</head> +<style type="text/css"> +a {color: #9f9; text-decoration: none} +a:hover {color: #0f0} +hr {color: #0f0} +html,table,body,textarea,input,form +{ +font-family: "Courier New", Courier, mono; +font-size: 8pt; +color: #0c0; +background-color: #020; +margin:0; +padding:0; +border:0; +} +input { background-color: #010; } +textarea { +border-width:1; +border-style:solid; +border-color:#0c0; +padding:3; +margin:3; +} +</style> +<script> +var foo="" + +" 123456789012345678901234567890123456789012345 789012345678901234567890123456789"+ +"0 2345678901234567890123456789012345678901234 6 89012345678901234567890123456789"+ +"01 34567890123456789012345678901234567890123 567 9012345678901234567890123456789"+ +"012 456789012345678901234567890123456789012 45678 012345678901234567890123456789"+ +"0123 5678901234567890123456789012345678901 3456789 12345678901234567890123456789"+ +"01234 67890123456789012345678901234567890 234567890 2345678901234567890123456789"+ +"012345 789012345678901234567890123456789 12345678901 345678901234567890123456789"+ +"0123456 8901234567890123456789012345678 0123456789012 45678901234567890123456789"+ +"01234567 90123456789012345678901234567 901234567890123 5678901234567890123456789"+ +"012345678 012345678901234567890123456 89012345678901234 678901234567890123456789"+ +"0123456789 1234567890123456789012345 7890123456789012345 78901234567890123456789"+ +"01234567890 23456789012345678901234 678901234567890123456 8901234567890123456789"+ +"012345678901 345678901234567890123 56789012345678901234567 901234567890123456789"+ +"0123456789012 4567890123456789012 4567890123456789012345678 0123456789012345678 "+ +"01234567890123 56789012345678901 345678901234567890123456789 12345678901234567 9"+ +"012345678901234 678901234567890 23456789012 567 01234567890 234567890123456 89"+ +"0123456789012345 7890123456789 123457789012 567 012345678901 3456789012345 789"+ +"01234567890123456 89012345678 012345678901234567890123456789012 45678901234 6789"+ +"012345678901234567 901234567 90123456789 12345678901 34567890123 567890123 56789"+ +"0123456789012345678 0123456 8901234567890 3456789 2345678901234 6789012 456789"+ +"01234567890123456789 12345 7890123456789012 0123456789012345 78901 3456789"+ +"012345678901234567890 234 67890123456789012345678901234567890123456 890 23456789"+ +"0123456789012345678901 3 5678901234567890123456789012345678901234567 9 123456789"+ +"01234567890123456789012 456789012345678901234567890123456789012345678 0123456789"; +function start2() +{ + // get the reference for the body + //var mybody = document.getElementsByTagName("body")[0]; + var mybody = document.getElementById("replace_me"); + var myroot = document.getElementById("a_parent"); + mytable = document.createElement("table"); + mytablebody = document.createElement("tbody"); + mytable.setAttribute("border","0"); + mytable.setAttribute("cellspacing","0"); + mytable.setAttribute("cellpadding","0"); + for(var j = 0; j < 24; j++) + { + mycurrent_row = document.createElement("tr"); + for(var i = 0; i < 80; i++) + { + mycurrent_cell = document.createElement("td"); + offset = (j*80)+i; + currenttext = document.createTextNode(foo.substring(offset,offset+1)); + mycurrent_cell.appendChild(currenttext); + mycurrent_row.appendChild(mycurrent_cell); + } + mytablebody.appendChild(mycurrent_row); + } + mytable.appendChild(mytablebody); + myroot.replaceChild(mytable,mybody); + //mybody.appendChild(mytable); +} +</script> +<body onload="start2();"> +<table align="LEFT" border="0" cellspacing="0" cellpadding="0"> +<div id="a_parent"> +<span id="replace_me"> +<tr align="left" valign="left"> + <td>/</td> + <td>h</td> + <td>o</td> + <td>m</td> + <td>e</td> + <td>/</td> + <td>n</td> + <td>o</td> + <td>a</td> + <td>h</td> + <td>/</td> + <td> </td> +</tr> +</table> +</span> +</div> +</body> +</html>
\ No newline at end of file diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/topip.py b/lldb/third_party/Python/module/pexpect-4.6/examples/topip.py new file mode 100755 index 00000000000..64dac3089cd --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/topip.py @@ -0,0 +1,299 @@ +#!/usr/bin/env python + +''' This runs netstat on a local or remote server. It calculates some simple +statistical information on the number of external inet connections. It groups +by IP address. This can be used to detect if one IP address is taking up an +excessive number of connections. It can also send an email alert if a given IP +address exceeds a threshold between runs of the script. This script can be used +as a drop-in Munin plugin or it can be used stand-alone from cron. I used this +on a busy web server that would sometimes get hit with denial of service +attacks. This made it easy to see if a script was opening many multiple +connections. A typical browser would open fewer than 10 connections at once. +A script might open over 100 simultaneous connections. + +./topip.py [-s server_hostname] [-u username] [-p password] + {-a from_addr,to_addr} {-n N} {-v} {--ipv6} + + -s : hostname of the remote server to login to. + -u : username to user for login. + -p : password to user for login. + -n : print stddev for the the number of the top 'N' ipaddresses. + -v : verbose - print stats and list of top ipaddresses. + -a : send alert if stddev goes over 20. + -l : to log message to /var/log/topip.log + --ipv6 : this parses netstat output that includes ipv6 format. + Note that this actually only works with ipv4 addresses, but for + versions of netstat that print in ipv6 format. + --stdev=N : Where N is an integer. This sets the trigger point + for alerts and logs. Default is to trigger if the + max value is over 5 standard deviations. + +Example: + + This will print stats for the top IP addresses connected to the given host: + + ./topip.py -s www.example.com -u mylogin -p mypassword -n 10 -v + + This will send an alert email if the maxip goes over the stddev trigger + value and the the current top ip is the same as the last top ip + (/tmp/topip.last): + + ./topip.py -s www.example.com -u mylogin -p mypassword \\ + -n 10 -v -a alert@example.com,user@example.com + + This will print the connection stats for the localhost in Munin format: + + ./topip.py + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +# See http://pexpect.sourceforge.net/ +import pexpect +import pxssh +import os +import sys +import time +import getopt +import pickle +import getpass +import smtplib +from pprint import pprint + + +try: + raw_input +except NameError: + raw_input = input + + +TOPIP_LOG_FILE = '/var/log/topip.log' +TOPIP_LAST_RUN_STATS = '/var/run/topip.last' + +def exit_with_usage(): + + print(globals()['__doc__']) + os._exit(1) + +def stats(r): + + '''This returns a dict of the median, average, standard deviation, + min and max of the given sequence. + + >>> from topip import stats + >>> print stats([5,6,8,9]) + {'med': 8, 'max': 9, 'avg': 7.0, 'stddev': 1.5811388300841898, 'min': 5} + >>> print stats([1000,1006,1008,1014]) + {'med': 1008, 'max': 1014, 'avg': 1007.0, 'stddev': 5.0, 'min': 1000} + >>> print stats([1,3,4,5,18,16,4,3,3,5,13]) + {'med': 4, 'max': 18, 'avg': 6.8181818181818183, 'stddev': 5.6216817577237475, 'min': 1} + >>> print stats([1,3,4,5,18,16,4,3,3,5,13,14,5,6,7,8,7,6,6,7,5,6,4,14,7]) + {'med': 6, 'max': 18, 'avg': 7.0800000000000001, 'stddev': 4.3259218670706474, 'min': 1} + ''' + + total = sum(r) + avg = float(total)/float(len(r)) + sdsq = sum([(i-avg)**2 for i in r]) + s = sorted(list(r)) + return dict(list(zip(['med', 'avg', 'stddev', 'min', 'max'], + (s[len(s)//2], avg, (sdsq/len(r))**.5, min(r), max(r))))) + +def send_alert (message, subject, addr_from, addr_to, smtp_server='localhost'): + + '''This sends an email alert. + ''' + + message = ( 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n' + % (addr_from, addr_to, subject) + message ) + server = smtplib.SMTP(smtp_server) + server.sendmail(addr_from, addr_to, message) + server.quit() + +def main(): + + # Parse the options, arguments, etc. + try: + optlist, args = getopt.getopt(sys.argv[1:], + 'h?valqs:u:p:n:', ['help','h','?','ipv6','stddev=']) + except Exception as e: + print(str(e)) + exit_with_usage() + options = dict(optlist) + + munin_flag = False + if len(args) > 0: + if args[0] == 'config': + print('graph_title Netstat Connections per IP') + print('graph_vlabel Socket connections per IP') + print('connections_max.label max') + print('connections_max.info Maximum number of connections per IP') + print('connections_avg.label avg') + print('connections_avg.info Average number of connections per IP') + print('connections_stddev.label stddev') + print('connections_stddev.info Standard deviation') + return 0 + elif args[0] != '': + print(args, len(args)) + return 0 + exit_with_usage() + if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]: + print('Help:') + exit_with_usage() + if '-s' in options: + hostname = options['-s'] + else: + # if host was not specified then assume localhost munin plugin. + munin_flag = True + hostname = 'localhost' + # If localhost then don't ask for username/password. + if hostname != 'localhost' and hostname != '127.0.0.1': + if '-u' in options: + username = options['-u'] + else: + username = raw_input('username: ') + if '-p' in options: + password = options['-p'] + else: + password = getpass.getpass('password: ') + use_localhost = False + else: + use_localhost = True + + if '-l' in options: + log_flag = True + else: + log_flag = False + if '-n' in options: + average_n = int(options['-n']) + else: + average_n = None + if '-v' in options: + verbose = True + else: + verbose = False + if '-a' in options: + alert_flag = True + (alert_addr_from, alert_addr_to) = tuple(options['-a'].split(',')) + else: + alert_flag = False + if '--ipv6' in options: + ipv6_flag = True + else: + ipv6_flag = False + if '--stddev' in options: + stddev_trigger = float(options['--stddev']) + else: + stddev_trigger = 5 + + if ipv6_flag: + netstat_pattern = r'(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+::ffff:(\S+):(\S+)\s+.*?\r' + else: + netstat_pattern = r'(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(?:::ffff:)*(\S+):(\S+)\s+.*?\r' + #netstat_pattern = r'(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+):(\S+)\s+.*?\r' + + # run netstat (either locally or via SSH). + if use_localhost: + p = pexpect.spawn('netstat -n -t') + PROMPT = pexpect.TIMEOUT + else: + p = pxssh.pxssh() + p.login(hostname, username, password) + p.sendline('netstat -n -t') + PROMPT = p.PROMPT + + # For each matching netstat_pattern put the ip address in the list. + ip_list = {} + try: + while 1: + i = p.expect([PROMPT, netstat_pattern]) + if i == 0: + break + k = p.match.groups()[4].decode('utf-8') + if k in ip_list: + ip_list[k] = ip_list[k] + 1 + else: + ip_list[k] = 1 + except: + pass + + # remove a few common, uninteresting addresses from the dictionary. + ip_list = dict([ (key,value) for key,value in ip_list.items() if '192.168.' not in key]) + ip_list = dict([ (key,value) for key,value in ip_list.items() if '127.0.0.1' not in key]) + + ip_list = list(ip_list.items()) + if len(ip_list) < 1: + if verbose: print('Warning: no networks connections worth looking at.') + return 0 + ip_list.sort(key=lambda x:x[1]) + + # generate some stats for the ip addresses found. + if average_n is not None and average_n <= 1: + average_n = None + # Reminder: the * unary operator treats the list elements as arguments. + zipped = zip(*ip_list[0:average_n]) + s = stats(list(zipped)[1]) + s['maxip'] = ip_list[0] + + # print munin-style or verbose results for the stats. + if munin_flag: + print('connections_max.value', s['max']) + print('connections_avg.value', s['avg']) + print('connections_stddev.value', s['stddev']) + return 0 + if verbose: + pprint (s) + print() + pprint (ip_list[0:average_n]) + + # load the stats from the last run. + try: + last_stats = pickle.load(file(TOPIP_LAST_RUN_STATS)) + except: + last_stats = {'maxip':None} + + if ( s['maxip'][1] > (s['stddev'] * stddev_trigger) + and s['maxip']==last_stats['maxip'] ): + if verbose: print('The maxip has been above trigger for two consecutive samples.') + if alert_flag: + if verbose: print('SENDING ALERT EMAIL') + send_alert(str(s), 'ALERT on %s' + % hostname, alert_addr_from, alert_addr_to) + if log_flag: + if verbose: print('LOGGING THIS EVENT') + fout = file(TOPIP_LOG_FILE,'a') + #dts = time.strftime('%Y:%m:%d:%H:%M:%S', time.localtime()) + dts = time.asctime() + fout.write ('%s - %d connections from %s\n' + % (dts,s['maxip'][1],str(s['maxip'][0]))) + fout.close() + + # save state to TOPIP_LAST_RUN_STATS + try: + pickle.dump(s, file(TOPIP_LAST_RUN_STATS,'w')) + os.chmod (TOPIP_LAST_RUN_STATS, 0o664) + except: + pass + # p.logout() + +if __name__ == '__main__': + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/examples/uptime.py b/lldb/third_party/Python/module/pexpect-4.6/examples/uptime.py new file mode 100755 index 00000000000..86b8dffa1c1 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/examples/uptime.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python + +'''This displays uptime information using uptime. This is redundant, +but it demonstrates expecting for a regular expression that uses subgroups. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import pexpect +import re + +# There are many different styles of uptime results. I try to parse them all. Yeee! +# Examples from different machines: +# [x86] Linux 2.4 (Redhat 7.3) +# 2:06pm up 63 days, 18 min, 3 users, load average: 0.32, 0.08, 0.02 +# [x86] Linux 2.4.18-14 (Redhat 8.0) +# 3:07pm up 29 min, 1 user, load average: 2.44, 2.51, 1.57 +# [PPC - G4] MacOS X 10.1 SERVER Edition +# 2:11PM up 3 days, 13:50, 3 users, load averages: 0.01, 0.00, 0.00 +# [powerpc] Darwin v1-58.corefa.com 8.2.0 Darwin Kernel Version 8.2.0 +# 10:35 up 18:06, 4 users, load averages: 0.52 0.47 0.36 +# [Sparc - R220] Sun Solaris (8) +# 2:13pm up 22 min(s), 1 user, load average: 0.02, 0.01, 0.01 +# [x86] Linux 2.4.18-14 (Redhat 8) +# 11:36pm up 4 days, 17:58, 1 user, load average: 0.03, 0.01, 0.00 +# AIX jwdir 2 5 0001DBFA4C00 +# 09:43AM up 23:27, 1 user, load average: 0.49, 0.32, 0.23 +# OpenBSD box3 2.9 GENERIC#653 i386 +# 6:08PM up 4 days, 22:26, 1 user, load averages: 0.13, 0.09, 0.08 + +# Note that, for Python 3 compatibility reasons, we are using spawnu and +# importing unicode_literals (above). spawnu accepts Unicode input and +# unicode_literals makes all string literals in this script Unicode by default. +p = pexpect.spawnu('uptime') + +# This parses uptime output into the major groups using regex group matching. +p.expect(r'up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])') +duration, users, av1, av5, av15 = p.match.groups() + +# The duration is a little harder to parse because of all the different +# styles of uptime. I'm sure there is a way to do this all at once with +# one single regex, but I bet it would be hard to read and maintain. +# If anyone wants to send me a version using a single regex I'd be happy to see it. +days = '0' +hours = '0' +mins = '0' +if 'day' in duration: + p.match = re.search(r'([0-9]+)\s+day',duration) + days = str(int(p.match.group(1))) +if ':' in duration: + p.match = re.search('([0-9]+):([0-9]+)',duration) + hours = str(int(p.match.group(1))) + mins = str(int(p.match.group(2))) +if 'min' in duration: + p.match = re.search(r'([0-9]+)\s+min',duration) + mins = str(int(p.match.group(1))) + +# Print the parsed fields in CSV format. +print('days, hours, minutes, users, cpu avg 1 min, cpu avg 5 min, cpu avg 15 min') +print('%s, %s, %s, %s, %s, %s, %s' % (days, hours, mins, users, av1, av5, av15)) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/notes/my_forkpty.py b/lldb/third_party/Python/module/pexpect-4.6/notes/my_forkpty.py new file mode 100644 index 00000000000..f2bef23bd68 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/notes/my_forkpty.py @@ -0,0 +1,89 @@ +import os, fcntl, termios +import time + +def my_forkpty(): + + (master_fd, slave_fd) = os.openpty() + + if (master_fd < 0 or slave_fd < 0): + raise ExceptionPexpect("Forkpty failed") + + # slave_name = ptsname(master_fd); + + pid = os.fork(); + if pid == -1: + raise ExceptionPexpect("Forkpty failed") + elif pid == 0: # Child + if hasattr(termios, 'TIOCNOTTY'): + # Some platforms require an explicit detach of the + # current controlling tty before closing stdin, stdout, stderr. + # OpenBSD says that this is obsolete, but doesn't hurt. + try: + fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) + except: + pass + else: #if fd >= 0: + fcntl.ioctl(fd, termios.TIOCNOTTY, 0) + os.close(fd) + + # The setsid() system call will place the process into its own session + # which has the effect of disassociating it from the controlling terminal. + # This is known to be true for OpenBSD. + os.setsid() + # except: return posix_error(); + + # Verify that we are disconnected from the controlling tty. + try: + fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) + os.close(fd) + raise ExceptionPexpect("Forkpty failed") + except: + pass + if 'TIOCSCTTY' in dir(termios): + # Make the pseudo terminal the controlling terminal for this process + # (the process must not currently have a controlling terminal). + if fcntl.ioctl(slave_fd, termios.TIOCSCTTY, '') < 0: + raise ExceptionPexpect("Forkpty failed") + +# # Verify that we can open to the slave pty file. */ +# fd = os.open(slave_name, os.O_RDWR); +# if fd < 0: +# raise ExceptionPexpect("Forkpty failed") +# else: +# os.close(fd); + + # Verify that we now have a controlling tty. + fd = os.open("/dev/tty", os.O_WRONLY) + if fd < 0: + raise ExceptionPexpect("This process could not get a controlling tty.") + else: + os.close(fd) + + os.close(master_fd) + os.dup2(slave_fd, 0) + os.dup2(slave_fd, 1) + os.dup2(slave_fd, 2) + if slave_fd > 2: + os.close(slave_fd) + pid = 0 + + else: + # PARENT + os.close(slave_fd); + + if pid == -1: + raise ExceptionPexpect("This process could not get a controlling tty.") +# if (pid == 0) +# PyOS_AfterFork(); + + return (pid, master_fd) + +pid, fd = my_forkpty () +if pid == 0: # child + print 'I am not a robot!' +else: + print '(pid, fd) = (%d, %d)' % (pid, fd) + time.sleep(1) # Give the child a chance to print. + print 'Robots always say:', os.read(fd,100) + os.close(fd) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/notes/notes.txt b/lldb/third_party/Python/module/pexpect-4.6/notes/notes.txt new file mode 100644 index 00000000000..8ff6cfe29da --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/notes/notes.txt @@ -0,0 +1,50 @@ + +#################### +# +# NOTES +# +#################### + +## def send_human(self, text, delay_min = 0, delay_max = 1): +## pass +## def spawn2(self, command, args): +## """return pid, fd_stdio, fd_stderr +## """ +## pass + + +# Reason for double fork: +# http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC15 +# Reason for ptys: +# http://www.erlenstar.demon.co.uk/unix/faq_4.html#SEC52 + +# Nonblocking on Win32? +# Research this as a way to maybe make pipe work for Win32. +# http://groups.google.com/groups?q=setraw+tty&hl=en&selm=uvgpvisvk.fsf%40roundpoint.com&rnum=7 +# +# if istty: +# if os.name=='posix': +# import tty +# tty.setraw(sys.stdin.fileno()) +# elif os.name=='nt': +# import win32file, win32con +# hstdin = win32file._get_osfhandle(sys.stdin.fileno()) +# modes = (win32file.GetConsoleMode(hstdin) +# & ~(win32con.ENABLE_LINE_INPUT +# |win32con.ENABLE_ECHO_INPUT)) +# win32file.SetConsoleMode(hstdin, modes) + +# Basic documentation: +# Explain use of lists of patterns and return index. +# Explain exceptions for non-handled special cases like EOF + +# Test bad fork +# Test ENOENT. In other words, no more TTY devices. + +#GLOBAL_SIGCHLD_RECEIVED = 0 +#def childdied (signum, frame): +# print 'Signal handler called with signal', signum +# frame.f_globals['pexpect'].GLOBAL_SIGCHLD_RECEIVED = 1 +# print str(frame.f_globals['pexpect'].GLOBAL_SIGCHLD_RECEIVED) +# GLOBAL_SIGCHLD_RECEIVED = 1 + diff --git a/lldb/third_party/Python/module/pexpect-4.6/notes/posixmodule.c.diff b/lldb/third_party/Python/module/pexpect-4.6/notes/posixmodule.c.diff new file mode 100644 index 00000000000..3bea1f9cba9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/notes/posixmodule.c.diff @@ -0,0 +1,233 @@ +*** Python-2.2.1.orig/Modules/posixmodule.c Tue Mar 12 16:38:31 2002 +--- Python-2.2.1/Modules/posixmodule.c Tue May 21 01:16:29 2002 +*************** +*** 1904,1910 **** + } + #endif + +! #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) + #ifdef HAVE_PTY_H + #include <pty.h> + #else +--- 1904,1913 ---- + } + #endif + +! #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(sun) +! #ifdef sun +! #include <sys/stropts.h> +! #endif + #ifdef HAVE_PTY_H + #include <pty.h> + #else +*************** +*** 1914,1920 **** + #endif /* HAVE_PTY_H */ + #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */ + +! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) + static char posix_openpty__doc__[] = + "openpty() -> (master_fd, slave_fd)\n\ + Open a pseudo-terminal, returning open fd's for both master and slave end.\n"; +--- 1917,1923 ---- + #endif /* HAVE_PTY_H */ + #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */ + +! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(sun) + static char posix_openpty__doc__[] = + "openpty() -> (master_fd, slave_fd)\n\ + Open a pseudo-terminal, returning open fd's for both master and slave end.\n"; +*************** +*** 1925,1932 **** + int master_fd, slave_fd; + #ifndef HAVE_OPENPTY + char * slave_name; + #endif +! + if (!PyArg_ParseTuple(args, ":openpty")) + return NULL; + +--- 1928,1941 ---- + int master_fd, slave_fd; + #ifndef HAVE_OPENPTY + char * slave_name; ++ #ifdef sun ++ void *sig_saved; + #endif +! #endif +! #if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) && defined(sun) +! extern char *ptsname(); +! #endif +! + if (!PyArg_ParseTuple(args, ":openpty")) + return NULL; + +*************** +*** 1933,1939 **** + #ifdef HAVE_OPENPTY + if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) + return posix_error(); +! #else + slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); + if (slave_name == NULL) + return posix_error(); +--- 1942,1948 ---- + #ifdef HAVE_OPENPTY + if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) + return posix_error(); +! #elif HAVE__GETPTY + slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); + if (slave_name == NULL) + return posix_error(); +*************** +*** 1941,1946 **** +--- 1950,1966 ---- + slave_fd = open(slave_name, O_RDWR); + if (slave_fd < 0) + return posix_error(); ++ #else ++ master_fd = open("/dev/ptmx", O_RDWR|O_NOCTTY); /* open master */ ++ sig_saved = signal(SIGCHLD, SIG_DFL); ++ grantpt(master_fd); /* change permission of slave */ ++ unlockpt(master_fd); /* unlock slave */ ++ signal(SIGCHLD,sig_saved); ++ slave_name = ptsname(master_fd); /* get name of slave */ ++ slave_fd = open(slave_name, O_RDWR); /* open slave */ ++ ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ ++ ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm*/ ++ ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat*/ + #endif /* HAVE_OPENPTY */ + + return Py_BuildValue("(ii)", master_fd, slave_fd); +*************** +*** 1948,1954 **** + } + #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) */ + +! #ifdef HAVE_FORKPTY + static char posix_forkpty__doc__[] = + "forkpty() -> (pid, master_fd)\n\ + Fork a new process with a new pseudo-terminal as controlling tty.\n\n\ +--- 1968,1974 ---- + } + #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) */ + +! #if defined(HAVE_FORKPTY) || defined(sun) + static char posix_forkpty__doc__[] = + "forkpty() -> (pid, master_fd)\n\ + Fork a new process with a new pseudo-terminal as controlling tty.\n\n\ +*************** +*** 1959,1968 **** +--- 1979,2067 ---- + posix_forkpty(PyObject *self, PyObject *args) + { + int master_fd, pid; ++ #if defined(sun) ++ int slave; ++ char * slave_name; ++ void *sig_saved; ++ int fd; ++ #endif + + if (!PyArg_ParseTuple(args, ":forkpty")) + return NULL; ++ #if defined(sun) ++ master_fd = open("/dev/ptmx", O_RDWR|O_NOCTTY); /* open master */ ++ sig_saved = signal(SIGCHLD, SIG_DFL); ++ grantpt(master_fd); /* change permission of slave */ ++ unlockpt(master_fd); /* unlock slave */ ++ signal(SIGCHLD,sig_saved); ++ slave_name = ptsname(master_fd); /* get name of slave */ ++ slave = open(slave_name, O_RDWR); /* open slave */ ++ ioctl(slave, I_PUSH, "ptem"); /* push ptem */ ++ ioctl(slave, I_PUSH, "ldterm"); /* push ldterm*/ ++ ioctl(slave, I_PUSH, "ttcompat"); /* push ttcompat*/ ++ if (master_fd < 0 || slave < 0) ++ { ++ return posix_error(); ++ } ++ switch (pid = fork()) { ++ case -1: ++ return posix_error(); ++ case 0: ++ /* First disconnect from the old controlling tty. */ ++ #ifdef TIOCNOTTY ++ fd = open("/dev/tty", O_RDWR | O_NOCTTY); ++ if (fd >= 0) { ++ (void) ioctl(fd, TIOCNOTTY, NULL); ++ close(fd); ++ } ++ #endif /* TIOCNOTTY */ ++ if (setsid() < 0) ++ return posix_error(); ++ ++ /* ++ * Verify that we are successfully disconnected from the controlling ++ * tty. ++ */ ++ fd = open("/dev/tty", O_RDWR | O_NOCTTY); ++ if (fd >= 0) { ++ return posix_error(); ++ close(fd); ++ } ++ /* Make it our controlling tty. */ ++ #ifdef TIOCSCTTY ++ if (ioctl(slave, TIOCSCTTY, NULL) < 0) ++ return posix_error(); ++ #endif /* TIOCSCTTY */ ++ fd = open(slave_name, O_RDWR); ++ if (fd < 0) { ++ return posix_error(); ++ } else { ++ close(fd); ++ } ++ /* Verify that we now have a controlling tty. */ ++ fd = open("/dev/tty", O_WRONLY); ++ if (fd < 0) ++ return posix_error(); ++ else { ++ close(fd); ++ } ++ (void) close(master_fd); ++ (void) dup2(slave, 0); ++ (void) dup2(slave, 1); ++ (void) dup2(slave, 2); ++ if (slave > 2) ++ (void) close(slave); ++ pid = 0; ++ break; ++ defautlt: ++ /* ++ * parent ++ */ ++ (void) close(slave); ++ } ++ #else + pid = forkpty(&master_fd, NULL, NULL, NULL); ++ #endif + if (pid == -1) + return posix_error(); + if (pid == 0) +*************** +*** 5607,5616 **** + #ifdef HAVE_FORK + {"fork", posix_fork, METH_VARARGS, posix_fork__doc__}, + #endif /* HAVE_FORK */ +! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) + {"openpty", posix_openpty, METH_VARARGS, posix_openpty__doc__}, + #endif /* HAVE_OPENPTY || HAVE__GETPTY */ +! #ifdef HAVE_FORKPTY + {"forkpty", posix_forkpty, METH_VARARGS, posix_forkpty__doc__}, + #endif /* HAVE_FORKPTY */ + #ifdef HAVE_GETEGID +--- 5706,5715 ---- + #ifdef HAVE_FORK + {"fork", posix_fork, METH_VARARGS, posix_fork__doc__}, + #endif /* HAVE_FORK */ +! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(sun) + {"openpty", posix_openpty, METH_VARARGS, posix_openpty__doc__}, + #endif /* HAVE_OPENPTY || HAVE__GETPTY */ +! #if defined(HAVE_FORKPTY) || defined(sun) + {"forkpty", posix_forkpty, METH_VARARGS, posix_forkpty__doc__}, + #endif /* HAVE_FORKPTY */ + #ifdef HAVE_GETEGID diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/ANSI.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/ANSI.py new file mode 100644 index 00000000000..1cd2e90e7ab --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/ANSI.py @@ -0,0 +1,351 @@ +'''This implements an ANSI (VT100) terminal emulator as a subclass of screen. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +# references: +# http://en.wikipedia.org/wiki/ANSI_escape_code +# http://www.retards.org/terminals/vt102.html +# http://vt100.net/docs/vt102-ug/contents.html +# http://vt100.net/docs/vt220-rm/ +# http://www.termsys.demon.co.uk/vtansi.htm + +from . import screen +from . import FSM +import string + +# +# The 'Do.*' functions are helper functions for the ANSI class. +# +def DoEmit (fsm): + + screen = fsm.memory[0] + screen.write_ch(fsm.input_symbol) + +def DoStartNumber (fsm): + + fsm.memory.append (fsm.input_symbol) + +def DoBuildNumber (fsm): + + ns = fsm.memory.pop() + ns = ns + fsm.input_symbol + fsm.memory.append (ns) + +def DoBackOne (fsm): + + screen = fsm.memory[0] + screen.cursor_back () + +def DoBack (fsm): + + count = int(fsm.memory.pop()) + screen = fsm.memory[0] + screen.cursor_back (count) + +def DoDownOne (fsm): + + screen = fsm.memory[0] + screen.cursor_down () + +def DoDown (fsm): + + count = int(fsm.memory.pop()) + screen = fsm.memory[0] + screen.cursor_down (count) + +def DoForwardOne (fsm): + + screen = fsm.memory[0] + screen.cursor_forward () + +def DoForward (fsm): + + count = int(fsm.memory.pop()) + screen = fsm.memory[0] + screen.cursor_forward (count) + +def DoUpReverse (fsm): + + screen = fsm.memory[0] + screen.cursor_up_reverse() + +def DoUpOne (fsm): + + screen = fsm.memory[0] + screen.cursor_up () + +def DoUp (fsm): + + count = int(fsm.memory.pop()) + screen = fsm.memory[0] + screen.cursor_up (count) + +def DoHome (fsm): + + c = int(fsm.memory.pop()) + r = int(fsm.memory.pop()) + screen = fsm.memory[0] + screen.cursor_home (r,c) + +def DoHomeOrigin (fsm): + + c = 1 + r = 1 + screen = fsm.memory[0] + screen.cursor_home (r,c) + +def DoEraseDown (fsm): + + screen = fsm.memory[0] + screen.erase_down() + +def DoErase (fsm): + + arg = int(fsm.memory.pop()) + screen = fsm.memory[0] + if arg == 0: + screen.erase_down() + elif arg == 1: + screen.erase_up() + elif arg == 2: + screen.erase_screen() + +def DoEraseEndOfLine (fsm): + + screen = fsm.memory[0] + screen.erase_end_of_line() + +def DoEraseLine (fsm): + + arg = int(fsm.memory.pop()) + screen = fsm.memory[0] + if arg == 0: + screen.erase_end_of_line() + elif arg == 1: + screen.erase_start_of_line() + elif arg == 2: + screen.erase_line() + +def DoEnableScroll (fsm): + + screen = fsm.memory[0] + screen.scroll_screen() + +def DoCursorSave (fsm): + + screen = fsm.memory[0] + screen.cursor_save_attrs() + +def DoCursorRestore (fsm): + + screen = fsm.memory[0] + screen.cursor_restore_attrs() + +def DoScrollRegion (fsm): + + screen = fsm.memory[0] + r2 = int(fsm.memory.pop()) + r1 = int(fsm.memory.pop()) + screen.scroll_screen_rows (r1,r2) + +def DoMode (fsm): + + screen = fsm.memory[0] + mode = fsm.memory.pop() # Should be 4 + # screen.setReplaceMode () + +def DoLog (fsm): + + screen = fsm.memory[0] + fsm.memory = [screen] + fout = open ('log', 'a') + fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n') + fout.close() + +class term (screen.screen): + + '''This class is an abstract, generic terminal. + This does nothing. This is a placeholder that + provides a common base class for other terminals + such as an ANSI terminal. ''' + + def __init__ (self, r=24, c=80, *args, **kwargs): + + screen.screen.__init__(self, r,c,*args,**kwargs) + +class ANSI (term): + '''This class implements an ANSI (VT100) terminal. + It is a stream filter that recognizes ANSI terminal + escape sequences and maintains the state of a screen object. ''' + + def __init__ (self, r=24,c=80,*args,**kwargs): + + term.__init__(self,r,c,*args,**kwargs) + + #self.screen = screen (24,80) + self.state = FSM.FSM ('INIT',[self]) + self.state.set_default_transition (DoLog, 'INIT') + self.state.add_transition_any ('INIT', DoEmit, 'INIT') + self.state.add_transition ('\x1b', 'INIT', None, 'ESC') + self.state.add_transition_any ('ESC', DoLog, 'INIT') + self.state.add_transition ('(', 'ESC', None, 'G0SCS') + self.state.add_transition (')', 'ESC', None, 'G1SCS') + self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT') + self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT') + self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT') + self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT') + self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT') + self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT') + self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT') + self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad. + self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND') + self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT') + self.state.add_transition ('[', 'ESC', None, 'ELB') + # ELB means Escape Left Bracket. That is ^[[ + self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT') + self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT') + self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT') + self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT') + self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT') + self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT') + self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT') + self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT') + self.state.add_transition ('m', 'ELB', self.do_sgr, 'INIT') + self.state.add_transition ('?', 'ELB', None, 'MODECRAP') + self.state.add_transition_list (string.digits, 'ELB', DoStartNumber, 'NUMBER_1') + self.state.add_transition_list (string.digits, 'NUMBER_1', DoBuildNumber, 'NUMBER_1') + self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT') + self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT') + self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT') + self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT') + self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT') + self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT') + self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT') + ### It gets worse... the 'm' code can have infinite number of + ### number;number;number before it. I've never seen more than two, + ### but the specs say it's allowed. crap! + self.state.add_transition ('m', 'NUMBER_1', self.do_sgr, 'INIT') + ### LED control. Same implementation problem as 'm' code. + self.state.add_transition ('q', 'NUMBER_1', self.do_decsca, 'INIT') + + # \E[?47h switch to alternate screen + # \E[?47l restores to normal screen from alternate screen. + self.state.add_transition_list (string.digits, 'MODECRAP', DoStartNumber, 'MODECRAP_NUM') + self.state.add_transition_list (string.digits, 'MODECRAP_NUM', DoBuildNumber, 'MODECRAP_NUM') + self.state.add_transition ('l', 'MODECRAP_NUM', self.do_modecrap, 'INIT') + self.state.add_transition ('h', 'MODECRAP_NUM', self.do_modecrap, 'INIT') + +#RM Reset Mode Esc [ Ps l none + self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON') + self.state.add_transition_any ('SEMICOLON', DoLog, 'INIT') + self.state.add_transition_list (string.digits, 'SEMICOLON', DoStartNumber, 'NUMBER_2') + self.state.add_transition_list (string.digits, 'NUMBER_2', DoBuildNumber, 'NUMBER_2') + self.state.add_transition_any ('NUMBER_2', DoLog, 'INIT') + self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT') + self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT') + self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT') + ### It gets worse... the 'm' code can have infinite number of + ### number;number;number before it. I've never seen more than two, + ### but the specs say it's allowed. crap! + self.state.add_transition ('m', 'NUMBER_2', self.do_sgr, 'INIT') + ### LED control. Same problem as 'm' code. + self.state.add_transition ('q', 'NUMBER_2', self.do_decsca, 'INIT') + self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X') + + # Create a state for 'q' and 'm' which allows an infinite number of ignored numbers + self.state.add_transition_any ('SEMICOLON_X', DoLog, 'INIT') + self.state.add_transition_list (string.digits, 'SEMICOLON_X', DoStartNumber, 'NUMBER_X') + self.state.add_transition_list (string.digits, 'NUMBER_X', DoBuildNumber, 'NUMBER_X') + self.state.add_transition_any ('NUMBER_X', DoLog, 'INIT') + self.state.add_transition ('m', 'NUMBER_X', self.do_sgr, 'INIT') + self.state.add_transition ('q', 'NUMBER_X', self.do_decsca, 'INIT') + self.state.add_transition (';', 'NUMBER_X', None, 'SEMICOLON_X') + + def process (self, c): + """Process a single character. Called by :meth:`write`.""" + if isinstance(c, bytes): + c = self._decode(c) + self.state.process(c) + + def process_list (self, l): + + self.write(l) + + def write (self, s): + """Process text, writing it to the virtual screen while handling + ANSI escape codes. + """ + if isinstance(s, bytes): + s = self._decode(s) + for c in s: + self.process(c) + + def flush (self): + pass + + def write_ch (self, ch): + '''This puts a character at the current cursor position. The cursor + position is moved forward with wrap-around, but no scrolling is done if + the cursor hits the lower-right corner of the screen. ''' + + if isinstance(ch, bytes): + ch = self._decode(ch) + + #\r and \n both produce a call to cr() and lf(), respectively. + ch = ch[0] + + if ch == u'\r': + self.cr() + return + if ch == u'\n': + self.crlf() + return + if ch == chr(screen.BS): + self.cursor_back() + return + self.put_abs(self.cur_r, self.cur_c, ch) + old_r = self.cur_r + old_c = self.cur_c + self.cursor_forward() + if old_c == self.cur_c: + self.cursor_down() + if old_r != self.cur_r: + self.cursor_home (self.cur_r, 1) + else: + self.scroll_up () + self.cursor_home (self.cur_r, 1) + self.erase_line() + + def do_sgr (self, fsm): + '''Select Graphic Rendition, e.g. color. ''' + screen = fsm.memory[0] + fsm.memory = [screen] + + def do_decsca (self, fsm): + '''Select character protection attribute. ''' + screen = fsm.memory[0] + fsm.memory = [screen] + + def do_modecrap (self, fsm): + '''Handler for \x1b[?<number>h and \x1b[?<number>l. If anyone + wanted to actually use these, they'd need to add more states to the + FSM rather than just improve or override this method. ''' + screen = fsm.memory[0] + fsm.memory = [screen] diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/FSM.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/FSM.py new file mode 100644 index 00000000000..46b392ea08a --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/FSM.py @@ -0,0 +1,334 @@ +#!/usr/bin/env python + +'''This module implements a Finite State Machine (FSM). In addition to state +this FSM also maintains a user defined "memory". So this FSM can be used as a +Push-down Automata (PDA) since a PDA is a FSM + memory. + +The following describes how the FSM works, but you will probably also need to +see the example function to understand how the FSM is used in practice. + +You define an FSM by building tables of transitions. For a given input symbol +the process() method uses these tables to decide what action to call and what +the next state will be. The FSM has a table of transitions that associate: + + (input_symbol, current_state) --> (action, next_state) + +Where "action" is a function you define. The symbols and states can be any +objects. You use the add_transition() and add_transition_list() methods to add +to the transition table. The FSM also has a table of transitions that +associate: + + (current_state) --> (action, next_state) + +You use the add_transition_any() method to add to this transition table. The +FSM also has one default transition that is not associated with any specific +input_symbol or state. You use the set_default_transition() method to set the +default transition. + +When an action function is called it is passed a reference to the FSM. The +action function may then access attributes of the FSM such as input_symbol, +current_state, or "memory". The "memory" attribute can be any object that you +want to pass along to the action functions. It is not used by the FSM itself. +For parsing you would typically pass a list to be used as a stack. + +The processing sequence is as follows. The process() method is given an +input_symbol to process. The FSM will search the table of transitions that +associate: + + (input_symbol, current_state) --> (action, next_state) + +If the pair (input_symbol, current_state) is found then process() will call the +associated action function and then set the current state to the next_state. + +If the FSM cannot find a match for (input_symbol, current_state) it will then +search the table of transitions that associate: + + (current_state) --> (action, next_state) + +If the current_state is found then the process() method will call the +associated action function and then set the current state to the next_state. +Notice that this table lacks an input_symbol. It lets you define transitions +for a current_state and ANY input_symbol. Hence, it is called the "any" table. +Remember, it is always checked after first searching the table for a specific +(input_symbol, current_state). + +For the case where the FSM did not match either of the previous two cases the +FSM will try to use the default transition. If the default transition is +defined then the process() method will call the associated action function and +then set the current state to the next_state. This lets you define a default +transition as a catch-all case. You can think of it as an exception handler. +There can be only one default transition. + +Finally, if none of the previous cases are defined for an input_symbol and +current_state then the FSM will raise an exception. This may be desirable, but +you can always prevent this just by defining a default transition. + +Noah Spurrier 20020822 + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +class ExceptionFSM(Exception): + + '''This is the FSM Exception class.''' + + def __init__(self, value): + self.value = value + + def __str__(self): + return 'ExceptionFSM: ' + str(self.value) + +class FSM: + + '''This is a Finite State Machine (FSM). + ''' + + def __init__(self, initial_state, memory=None): + + '''This creates the FSM. You set the initial state here. The "memory" + attribute is any object that you want to pass along to the action + functions. It is not used by the FSM. For parsing you would typically + pass a list to be used as a stack. ''' + + # Map (input_symbol, current_state) --> (action, next_state). + self.state_transitions = {} + # Map (current_state) --> (action, next_state). + self.state_transitions_any = {} + self.default_transition = None + + self.input_symbol = None + self.initial_state = initial_state + self.current_state = self.initial_state + self.next_state = None + self.action = None + self.memory = memory + + def reset (self): + + '''This sets the current_state to the initial_state and sets + input_symbol to None. The initial state was set by the constructor + __init__(). ''' + + self.current_state = self.initial_state + self.input_symbol = None + + def add_transition (self, input_symbol, state, action=None, next_state=None): + + '''This adds a transition that associates: + + (input_symbol, current_state) --> (action, next_state) + + The action may be set to None in which case the process() method will + ignore the action and only set the next_state. The next_state may be + set to None in which case the current state will be unchanged. + + You can also set transitions for a list of symbols by using + add_transition_list(). ''' + + if next_state is None: + next_state = state + self.state_transitions[(input_symbol, state)] = (action, next_state) + + def add_transition_list (self, list_input_symbols, state, action=None, next_state=None): + + '''This adds the same transition for a list of input symbols. + You can pass a list or a string. Note that it is handy to use + string.digits, string.whitespace, string.letters, etc. to add + transitions that match character classes. + + The action may be set to None in which case the process() method will + ignore the action and only set the next_state. The next_state may be + set to None in which case the current state will be unchanged. ''' + + if next_state is None: + next_state = state + for input_symbol in list_input_symbols: + self.add_transition (input_symbol, state, action, next_state) + + def add_transition_any (self, state, action=None, next_state=None): + + '''This adds a transition that associates: + + (current_state) --> (action, next_state) + + That is, any input symbol will match the current state. + The process() method checks the "any" state associations after it first + checks for an exact match of (input_symbol, current_state). + + The action may be set to None in which case the process() method will + ignore the action and only set the next_state. The next_state may be + set to None in which case the current state will be unchanged. ''' + + if next_state is None: + next_state = state + self.state_transitions_any [state] = (action, next_state) + + def set_default_transition (self, action, next_state): + + '''This sets the default transition. This defines an action and + next_state if the FSM cannot find the input symbol and the current + state in the transition list and if the FSM cannot find the + current_state in the transition_any list. This is useful as a final + fall-through state for catching errors and undefined states. + + The default transition can be removed by setting the attribute + default_transition to None. ''' + + self.default_transition = (action, next_state) + + def get_transition (self, input_symbol, state): + + '''This returns (action, next state) given an input_symbol and state. + This does not modify the FSM state, so calling this method has no side + effects. Normally you do not call this method directly. It is called by + process(). + + The sequence of steps to check for a defined transition goes from the + most specific to the least specific. + + 1. Check state_transitions[] that match exactly the tuple, + (input_symbol, state) + + 2. Check state_transitions_any[] that match (state) + In other words, match a specific state and ANY input_symbol. + + 3. Check if the default_transition is defined. + This catches any input_symbol and any state. + This is a handler for errors, undefined states, or defaults. + + 4. No transition was defined. If we get here then raise an exception. + ''' + + if (input_symbol, state) in self.state_transitions: + return self.state_transitions[(input_symbol, state)] + elif state in self.state_transitions_any: + return self.state_transitions_any[state] + elif self.default_transition is not None: + return self.default_transition + else: + raise ExceptionFSM ('Transition is undefined: (%s, %s).' % + (str(input_symbol), str(state)) ) + + def process (self, input_symbol): + + '''This is the main method that you call to process input. This may + cause the FSM to change state and call an action. This method calls + get_transition() to find the action and next_state associated with the + input_symbol and current_state. If the action is None then the action + is not called and only the current state is changed. This method + processes one complete input symbol. You can process a list of symbols + (or a string) by calling process_list(). ''' + + self.input_symbol = input_symbol + (self.action, self.next_state) = self.get_transition (self.input_symbol, self.current_state) + if self.action is not None: + self.action (self) + self.current_state = self.next_state + self.next_state = None + + def process_list (self, input_symbols): + + '''This takes a list and sends each element to process(). The list may + be a string or any iterable object. ''' + + for s in input_symbols: + self.process (s) + +############################################################################## +# The following is an example that demonstrates the use of the FSM class to +# process an RPN expression. Run this module from the command line. You will +# get a prompt > for input. Enter an RPN Expression. Numbers may be integers. +# Operators are * / + - Use the = sign to evaluate and print the expression. +# For example: +# +# 167 3 2 2 * * * 1 - = +# +# will print: +# +# 2003 +############################################################################## + +import sys +import string + +PY3 = (sys.version_info[0] >= 3) + +# +# These define the actions. +# Note that "memory" is a list being used as a stack. +# + +def BeginBuildNumber (fsm): + fsm.memory.append (fsm.input_symbol) + +def BuildNumber (fsm): + s = fsm.memory.pop () + s = s + fsm.input_symbol + fsm.memory.append (s) + +def EndBuildNumber (fsm): + s = fsm.memory.pop () + fsm.memory.append (int(s)) + +def DoOperator (fsm): + ar = fsm.memory.pop() + al = fsm.memory.pop() + if fsm.input_symbol == '+': + fsm.memory.append (al + ar) + elif fsm.input_symbol == '-': + fsm.memory.append (al - ar) + elif fsm.input_symbol == '*': + fsm.memory.append (al * ar) + elif fsm.input_symbol == '/': + fsm.memory.append (al / ar) + +def DoEqual (fsm): + print(str(fsm.memory.pop())) + +def Error (fsm): + print('That does not compute.') + print(str(fsm.input_symbol)) + +def main(): + + '''This is where the example starts and the FSM state transitions are + defined. Note that states are strings (such as 'INIT'). This is not + necessary, but it makes the example easier to read. ''' + + f = FSM ('INIT', []) + f.set_default_transition (Error, 'INIT') + f.add_transition_any ('INIT', None, 'INIT') + f.add_transition ('=', 'INIT', DoEqual, 'INIT') + f.add_transition_list (string.digits, 'INIT', BeginBuildNumber, 'BUILDING_NUMBER') + f.add_transition_list (string.digits, 'BUILDING_NUMBER', BuildNumber, 'BUILDING_NUMBER') + f.add_transition_list (string.whitespace, 'BUILDING_NUMBER', EndBuildNumber, 'INIT') + f.add_transition_list ('+-*/', 'INIT', DoOperator, 'INIT') + + print() + print('Enter an RPN Expression.') + print('Numbers may be integers. Operators are * / + -') + print('Use the = sign to evaluate and print the expression.') + print('For example: ') + print(' 167 3 2 2 * * * 1 - =') + inputstr = (input if PY3 else raw_input)('> ') # analysis:ignore + f.process_list(inputstr) + + +if __name__ == '__main__': + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/__init__.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/__init__.py new file mode 100644 index 00000000000..2a18d1911a9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/__init__.py @@ -0,0 +1,85 @@ +'''Pexpect is a Python module for spawning child applications and controlling +them automatically. Pexpect can be used for automating interactive applications +such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup +scripts for duplicating software package installations on different servers. It +can be used for automated software testing. Pexpect is in the spirit of Don +Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python +require TCL and Expect or require C extensions to be compiled. Pexpect does not +use C, Expect, or TCL extensions. It should work on any platform that supports +the standard Python pty module. The Pexpect interface focuses on ease of use so +that simple tasks are easy. + +There are two main interfaces to the Pexpect system; these are the function, +run() and the class, spawn. The spawn class is more powerful. The run() +function is simpler than spawn, and is good for quickly calling program. When +you call the run() function it executes a given program and then returns the +output. This is a handy replacement for os.system(). + +For example:: + + pexpect.run('ls -la') + +The spawn class is the more powerful interface to the Pexpect system. You can +use this to spawn a child program then interact with it by sending input and +expecting responses (waiting for patterns in the child's output). + +For example:: + + child = pexpect.spawn('scp foo user@example.com:.') + child.expect('Password:') + child.sendline(mypassword) + +This works even for commands that ask for passwords or other input outside of +the normal stdio streams. For example, ssh reads input directly from the TTY +device which bypasses stdin. + +Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett, +Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids +vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin, +Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey, +Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume +Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John +Spiegel, Jan Grant, and Shane Kerr. Let me know if I forgot anyone. + +Pexpect is free, open source, and all that good stuff. +http://pexpect.sourceforge.net/ + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +import sys +PY3 = (sys.version_info[0] >= 3) + +from .exceptions import ExceptionPexpect, EOF, TIMEOUT +from .utils import split_command_line, which, is_executable_file +from .expect import Expecter, searcher_re, searcher_string + +if sys.platform != 'win32': + # On Unix, these are available at the top level for backwards compatibility + from .pty_spawn import spawn, spawnu + from .run import run, runu + +__version__ = '4.6.0' +__revision__ = '' +__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu', + 'which', 'split_command_line', '__version__', '__revision__'] + + + +# vim: set shiftround expandtab tabstop=4 shiftwidth=4 ft=python autoindent : diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/_async.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/_async.py new file mode 100644 index 00000000000..bdd515b1f50 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/_async.py @@ -0,0 +1,87 @@ +import asyncio +import errno + +from pexpect import EOF + +@asyncio.coroutine +def expect_async(expecter, timeout=None): + # First process data that was previously read - if it maches, we don't need + # async stuff. + previously_read = expecter.spawn.buffer + expecter.spawn._buffer = expecter.spawn.buffer_type() + expecter.spawn._before = expecter.spawn.buffer_type() + idx = expecter.new_data(previously_read) + if idx is not None: + return idx + if not expecter.spawn.async_pw_transport: + pw = PatternWaiter() + pw.set_expecter(expecter) + transport, pw = yield from asyncio.get_event_loop()\ + .connect_read_pipe(lambda: pw, expecter.spawn) + expecter.spawn.async_pw_transport = pw, transport + else: + pw, transport = expecter.spawn.async_pw_transport + pw.set_expecter(expecter) + transport.resume_reading() + try: + return (yield from asyncio.wait_for(pw.fut, timeout)) + except asyncio.TimeoutError as e: + transport.pause_reading() + return expecter.timeout(e) + + +class PatternWaiter(asyncio.Protocol): + transport = None + + def set_expecter(self, expecter): + self.expecter = expecter + self.fut = asyncio.Future() + + def found(self, result): + if not self.fut.done(): + self.fut.set_result(result) + self.transport.pause_reading() + + def error(self, exc): + if not self.fut.done(): + self.fut.set_exception(exc) + self.transport.pause_reading() + + def connection_made(self, transport): + self.transport = transport + + def data_received(self, data): + spawn = self.expecter.spawn + s = spawn._decoder.decode(data) + spawn._log(s, 'read') + + if self.fut.done(): + spawn._buffer.write(s) + return + + try: + index = self.expecter.new_data(s) + if index is not None: + # Found a match + self.found(index) + except Exception as e: + self.expecter.errored() + self.error(e) + + def eof_received(self): + # N.B. If this gets called, async will close the pipe (the spawn object) + # for us + try: + self.expecter.spawn.flag_eof = True + index = self.expecter.eof() + except EOF as e: + self.error(e) + else: + self.found(index) + + def connection_lost(self, exc): + if isinstance(exc, OSError) and exc.errno == errno.EIO: + # We may get here without eof_received being called, e.g on Linux + self.eof_received() + elif exc is not None: + self.error(exc) diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh b/lldb/third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh new file mode 100644 index 00000000000..c734ac90b85 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh @@ -0,0 +1,16 @@ +# Different platforms have different names for the systemwide bashrc +if [[ -f /etc/bashrc ]]; then + source /etc/bashrc +fi +if [[ -f /etc/bash.bashrc ]]; then + source /etc/bash.bashrc +fi +if [[ -f ~/.bashrc ]]; then + source ~/.bashrc +fi + +# Reset PS1 so pexpect can find it +PS1="$" + +# Unset PROMPT_COMMAND, so that it can't change PS1 to something unexpected. +unset PROMPT_COMMAND diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/exceptions.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/exceptions.py new file mode 100644 index 00000000000..cb360f02614 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/exceptions.py @@ -0,0 +1,35 @@ +"""Exception classes used by Pexpect""" + +import traceback +import sys + +class ExceptionPexpect(Exception): + '''Base class for all exceptions raised by this module. + ''' + + def __init__(self, value): + super(ExceptionPexpect, self).__init__(value) + self.value = value + + def __str__(self): + return str(self.value) + + def get_trace(self): + '''This returns an abbreviated stack trace with lines that only concern + the caller. In other words, the stack trace inside the Pexpect module + is not included. ''' + + tblist = traceback.extract_tb(sys.exc_info()[2]) + tblist = [item for item in tblist if ('pexpect/__init__' not in item[0]) + and ('pexpect/expect' not in item[0])] + tblist = traceback.format_list(tblist) + return ''.join(tblist) + + +class EOF(ExceptionPexpect): + '''Raised when EOF is read from a child. + This usually means the child has exited.''' + + +class TIMEOUT(ExceptionPexpect): + '''Raised when a read time exceeds the timeout. ''' diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/expect.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/expect.py new file mode 100644 index 00000000000..1c0275b4853 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/expect.py @@ -0,0 +1,306 @@ +import time + +from .exceptions import EOF, TIMEOUT + +class Expecter(object): + def __init__(self, spawn, searcher, searchwindowsize=-1): + self.spawn = spawn + self.searcher = searcher + if searchwindowsize == -1: + searchwindowsize = spawn.searchwindowsize + self.searchwindowsize = searchwindowsize + + def new_data(self, data): + spawn = self.spawn + searcher = self.searcher + + pos = spawn._buffer.tell() + spawn._buffer.write(data) + spawn._before.write(data) + + # determine which chunk of data to search; if a windowsize is + # specified, this is the *new* data + the preceding <windowsize> bytes + if self.searchwindowsize: + spawn._buffer.seek(max(0, pos - self.searchwindowsize)) + window = spawn._buffer.read(self.searchwindowsize + len(data)) + else: + # otherwise, search the whole buffer (really slow for large datasets) + window = spawn.buffer + index = searcher.search(window, len(data)) + if index >= 0: + spawn._buffer = spawn.buffer_type() + spawn._buffer.write(window[searcher.end:]) + spawn.before = spawn._before.getvalue()[0:-(len(window) - searcher.start)] + spawn._before = spawn.buffer_type() + spawn.after = window[searcher.start: searcher.end] + spawn.match = searcher.match + spawn.match_index = index + # Found a match + return index + elif self.searchwindowsize: + spawn._buffer = spawn.buffer_type() + spawn._buffer.write(window) + + def eof(self, err=None): + spawn = self.spawn + + spawn.before = spawn.buffer + spawn._buffer = spawn.buffer_type() + spawn._before = spawn.buffer_type() + spawn.after = EOF + index = self.searcher.eof_index + if index >= 0: + spawn.match = EOF + spawn.match_index = index + return index + else: + spawn.match = None + spawn.match_index = None + msg = str(spawn) + msg += '\nsearcher: %s' % self.searcher + if err is not None: + msg = str(err) + '\n' + msg + raise EOF(msg) + + def timeout(self, err=None): + spawn = self.spawn + + spawn.before = spawn.buffer + spawn.after = TIMEOUT + index = self.searcher.timeout_index + if index >= 0: + spawn.match = TIMEOUT + spawn.match_index = index + return index + else: + spawn.match = None + spawn.match_index = None + msg = str(spawn) + msg += '\nsearcher: %s' % self.searcher + if err is not None: + msg = str(err) + '\n' + msg + raise TIMEOUT(msg) + + def errored(self): + spawn = self.spawn + spawn.before = spawn.buffer + spawn.after = None + spawn.match = None + spawn.match_index = None + + def expect_loop(self, timeout=-1): + """Blocking expect""" + spawn = self.spawn + + if timeout is not None: + end_time = time.time() + timeout + + try: + incoming = spawn.buffer + spawn._buffer = spawn.buffer_type() + spawn._before = spawn.buffer_type() + while True: + idx = self.new_data(incoming) + # Keep reading until exception or return. + if idx is not None: + return idx + # No match at this point + if (timeout is not None) and (timeout < 0): + return self.timeout() + # Still have time left, so read more data + incoming = spawn.read_nonblocking(spawn.maxread, timeout) + if self.spawn.delayafterread is not None: + time.sleep(self.spawn.delayafterread) + if timeout is not None: + timeout = end_time - time.time() + except EOF as e: + return self.eof(e) + except TIMEOUT as e: + return self.timeout(e) + except: + self.errored() + raise + + +class searcher_string(object): + '''This is a plain string search helper for the spawn.expect_any() method. + This helper class is for speed. For more powerful regex patterns + see the helper class, searcher_re. + + Attributes: + + eof_index - index of EOF, or -1 + timeout_index - index of TIMEOUT, or -1 + + After a successful match by the search() method the following attributes + are available: + + start - index into the buffer, first byte of match + end - index into the buffer, first byte after match + match - the matching string itself + + ''' + + def __init__(self, strings): + '''This creates an instance of searcher_string. This argument 'strings' + may be a list; a sequence of strings; or the EOF or TIMEOUT types. ''' + + self.eof_index = -1 + self.timeout_index = -1 + self._strings = [] + for n, s in enumerate(strings): + if s is EOF: + self.eof_index = n + continue + if s is TIMEOUT: + self.timeout_index = n + continue + self._strings.append((n, s)) + + def __str__(self): + '''This returns a human-readable string that represents the state of + the object.''' + + ss = [(ns[0], ' %d: %r' % ns) for ns in self._strings] + ss.append((-1, 'searcher_string:')) + if self.eof_index >= 0: + ss.append((self.eof_index, ' %d: EOF' % self.eof_index)) + if self.timeout_index >= 0: + ss.append((self.timeout_index, + ' %d: TIMEOUT' % self.timeout_index)) + ss.sort() + ss = list(zip(*ss))[1] + return '\n'.join(ss) + + def search(self, buffer, freshlen, searchwindowsize=None): + '''This searches 'buffer' for the first occurrence of one of the search + strings. 'freshlen' must indicate the number of bytes at the end of + 'buffer' which have not been searched before. It helps to avoid + searching the same, possibly big, buffer over and over again. + + See class spawn for the 'searchwindowsize' argument. + + If there is a match this returns the index of that string, and sets + 'start', 'end' and 'match'. Otherwise, this returns -1. ''' + + first_match = None + + # 'freshlen' helps a lot here. Further optimizations could + # possibly include: + # + # using something like the Boyer-Moore Fast String Searching + # Algorithm; pre-compiling the search through a list of + # strings into something that can scan the input once to + # search for all N strings; realize that if we search for + # ['bar', 'baz'] and the input is '...foo' we need not bother + # rescanning until we've read three more bytes. + # + # Sadly, I don't know enough about this interesting topic. /grahn + + for index, s in self._strings: + if searchwindowsize is None: + # the match, if any, can only be in the fresh data, + # or at the very end of the old data + offset = -(freshlen + len(s)) + else: + # better obey searchwindowsize + offset = -searchwindowsize + n = buffer.find(s, offset) + if n >= 0 and (first_match is None or n < first_match): + first_match = n + best_index, best_match = index, s + if first_match is None: + return -1 + self.match = best_match + self.start = first_match + self.end = self.start + len(self.match) + return best_index + + +class searcher_re(object): + '''This is regular expression string search helper for the + spawn.expect_any() method. This helper class is for powerful + pattern matching. For speed, see the helper class, searcher_string. + + Attributes: + + eof_index - index of EOF, or -1 + timeout_index - index of TIMEOUT, or -1 + + After a successful match by the search() method the following attributes + are available: + + start - index into the buffer, first byte of match + end - index into the buffer, first byte after match + match - the re.match object returned by a successful re.search + + ''' + + def __init__(self, patterns): + '''This creates an instance that searches for 'patterns' Where + 'patterns' may be a list or other sequence of compiled regular + expressions, or the EOF or TIMEOUT types.''' + + self.eof_index = -1 + self.timeout_index = -1 + self._searches = [] + for n, s in zip(list(range(len(patterns))), patterns): + if s is EOF: + self.eof_index = n + continue + if s is TIMEOUT: + self.timeout_index = n + continue + self._searches.append((n, s)) + + def __str__(self): + '''This returns a human-readable string that represents the state of + the object.''' + + #ss = [(n, ' %d: re.compile("%s")' % + # (n, repr(s.pattern))) for n, s in self._searches] + ss = list() + for n, s in self._searches: + ss.append((n, ' %d: re.compile(%r)' % (n, s.pattern))) + ss.append((-1, 'searcher_re:')) + if self.eof_index >= 0: + ss.append((self.eof_index, ' %d: EOF' % self.eof_index)) + if self.timeout_index >= 0: + ss.append((self.timeout_index, ' %d: TIMEOUT' % + self.timeout_index)) + ss.sort() + ss = list(zip(*ss))[1] + return '\n'.join(ss) + + def search(self, buffer, freshlen, searchwindowsize=None): + '''This searches 'buffer' for the first occurrence of one of the regular + expressions. 'freshlen' must indicate the number of bytes at the end of + 'buffer' which have not been searched before. + + See class spawn for the 'searchwindowsize' argument. + + If there is a match this returns the index of that string, and sets + 'start', 'end' and 'match'. Otherwise, returns -1.''' + + first_match = None + # 'freshlen' doesn't help here -- we cannot predict the + # length of a match, and the re module provides no help. + if searchwindowsize is None: + searchstart = 0 + else: + searchstart = max(0, len(buffer) - searchwindowsize) + for index, s in self._searches: + match = s.search(buffer, searchstart) + if match is None: + continue + n = match.start() + if first_match is None or n < first_match: + first_match = n + the_match = match + best_index = index + if first_match is None: + return -1 + self.start = first_match + self.match = the_match + self.end = self.match.end() + return best_index diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py new file mode 100644 index 00000000000..cddd50e1005 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py @@ -0,0 +1,148 @@ +'''This is like pexpect, but it will work with any file descriptor that you +pass it. You are responsible for opening and close the file descriptor. +This allows you to use Pexpect with sockets and named pipes (FIFOs). + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from .spawnbase import SpawnBase +from .exceptions import ExceptionPexpect, TIMEOUT +from .utils import select_ignore_interrupts, poll_ignore_interrupts +import os + +__all__ = ['fdspawn'] + +class fdspawn(SpawnBase): + '''This is like pexpect.spawn but allows you to supply your own open file + descriptor. For example, you could use it to read through a file looking + for patterns, or to control a modem or serial device. ''' + + def __init__ (self, fd, args=None, timeout=30, maxread=2000, searchwindowsize=None, + logfile=None, encoding=None, codec_errors='strict', use_poll=False): + '''This takes a file descriptor (an int) or an object that support the + fileno() method (returning an int). All Python file-like objects + support fileno(). ''' + + if type(fd) != type(0) and hasattr(fd, 'fileno'): + fd = fd.fileno() + + if type(fd) != type(0): + raise ExceptionPexpect('The fd argument is not an int. If this is a command string then maybe you want to use pexpect.spawn.') + + try: # make sure fd is a valid file descriptor + os.fstat(fd) + except OSError: + raise ExceptionPexpect('The fd argument is not a valid file descriptor.') + + self.args = None + self.command = None + SpawnBase.__init__(self, timeout, maxread, searchwindowsize, logfile, + encoding=encoding, codec_errors=codec_errors) + self.child_fd = fd + self.own_fd = False + self.closed = False + self.name = '<file descriptor %d>' % fd + self.use_poll = use_poll + + def close (self): + """Close the file descriptor. + + Calling this method a second time does nothing, but if the file + descriptor was closed elsewhere, :class:`OSError` will be raised. + """ + if self.child_fd == -1: + return + + self.flush() + os.close(self.child_fd) + self.child_fd = -1 + self.closed = True + + def isalive (self): + '''This checks if the file descriptor is still valid. If :func:`os.fstat` + does not raise an exception then we assume it is alive. ''' + + if self.child_fd == -1: + return False + try: + os.fstat(self.child_fd) + return True + except: + return False + + def terminate (self, force=False): # pragma: no cover + '''Deprecated and invalid. Just raises an exception.''' + raise ExceptionPexpect('This method is not valid for file descriptors.') + + # These four methods are left around for backwards compatibility, but not + # documented as part of fdpexpect. You're encouraged to use os.write + # directly. + def send(self, s): + "Write to fd, return number of bytes written" + s = self._coerce_send_string(s) + self._log(s, 'send') + + b = self._encoder.encode(s, final=False) + return os.write(self.child_fd, b) + + def sendline(self, s): + "Write to fd with trailing newline, return number of bytes written" + s = self._coerce_send_string(s) + return self.send(s + self.linesep) + + def write(self, s): + "Write to fd, return None" + self.send(s) + + def writelines(self, sequence): + "Call self.write() for each item in sequence" + for s in sequence: + self.write(s) + + def read_nonblocking(self, size=1, timeout=-1): + """ + Read from the file descriptor and return the result as a string. + + The read_nonblocking method of :class:`SpawnBase` assumes that a call + to os.read will not block (timeout parameter is ignored). This is not + the case for POSIX file-like objects such as sockets and serial ports. + + Use :func:`select.select`, timeout is implemented conditionally for + POSIX systems. + + :param int size: Read at most *size* bytes. + :param int timeout: Wait timeout seconds for file descriptor to be + ready to read. When -1 (default), use self.timeout. When 0, poll. + :return: String containing the bytes read + """ + if os.name == 'posix': + if timeout == -1: + timeout = self.timeout + rlist = [self.child_fd] + wlist = [] + xlist = [] + if self.use_poll: + rlist = poll_ignore_interrupts(rlist, timeout) + else: + rlist, wlist, xlist = select_ignore_interrupts( + rlist, wlist, xlist, timeout + ) + if self.child_fd not in rlist: + raise TIMEOUT('Timeout exceeded.') + return super(fdspawn, self).read_nonblocking(size) diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py new file mode 100644 index 00000000000..4bb58cfe76c --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py @@ -0,0 +1,188 @@ +"""Provides an interface like pexpect.spawn interface using subprocess.Popen +""" +import os +import threading +import subprocess +import sys +import time +import signal +import shlex + +try: + from queue import Queue, Empty # Python 3 +except ImportError: + from Queue import Queue, Empty # Python 2 + +from .spawnbase import SpawnBase, PY3 +from .exceptions import EOF +from .utils import string_types + +class PopenSpawn(SpawnBase): + def __init__(self, cmd, timeout=30, maxread=2000, searchwindowsize=None, + logfile=None, cwd=None, env=None, encoding=None, + codec_errors='strict', preexec_fn=None): + super(PopenSpawn, self).__init__(timeout=timeout, maxread=maxread, + searchwindowsize=searchwindowsize, logfile=logfile, + encoding=encoding, codec_errors=codec_errors) + + # Note that `SpawnBase` initializes `self.crlf` to `\r\n` + # because the default behaviour for a PTY is to convert + # incoming LF to `\r\n` (see the `onlcr` flag and + # https://stackoverflow.com/a/35887657/5397009). Here we set + # it to `os.linesep` because that is what the spawned + # application outputs by default and `popen` doesn't translate + # anything. + if encoding is None: + self.crlf = os.linesep.encode ("ascii") + else: + self.crlf = self.string_type (os.linesep) + + kwargs = dict(bufsize=0, stdin=subprocess.PIPE, + stderr=subprocess.STDOUT, stdout=subprocess.PIPE, + cwd=cwd, preexec_fn=preexec_fn, env=env) + + if sys.platform == 'win32': + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + kwargs['startupinfo'] = startupinfo + kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP + + if isinstance(cmd, string_types) and sys.platform != 'win32': + cmd = shlex.split(cmd, posix=os.name == 'posix') + + self.proc = subprocess.Popen(cmd, **kwargs) + self.pid = self.proc.pid + self.closed = False + self._buf = self.string_type() + + self._read_queue = Queue() + self._read_thread = threading.Thread(target=self._read_incoming) + self._read_thread.setDaemon(True) + self._read_thread.start() + + _read_reached_eof = False + + def read_nonblocking(self, size, timeout): + buf = self._buf + if self._read_reached_eof: + # We have already finished reading. Use up any buffered data, + # then raise EOF + if buf: + self._buf = buf[size:] + return buf[:size] + else: + self.flag_eof = True + raise EOF('End Of File (EOF).') + + if timeout == -1: + timeout = self.timeout + elif timeout is None: + timeout = 1e6 + + t0 = time.time() + while (time.time() - t0) < timeout and size and len(buf) < size: + try: + incoming = self._read_queue.get_nowait() + except Empty: + break + else: + if incoming is None: + self._read_reached_eof = True + break + + buf += self._decoder.decode(incoming, final=False) + + r, self._buf = buf[:size], buf[size:] + + self._log(r, 'read') + return r + + def _read_incoming(self): + """Run in a thread to move output from a pipe to a queue.""" + fileno = self.proc.stdout.fileno() + while 1: + buf = b'' + try: + buf = os.read(fileno, 1024) + except OSError as e: + self._log(e, 'read') + + if not buf: + # This indicates we have reached EOF + self._read_queue.put(None) + return + + self._read_queue.put(buf) + + def write(self, s): + '''This is similar to send() except that there is no return value. + ''' + self.send(s) + + def writelines(self, sequence): + '''This calls write() for each element in the sequence. + + The sequence can be any iterable object producing strings, typically a + list of strings. This does not add line separators. There is no return + value. + ''' + for s in sequence: + self.send(s) + + def send(self, s): + '''Send data to the subprocess' stdin. + + Returns the number of bytes written. + ''' + s = self._coerce_send_string(s) + self._log(s, 'send') + + b = self._encoder.encode(s, final=False) + if PY3: + return self.proc.stdin.write(b) + else: + # On Python 2, .write() returns None, so we return the length of + # bytes written ourselves. This assumes they all got written. + self.proc.stdin.write(b) + return len(b) + + def sendline(self, s=''): + '''Wraps send(), sending string ``s`` to child process, with os.linesep + automatically appended. Returns number of bytes written. ''' + + n = self.send(s) + return n + self.send(self.linesep) + + def wait(self): + '''Wait for the subprocess to finish. + + Returns the exit code. + ''' + status = self.proc.wait() + if status >= 0: + self.exitstatus = status + self.signalstatus = None + else: + self.exitstatus = None + self.signalstatus = -status + self.terminated = True + return status + + def kill(self, sig): + '''Sends a Unix signal to the subprocess. + + Use constants from the :mod:`signal` module to specify which signal. + ''' + if sys.platform == 'win32': + if sig in [signal.SIGINT, signal.CTRL_C_EVENT]: + sig = signal.CTRL_C_EVENT + elif sig in [signal.SIGBREAK, signal.CTRL_BREAK_EVENT]: + sig = signal.CTRL_BREAK_EVENT + else: + sig = signal.SIGTERM + + os.kill(self.proc.pid, sig) + + def sendeof(self): + '''Closes the stdin pipe from the writing end.''' + self.proc.stdin.close() diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py new file mode 100644 index 00000000000..e0e2b54fd03 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py @@ -0,0 +1,833 @@ +import os +import sys +import time +import pty +import tty +import errno +import signal +from contextlib import contextmanager + +import ptyprocess +from ptyprocess.ptyprocess import use_native_pty_fork + +from .exceptions import ExceptionPexpect, EOF, TIMEOUT +from .spawnbase import SpawnBase +from .utils import ( + which, split_command_line, select_ignore_interrupts, poll_ignore_interrupts +) + +@contextmanager +def _wrap_ptyprocess_err(): + """Turn ptyprocess errors into our own ExceptionPexpect errors""" + try: + yield + except ptyprocess.PtyProcessError as e: + raise ExceptionPexpect(*e.args) + +PY3 = (sys.version_info[0] >= 3) + +class spawn(SpawnBase): + '''This is the main class interface for Pexpect. Use this class to start + and control child applications. ''' + + # This is purely informational now - changing it has no effect + use_native_pty_fork = use_native_pty_fork + + def __init__(self, command, args=[], timeout=30, maxread=2000, + searchwindowsize=None, logfile=None, cwd=None, env=None, + ignore_sighup=False, echo=True, preexec_fn=None, + encoding=None, codec_errors='strict', dimensions=None, + use_poll=False): + '''This is the constructor. The command parameter may be a string that + includes a command and any arguments to the command. For example:: + + child = pexpect.spawn('/usr/bin/ftp') + child = pexpect.spawn('/usr/bin/ssh user@example.com') + child = pexpect.spawn('ls -latr /tmp') + + You may also construct it with a list of arguments like so:: + + child = pexpect.spawn('/usr/bin/ftp', []) + child = pexpect.spawn('/usr/bin/ssh', ['user@example.com']) + child = pexpect.spawn('ls', ['-latr', '/tmp']) + + After this the child application will be created and will be ready to + talk to. For normal use, see expect() and send() and sendline(). + + Remember that Pexpect does NOT interpret shell meta characters such as + redirect, pipe, or wild cards (``>``, ``|``, or ``*``). This is a + common mistake. If you want to run a command and pipe it through + another command then you must also start a shell. For example:: + + child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"') + child.expect(pexpect.EOF) + + The second form of spawn (where you pass a list of arguments) is useful + in situations where you wish to spawn a command and pass it its own + argument list. This can make syntax more clear. For example, the + following is equivalent to the previous example:: + + shell_cmd = 'ls -l | grep LOG > logs.txt' + child = pexpect.spawn('/bin/bash', ['-c', shell_cmd]) + child.expect(pexpect.EOF) + + The maxread attribute sets the read buffer size. This is maximum number + of bytes that Pexpect will try to read from a TTY at one time. Setting + the maxread size to 1 will turn off buffering. Setting the maxread + value higher may help performance in cases where large amounts of + output are read back from the child. This feature is useful in + conjunction with searchwindowsize. + + When the keyword argument *searchwindowsize* is None (default), the + full buffer is searched at each iteration of receiving incoming data. + The default number of bytes scanned at each iteration is very large + and may be reduced to collaterally reduce search cost. After + :meth:`~.expect` returns, the full buffer attribute remains up to + size *maxread* irrespective of *searchwindowsize* value. + + When the keyword argument ``timeout`` is specified as a number, + (default: *30*), then :class:`TIMEOUT` will be raised after the value + specified has elapsed, in seconds, for any of the :meth:`~.expect` + family of method calls. When None, TIMEOUT will not be raised, and + :meth:`~.expect` may block indefinitely until match. + + + The logfile member turns on or off logging. All input and output will + be copied to the given file object. Set logfile to None to stop + logging. This is the default. Set logfile to sys.stdout to echo + everything to standard output. The logfile is flushed after each write. + + Example log input and output to a file:: + + child = pexpect.spawn('some_command') + fout = open('mylog.txt','wb') + child.logfile = fout + + Example log to stdout:: + + # In Python 2: + child = pexpect.spawn('some_command') + child.logfile = sys.stdout + + # In Python 3, we'll use the ``encoding`` argument to decode data + # from the subprocess and handle it as unicode: + child = pexpect.spawn('some_command', encoding='utf-8') + child.logfile = sys.stdout + + The logfile_read and logfile_send members can be used to separately log + the input from the child and output sent to the child. Sometimes you + don't want to see everything you write to the child. You only want to + log what the child sends back. For example:: + + child = pexpect.spawn('some_command') + child.logfile_read = sys.stdout + + You will need to pass an encoding to spawn in the above code if you are + using Python 3. + + To separately log output sent to the child use logfile_send:: + + child.logfile_send = fout + + If ``ignore_sighup`` is True, the child process will ignore SIGHUP + signals. The default is False from Pexpect 4.0, meaning that SIGHUP + will be handled normally by the child. + + The delaybeforesend helps overcome a weird behavior that many users + were experiencing. The typical problem was that a user would expect() a + "Password:" prompt and then immediately call sendline() to send the + password. The user would then see that their password was echoed back + to them. Passwords don't normally echo. The problem is caused by the + fact that most applications print out the "Password" prompt and then + turn off stdin echo, but if you send your password before the + application turned off echo, then you get your password echoed. + Normally this wouldn't be a problem when interacting with a human at a + real keyboard. If you introduce a slight delay just before writing then + this seems to clear up the problem. This was such a common problem for + many users that I decided that the default pexpect behavior should be + to sleep just before writing to the child application. 1/20th of a + second (50 ms) seems to be enough to clear up the problem. You can set + delaybeforesend to None to return to the old behavior. + + Note that spawn is clever about finding commands on your path. + It uses the same logic that "which" uses to find executables. + + If you wish to get the exit status of the child you must call the + close() method. The exit or signal status of the child will be stored + in self.exitstatus or self.signalstatus. If the child exited normally + then exitstatus will store the exit return code and signalstatus will + be None. If the child was terminated abnormally with a signal then + signalstatus will store the signal value and exitstatus will be None:: + + child = pexpect.spawn('some_command') + child.close() + print(child.exitstatus, child.signalstatus) + + If you need more detail you can also read the self.status member which + stores the status returned by os.waitpid. You can interpret this using + os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. + + The echo attribute may be set to False to disable echoing of input. + As a pseudo-terminal, all input echoed by the "keyboard" (send() + or sendline()) will be repeated to output. For many cases, it is + not desirable to have echo enabled, and it may be later disabled + using setecho(False) followed by waitnoecho(). However, for some + platforms such as Solaris, this is not possible, and should be + disabled immediately on spawn. + + If preexec_fn is given, it will be called in the child process before + launching the given command. This is useful to e.g. reset inherited + signal handlers. + + The dimensions attribute specifies the size of the pseudo-terminal as + seen by the subprocess, and is specified as a two-entry tuple (rows, + columns). If this is unspecified, the defaults in ptyprocess will apply. + + The use_poll attribute enables using select.poll() over select.select() + for socket handling. This is handy if your system could have > 1024 fds + ''' + super(spawn, self).__init__(timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize, + logfile=logfile, encoding=encoding, codec_errors=codec_errors) + self.STDIN_FILENO = pty.STDIN_FILENO + self.STDOUT_FILENO = pty.STDOUT_FILENO + self.STDERR_FILENO = pty.STDERR_FILENO + self.cwd = cwd + self.env = env + self.echo = echo + self.ignore_sighup = ignore_sighup + self.__irix_hack = sys.platform.lower().startswith('irix') + if command is None: + self.command = None + self.args = None + self.name = '<pexpect factory incomplete>' + else: + self._spawn(command, args, preexec_fn, dimensions) + self.use_poll = use_poll + + def __str__(self): + '''This returns a human-readable string that represents the state of + the object. ''' + + s = [] + s.append(repr(self)) + s.append('command: ' + str(self.command)) + s.append('args: %r' % (self.args,)) + s.append('buffer (last 100 chars): %r' % self.buffer[-100:]) + s.append('before (last 100 chars): %r' % self.before[-100:] if self.before else '') + s.append('after: %r' % (self.after,)) + s.append('match: %r' % (self.match,)) + s.append('match_index: ' + str(self.match_index)) + s.append('exitstatus: ' + str(self.exitstatus)) + if hasattr(self, 'ptyproc'): + s.append('flag_eof: ' + str(self.flag_eof)) + s.append('pid: ' + str(self.pid)) + s.append('child_fd: ' + str(self.child_fd)) + s.append('closed: ' + str(self.closed)) + s.append('timeout: ' + str(self.timeout)) + s.append('delimiter: ' + str(self.delimiter)) + s.append('logfile: ' + str(self.logfile)) + s.append('logfile_read: ' + str(self.logfile_read)) + s.append('logfile_send: ' + str(self.logfile_send)) + s.append('maxread: ' + str(self.maxread)) + s.append('ignorecase: ' + str(self.ignorecase)) + s.append('searchwindowsize: ' + str(self.searchwindowsize)) + s.append('delaybeforesend: ' + str(self.delaybeforesend)) + s.append('delayafterclose: ' + str(self.delayafterclose)) + s.append('delayafterterminate: ' + str(self.delayafterterminate)) + return '\n'.join(s) + + def _spawn(self, command, args=[], preexec_fn=None, dimensions=None): + '''This starts the given command in a child process. This does all the + fork/exec type of stuff for a pty. This is called by __init__. If args + is empty then command will be parsed (split on spaces) and args will be + set to parsed arguments. ''' + + # The pid and child_fd of this object get set by this method. + # Note that it is difficult for this method to fail. + # You cannot detect if the child process cannot start. + # So the only way you can tell if the child process started + # or not is to try to read from the file descriptor. If you get + # EOF immediately then it means that the child is already dead. + # That may not necessarily be bad because you may have spawned a child + # that performs some task; creates no stdout output; and then dies. + + # If command is an int type then it may represent a file descriptor. + if isinstance(command, type(0)): + raise ExceptionPexpect('Command is an int type. ' + + 'If this is a file descriptor then maybe you want to ' + + 'use fdpexpect.fdspawn which takes an existing ' + + 'file descriptor instead of a command string.') + + if not isinstance(args, type([])): + raise TypeError('The argument, args, must be a list.') + + if args == []: + self.args = split_command_line(command) + self.command = self.args[0] + else: + # Make a shallow copy of the args list. + self.args = args[:] + self.args.insert(0, command) + self.command = command + + command_with_path = which(self.command, env=self.env) + if command_with_path is None: + raise ExceptionPexpect('The command was not found or was not ' + + 'executable: %s.' % self.command) + self.command = command_with_path + self.args[0] = self.command + + self.name = '<' + ' '.join(self.args) + '>' + + assert self.pid is None, 'The pid member must be None.' + assert self.command is not None, 'The command member must not be None.' + + kwargs = {'echo': self.echo, 'preexec_fn': preexec_fn} + if self.ignore_sighup: + def preexec_wrapper(): + "Set SIGHUP to be ignored, then call the real preexec_fn" + signal.signal(signal.SIGHUP, signal.SIG_IGN) + if preexec_fn is not None: + preexec_fn() + kwargs['preexec_fn'] = preexec_wrapper + + if dimensions is not None: + kwargs['dimensions'] = dimensions + + if self.encoding is not None: + # Encode command line using the specified encoding + self.args = [a if isinstance(a, bytes) else a.encode(self.encoding) + for a in self.args] + + self.ptyproc = self._spawnpty(self.args, env=self.env, + cwd=self.cwd, **kwargs) + + self.pid = self.ptyproc.pid + self.child_fd = self.ptyproc.fd + + + self.terminated = False + self.closed = False + + def _spawnpty(self, args, **kwargs): + '''Spawn a pty and return an instance of PtyProcess.''' + return ptyprocess.PtyProcess.spawn(args, **kwargs) + + def close(self, force=True): + '''This closes the connection with the child application. Note that + calling close() more than once is valid. This emulates standard Python + behavior with files. Set force to True if you want to make sure that + the child is terminated (SIGKILL is sent if the child ignores SIGHUP + and SIGINT). ''' + + self.flush() + with _wrap_ptyprocess_err(): + # PtyProcessError may be raised if it is not possible to terminate + # the child. + self.ptyproc.close(force=force) + self.isalive() # Update exit status from ptyproc + self.child_fd = -1 + self.closed = True + + def isatty(self): + '''This returns True if the file descriptor is open and connected to a + tty(-like) device, else False. + + On SVR4-style platforms implementing streams, such as SunOS and HP-UX, + the child pty may not appear as a terminal device. This means + methods such as setecho(), setwinsize(), getwinsize() may raise an + IOError. ''' + + return os.isatty(self.child_fd) + + def waitnoecho(self, timeout=-1): + '''This waits until the terminal ECHO flag is set False. This returns + True if the echo mode is off. This returns False if the ECHO flag was + not set False before the timeout. This can be used to detect when the + child is waiting for a password. Usually a child application will turn + off echo mode when it is waiting for the user to enter a password. For + example, instead of expecting the "password:" prompt you can wait for + the child to set ECHO off:: + + p = pexpect.spawn('ssh user@example.com') + p.waitnoecho() + p.sendline(mypassword) + + If timeout==-1 then this method will use the value in self.timeout. + If timeout==None then this method to block until ECHO flag is False. + ''' + + if timeout == -1: + timeout = self.timeout + if timeout is not None: + end_time = time.time() + timeout + while True: + if not self.getecho(): + return True + if timeout < 0 and timeout is not None: + return False + if timeout is not None: + timeout = end_time - time.time() + time.sleep(0.1) + + def getecho(self): + '''This returns the terminal echo mode. This returns True if echo is + on or False if echo is off. Child applications that are expecting you + to enter a password often set ECHO False. See waitnoecho(). + + Not supported on platforms where ``isatty()`` returns False. ''' + return self.ptyproc.getecho() + + def setecho(self, state): + '''This sets the terminal echo mode on or off. Note that anything the + child sent before the echo will be lost, so you should be sure that + your input buffer is empty before you call setecho(). For example, the + following will work as expected:: + + p = pexpect.spawn('cat') # Echo is on by default. + p.sendline('1234') # We expect see this twice from the child... + p.expect(['1234']) # ... once from the tty echo... + p.expect(['1234']) # ... and again from cat itself. + p.setecho(False) # Turn off tty echo + p.sendline('abcd') # We will set this only once (echoed by cat). + p.sendline('wxyz') # We will set this only once (echoed by cat) + p.expect(['abcd']) + p.expect(['wxyz']) + + The following WILL NOT WORK because the lines sent before the setecho + will be lost:: + + p = pexpect.spawn('cat') + p.sendline('1234') + p.setecho(False) # Turn off tty echo + p.sendline('abcd') # We will set this only once (echoed by cat). + p.sendline('wxyz') # We will set this only once (echoed by cat) + p.expect(['1234']) + p.expect(['1234']) + p.expect(['abcd']) + p.expect(['wxyz']) + + + Not supported on platforms where ``isatty()`` returns False. + ''' + return self.ptyproc.setecho(state) + + def read_nonblocking(self, size=1, timeout=-1): + '''This reads at most size characters from the child application. It + includes a timeout. If the read does not complete within the timeout + period then a TIMEOUT exception is raised. If the end of file is read + then an EOF exception will be raised. If a logfile is specified, a + copy is written to that log. + + If timeout is None then the read may block indefinitely. + If timeout is -1 then the self.timeout value is used. If timeout is 0 + then the child is polled and if there is no data immediately ready + then this will raise a TIMEOUT exception. + + The timeout refers only to the amount of time to read at least one + character. This is not affected by the 'size' parameter, so if you call + read_nonblocking(size=100, timeout=30) and only one character is + available right away then one character will be returned immediately. + It will not wait for 30 seconds for another 99 characters to come in. + + This is a wrapper around os.read(). It uses select.select() to + implement the timeout. ''' + + if self.closed: + raise ValueError('I/O operation on closed file.') + + if timeout == -1: + timeout = self.timeout + + # Note that some systems such as Solaris do not give an EOF when + # the child dies. In fact, you can still try to read + # from the child_fd -- it will block forever or until TIMEOUT. + # For this case, I test isalive() before doing any reading. + # If isalive() is false, then I pretend that this is the same as EOF. + if not self.isalive(): + # timeout of 0 means "poll" + if self.use_poll: + r = poll_ignore_interrupts([self.child_fd], timeout) + else: + r, w, e = select_ignore_interrupts([self.child_fd], [], [], 0) + if not r: + self.flag_eof = True + raise EOF('End Of File (EOF). Braindead platform.') + elif self.__irix_hack: + # Irix takes a long time before it realizes a child was terminated. + # FIXME So does this mean Irix systems are forced to always have + # FIXME a 2 second delay when calling read_nonblocking? That sucks. + if self.use_poll: + r = poll_ignore_interrupts([self.child_fd], timeout) + else: + r, w, e = select_ignore_interrupts([self.child_fd], [], [], 2) + if not r and not self.isalive(): + self.flag_eof = True + raise EOF('End Of File (EOF). Slow platform.') + if self.use_poll: + r = poll_ignore_interrupts([self.child_fd], timeout) + else: + r, w, e = select_ignore_interrupts( + [self.child_fd], [], [], timeout + ) + + if not r: + if not self.isalive(): + # Some platforms, such as Irix, will claim that their + # processes are alive; timeout on the select; and + # then finally admit that they are not alive. + self.flag_eof = True + raise EOF('End of File (EOF). Very slow platform.') + else: + raise TIMEOUT('Timeout exceeded.') + + if self.child_fd in r: + return super(spawn, self).read_nonblocking(size) + + raise ExceptionPexpect('Reached an unexpected state.') # pragma: no cover + + def write(self, s): + '''This is similar to send() except that there is no return value. + ''' + + self.send(s) + + def writelines(self, sequence): + '''This calls write() for each element in the sequence. The sequence + can be any iterable object producing strings, typically a list of + strings. This does not add line separators. There is no return value. + ''' + + for s in sequence: + self.write(s) + + def send(self, s): + '''Sends string ``s`` to the child process, returning the number of + bytes written. If a logfile is specified, a copy is written to that + log. + + The default terminal input mode is canonical processing unless set + otherwise by the child process. This allows backspace and other line + processing to be performed prior to transmitting to the receiving + program. As this is buffered, there is a limited size of such buffer. + + On Linux systems, this is 4096 (defined by N_TTY_BUF_SIZE). All + other systems honor the POSIX.1 definition PC_MAX_CANON -- 1024 + on OSX, 256 on OpenSolaris, and 1920 on FreeBSD. + + This value may be discovered using fpathconf(3):: + + >>> from os import fpathconf + >>> print(fpathconf(0, 'PC_MAX_CANON')) + 256 + + On such a system, only 256 bytes may be received per line. Any + subsequent bytes received will be discarded. BEL (``'\a'``) is then + sent to output if IMAXBEL (termios.h) is set by the tty driver. + This is usually enabled by default. Linux does not honor this as + an option -- it behaves as though it is always set on. + + Canonical input processing may be disabled altogether by executing + a shell, then stty(1), before executing the final program:: + + >>> bash = pexpect.spawn('/bin/bash', echo=False) + >>> bash.sendline('stty -icanon') + >>> bash.sendline('base64') + >>> bash.sendline('x' * 5000) + ''' + + if self.delaybeforesend is not None: + time.sleep(self.delaybeforesend) + + s = self._coerce_send_string(s) + self._log(s, 'send') + + b = self._encoder.encode(s, final=False) + return os.write(self.child_fd, b) + + def sendline(self, s=''): + '''Wraps send(), sending string ``s`` to child process, with + ``os.linesep`` automatically appended. Returns number of bytes + written. Only a limited number of bytes may be sent for each + line in the default terminal mode, see docstring of :meth:`send`. + ''' + s = self._coerce_send_string(s) + return self.send(s + self.linesep) + + def _log_control(self, s): + """Write control characters to the appropriate log files""" + if self.encoding is not None: + s = s.decode(self.encoding, 'replace') + self._log(s, 'send') + + def sendcontrol(self, char): + '''Helper method that wraps send() with mnemonic access for sending control + character to the child (such as Ctrl-C or Ctrl-D). For example, to send + Ctrl-G (ASCII 7, bell, '\a'):: + + child.sendcontrol('g') + + See also, sendintr() and sendeof(). + ''' + n, byte = self.ptyproc.sendcontrol(char) + self._log_control(byte) + return n + + def sendeof(self): + '''This sends an EOF to the child. This sends a character which causes + the pending parent output buffer to be sent to the waiting child + program without waiting for end-of-line. If it is the first character + of the line, the read() in the user program returns 0, which signifies + end-of-file. This means to work as expected a sendeof() has to be + called at the beginning of a line. This method does not send a newline. + It is the responsibility of the caller to ensure the eof is sent at the + beginning of a line. ''' + + n, byte = self.ptyproc.sendeof() + self._log_control(byte) + + def sendintr(self): + '''This sends a SIGINT to the child. It does not require + the SIGINT to be the first character on a line. ''' + + n, byte = self.ptyproc.sendintr() + self._log_control(byte) + + @property + def flag_eof(self): + return self.ptyproc.flag_eof + + @flag_eof.setter + def flag_eof(self, value): + self.ptyproc.flag_eof = value + + def eof(self): + '''This returns True if the EOF exception was ever raised. + ''' + return self.flag_eof + + def terminate(self, force=False): + '''This forces a child process to terminate. It starts nicely with + SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This + returns True if the child was terminated. This returns False if the + child could not be terminated. ''' + + if not self.isalive(): + return True + try: + self.kill(signal.SIGHUP) + time.sleep(self.delayafterterminate) + if not self.isalive(): + return True + self.kill(signal.SIGCONT) + time.sleep(self.delayafterterminate) + if not self.isalive(): + return True + self.kill(signal.SIGINT) + time.sleep(self.delayafterterminate) + if not self.isalive(): + return True + if force: + self.kill(signal.SIGKILL) + time.sleep(self.delayafterterminate) + if not self.isalive(): + return True + else: + return False + return False + except OSError: + # I think there are kernel timing issues that sometimes cause + # this to happen. I think isalive() reports True, but the + # process is dead to the kernel. + # Make one last attempt to see if the kernel is up to date. + time.sleep(self.delayafterterminate) + if not self.isalive(): + return True + else: + return False + + def wait(self): + '''This waits until the child exits. This is a blocking call. This will + not read any data from the child, so this will block forever if the + child has unread output and has terminated. In other words, the child + may have printed output then called exit(), but, the child is + technically still alive until its output is read by the parent. + + This method is non-blocking if :meth:`wait` has already been called + previously or :meth:`isalive` method returns False. It simply returns + the previously determined exit status. + ''' + + ptyproc = self.ptyproc + with _wrap_ptyprocess_err(): + # exception may occur if "Is some other process attempting + # "job control with our child pid?" + exitstatus = ptyproc.wait() + self.status = ptyproc.status + self.exitstatus = ptyproc.exitstatus + self.signalstatus = ptyproc.signalstatus + self.terminated = True + + return exitstatus + + def isalive(self): + '''This tests if the child process is running or not. This is + non-blocking. If the child was terminated then this will read the + exitstatus or signalstatus of the child. This returns True if the child + process appears to be running or False if not. It can take literally + SECONDS for Solaris to return the right status. ''' + + ptyproc = self.ptyproc + with _wrap_ptyprocess_err(): + alive = ptyproc.isalive() + + if not alive: + self.status = ptyproc.status + self.exitstatus = ptyproc.exitstatus + self.signalstatus = ptyproc.signalstatus + self.terminated = True + + return alive + + def kill(self, sig): + + '''This sends the given signal to the child application. In keeping + with UNIX tradition it has a misleading name. It does not necessarily + kill the child unless you send the right signal. ''' + + # Same as os.kill, but the pid is given for you. + if self.isalive(): + os.kill(self.pid, sig) + + def getwinsize(self): + '''This returns the terminal window size of the child tty. The return + value is a tuple of (rows, cols). ''' + return self.ptyproc.getwinsize() + + def setwinsize(self, rows, cols): + '''This sets the terminal window size of the child tty. This will cause + a SIGWINCH signal to be sent to the child. This does not change the + physical window size. It changes the size reported to TTY-aware + applications like vi or curses -- applications that respond to the + SIGWINCH signal. ''' + return self.ptyproc.setwinsize(rows, cols) + + + def interact(self, escape_character=chr(29), + input_filter=None, output_filter=None): + + '''This gives control of the child process to the interactive user (the + human at the keyboard). Keystrokes are sent to the child process, and + the stdout and stderr output of the child process is printed. This + simply echos the child stdout and child stderr to the real stdout and + it echos the real stdin to the child stdin. When the user types the + escape_character this method will return None. The escape_character + will not be transmitted. The default for escape_character is + entered as ``Ctrl - ]``, the very same as BSD telnet. To prevent + escaping, escape_character may be set to None. + + If a logfile is specified, then the data sent and received from the + child process in interact mode is duplicated to the given log. + + You may pass in optional input and output filter functions. These + functions should take a string and return a string. The output_filter + will be passed all the output from the child process. The input_filter + will be passed all the keyboard input from the user. The input_filter + is run BEFORE the check for the escape_character. + + Note that if you change the window size of the parent the SIGWINCH + signal will not be passed through to the child. If you want the child + window size to change when the parent's window size changes then do + something like the following example:: + + import pexpect, struct, fcntl, termios, signal, sys + def sigwinch_passthrough (sig, data): + s = struct.pack("HHHH", 0, 0, 0, 0) + a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), + termios.TIOCGWINSZ , s)) + if not p.closed: + p.setwinsize(a[0],a[1]) + + # Note this 'p' is global and used in sigwinch_passthrough. + p = pexpect.spawn('/bin/bash') + signal.signal(signal.SIGWINCH, sigwinch_passthrough) + p.interact() + ''' + + # Flush the buffer. + self.write_to_stdout(self.buffer) + self.stdout.flush() + self._buffer = self.buffer_type() + mode = tty.tcgetattr(self.STDIN_FILENO) + tty.setraw(self.STDIN_FILENO) + if escape_character is not None and PY3: + escape_character = escape_character.encode('latin-1') + try: + self.__interact_copy(escape_character, input_filter, output_filter) + finally: + tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode) + + def __interact_writen(self, fd, data): + '''This is used by the interact() method. + ''' + + while data != b'' and self.isalive(): + n = os.write(fd, data) + data = data[n:] + + def __interact_read(self, fd): + '''This is used by the interact() method. + ''' + + return os.read(fd, 1000) + + def __interact_copy( + self, escape_character=None, input_filter=None, output_filter=None + ): + + '''This is used by the interact() method. + ''' + + while self.isalive(): + if self.use_poll: + r = poll_ignore_interrupts([self.child_fd, self.STDIN_FILENO]) + else: + r, w, e = select_ignore_interrupts( + [self.child_fd, self.STDIN_FILENO], [], [] + ) + if self.child_fd in r: + try: + data = self.__interact_read(self.child_fd) + except OSError as err: + if err.args[0] == errno.EIO: + # Linux-style EOF + break + raise + if data == b'': + # BSD-style EOF + break + if output_filter: + data = output_filter(data) + self._log(data, 'read') + os.write(self.STDOUT_FILENO, data) + if self.STDIN_FILENO in r: + data = self.__interact_read(self.STDIN_FILENO) + if input_filter: + data = input_filter(data) + i = -1 + if escape_character is not None: + i = data.rfind(escape_character) + if i != -1: + data = data[:i] + if data: + self._log(data, 'send') + self.__interact_writen(self.child_fd, data) + break + self._log(data, 'send') + self.__interact_writen(self.child_fd, data) + + +def spawnu(*args, **kwargs): + """Deprecated: pass encoding to spawn() instead.""" + kwargs.setdefault('encoding', 'utf-8') + return spawn(*args, **kwargs) diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/pxssh.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/pxssh.py new file mode 100644 index 00000000000..ef2e91186b3 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/pxssh.py @@ -0,0 +1,499 @@ +'''This class extends pexpect.spawn to specialize setting up SSH connections. +This adds methods for login, logout, and expecting the shell prompt. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from pexpect import ExceptionPexpect, TIMEOUT, EOF, spawn +import time +import os +import sys +import re + +__all__ = ['ExceptionPxssh', 'pxssh'] + +# Exception classes used by this module. +class ExceptionPxssh(ExceptionPexpect): + '''Raised for pxssh exceptions. + ''' + +if sys.version_info > (3, 0): + from shlex import quote +else: + _find_unsafe = re.compile(r'[^\w@%+=:,./-]').search + + def quote(s): + """Return a shell-escaped version of the string *s*.""" + if not s: + return "''" + if _find_unsafe(s) is None: + return s + + # use single quotes, and put single quotes into double quotes + # the string $'b is then quoted as '$'"'"'b' + return "'" + s.replace("'", "'\"'\"'") + "'" + +class pxssh (spawn): + '''This class extends pexpect.spawn to specialize setting up SSH + connections. This adds methods for login, logout, and expecting the shell + prompt. It does various tricky things to handle many situations in the SSH + login process. For example, if the session is your first login, then pxssh + automatically accepts the remote certificate; or if you have public key + authentication setup then pxssh won't wait for the password prompt. + + pxssh uses the shell prompt to synchronize output from the remote host. In + order to make this more robust it sets the shell prompt to something more + unique than just $ or #. This should work on most Borne/Bash or Csh style + shells. + + Example that runs a few commands on a remote server and prints the result:: + + from pexpect import pxssh + import getpass + try: + s = pxssh.pxssh() + hostname = raw_input('hostname: ') + username = raw_input('username: ') + password = getpass.getpass('password: ') + s.login(hostname, username, password) + s.sendline('uptime') # run a command + s.prompt() # match the prompt + print(s.before) # print everything before the prompt. + s.sendline('ls -l') + s.prompt() + print(s.before) + s.sendline('df') + s.prompt() + print(s.before) + s.logout() + except pxssh.ExceptionPxssh as e: + print("pxssh failed on login.") + print(e) + + Example showing how to specify SSH options:: + + from pexpect import pxssh + s = pxssh.pxssh(options={ + "StrictHostKeyChecking": "no", + "UserKnownHostsFile": "/dev/null"}) + ... + + Note that if you have ssh-agent running while doing development with pxssh + then this can lead to a lot of confusion. Many X display managers (xdm, + gdm, kdm, etc.) will automatically start a GUI agent. You may see a GUI + dialog box popup asking for a password during development. You should turn + off any key agents during testing. The 'force_password' attribute will turn + off public key authentication. This will only work if the remote SSH server + is configured to allow password logins. Example of using 'force_password' + attribute:: + + s = pxssh.pxssh() + s.force_password = True + hostname = raw_input('hostname: ') + username = raw_input('username: ') + password = getpass.getpass('password: ') + s.login (hostname, username, password) + + `debug_command_string` is only for the test suite to confirm that the string + generated for SSH is correct, using this will not allow you to do + anything other than get a string back from `pxssh.pxssh.login()`. + ''' + + def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None, + logfile=None, cwd=None, env=None, ignore_sighup=True, echo=True, + options={}, encoding=None, codec_errors='strict', + debug_command_string=False): + + spawn.__init__(self, None, timeout=timeout, maxread=maxread, + searchwindowsize=searchwindowsize, logfile=logfile, + cwd=cwd, env=env, ignore_sighup=ignore_sighup, echo=echo, + encoding=encoding, codec_errors=codec_errors) + + self.name = '<pxssh>' + + #SUBTLE HACK ALERT! Note that the command that SETS the prompt uses a + #slightly different string than the regular expression to match it. This + #is because when you set the prompt the command will echo back, but we + #don't want to match the echoed command. So if we make the set command + #slightly different than the regex we eliminate the problem. To make the + #set command different we add a backslash in front of $. The $ doesn't + #need to be escaped, but it doesn't hurt and serves to make the set + #prompt command different than the regex. + + # used to match the command-line prompt + self.UNIQUE_PROMPT = r"\[PEXPECT\][\$\#] " + self.PROMPT = self.UNIQUE_PROMPT + + # used to set shell command-line prompt to UNIQUE_PROMPT. + self.PROMPT_SET_SH = r"PS1='[PEXPECT]\$ '" + self.PROMPT_SET_CSH = r"set prompt='[PEXPECT]\$ '" + self.SSH_OPTS = ("-o'RSAAuthentication=no'" + + " -o 'PubkeyAuthentication=no'") +# Disabling host key checking, makes you vulnerable to MITM attacks. +# + " -o 'StrictHostKeyChecking=no'" +# + " -o 'UserKnownHostsFile /dev/null' ") + # Disabling X11 forwarding gets rid of the annoying SSH_ASKPASS from + # displaying a GUI password dialog. I have not figured out how to + # disable only SSH_ASKPASS without also disabling X11 forwarding. + # Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying! + #self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'" + self.force_password = False + + self.debug_command_string = debug_command_string + + # User defined SSH options, eg, + # ssh.otions = dict(StrictHostKeyChecking="no",UserKnownHostsFile="/dev/null") + self.options = options + + def levenshtein_distance(self, a, b): + '''This calculates the Levenshtein distance between a and b. + ''' + + n, m = len(a), len(b) + if n > m: + a,b = b,a + n,m = m,n + current = range(n+1) + for i in range(1,m+1): + previous, current = current, [i]+[0]*n + for j in range(1,n+1): + add, delete = previous[j]+1, current[j-1]+1 + change = previous[j-1] + if a[j-1] != b[i-1]: + change = change + 1 + current[j] = min(add, delete, change) + return current[n] + + def try_read_prompt(self, timeout_multiplier): + '''This facilitates using communication timeouts to perform + synchronization as quickly as possible, while supporting high latency + connections with a tunable worst case performance. Fast connections + should be read almost immediately. Worst case performance for this + method is timeout_multiplier * 3 seconds. + ''' + + # maximum time allowed to read the first response + first_char_timeout = timeout_multiplier * 0.5 + + # maximum time allowed between subsequent characters + inter_char_timeout = timeout_multiplier * 0.1 + + # maximum time for reading the entire prompt + total_timeout = timeout_multiplier * 3.0 + + prompt = self.string_type() + begin = time.time() + expired = 0.0 + timeout = first_char_timeout + + while expired < total_timeout: + try: + prompt += self.read_nonblocking(size=1, timeout=timeout) + expired = time.time() - begin # updated total time expired + timeout = inter_char_timeout + except TIMEOUT: + break + + return prompt + + def sync_original_prompt (self, sync_multiplier=1.0): + '''This attempts to find the prompt. Basically, press enter and record + the response; press enter again and record the response; if the two + responses are similar then assume we are at the original prompt. + This can be a slow function. Worst case with the default sync_multiplier + can take 12 seconds. Low latency connections are more likely to fail + with a low sync_multiplier. Best case sync time gets worse with a + high sync multiplier (500 ms with default). ''' + + # All of these timing pace values are magic. + # I came up with these based on what seemed reliable for + # connecting to a heavily loaded machine I have. + self.sendline() + time.sleep(0.1) + + try: + # Clear the buffer before getting the prompt. + self.try_read_prompt(sync_multiplier) + except TIMEOUT: + pass + + self.sendline() + x = self.try_read_prompt(sync_multiplier) + + self.sendline() + a = self.try_read_prompt(sync_multiplier) + + self.sendline() + b = self.try_read_prompt(sync_multiplier) + + ld = self.levenshtein_distance(a,b) + len_a = len(a) + if len_a == 0: + return False + if float(ld)/len_a < 0.4: + return True + return False + + ### TODO: This is getting messy and I'm pretty sure this isn't perfect. + ### TODO: I need to draw a flow chart for this. + ### TODO: Unit tests for SSH tunnels, remote SSH command exec, disabling original prompt sync + def login (self, server, username, password='', terminal_type='ansi', + original_prompt=r"[#$]", login_timeout=10, port=None, + auto_prompt_reset=True, ssh_key=None, quiet=True, + sync_multiplier=1, check_local_ip=True, + password_regex=r'(?i)(?:password:)|(?:passphrase for key)', + ssh_tunnels={}, spawn_local_ssh=True, + sync_original_prompt=True, ssh_config=None): + '''This logs the user into the given server. + + It uses + 'original_prompt' to try to find the prompt right after login. When it + finds the prompt it immediately tries to reset the prompt to something + more easily matched. The default 'original_prompt' is very optimistic + and is easily fooled. It's more reliable to try to match the original + prompt as exactly as possible to prevent false matches by server + strings such as the "Message Of The Day". On many systems you can + disable the MOTD on the remote server by creating a zero-length file + called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found + then this will not necessarily cause the login to fail. In the case of + a timeout when looking for the prompt we assume that the original + prompt was so weird that we could not match it, so we use a few tricks + to guess when we have reached the prompt. Then we hope for the best and + blindly try to reset the prompt to something more unique. If that fails + then login() raises an :class:`ExceptionPxssh` exception. + + In some situations it is not possible or desirable to reset the + original prompt. In this case, pass ``auto_prompt_reset=False`` to + inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh + uses a unique prompt in the :meth:`prompt` method. If the original prompt is + not reset then this will disable the :meth:`prompt` method unless you + manually set the :attr:`PROMPT` attribute. + + Set ``password_regex`` if there is a MOTD message with `password` in it. + Changing this is like playing in traffic, don't (p)expect it to match straight + away. + + If you require to connect to another SSH server from the your original SSH + connection set ``spawn_local_ssh`` to `False` and this will use your current + session to do so. Setting this option to `False` and not having an active session + will trigger an error. + + Set ``ssh_key`` to a file path to an SSH private key to use that SSH key + for the session authentication. + Set ``ssh_key`` to `True` to force passing the current SSH authentication socket + to the desired ``hostname``. + + Set ``ssh_config`` to a file path string of an SSH client config file to pass that + file to the client to handle itself. You may set any options you wish in here, however + doing so will require you to post extra information that you may not want to if you + run into issues. + ''' + + session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT] + session_init_regex_array = [] + session_init_regex_array.extend(session_regex_array) + session_init_regex_array.extend(["(?i)connection closed by remote host", EOF]) + + ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()]) + if quiet: + ssh_options = ssh_options + ' -q' + if not check_local_ip: + ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'" + if self.force_password: + ssh_options = ssh_options + ' ' + self.SSH_OPTS + if ssh_config is not None: + if spawn_local_ssh and not os.path.isfile(ssh_config): + raise ExceptionPxssh('SSH config does not exist or is not a file.') + ssh_options = ssh_options + '-F ' + ssh_config + if port is not None: + ssh_options = ssh_options + ' -p %s'%(str(port)) + if ssh_key is not None: + # Allow forwarding our SSH key to the current session + if ssh_key==True: + ssh_options = ssh_options + ' -A' + else: + if spawn_local_ssh and not os.path.isfile(ssh_key): + raise ExceptionPxssh('private ssh key does not exist or is not a file.') + ssh_options = ssh_options + ' -i %s' % (ssh_key) + + # SSH tunnels, make sure you know what you're putting into the lists + # under each heading. Do not expect these to open 100% of the time, + # The port you're requesting might be bound. + # + # The structure should be like this: + # { 'local': ['2424:localhost:22'], # Local SSH tunnels + # 'remote': ['2525:localhost:22'], # Remote SSH tunnels + # 'dynamic': [8888] } # Dynamic/SOCKS tunnels + if ssh_tunnels!={} and isinstance({},type(ssh_tunnels)): + tunnel_types = { + 'local':'L', + 'remote':'R', + 'dynamic':'D' + } + for tunnel_type in tunnel_types: + cmd_type = tunnel_types[tunnel_type] + if tunnel_type in ssh_tunnels: + tunnels = ssh_tunnels[tunnel_type] + for tunnel in tunnels: + if spawn_local_ssh==False: + tunnel = quote(str(tunnel)) + ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(tunnel) + cmd = "ssh %s -l %s %s" % (ssh_options, username, server) + if self.debug_command_string: + return(cmd) + + # Are we asking for a local ssh command or to spawn one in another session? + if spawn_local_ssh: + spawn._spawn(self, cmd) + else: + self.sendline(cmd) + + # This does not distinguish between a remote server 'password' prompt + # and a local ssh 'passphrase' prompt (for unlocking a private key). + i = self.expect(session_init_regex_array, timeout=login_timeout) + + # First phase + if i==0: + # New certificate -- always accept it. + # This is what you get if SSH does not have the remote host's + # public key stored in the 'known_hosts' cache. + self.sendline("yes") + i = self.expect(session_regex_array) + if i==2: # password or passphrase + self.sendline(password) + i = self.expect(session_regex_array) + if i==4: + self.sendline(terminal_type) + i = self.expect(session_regex_array) + if i==7: + self.close() + raise ExceptionPxssh('Could not establish connection to host') + + # Second phase + if i==0: + # This is weird. This should not happen twice in a row. + self.close() + raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.') + elif i==1: # can occur if you have a public key pair set to authenticate. + ### TODO: May NOT be OK if expect() got tricked and matched a false prompt. + pass + elif i==2: # password prompt again + # For incorrect passwords, some ssh servers will + # ask for the password again, others return 'denied' right away. + # If we get the password prompt again then this means + # we didn't get the password right the first time. + self.close() + raise ExceptionPxssh('password refused') + elif i==3: # permission denied -- password was bad. + self.close() + raise ExceptionPxssh('permission denied') + elif i==4: # terminal type again? WTF? + self.close() + raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.') + elif i==5: # Timeout + #This is tricky... I presume that we are at the command-line prompt. + #It may be that the shell prompt was so weird that we couldn't match + #it. Or it may be that we couldn't log in for some other reason. I + #can't be sure, but it's safe to guess that we did login because if + #I presume wrong and we are not logged in then this should be caught + #later when I try to set the shell prompt. + pass + elif i==6: # Connection closed by remote host + self.close() + raise ExceptionPxssh('connection closed') + else: # Unexpected + self.close() + raise ExceptionPxssh('unexpected login response') + if sync_original_prompt: + if not self.sync_original_prompt(sync_multiplier): + self.close() + raise ExceptionPxssh('could not synchronize with original prompt') + # We appear to be in. + # set shell prompt to something unique. + if auto_prompt_reset: + if not self.set_unique_prompt(): + self.close() + raise ExceptionPxssh('could not set shell prompt ' + '(received: %r, expected: %r).' % ( + self.before, self.PROMPT,)) + return True + + def logout (self): + '''Sends exit to the remote shell. + + If there are stopped jobs then this automatically sends exit twice. + ''' + self.sendline("exit") + index = self.expect([EOF, "(?i)there are stopped jobs"]) + if index==1: + self.sendline("exit") + self.expect(EOF) + self.close() + + def prompt(self, timeout=-1): + '''Match the next shell prompt. + + This is little more than a short-cut to the :meth:`~pexpect.spawn.expect` + method. Note that if you called :meth:`login` with + ``auto_prompt_reset=False``, then before calling :meth:`prompt` you must + set the :attr:`PROMPT` attribute to a regex that it will use for + matching the prompt. + + Calling :meth:`prompt` will erase the contents of the :attr:`before` + attribute even if no prompt is ever matched. If timeout is not given or + it is set to -1 then self.timeout is used. + + :return: True if the shell prompt was matched, False if the timeout was + reached. + ''' + + if timeout == -1: + timeout = self.timeout + i = self.expect([self.PROMPT, TIMEOUT], timeout=timeout) + if i==1: + return False + return True + + def set_unique_prompt(self): + '''This sets the remote prompt to something more unique than ``#`` or ``$``. + This makes it easier for the :meth:`prompt` method to match the shell prompt + unambiguously. This method is called automatically by the :meth:`login` + method, but you may want to call it manually if you somehow reset the + shell prompt. For example, if you 'su' to a different user then you + will need to manually reset the prompt. This sends shell commands to + the remote host to set the prompt, so this assumes the remote host is + ready to receive commands. + + Alternatively, you may use your own prompt pattern. In this case you + should call :meth:`login` with ``auto_prompt_reset=False``; then set the + :attr:`PROMPT` attribute to a regular expression. After that, the + :meth:`prompt` method will try to match your prompt pattern. + ''' + + self.sendline("unset PROMPT_COMMAND") + self.sendline(self.PROMPT_SET_SH) # sh-style + i = self.expect ([TIMEOUT, self.PROMPT], timeout=10) + if i == 0: # csh-style + self.sendline(self.PROMPT_SET_CSH) + i = self.expect([TIMEOUT, self.PROMPT], timeout=10) + if i == 0: + return False + return True + +# vi:ts=4:sw=4:expandtab:ft=python: diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/replwrap.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/replwrap.py new file mode 100644 index 00000000000..ed0e657d739 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/replwrap.py @@ -0,0 +1,122 @@ +"""Generic wrapper for read-eval-print-loops, a.k.a. interactive shells +""" +import os.path +import signal +import sys + +import pexpect + +PY3 = (sys.version_info[0] >= 3) + +if PY3: + basestring = str + +PEXPECT_PROMPT = u'[PEXPECT_PROMPT>' +PEXPECT_CONTINUATION_PROMPT = u'[PEXPECT_PROMPT+' + +class REPLWrapper(object): + """Wrapper for a REPL. + + :param cmd_or_spawn: This can either be an instance of :class:`pexpect.spawn` + in which a REPL has already been started, or a str command to start a new + REPL process. + :param str orig_prompt: The prompt to expect at first. + :param str prompt_change: A command to change the prompt to something more + unique. If this is ``None``, the prompt will not be changed. This will + be formatted with the new and continuation prompts as positional + parameters, so you can use ``{}`` style formatting to insert them into + the command. + :param str new_prompt: The more unique prompt to expect after the change. + :param str extra_init_cmd: Commands to do extra initialisation, such as + disabling pagers. + """ + def __init__(self, cmd_or_spawn, orig_prompt, prompt_change, + new_prompt=PEXPECT_PROMPT, + continuation_prompt=PEXPECT_CONTINUATION_PROMPT, + extra_init_cmd=None): + if isinstance(cmd_or_spawn, basestring): + self.child = pexpect.spawn(cmd_or_spawn, echo=False, encoding='utf-8') + else: + self.child = cmd_or_spawn + if self.child.echo: + # Existing spawn instance has echo enabled, disable it + # to prevent our input from being repeated to output. + self.child.setecho(False) + self.child.waitnoecho() + + if prompt_change is None: + self.prompt = orig_prompt + else: + self.set_prompt(orig_prompt, + prompt_change.format(new_prompt, continuation_prompt)) + self.prompt = new_prompt + self.continuation_prompt = continuation_prompt + + self._expect_prompt() + + if extra_init_cmd is not None: + self.run_command(extra_init_cmd) + + def set_prompt(self, orig_prompt, prompt_change): + self.child.expect(orig_prompt) + self.child.sendline(prompt_change) + + def _expect_prompt(self, timeout=-1): + return self.child.expect_exact([self.prompt, self.continuation_prompt], + timeout=timeout) + + def run_command(self, command, timeout=-1): + """Send a command to the REPL, wait for and return output. + + :param str command: The command to send. Trailing newlines are not needed. + This should be a complete block of input that will trigger execution; + if a continuation prompt is found after sending input, :exc:`ValueError` + will be raised. + :param int timeout: How long to wait for the next prompt. -1 means the + default from the :class:`pexpect.spawn` object (default 30 seconds). + None means to wait indefinitely. + """ + # Split up multiline commands and feed them in bit-by-bit + cmdlines = command.splitlines() + # splitlines ignores trailing newlines - add it back in manually + if command.endswith('\n'): + cmdlines.append('') + if not cmdlines: + raise ValueError("No command was given") + + res = [] + self.child.sendline(cmdlines[0]) + for line in cmdlines[1:]: + self._expect_prompt(timeout=timeout) + res.append(self.child.before) + self.child.sendline(line) + + # Command was fully submitted, now wait for the next prompt + if self._expect_prompt(timeout=timeout) == 1: + # We got the continuation prompt - command was incomplete + self.child.kill(signal.SIGINT) + self._expect_prompt(timeout=1) + raise ValueError("Continuation prompt found - input was incomplete:\n" + + command) + return u''.join(res + [self.child.before]) + +def python(command="python"): + """Start a Python shell and return a :class:`REPLWrapper` object.""" + return REPLWrapper(command, u">>> ", u"import sys; sys.ps1={0!r}; sys.ps2={1!r}") + +def bash(command="bash"): + """Start a bash shell and return a :class:`REPLWrapper` object.""" + bashrc = os.path.join(os.path.dirname(__file__), 'bashrc.sh') + child = pexpect.spawn(command, ['--rcfile', bashrc], echo=False, + encoding='utf-8') + + # If the user runs 'env', the value of PS1 will be in the output. To avoid + # replwrap seeing that as the next prompt, we'll embed the marker characters + # for invisible characters in the prompt; these show up when inspecting the + # environment variable, but not when bash displays the prompt. + ps1 = PEXPECT_PROMPT[:5] + u'\\[\\]' + PEXPECT_PROMPT[5:] + ps2 = PEXPECT_CONTINUATION_PROMPT[:5] + u'\\[\\]' + PEXPECT_CONTINUATION_PROMPT[5:] + prompt_change = u"PS1='{0}' PS2='{1}' PROMPT_COMMAND=''".format(ps1, ps2) + + return REPLWrapper(child, u'\\$', prompt_change, + extra_init_cmd="export PAGER=cat") diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/run.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/run.py new file mode 100644 index 00000000000..d9dfe76ba58 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/run.py @@ -0,0 +1,157 @@ +import sys +import types + +from .exceptions import EOF, TIMEOUT +from .pty_spawn import spawn + +def run(command, timeout=30, withexitstatus=False, events=None, + extra_args=None, logfile=None, cwd=None, env=None, **kwargs): + + ''' + This function runs the given command; waits for it to finish; then + returns all output as a string. STDERR is included in output. If the full + path to the command is not given then the path is searched. + + Note that lines are terminated by CR/LF (\\r\\n) combination even on + UNIX-like systems because this is the standard for pseudottys. If you set + 'withexitstatus' to true, then run will return a tuple of (command_output, + exitstatus). If 'withexitstatus' is false then this returns just + command_output. + + The run() function can often be used instead of creating a spawn instance. + For example, the following code uses spawn:: + + from pexpect import * + child = spawn('scp foo user@example.com:.') + child.expect('(?i)password') + child.sendline(mypassword) + + The previous code can be replace with the following:: + + from pexpect import * + run('scp foo user@example.com:.', events={'(?i)password': mypassword}) + + **Examples** + + Start the apache daemon on the local machine:: + + from pexpect import * + run("/usr/local/apache/bin/apachectl start") + + Check in a file using SVN:: + + from pexpect import * + run("svn ci -m 'automatic commit' my_file.py") + + Run a command and capture exit status:: + + from pexpect import * + (command_output, exitstatus) = run('ls -l /bin', withexitstatus=1) + + The following will run SSH and execute 'ls -l' on the remote machine. The + password 'secret' will be sent if the '(?i)password' pattern is ever seen:: + + run("ssh username@machine.example.com 'ls -l'", + events={'(?i)password':'secret\\n'}) + + This will start mencoder to rip a video from DVD. This will also display + progress ticks every 5 seconds as it runs. For example:: + + from pexpect import * + def print_ticks(d): + print d['event_count'], + run("mencoder dvd://1 -o video.avi -oac copy -ovc copy", + events={TIMEOUT:print_ticks}, timeout=5) + + The 'events' argument should be either a dictionary or a tuple list that + contains patterns and responses. Whenever one of the patterns is seen + in the command output, run() will send the associated response string. + So, run() in the above example can be also written as: + + run("mencoder dvd://1 -o video.avi -oac copy -ovc copy", + events=[(TIMEOUT,print_ticks)], timeout=5) + + Use a tuple list for events if the command output requires a delicate + control over what pattern should be matched, since the tuple list is passed + to pexpect() as its pattern list, with the order of patterns preserved. + + Note that you should put newlines in your string if Enter is necessary. + + Like the example above, the responses may also contain a callback, either + a function or method. It should accept a dictionary value as an argument. + The dictionary contains all the locals from the run() function, so you can + access the child spawn object or any other variable defined in run() + (event_count, child, and extra_args are the most useful). A callback may + return True to stop the current run process. Otherwise run() continues + until the next event. A callback may also return a string which will be + sent to the child. 'extra_args' is not used by directly run(). It provides + a way to pass data to a callback function through run() through the locals + dictionary passed to a callback. + + Like :class:`spawn`, passing *encoding* will make it work with unicode + instead of bytes. You can pass *codec_errors* to control how errors in + encoding and decoding are handled. + ''' + if timeout == -1: + child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env, + **kwargs) + else: + child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, + cwd=cwd, env=env, **kwargs) + if isinstance(events, list): + patterns= [x for x,y in events] + responses = [y for x,y in events] + elif isinstance(events, dict): + patterns = list(events.keys()) + responses = list(events.values()) + else: + # This assumes EOF or TIMEOUT will eventually cause run to terminate. + patterns = None + responses = None + child_result_list = [] + event_count = 0 + while True: + try: + index = child.expect(patterns) + if isinstance(child.after, child.allowed_string_types): + child_result_list.append(child.before + child.after) + else: + # child.after may have been a TIMEOUT or EOF, + # which we don't want appended to the list. + child_result_list.append(child.before) + if isinstance(responses[index], child.allowed_string_types): + child.send(responses[index]) + elif (isinstance(responses[index], types.FunctionType) or + isinstance(responses[index], types.MethodType)): + callback_result = responses[index](locals()) + sys.stdout.flush() + if isinstance(callback_result, child.allowed_string_types): + child.send(callback_result) + elif callback_result: + break + else: + raise TypeError("parameter `event' at index {index} must be " + "a string, method, or function: {value!r}" + .format(index=index, value=responses[index])) + event_count = event_count + 1 + except TIMEOUT: + child_result_list.append(child.before) + break + except EOF: + child_result_list.append(child.before) + break + child_result = child.string_type().join(child_result_list) + if withexitstatus: + child.close() + return (child_result, child.exitstatus) + else: + return child_result + +def runu(command, timeout=30, withexitstatus=False, events=None, + extra_args=None, logfile=None, cwd=None, env=None, **kwargs): + """Deprecated: pass encoding to run() instead. + """ + kwargs.setdefault('encoding', 'utf-8') + return run(command, timeout=timeout, withexitstatus=withexitstatus, + events=events, extra_args=extra_args, logfile=logfile, cwd=cwd, + env=env, **kwargs) diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/screen.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/screen.py new file mode 100644 index 00000000000..5ab45b94679 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/screen.py @@ -0,0 +1,431 @@ +'''This implements a virtual screen. This is used to support ANSI terminal +emulation. The screen representation and state is implemented in this class. +Most of the methods are inspired by ANSI screen control codes. The +:class:`~pexpect.ANSI.ANSI` class extends this class to add parsing of ANSI +escape codes. + +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +import codecs +import copy +import sys + +import warnings + +warnings.warn(("pexpect.screen and pexpect.ANSI are deprecated. " + "We recommend using pyte to emulate a terminal screen: " + "https://pypi.python.org/pypi/pyte"), + stacklevel=2) + +NUL = 0 # Fill character; ignored on input. +ENQ = 5 # Transmit answerback message. +BEL = 7 # Ring the bell. +BS = 8 # Move cursor left. +HT = 9 # Move cursor to next tab stop. +LF = 10 # Line feed. +VT = 11 # Same as LF. +FF = 12 # Same as LF. +CR = 13 # Move cursor to left margin or newline. +SO = 14 # Invoke G1 character set. +SI = 15 # Invoke G0 character set. +XON = 17 # Resume transmission. +XOFF = 19 # Halt transmission. +CAN = 24 # Cancel escape sequence. +SUB = 26 # Same as CAN. +ESC = 27 # Introduce a control sequence. +DEL = 127 # Fill character; ignored on input. +SPACE = u' ' # Space or blank character. + +PY3 = (sys.version_info[0] >= 3) +if PY3: + unicode = str + +def constrain (n, min, max): + + '''This returns a number, n constrained to the min and max bounds. ''' + + if n < min: + return min + if n > max: + return max + return n + +class screen: + '''This object maintains the state of a virtual text screen as a + rectangular array. This maintains a virtual cursor position and handles + scrolling as characters are added. This supports most of the methods needed + by an ANSI text screen. Row and column indexes are 1-based (not zero-based, + like arrays). + + Characters are represented internally using unicode. Methods that accept + input characters, when passed 'bytes' (which in Python 2 is equivalent to + 'str'), convert them from the encoding specified in the 'encoding' + parameter to the constructor. Methods that return screen contents return + unicode strings, with the exception of __str__() under Python 2. Passing + ``encoding=None`` limits the API to only accept unicode input, so passing + bytes in will raise :exc:`TypeError`. + ''' + def __init__(self, r=24, c=80, encoding='latin-1', encoding_errors='replace'): + '''This initializes a blank screen of the given dimensions.''' + + self.rows = r + self.cols = c + self.encoding = encoding + self.encoding_errors = encoding_errors + if encoding is not None: + self.decoder = codecs.getincrementaldecoder(encoding)(encoding_errors) + else: + self.decoder = None + self.cur_r = 1 + self.cur_c = 1 + self.cur_saved_r = 1 + self.cur_saved_c = 1 + self.scroll_row_start = 1 + self.scroll_row_end = self.rows + self.w = [ [SPACE] * self.cols for _ in range(self.rows)] + + def _decode(self, s): + '''This converts from the external coding system (as passed to + the constructor) to the internal one (unicode). ''' + if self.decoder is not None: + return self.decoder.decode(s) + else: + raise TypeError("This screen was constructed with encoding=None, " + "so it does not handle bytes.") + + def _unicode(self): + '''This returns a printable representation of the screen as a unicode + string (which, under Python 3.x, is the same as 'str'). The end of each + screen line is terminated by a newline.''' + + return u'\n'.join ([ u''.join(c) for c in self.w ]) + + if PY3: + __str__ = _unicode + else: + __unicode__ = _unicode + + def __str__(self): + '''This returns a printable representation of the screen. The end of + each screen line is terminated by a newline. ''' + encoding = self.encoding or 'ascii' + return self._unicode().encode(encoding, 'replace') + + def dump (self): + '''This returns a copy of the screen as a unicode string. This is similar to + __str__/__unicode__ except that lines are not terminated with line + feeds.''' + + return u''.join ([ u''.join(c) for c in self.w ]) + + def pretty (self): + '''This returns a copy of the screen as a unicode string with an ASCII + text box around the screen border. This is similar to + __str__/__unicode__ except that it adds a box.''' + + top_bot = u'+' + u'-'*self.cols + u'+\n' + return top_bot + u'\n'.join([u'|'+line+u'|' for line in unicode(self).split(u'\n')]) + u'\n' + top_bot + + def fill (self, ch=SPACE): + + if isinstance(ch, bytes): + ch = self._decode(ch) + + self.fill_region (1,1,self.rows,self.cols, ch) + + def fill_region (self, rs,cs, re,ce, ch=SPACE): + + if isinstance(ch, bytes): + ch = self._decode(ch) + + rs = constrain (rs, 1, self.rows) + re = constrain (re, 1, self.rows) + cs = constrain (cs, 1, self.cols) + ce = constrain (ce, 1, self.cols) + if rs > re: + rs, re = re, rs + if cs > ce: + cs, ce = ce, cs + for r in range (rs, re+1): + for c in range (cs, ce + 1): + self.put_abs (r,c,ch) + + def cr (self): + '''This moves the cursor to the beginning (col 1) of the current row. + ''' + + self.cursor_home (self.cur_r, 1) + + def lf (self): + '''This moves the cursor down with scrolling. + ''' + + old_r = self.cur_r + self.cursor_down() + if old_r == self.cur_r: + self.scroll_up () + self.erase_line() + + def crlf (self): + '''This advances the cursor with CRLF properties. + The cursor will line wrap and the screen may scroll. + ''' + + self.cr () + self.lf () + + def newline (self): + '''This is an alias for crlf(). + ''' + + self.crlf() + + def put_abs (self, r, c, ch): + '''Screen array starts at 1 index.''' + + r = constrain (r, 1, self.rows) + c = constrain (c, 1, self.cols) + if isinstance(ch, bytes): + ch = self._decode(ch)[0] + else: + ch = ch[0] + self.w[r-1][c-1] = ch + + def put (self, ch): + '''This puts a characters at the current cursor position. + ''' + + if isinstance(ch, bytes): + ch = self._decode(ch) + + self.put_abs (self.cur_r, self.cur_c, ch) + + def insert_abs (self, r, c, ch): + '''This inserts a character at (r,c). Everything under + and to the right is shifted right one character. + The last character of the line is lost. + ''' + + if isinstance(ch, bytes): + ch = self._decode(ch) + + r = constrain (r, 1, self.rows) + c = constrain (c, 1, self.cols) + for ci in range (self.cols, c, -1): + self.put_abs (r,ci, self.get_abs(r,ci-1)) + self.put_abs (r,c,ch) + + def insert (self, ch): + + if isinstance(ch, bytes): + ch = self._decode(ch) + + self.insert_abs (self.cur_r, self.cur_c, ch) + + def get_abs (self, r, c): + + r = constrain (r, 1, self.rows) + c = constrain (c, 1, self.cols) + return self.w[r-1][c-1] + + def get (self): + + self.get_abs (self.cur_r, self.cur_c) + + def get_region (self, rs,cs, re,ce): + '''This returns a list of lines representing the region. + ''' + + rs = constrain (rs, 1, self.rows) + re = constrain (re, 1, self.rows) + cs = constrain (cs, 1, self.cols) + ce = constrain (ce, 1, self.cols) + if rs > re: + rs, re = re, rs + if cs > ce: + cs, ce = ce, cs + sc = [] + for r in range (rs, re+1): + line = u'' + for c in range (cs, ce + 1): + ch = self.get_abs (r,c) + line = line + ch + sc.append (line) + return sc + + def cursor_constrain (self): + '''This keeps the cursor within the screen area. + ''' + + self.cur_r = constrain (self.cur_r, 1, self.rows) + self.cur_c = constrain (self.cur_c, 1, self.cols) + + def cursor_home (self, r=1, c=1): # <ESC>[{ROW};{COLUMN}H + + self.cur_r = r + self.cur_c = c + self.cursor_constrain () + + def cursor_back (self,count=1): # <ESC>[{COUNT}D (not confused with down) + + self.cur_c = self.cur_c - count + self.cursor_constrain () + + def cursor_down (self,count=1): # <ESC>[{COUNT}B (not confused with back) + + self.cur_r = self.cur_r + count + self.cursor_constrain () + + def cursor_forward (self,count=1): # <ESC>[{COUNT}C + + self.cur_c = self.cur_c + count + self.cursor_constrain () + + def cursor_up (self,count=1): # <ESC>[{COUNT}A + + self.cur_r = self.cur_r - count + self.cursor_constrain () + + def cursor_up_reverse (self): # <ESC> M (called RI -- Reverse Index) + + old_r = self.cur_r + self.cursor_up() + if old_r == self.cur_r: + self.scroll_up() + + def cursor_force_position (self, r, c): # <ESC>[{ROW};{COLUMN}f + '''Identical to Cursor Home.''' + + self.cursor_home (r, c) + + def cursor_save (self): # <ESC>[s + '''Save current cursor position.''' + + self.cursor_save_attrs() + + def cursor_unsave (self): # <ESC>[u + '''Restores cursor position after a Save Cursor.''' + + self.cursor_restore_attrs() + + def cursor_save_attrs (self): # <ESC>7 + '''Save current cursor position.''' + + self.cur_saved_r = self.cur_r + self.cur_saved_c = self.cur_c + + def cursor_restore_attrs (self): # <ESC>8 + '''Restores cursor position after a Save Cursor.''' + + self.cursor_home (self.cur_saved_r, self.cur_saved_c) + + def scroll_constrain (self): + '''This keeps the scroll region within the screen region.''' + + if self.scroll_row_start <= 0: + self.scroll_row_start = 1 + if self.scroll_row_end > self.rows: + self.scroll_row_end = self.rows + + def scroll_screen (self): # <ESC>[r + '''Enable scrolling for entire display.''' + + self.scroll_row_start = 1 + self.scroll_row_end = self.rows + + def scroll_screen_rows (self, rs, re): # <ESC>[{start};{end}r + '''Enable scrolling from row {start} to row {end}.''' + + self.scroll_row_start = rs + self.scroll_row_end = re + self.scroll_constrain() + + def scroll_down (self): # <ESC>D + '''Scroll display down one line.''' + + # Screen is indexed from 1, but arrays are indexed from 0. + s = self.scroll_row_start - 1 + e = self.scroll_row_end - 1 + self.w[s+1:e+1] = copy.deepcopy(self.w[s:e]) + + def scroll_up (self): # <ESC>M + '''Scroll display up one line.''' + + # Screen is indexed from 1, but arrays are indexed from 0. + s = self.scroll_row_start - 1 + e = self.scroll_row_end - 1 + self.w[s:e] = copy.deepcopy(self.w[s+1:e+1]) + + def erase_end_of_line (self): # <ESC>[0K -or- <ESC>[K + '''Erases from the current cursor position to the end of the current + line.''' + + self.fill_region (self.cur_r, self.cur_c, self.cur_r, self.cols) + + def erase_start_of_line (self): # <ESC>[1K + '''Erases from the current cursor position to the start of the current + line.''' + + self.fill_region (self.cur_r, 1, self.cur_r, self.cur_c) + + def erase_line (self): # <ESC>[2K + '''Erases the entire current line.''' + + self.fill_region (self.cur_r, 1, self.cur_r, self.cols) + + def erase_down (self): # <ESC>[0J -or- <ESC>[J + '''Erases the screen from the current line down to the bottom of the + screen.''' + + self.erase_end_of_line () + self.fill_region (self.cur_r + 1, 1, self.rows, self.cols) + + def erase_up (self): # <ESC>[1J + '''Erases the screen from the current line up to the top of the + screen.''' + + self.erase_start_of_line () + self.fill_region (self.cur_r-1, 1, 1, self.cols) + + def erase_screen (self): # <ESC>[2J + '''Erases the screen with the background color.''' + + self.fill () + + def set_tab (self): # <ESC>H + '''Sets a tab at the current position.''' + + pass + + def clear_tab (self): # <ESC>[g + '''Clears tab at the current position.''' + + pass + + def clear_all_tabs (self): # <ESC>[3g + '''Clears all tabs.''' + + pass + +# Insert line Esc [ Pn L +# Delete line Esc [ Pn M +# Delete character Esc [ Pn P +# Scrolling region Esc [ Pn(top);Pn(bot) r + diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py new file mode 100644 index 00000000000..63c0b4204eb --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py @@ -0,0 +1,522 @@ +from io import StringIO, BytesIO +import codecs +import os +import sys +import re +import errno +from .exceptions import ExceptionPexpect, EOF, TIMEOUT +from .expect import Expecter, searcher_string, searcher_re + +PY3 = (sys.version_info[0] >= 3) +text_type = str if PY3 else unicode + +class _NullCoder(object): + """Pass bytes through unchanged.""" + @staticmethod + def encode(b, final=False): + return b + + @staticmethod + def decode(b, final=False): + return b + +class SpawnBase(object): + """A base class providing the backwards-compatible spawn API for Pexpect. + + This should not be instantiated directly: use :class:`pexpect.spawn` or + :class:`pexpect.fdpexpect.fdspawn`. + """ + encoding = None + pid = None + flag_eof = False + + def __init__(self, timeout=30, maxread=2000, searchwindowsize=None, + logfile=None, encoding=None, codec_errors='strict'): + self.stdin = sys.stdin + self.stdout = sys.stdout + self.stderr = sys.stderr + + self.searcher = None + self.ignorecase = False + self.before = None + self.after = None + self.match = None + self.match_index = None + self.terminated = True + self.exitstatus = None + self.signalstatus = None + # status returned by os.waitpid + self.status = None + # the child file descriptor is initially closed + self.child_fd = -1 + self.timeout = timeout + self.delimiter = EOF + self.logfile = logfile + # input from child (read_nonblocking) + self.logfile_read = None + # output to send (send, sendline) + self.logfile_send = None + # max bytes to read at one time into buffer + self.maxread = maxread + # Data before searchwindowsize point is preserved, but not searched. + self.searchwindowsize = searchwindowsize + # Delay used before sending data to child. Time in seconds. + # Set this to None to skip the time.sleep() call completely. + self.delaybeforesend = 0.05 + # Used by close() to give kernel time to update process status. + # Time in seconds. + self.delayafterclose = 0.1 + # Used by terminate() to give kernel time to update process status. + # Time in seconds. + self.delayafterterminate = 0.1 + # Delay in seconds to sleep after each call to read_nonblocking(). + # Set this to None to skip the time.sleep() call completely: that + # would restore the behavior from pexpect-2.0 (for performance + # reasons or because you don't want to release Python's global + # interpreter lock). + self.delayafterread = 0.0001 + self.softspace = False + self.name = '<' + repr(self) + '>' + self.closed = True + + # Unicode interface + self.encoding = encoding + self.codec_errors = codec_errors + if encoding is None: + # bytes mode (accepts some unicode for backwards compatibility) + self._encoder = self._decoder = _NullCoder() + self.string_type = bytes + self.buffer_type = BytesIO + self.crlf = b'\r\n' + if PY3: + self.allowed_string_types = (bytes, str) + self.linesep = os.linesep.encode('ascii') + def write_to_stdout(b): + try: + return sys.stdout.buffer.write(b) + except AttributeError: + # If stdout has been replaced, it may not have .buffer + return sys.stdout.write(b.decode('ascii', 'replace')) + self.write_to_stdout = write_to_stdout + else: + self.allowed_string_types = (basestring,) # analysis:ignore + self.linesep = os.linesep + self.write_to_stdout = sys.stdout.write + else: + # unicode mode + self._encoder = codecs.getincrementalencoder(encoding)(codec_errors) + self._decoder = codecs.getincrementaldecoder(encoding)(codec_errors) + self.string_type = text_type + self.buffer_type = StringIO + self.crlf = u'\r\n' + self.allowed_string_types = (text_type, ) + if PY3: + self.linesep = os.linesep + else: + self.linesep = os.linesep.decode('ascii') + # This can handle unicode in both Python 2 and 3 + self.write_to_stdout = sys.stdout.write + # storage for async transport + self.async_pw_transport = None + # This is the read buffer. See maxread. + self._buffer = self.buffer_type() + + def _log(self, s, direction): + if self.logfile is not None: + self.logfile.write(s) + self.logfile.flush() + second_log = self.logfile_send if (direction=='send') else self.logfile_read + if second_log is not None: + second_log.write(s) + second_log.flush() + + # For backwards compatibility, in bytes mode (when encoding is None) + # unicode is accepted for send and expect. Unicode mode is strictly unicode + # only. + def _coerce_expect_string(self, s): + if self.encoding is None and not isinstance(s, bytes): + return s.encode('ascii') + return s + + def _coerce_send_string(self, s): + if self.encoding is None and not isinstance(s, bytes): + return s.encode('utf-8') + return s + + def _get_buffer(self): + return self._buffer.getvalue() + + def _set_buffer(self, value): + self._buffer = self.buffer_type() + self._buffer.write(value) + + # This property is provided for backwards compatability (self.buffer used + # to be a string/bytes object) + buffer = property(_get_buffer, _set_buffer) + + def read_nonblocking(self, size=1, timeout=None): + """This reads data from the file descriptor. + + This is a simple implementation suitable for a regular file. Subclasses using ptys or pipes should override it. + + The timeout parameter is ignored. + """ + + try: + s = os.read(self.child_fd, size) + except OSError as err: + if err.args[0] == errno.EIO: + # Linux-style EOF + self.flag_eof = True + raise EOF('End Of File (EOF). Exception style platform.') + raise + if s == b'': + # BSD-style EOF + self.flag_eof = True + raise EOF('End Of File (EOF). Empty string style platform.') + + s = self._decoder.decode(s, final=False) + self._log(s, 'read') + return s + + def _pattern_type_err(self, pattern): + raise TypeError('got {badtype} ({badobj!r}) as pattern, must be one' + ' of: {goodtypes}, pexpect.EOF, pexpect.TIMEOUT'\ + .format(badtype=type(pattern), + badobj=pattern, + goodtypes=', '.join([str(ast)\ + for ast in self.allowed_string_types]) + ) + ) + + def compile_pattern_list(self, patterns): + '''This compiles a pattern-string or a list of pattern-strings. + Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of + those. Patterns may also be None which results in an empty list (you + might do this if waiting for an EOF or TIMEOUT condition without + expecting any pattern). + + This is used by expect() when calling expect_list(). Thus expect() is + nothing more than:: + + cpl = self.compile_pattern_list(pl) + return self.expect_list(cpl, timeout) + + If you are using expect() within a loop it may be more + efficient to compile the patterns first and then call expect_list(). + This avoid calls in a loop to compile_pattern_list():: + + cpl = self.compile_pattern_list(my_pattern) + while some_condition: + ... + i = self.expect_list(cpl, timeout) + ... + ''' + + if patterns is None: + return [] + if not isinstance(patterns, list): + patterns = [patterns] + + # Allow dot to match \n + compile_flags = re.DOTALL + if self.ignorecase: + compile_flags = compile_flags | re.IGNORECASE + compiled_pattern_list = [] + for idx, p in enumerate(patterns): + if isinstance(p, self.allowed_string_types): + p = self._coerce_expect_string(p) + compiled_pattern_list.append(re.compile(p, compile_flags)) + elif p is EOF: + compiled_pattern_list.append(EOF) + elif p is TIMEOUT: + compiled_pattern_list.append(TIMEOUT) + elif isinstance(p, type(re.compile(''))): + compiled_pattern_list.append(p) + else: + self._pattern_type_err(p) + return compiled_pattern_list + + def expect(self, pattern, timeout=-1, searchwindowsize=-1, async_=False, **kw): + '''This seeks through the stream until a pattern is matched. The + pattern is overloaded and may take several types. The pattern can be a + StringType, EOF, a compiled re, or a list of any of those types. + Strings will be compiled to re types. This returns the index into the + pattern list. If the pattern was not a list this returns index 0 on a + successful match. This may raise exceptions for EOF or TIMEOUT. To + avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern + list. That will cause expect to match an EOF or TIMEOUT condition + instead of raising an exception. + + If you pass a list of patterns and more than one matches, the first + match in the stream is chosen. If more than one pattern matches at that + point, the leftmost in the pattern list is chosen. For example:: + + # the input is 'foobar' + index = p.expect(['bar', 'foo', 'foobar']) + # returns 1('foo') even though 'foobar' is a "better" match + + Please note, however, that buffering can affect this behavior, since + input arrives in unpredictable chunks. For example:: + + # the input is 'foobar' + index = p.expect(['foobar', 'foo']) + # returns 0('foobar') if all input is available at once, + # but returns 1('foo') if parts of the final 'bar' arrive late + + When a match is found for the given pattern, the class instance + attribute *match* becomes an re.MatchObject result. Should an EOF + or TIMEOUT pattern match, then the match attribute will be an instance + of that exception class. The pairing before and after class + instance attributes are views of the data preceding and following + the matching pattern. On general exception, class attribute + *before* is all data received up to the exception, while *match* and + *after* attributes are value None. + + When the keyword argument timeout is -1 (default), then TIMEOUT will + raise after the default value specified by the class timeout + attribute. When None, TIMEOUT will not be raised and may block + indefinitely until match. + + When the keyword argument searchwindowsize is -1 (default), then the + value specified by the class maxread attribute is used. + + A list entry may be EOF or TIMEOUT instead of a string. This will + catch these exceptions and return the index of the list entry instead + of raising the exception. The attribute 'after' will be set to the + exception type. The attribute 'match' will be None. This allows you to + write code like this:: + + index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT]) + if index == 0: + do_something() + elif index == 1: + do_something_else() + elif index == 2: + do_some_other_thing() + elif index == 3: + do_something_completely_different() + + instead of code like this:: + + try: + index = p.expect(['good', 'bad']) + if index == 0: + do_something() + elif index == 1: + do_something_else() + except EOF: + do_some_other_thing() + except TIMEOUT: + do_something_completely_different() + + These two forms are equivalent. It all depends on what you want. You + can also just expect the EOF if you are waiting for all output of a + child to finish. For example:: + + p = pexpect.spawn('/bin/ls') + p.expect(pexpect.EOF) + print p.before + + If you are trying to optimize for speed then see expect_list(). + + On Python 3.4, or Python 3.3 with asyncio installed, passing + ``async_=True`` will make this return an :mod:`asyncio` coroutine, + which you can yield from to get the same result that this method would + normally give directly. So, inside a coroutine, you can replace this code:: + + index = p.expect(patterns) + + With this non-blocking form:: + + index = yield from p.expect(patterns, async_=True) + ''' + if 'async' in kw: + async_ = kw.pop('async') + if kw: + raise TypeError("Unknown keyword arguments: {}".format(kw)) + + compiled_pattern_list = self.compile_pattern_list(pattern) + return self.expect_list(compiled_pattern_list, + timeout, searchwindowsize, async_) + + def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1, + async_=False, **kw): + '''This takes a list of compiled regular expressions and returns the + index into the pattern_list that matched the child output. The list may + also contain EOF or TIMEOUT(which are not compiled regular + expressions). This method is similar to the expect() method except that + expect_list() does not recompile the pattern list on every call. This + may help if you are trying to optimize for speed, otherwise just use + the expect() method. This is called by expect(). + + + Like :meth:`expect`, passing ``async_=True`` will make this return an + asyncio coroutine. + ''' + if timeout == -1: + timeout = self.timeout + if 'async' in kw: + async_ = kw.pop('async') + if kw: + raise TypeError("Unknown keyword arguments: {}".format(kw)) + + exp = Expecter(self, searcher_re(pattern_list), searchwindowsize) + if async_: + from ._async import expect_async + return expect_async(exp, timeout) + else: + return exp.expect_loop(timeout) + + def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1, + async_=False, **kw): + + '''This is similar to expect(), but uses plain string matching instead + of compiled regular expressions in 'pattern_list'. The 'pattern_list' + may be a string; a list or other sequence of strings; or TIMEOUT and + EOF. + + This call might be faster than expect() for two reasons: string + searching is faster than RE matching and it is possible to limit the + search to just the end of the input buffer. + + This method is also useful when you don't want to have to worry about + escaping regular expression characters that you want to match. + + Like :meth:`expect`, passing ``async_=True`` will make this return an + asyncio coroutine. + ''' + if timeout == -1: + timeout = self.timeout + if 'async' in kw: + async_ = kw.pop('async') + if kw: + raise TypeError("Unknown keyword arguments: {}".format(kw)) + + if (isinstance(pattern_list, self.allowed_string_types) or + pattern_list in (TIMEOUT, EOF)): + pattern_list = [pattern_list] + + def prepare_pattern(pattern): + if pattern in (TIMEOUT, EOF): + return pattern + if isinstance(pattern, self.allowed_string_types): + return self._coerce_expect_string(pattern) + self._pattern_type_err(pattern) + + try: + pattern_list = iter(pattern_list) + except TypeError: + self._pattern_type_err(pattern_list) + pattern_list = [prepare_pattern(p) for p in pattern_list] + + exp = Expecter(self, searcher_string(pattern_list), searchwindowsize) + if async_: + from ._async import expect_async + return expect_async(exp, timeout) + else: + return exp.expect_loop(timeout) + + def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1): + '''This is the common loop used inside expect. The 'searcher' should be + an instance of searcher_re or searcher_string, which describes how and + what to search for in the input. + + See expect() for other arguments, return value and exceptions. ''' + + exp = Expecter(self, searcher, searchwindowsize) + return exp.expect_loop(timeout) + + def read(self, size=-1): + '''This reads at most "size" bytes from the file (less if the read hits + EOF before obtaining size bytes). If the size argument is negative or + omitted, read all data until EOF is reached. The bytes are returned as + a string object. An empty string is returned when EOF is encountered + immediately. ''' + + if size == 0: + return self.string_type() + if size < 0: + # delimiter default is EOF + self.expect(self.delimiter) + return self.before + + # I could have done this more directly by not using expect(), but + # I deliberately decided to couple read() to expect() so that + # I would catch any bugs early and ensure consistent behavior. + # It's a little less efficient, but there is less for me to + # worry about if I have to later modify read() or expect(). + # Note, it's OK if size==-1 in the regex. That just means it + # will never match anything in which case we stop only on EOF. + cre = re.compile(self._coerce_expect_string('.{%d}' % size), re.DOTALL) + # delimiter default is EOF + index = self.expect([cre, self.delimiter]) + if index == 0: + ### FIXME self.before should be ''. Should I assert this? + return self.after + return self.before + + def readline(self, size=-1): + '''This reads and returns one entire line. The newline at the end of + line is returned as part of the string, unless the file ends without a + newline. An empty string is returned if EOF is encountered immediately. + This looks for a newline as a CR/LF pair (\\r\\n) even on UNIX because + this is what the pseudotty device returns. So contrary to what you may + expect you will receive newlines as \\r\\n. + + If the size argument is 0 then an empty string is returned. In all + other cases the size argument is ignored, which is not standard + behavior for a file-like object. ''' + + if size == 0: + return self.string_type() + # delimiter default is EOF + index = self.expect([self.crlf, self.delimiter]) + if index == 0: + return self.before + self.crlf + else: + return self.before + + def __iter__(self): + '''This is to support iterators over a file-like object. + ''' + return iter(self.readline, self.string_type()) + + def readlines(self, sizehint=-1): + '''This reads until EOF using readline() and returns a list containing + the lines thus read. The optional 'sizehint' argument is ignored. + Remember, because this reads until EOF that means the child + process should have closed its stdout. If you run this method on + a child that is still running with its stdout open then this + method will block until it timesout.''' + + lines = [] + while True: + line = self.readline() + if not line: + break + lines.append(line) + return lines + + def fileno(self): + '''Expose file descriptor for a file-like interface + ''' + return self.child_fd + + def flush(self): + '''This does nothing. It is here to support the interface for a + File-like object. ''' + pass + + def isatty(self): + """Overridden in subclass using tty""" + return False + + # For 'with spawn(...) as child:' + def __enter__(self): + return self + + def __exit__(self, etype, evalue, tb): + # We rely on subclasses to implement close(). If they don't, it's not + # clear what a context manager should do. + self.close() diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/utils.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/utils.py new file mode 100644 index 00000000000..f7745196090 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/pexpect/utils.py @@ -0,0 +1,187 @@ +import os +import sys +import stat +import select +import time +import errno + +try: + InterruptedError +except NameError: + # Alias Python2 exception to Python3 + InterruptedError = select.error + +if sys.version_info[0] >= 3: + string_types = (str,) +else: + string_types = (unicode, str) + + +def is_executable_file(path): + """Checks that path is an executable regular file, or a symlink towards one. + + This is roughly ``os.path isfile(path) and os.access(path, os.X_OK)``. + """ + # follow symlinks, + fpath = os.path.realpath(path) + + if not os.path.isfile(fpath): + # non-files (directories, fifo, etc.) + return False + + mode = os.stat(fpath).st_mode + + if (sys.platform.startswith('sunos') + and os.getuid() == 0): + # When root on Solaris, os.X_OK is True for *all* files, irregardless + # of their executability -- instead, any permission bit of any user, + # group, or other is fine enough. + # + # (This may be true for other "Unix98" OS's such as HP-UX and AIX) + return bool(mode & (stat.S_IXUSR | + stat.S_IXGRP | + stat.S_IXOTH)) + + return os.access(fpath, os.X_OK) + + +def which(filename, env=None): + '''This takes a given filename; tries to find it in the environment path; + then checks if it is executable. This returns the full path to the filename + if found and executable. Otherwise this returns None.''' + + # Special case where filename contains an explicit path. + if os.path.dirname(filename) != '' and is_executable_file(filename): + return filename + if env is None: + env = os.environ + p = env.get('PATH') + if not p: + p = os.defpath + pathlist = p.split(os.pathsep) + for path in pathlist: + ff = os.path.join(path, filename) + if is_executable_file(ff): + return ff + return None + + +def split_command_line(command_line): + + '''This splits a command line into a list of arguments. It splits arguments + on spaces, but handles embedded quotes, doublequotes, and escaped + characters. It's impossible to do this with a regular expression, so I + wrote a little state machine to parse the command line. ''' + + arg_list = [] + arg = '' + + # Constants to name the states we can be in. + state_basic = 0 + state_esc = 1 + state_singlequote = 2 + state_doublequote = 3 + # The state when consuming whitespace between commands. + state_whitespace = 4 + state = state_basic + + for c in command_line: + if state == state_basic or state == state_whitespace: + if c == '\\': + # Escape the next character + state = state_esc + elif c == r"'": + # Handle single quote + state = state_singlequote + elif c == r'"': + # Handle double quote + state = state_doublequote + elif c.isspace(): + # Add arg to arg_list if we aren't in the middle of whitespace. + if state == state_whitespace: + # Do nothing. + None + else: + arg_list.append(arg) + arg = '' + state = state_whitespace + else: + arg = arg + c + state = state_basic + elif state == state_esc: + arg = arg + c + state = state_basic + elif state == state_singlequote: + if c == r"'": + state = state_basic + else: + arg = arg + c + elif state == state_doublequote: + if c == r'"': + state = state_basic + else: + arg = arg + c + + if arg != '': + arg_list.append(arg) + return arg_list + + +def select_ignore_interrupts(iwtd, owtd, ewtd, timeout=None): + + '''This is a wrapper around select.select() that ignores signals. If + select.select raises a select.error exception and errno is an EINTR + error then it is ignored. Mainly this is used to ignore sigwinch + (terminal resize). ''' + + # if select() is interrupted by a signal (errno==EINTR) then + # we loop back and enter the select() again. + if timeout is not None: + end_time = time.time() + timeout + while True: + try: + return select.select(iwtd, owtd, ewtd, timeout) + except InterruptedError: + err = sys.exc_info()[1] + if err.args[0] == errno.EINTR: + # if we loop back we have to subtract the + # amount of time we already waited. + if timeout is not None: + timeout = end_time - time.time() + if timeout < 0: + return([], [], []) + else: + # something else caused the select.error, so + # this actually is an exception. + raise + + +def poll_ignore_interrupts(fds, timeout=None): + '''Simple wrapper around poll to register file descriptors and + ignore signals.''' + + if timeout is not None: + end_time = time.time() + timeout + + poller = select.poll() + for fd in fds: + poller.register(fd, select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR) + + while True: + try: + timeout_ms = None if timeout is None else timeout * 1000 + results = poller.poll(timeout_ms) + return [afd for afd, _ in results] + except InterruptedError: + err = sys.exc_info()[1] + if err.args[0] == errno.EINTR: + # if we loop back we have to subtract the + # amount of time we already waited. + if timeout is not None: + timeout = end_time - time.time() + if timeout < 0: + return [] + else: + # something else caused the select.error, so + # this actually is an exception. + raise diff --git a/lldb/third_party/Python/module/pexpect-4.6/requirements-testing.txt b/lldb/third_party/Python/module/pexpect-4.6/requirements-testing.txt new file mode 100644 index 00000000000..1894122c85c --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/requirements-testing.txt @@ -0,0 +1,5 @@ +pytest +pytest-cov +coverage +coveralls +pytest-capturelog diff --git a/lldb/third_party/Python/module/pexpect-4.6/setup.cfg b/lldb/third_party/Python/module/pexpect-4.6/setup.cfg new file mode 100644 index 00000000000..b2a82dcdc6c --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/setup.cfg @@ -0,0 +1,5 @@ +[tool:pytest] +norecursedirs = .git + +[bdist_wheel] +universal=1 diff --git a/lldb/third_party/Python/module/pexpect-4.6/setup.py b/lldb/third_party/Python/module/pexpect-4.6/setup.py new file mode 100644 index 00000000000..4e61e795c2a --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/setup.py @@ -0,0 +1,71 @@ +# encoding: utf-8 +from distutils.core import setup +import os +import re +import sys + +if any(a == 'bdist_wheel' for a in sys.argv): + from setuptools import setup + +with open(os.path.join(os.path.dirname(__file__), 'pexpect', '__init__.py'), 'r') as f: + for line in f: + version_match = re.search(r"__version__ = ['\"]([^'\"]*)['\"]", line) + if version_match: + version = version_match.group(1) + break + else: + raise Exception("couldn't find version number") + +long_description = """ +Pexpect is a pure Python module for spawning child applications; controlling +them; and responding to expected patterns in their output. Pexpect works like +Don Libes' Expect. Pexpect allows your script to spawn a child application and +control it as if a human were typing commands. + +Pexpect can be used for automating interactive applications such as ssh, ftp, +passwd, telnet, etc. It can be used to a automate setup scripts for duplicating +software package installations on different servers. It can be used for +automated software testing. Pexpect is in the spirit of Don Libes' Expect, but +Pexpect is pure Python. + +The main features of Pexpect require the pty module in the Python standard +library, which is only available on Unix-like systems. Some features—waiting +for patterns from file descriptors or subprocesses—are also available on +Windows. +""" + +setup(name='pexpect', + version=version, + packages=['pexpect'], + package_data={'pexpect': ['bashrc.sh']}, + description='Pexpect allows easy control of interactive console applications.', + long_description=long_description, + author='Noah Spurrier; Thomas Kluyver; Jeff Quast', + author_email='noah@noah.org, thomas@kluyver.me.uk, contact@jeffquast.com', + url='https://pexpect.readthedocs.io/', + license='ISC license', + platforms='UNIX', + classifiers = [ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: ISC License (ISCL)', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Topic :: Software Development', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: Software Development :: Quality Assurance', + 'Topic :: Software Development :: Testing', + 'Topic :: System', + 'Topic :: System :: Archiving :: Packaging', + 'Topic :: System :: Installation/Setup', + 'Topic :: System :: Shells', + 'Topic :: System :: Software Distribution', + 'Topic :: Terminals', + ], + install_requires=['ptyprocess>=0.5'], +) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/PexpectTestCase.py b/lldb/third_party/Python/module/pexpect-4.6/tests/PexpectTestCase.py new file mode 100644 index 00000000000..307437efad3 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/PexpectTestCase.py @@ -0,0 +1,108 @@ + +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from __future__ import print_function + +import contextlib +import unittest +import signal +import sys +import os + + +class PexpectTestCase(unittest.TestCase): + def setUp(self): + self.PYTHONBIN = sys.executable + self.original_path = os.getcwd() + tests_dir = os.path.dirname(__file__) + self.project_dir = project_dir = os.path.dirname(tests_dir) + + # all tests are executed in this folder; there are many auxiliary + # programs in this folder executed by spawn(). + os.chdir(tests_dir) + + # If the pexpect raises an exception after fork(), but before + # exec(), our test runner *also* forks. We prevent this by + # storing our pid and asserting equality on tearDown. + self.pid = os.getpid() + + coverage_rc = os.path.join(project_dir, '.coveragerc') + os.environ['COVERAGE_PROCESS_START'] = coverage_rc + os.environ['COVERAGE_FILE'] = os.path.join(project_dir, '.coverage') + print('\n', self.id(), end=' ') + sys.stdout.flush() + + # some build agents will ignore SIGHUP and SIGINT, which python + # inherits. This causes some of the tests related to terminate() + # to fail. We set them to the default handlers that they should + # be, and restore them back to their SIG_IGN value on tearDown. + # + # I'm not entirely convinced they need to be restored, only our + # test runner is affected. + self.restore_ignored_signals = [ + value for value in (signal.SIGHUP, signal.SIGINT,) + if signal.getsignal(value) == signal.SIG_IGN] + if signal.SIGHUP in self.restore_ignored_signals: + # sighup should be set to default handler + signal.signal(signal.SIGHUP, signal.SIG_DFL) + if signal.SIGINT in self.restore_ignored_signals: + # SIGINT should be set to signal.default_int_handler + signal.signal(signal.SIGINT, signal.default_int_handler) + unittest.TestCase.setUp(self) + + def tearDown(self): + # restore original working folder + os.chdir(self.original_path) + + if self.pid != os.getpid(): + # The build server pattern-matches phrase 'Test runner has forked!' + print("Test runner has forked! This means a child process raised " + "an exception before exec() in a test case, the error is " + "more than likely found above this line in stderr.", + file=sys.stderr) + exit(1) + + # restore signal handlers + for signal_value in self.restore_ignored_signals: + signal.signal(signal_value, signal.SIG_IGN) + + if sys.version_info < (2, 7): + # We want to use these methods, which are new/improved in 2.7, but + # we are still supporting 2.6 for the moment. This section can be + # removed when we drop Python 2.6 support. + @contextlib.contextmanager + def assertRaises(self, excClass): + try: + yield + except Exception as e: + assert isinstance(e, excClass) + else: + raise AssertionError("%s was not raised" % excClass) + + @contextlib.contextmanager + def assertRaisesRegexp(self, excClass, pattern): + import re + try: + yield + except Exception as e: + assert isinstance(e, excClass) + assert re.match(pattern, str(e)) + else: + raise AssertionError("%s was not raised" % excClass) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/README b/lldb/third_party/Python/module/pexpect-4.6/tests/README new file mode 100644 index 00000000000..ef5b613498e --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/README @@ -0,0 +1,8 @@ + +The best way to run these tests is from the directory above this one. Run: + + py.test + +To run a specific test file: + + py.test tests/test_constructor.py diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/TESTDATA.txt b/lldb/third_party/Python/module/pexpect-4.6/tests/TESTDATA.txt new file mode 100644 index 00000000000..adb9c01360f --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/TESTDATA.txt @@ -0,0 +1,8 @@ +This is test data. + One + 2 + THREE + IV + ..... + 110 +This is the end of test data: END diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/__init__.py b/lldb/third_party/Python/module/pexpect-4.6/tests/__init__.py new file mode 100755 index 00000000000..f717d82ecf5 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/__init__.py @@ -0,0 +1,25 @@ + +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +# __init__.py +# The mere presence of this file makes the dir a package. +pass + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/adhoc.py b/lldb/third_party/Python/module/pexpect-4.6/tests/adhoc.py new file mode 100755 index 00000000000..0813d349ee9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/adhoc.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from __future__ import print_function + +import pexpect +import time + +p = pexpect.spawn ('./a.out') +print(p.exitstatus) +p.expect (pexpect.EOF) +print(p.before) +time.sleep(1) +print('exitstatus:', p.exitstatus) +print('isalive',p.isalive()) +print('exitstatus',p.exitstatus) +print('isalive',p.isalive()) +print('exitstatus',p.exitstatus) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/alarm_die.py b/lldb/third_party/Python/module/pexpect-4.6/tests/alarm_die.py new file mode 100644 index 00000000000..a1519abac1d --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/alarm_die.py @@ -0,0 +1,5 @@ +import signal, time + +signal.alarm(1) # Schedule SIGALRM in 1s + +time.sleep(6)
\ No newline at end of file diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/bambi.vt b/lldb/third_party/Python/module/pexpect-4.6/tests/bambi.vt new file mode 100644 index 00000000000..853f099b4c5 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/bambi.vt @@ -0,0 +1,417 @@ +[?25l +[1;24r +[2J +[10;1H The +[10;1H The Adventures +[10;1H The Adventures of +[10;1H The Adventures of BAMBI +[16;1H +[15;1H Number +[15;1H Number One : +[15;1H Number One : BAMBI +[15;1H Number One : BAMBI versus +[15;1H Number One : BAMBI versus GODZILLA +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[16;1H +[2J +[23;5H ,| *./[24;5H\|(/|/[1;1H +[22;38H /|[23;38H |/`|',[24;38H/| \|/[1;1H +[23;65H \/_,| /| /,[24;65H /<|\\/\|/|\[1;1H +[15;1H _^_ +[16;1H o / .\ +[17;1H \,--------; __o +[18;1H / .:::. . / +[19;1H \___________/ +[20;1H |\ |\ +[21;1H | > | \ +[22;1H / / | \ +[15;2H _^_ +[16;2H o / .\ +[17;2H \,--------; __o +[18;2H / .:::. . / +[19;2H \___________/ +[20;2H \| |\ +[21;2H \ | \ +[22;2H / \ / | +[15;3H _^_ +[16;3H o / .\ +[17;3H \,--------; __o +[18;3H / .:::. . / +[19;3H \___________/ +[20;3H \\ \| +[21;3H \\ \ +[22;3H | \ |\ +[15;4H _^_ +[16;4H o / .\ +[17;4H \,--------; __o +[18;4H / .:::. . / +[19;4H \___________/ +[20;4H \\ \| +[21;4H >\ \ +[22;4H / | /| +[15;5H _^_ +[16;5H o / .\ +[17;5H \,--------; __o +[18;5H / .:::.. . / +[19;5H \___________/ +[20;5H |\ |\ +[21;5H | > | \ +[22;5H / / | \ +[15;6H _^_ +[16;6H o / .\ +[17;6H \,--------; __o +[18;6H / .:::.. . / +[19;6H \___________/ +[20;6H \| |\ +[21;6H \ | \ +[22;6H / \ / | +[15;18H +[16;18H +[17;18H--,_^_ +[18;18H. .\ +[19;18H__--___o +[17;18H--_ +[18;18H. \ +[19;18H__ \/| +[20;18H|\( .| +[21;18H| \\ / +[22;18H | " +[17;18H--_ +[18;18H. \ +[19;18H__ \/| +[20;18H|\( .| +[21;18H| \\ / +[22;18H | " +[17;18H--_ +[18;18H. \ +[19;18H__ \/| +[20;18H|\( .| +[21;18H| \\ / +[22;18H | " +[17;18H--_ +[18;18H. \ +[19;18H__ \/| +[20;18H|\( .| +[21;18H| \\ / +[22;18H | " +[17;18H--,_^_ +[18;18H. .\ +[19;18H__--___o +[20;18H|\ +[21;18H| \ +[22;18H | +[15;7H _^_ +[16;7H o / .\ +[17;7H \,--------; __o +[18;7H / .:::.. . / +[19;7H \___________/ +[20;7H \\ \| +[21;7H \\ \ +[22;7H | \ |\ +[15;8H _^_ +[16;8H o / .\ +[17;8H \,--------; __o +[18;8H / .:::.. . / +[19;8H \___________/ +[20;8H \\ \| +[21;8H >\ \ +[22;8H / | /| +[15;9H _^_ +[16;9H o / .\ +[17;9H \,--------; __o +[18;9H / .:::.. . / +[19;9H \___________/ +[20;9H |\ |\ +[21;9H | > | \ +[22;9H / / | \ +[15;10H _^_ +[16;10H o / .\ +[17;10H \,--------; __o +[18;10H / .:::.. . / +[19;10H \___________/ +[20;10H \| |\ +[21;10H \ | \ +[22;10H / \ / | +[15;11H _^_ +[16;11H o / .\ +[17;11H \,--------; __o +[18;11H / .:::.. . / +[19;11H \___________/ +[20;11H \\ \| +[21;11H \\ \ +[22;11H | \ |\ +[15;12H _^_ +[16;12H o / .\ +[17;12H \,--------; __o +[18;12H / .:::.. . / +[19;12H \___________/ +[20;12H \\ \| +[21;12H >\ \ +[22;12H / | /| +[15;13H _^_ +[16;13H o / .\ +[17;13H \,--------; __o +[18;13H / .:::.. . / +[19;13H \___________/ +[20;13H |\ |\ +[21;13H | > | \ +[22;13H / / | \ +[15;14H _^_ +[16;14H o / .\ +[17;14H \,--------; __o +[18;14H / .:::.. . / +[19;14H \___________/ +[20;14H \| |\ +[21;14H \ | \ +[22;14H / \ / | +[15;15H _^_ +[16;15H o / .\ +[17;15H \,--------; __o +[18;15H / .:::.. . / +[19;15H \___________/ +[20;15H \\ \| +[21;15H \\ \ +[22;15H | \ |\ +[15;16H _^_ +[16;16H o / .\ +[17;16H \,--------; __o +[18;16H / .:::.. . / +[19;16H \___________/ +[20;16H \\ \| +[21;16H >\ \ +[22;16H / | /| +[15;17H _^_ +[16;17H o / .\ +[17;17H \,--------; __o +[18;17H / .:::.. . / +[19;17H \___________/ +[20;17H |\ |\ +[21;17H | > | \ +[22;17H / / | \ +[15;29H +[16;29H +[17;29H--,_^_ +[18;29H. .\ +[19;29H__--___o +[17;29H--_ +[18;29H. \ +[19;29H__ \/| +[20;29H|\( .| +[21;29H| \\ / +[22;29H| \" +[17;29H--_ +[18;29H. \ +[19;29H__ \/| +[20;29H|\( .| +[21;29H| \\ / +[22;29H| \" +[17;29H--,_^_ +[18;29H. .\ +[19;29H__--___o +[20;29H|\ +[21;29H| \ +[22;29H| \ +[17;29H--,_^_ +[18;29H. .\ +[19;29H__--___o +[20;29H|\ +[21;29H| \ +[22;29H| \ +[17;29H--_ +[18;29H. \ +[19;29H__ \/| +[20;29H|\( .| +[21;29H| \\ / +[22;29H| \" +[17;29H--_ +[18;29H. \ +[19;29H__ \/| +[20;29H|\( .| +[21;29H| \\ / +[22;29H| \" +[17;29H--_ +[18;29H. \ +[19;29H__ \/| +[20;29H|\( .| +[21;29H| \\ / +[22;29H| \" +[17;29H--,_^_ +[18;29H. .\ +[19;29H__--___o +[20;29H|\ +[21;29H| \ +[22;29H| \ +[15;18H _^_ +[16;18H o / .\ +[17;18H \,--------; __o +[18;18H / .:::.. . / +[19;18H \___________/ +[20;18H \| |\ +[21;18H \ | \ +[22;18H / \ / | +[15;19H _^_ +[16;19H o / .\ +[17;19H \,--------; __o +[18;19H / .:::.. . / +[19;19H \___________/ +[20;19H \\ \| +[21;19H \\ \ +[22;19H | \ |\ +[15;20H _^_ +[16;20H o / .\ +[17;20H \,--------; __o +[18;20H / .:::.. . / +[19;20H \___________/ +[20;20H \\ \| +[21;20H >\ \ +[22;20H / | /| +[15;21H _^_ +[16;21H o / .\ +[17;21H \,--------; __o +[18;21H / .:::.. . / +[19;21H \___________/ +[20;21H |\ |\ +[21;21H | > | \ +[22;21H / / | \ +[15;22H _^_ +[16;22H o / .\ +[17;22H \,--------; __o +[18;22H / .:::.. . / +[19;22H \___________/ +[20;22H \| |\ +[21;22H \ | \ +[22;22H / \ / | +[15;23H _^_ +[16;23H o / .\ +[17;23H \,--------; __o +[18;23H / .:::.. . / +[19;23H \___________/ +[20;23H \\ \| +[21;23H \\ \ +[22;23H | \ |\ +[15;24H _^_ +[16;24H o / .\ +[17;24H \,--------; __o +[18;24H / .:::.. . / +[19;24H \___________/ +[20;24H \\ \| +[21;24H >\ \ +[22;24H / | /| +[15;24H +[16;24H o +[17;24H \,----------,_^_ +[18;24H / .:::.. . .\ +[19;24H \___________--___o +[20;24H \\ \| +[21;24H >\ \ +[22;24H / | /| +[15;24H +[16;24H o +[17;24H \,----------_ +[18;24H / .:::.. . \ +[19;24H \___________ \/| +[20;24H \\ \|( .| +[21;24H >\ \ \ / +[22;24H / | /| " +[1;15r +[1;10H`' `.__________________________________/M +[1;10H( / ([1;54H/M +[1;10H(-.___[1;55H)M +[1;11H/ \/[1;55H)M +[1;12H_______.--'[1;54H\M +[1;23H,____________/[1;53H\M +[1;37H( / )M +[1;37H( ) /M +[1;37H\ \ )M +[1;36H( )M +[1;36H( ( /M +[1;36H\ ( )M +[1;35H( \ )M +[1;35H( ( /M +[1;16r +[1;35H\ ( ) )M +[1;17r +[1;34H( ( / )M +[1;18r +[1;34H( \ ) /M +[1;19r +[1;34H\ ( ) )M +[1;20r +[1;33H( ) )M +[1;21r +[1;33H( ) /M +[1;22r +[1;33H\ / )M +[1;24r +[1;32H( ) ) +[23;25H / > | \ +[1;1H +[1;1H +[10;1H T[10;1H T[10;1H T +[10;1H T H[10;1H T H[10;1H T H +[10;1H T H E[10;1H T H E[10;1H T H E [10;1H T H E +[10;1H T H E E[10;1H T H E E[10;1H T H E E +[10;1H T H E E N[10;1H T H E E N[10;1H T H E E N +[10;1H T H E E N D[10;1H T H E E N D +[11;1H =============== +[22;1H +[?25h diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/depricated_test_filedescriptor.py b/lldb/third_party/Python/module/pexpect-4.6/tests/depricated_test_filedescriptor.py new file mode 100755 index 00000000000..6b0ef3e8cc8 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/depricated_test_filedescriptor.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +import PexpectTestCase +import os + +class ExpectTestCase(PexpectTestCase.PexpectTestCase): + def setUp(self): + print(self.id()) + PexpectTestCase.PexpectTestCase.setUp(self) + + def test_fd (self): + fd = os.open ('TESTDATA.txt', os.O_RDONLY) + s = pexpect.spawn (fd) + s.expect ('This is the end of test data:') + s.expect (pexpect.EOF) + assert s.before == ' END\n' + + def test_maxread (self): + fd = os.open ('TESTDATA.txt', os.O_RDONLY) + s = pexpect.spawn (fd) + s.maxread = 100 + s.expect('2') + s.expect ('This is the end of test data:') + s.expect (pexpect.EOF) + assert s.before == ' END\n' + + def test_fd_isalive (self): + fd = os.open ('TESTDATA.txt', os.O_RDONLY) + s = pexpect.spawn (fd) + assert s.isalive() + os.close (fd) + assert not s.isalive() + + def test_fd_isatty (self): + fd = os.open ('TESTDATA.txt', os.O_RDONLY) + s = pexpect.spawn (fd) + assert not s.isatty() + os.close(fd) + +### def test_close_does_not_close_fd (self): +### '''Calling close() on a pexpect.spawn object should not +### close the underlying file descriptor. +### ''' +### fd = os.open ('TESTDATA.txt', os.O_RDONLY) +### s = pexpect.spawn (fd) +### try: +### s.close() +### self.fail('Expected an Exception.') +### except pexpect.ExceptionPexpect, e: +### pass + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(ExpectTestCase, 'test') + +#fout = open('delete_me_1','wb') +#fout.write(the_old_way) +#fout.close +#fout = open('delete_me_2', 'wb') +#fout.write(the_new_way) +#fout.close diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/echo_w_prompt.py b/lldb/third_party/Python/module/pexpect-4.6/tests/echo_w_prompt.py new file mode 100644 index 00000000000..3c8055357df --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/echo_w_prompt.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function + +try: + raw_input +except NameError: + raw_input = input + +while True: + try: + a = raw_input('<in >') + except EOFError: + print('<eof>') + break + print('<out>', a, sep='') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/echo_wait.py b/lldb/third_party/Python/module/pexpect-4.6/tests/echo_wait.py new file mode 100755 index 00000000000..e15205925cf --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/echo_wait.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import time +import termios +import sys + +# a dumb PAM will print the password prompt first then set ECHO +# False. What it should do it set ECHO False first then print the +# prompt. Otherwise, if we see the password prompt and type out +# password real fast before it turns off ECHO then some or all of +# our password might be visibly echod back to us. Sounds unlikely? +# It happens. + +print("fake password:") +sys.stdout.flush() +time.sleep(3) +attr = termios.tcgetattr(sys.stdout) +attr[3] = attr[3] & ~termios.ECHO +termios.tcsetattr(sys.stdout, termios.TCSANOW, attr) +time.sleep(12) +attr[3] = attr[3] | termios.ECHO +termios.tcsetattr(sys.stdout, termios.TCSANOW, attr) +time.sleep(2) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/exit1.py b/lldb/third_party/Python/module/pexpect-4.6/tests/exit1.py new file mode 100755 index 00000000000..587b8adde79 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/exit1.py @@ -0,0 +1,24 @@ +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import os, sys + +print("Hello") +sys.stdout.flush() +os._exit(1) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/exit667.c b/lldb/third_party/Python/module/pexpect-4.6/tests/exit667.c new file mode 100644 index 00000000000..962b9fdb676 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/exit667.c @@ -0,0 +1,26 @@ +/* + PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +#include <stdio.h> +int main () +{ + printf ("Hello world!\n"); + exit(7); +} diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/fakessh/ssh b/lldb/third_party/Python/module/pexpect-4.6/tests/fakessh/ssh new file mode 100755 index 00000000000..d3259e4a252 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/fakessh/ssh @@ -0,0 +1,34 @@ +#!/usr/bin/env python +from __future__ import print_function + +import getpass +import sys +PY3 = (sys.version_info[0] >= 3) +if not PY3: + input = raw_input + +server = sys.argv[-1] +if server == 'noserver': + print('No route to host') + sys.exit(1) + +print("Mock SSH client for tests. Do not enter real security info.") + +pw = getpass.getpass('password:') +if pw != 's3cret': + print('Permission denied!') + sys.exit(1) + +prompt = "$" +while True: + cmd = input(prompt) + if cmd.startswith('PS1='): + prompt = eval(cmd[4:]).replace('\$', '$') + elif cmd == 'ping': + print('pong') + elif cmd.startswith('ls'): + print('file1.py', 'file2.html', sep='\t') + elif cmd == 'echo $?': + print(0) + elif cmd in ('exit', 'logout'): + break diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/getch.py b/lldb/third_party/Python/module/pexpect-4.6/tests/getch.py new file mode 100755 index 00000000000..a362e521d31 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/getch.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from __future__ import print_function +import sys, tty, termios + +if hasattr(sys.stdin, 'buffer'): + # Python 3: we want to read raw bytes + stdin = sys.stdin.buffer +else: + stdin = sys.stdin + +def main(): + print('READY', end='\r\n') + while True: + try: + val = ord(stdin.read(1)) + except KeyboardInterrupt: + val = 3 + print('%d<STOP>' % (val,), end='\r\n') + if val == 0: + # StopIteration equivalent is ctrl+' ' (\x00, NUL) + break + +if __name__ == '__main__': + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + main() + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/globe.vt b/lldb/third_party/Python/module/pexpect-4.6/tests/globe.vt new file mode 100644 index 00000000000..85dc78d7729 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/globe.vt @@ -0,0 +1,690 @@ +[H[J _-o#&&*''''?d:>b\_ + _o/"`'' '',, dMF9MMMMMHo_ + .o&#' `"MbHMMMMMMMMMMMHo. + .o"" ' vodM*$&&HMMMMMMMMMM?. + ,' $M&ood,~'`(&##MMMMMMH\ + / ,MMMMMMM#b?#bobMMMMHMMML + & ?MMMMMMMMMMMMMMMMM7MMM$R*Hk + ?$. :MMMMMMMMMMMMMMMMMMM/HMMM|`*L +| |MMMMMMMMMMMMMMMMMMMMbMH' T, +$H#: `*MMMMMMMMMMMMMMMMMMMMb#}' `? +]MMH# ""*""""*#MMMMMMMMMMMMM' - +MMMMMb_ |MMMMMMMMMMMP' : +HMMMMMMMHo `MMMMMMMMMT . +?MMMMMMMMP 9MMMMMMMM} - +-?MMMMMMM |MMMMMMMMM?,d- ' + :|MMMMMM- `MMMMMMMT .M|. : + .9MMM[ &MMMMM*' `' . + :9MMk `MMM#" - + &M} ` .- + `&. . + `~, . ./ + . _ .- + '`--._,dd###pp=""' +[H _v->#H#P? "':o<>\_ + .,dP` `'' "'-o.+H6&MMMHo_ + oHMH9' `?&bHMHMMMMMMHo. + oMP"' ' ooMP*#&HMMMMMMM?. + ,M* - `*MSdob//`^&##MMMH\ + d*' .,MMMMMMH#o>#ooMMMMMb + HM- :HMMMMMMMMMMMMMMM&HM[R\ + d"Z\. 9MMMMMMMMMMMMMMMMM[HMM|: +-H - MMMMMMMMMMMMMMMMMMMbMP' : +:??Mb# `9MMMMMMMMMMMMMMMMMMH#! . +: MMMMH#, "*""""`#HMMMMMMMMMMH - +||MMMMMM6\. {MMMMMMMMMH' : +:|MMMMMMMMMMHo `9MMMMMMMM' . +. HMMMMMMMMMMP' !MMMMMMMM ` +- `#MMMMMMMMM HMMMMMMM*,/ : + : ?MMMMMMMF HMMMMMM',P' : + . HMMMMR' {MMMMP' ^' - + : `HMMMT iMMH' .' + -.`HMH . + -:*H . ' + -`\,, . .- + ' . _ .-` + '`~\.__,obb#q==~''' +[H .ovr:HMM#?:`' >b\_ + .,:&Hi' `' "' \\|&bSMHo_ + oHMMM#*} `?&dMMMMMMHo. + .dMMMH"'''' ,oHH*&&9MMMM?. + ,MMM*' `*M\bd<|"*&#MH\ + dHH?' :MMMMMM#bd#odMML + H' |\ `dMMMMMMMMMMMMMM9Mk + JL/"7+,. `MMMMMMMMMMMMMMMH9ML +-`Hp ' |MMMMMMMMMMMMMMMMHH|: +: \\#M#d? `HMMMMMMMMMMMMMMMMH. +. JMMMMM##, ``*""'"*#MMMMMMMMH +-. ,MMMMMMMM6o_ |MMMMMMMM': +: |MMMMMMMMMMMMMb\ TMMMMMMT : +. ?MMMMMMMMMMMMM' :MMMMMM|.` +- ?HMMMMMMMMMM: HMMMMMM\|: + : 9MMMMMMMMH' `MMMMMP.P. + . `MMMMMMT'' HMMM*''- + - TMMMMM' MM*' - + '. HMM# - + -. `9M: .' + -. `b,, . . ' + '-\ ., .-` + '-:b~\\_,oddq==--" +[H _oo##'9MMHb':'-,o_ + .oH":HH$' ""' "' -\7*R&o_ + .oHMMMHMH#9: "\bMMMMHo. + dMMMMMM*""'`' .oHM"H9MM?. + ,MMMMMM' "HLbd<|?&H\ + JMMH#H' |MMMMM#b>bHb + :MH ."\ `|MMMMMMMMMMMM& + .:M:d-"|:b.. 9MMMMMMMMMMMMM+ +: "*H| - &MMMMMMMMMMMMMH: +. `LvdHH#d? `?MMMMMMMMMMMMMb +: iMMMMMMH#b `"*"'"#HMMMMMM +. . ,MMMMMMMMMMb\. {MMMMMH +- |MMMMMMMMMMMMMMHb, `MMMMM| +: |MMMMMMMMMMMMMMH' &MMMM, +- `#MMMMMMMMMMMM |MMMM6- + : `MMMMMMMMMM+ ]MMMT/ + . `MMMMMMMP" HMM*` + - |MMMMMH' ,M#'- + '. :MMMH| .- + . |MM - + ` . `#?.. . ..' + -. _. .- + '-|.#qo__,,ob=~~-'' +[H _ooppH[`MMMD::--\_ + _oHMR":&M&. ""' "' /&\\_ + oHMMMMMHMMH#9, `"<MMHo. + oHMMMMMMMM*""'`` .dMP#M?. + .dMMMMMMMM* `H\do?&\ + -iMMMHH#H' &MMMHb#? + : ZMM' 7-. `{MMMMMMMMH + . .M6_d|"`$|v.. 9MMMMMMMMML +- `'*H# : |MMMMMMMMMM: +: *\\dHM#dd. ?MMMMMMMMMb +- |MMMMMMM##\ `"*""?HMMM +: . |MMMMMMMMMMMo\. {MMM +. {MMMMMMMMMMMMMMMHo. `MMM +- ?MMMMMMMMMMMMMMM*' -MMP +: `#MMMMMMMMMMMMT dMM' + - |MMMMMMMMMMH' -MMT + : `MMMMMMMM"' JMP + - MMMMMMH' ,H? + '. HMMM#' : + . ?MM- . ' + -. *M:.. .- + - . _. .- + '-.~-dHb__\ov+~~-` +[H .oo>#&H6?*MMH:-.._ + .oHMMMR:"&MZ\ `"' " |$-_ + ..dMMMMMMMMdMMM#9\ `'HHo. + . ,dMMMMMMMMMMM"`' ` ?MP?. + . |MMMMMMMMMMM' `"$b&\ + - |MMMMHH##M' HMMH? + - TTMM| >.. \MMMMMH + : |MM\,#-""$~b\. `MMMMMM+ +. ``"H&# - &MMMMMM| +: *\v,#MHddc. `9MMMMMb +. MMMMMMMM##\ `"":HM +- . .HMMMMMMMMMMRo_. |M +: |MMMMMMMMMMMMMMMM#\ :M +- `HMMMMMMMMMMMMMMM' |T +: `*HMMMMMMMMMMMM' H' + : MMMMMMMMMMM| |T + . MMMMMMMM?' ./ + `. MMMMMMH' ./ + -. |MMMH#' . + . `MM* . ' + -. #M: . . .- + ` . ., .- + '-.-~ooHH__,,v~--` +[H _ood>H&H&Z?#M#b-\. + .\HMMMMMR?`\M6b."`' ''``v. + .. .MMMMMMMMMMHMMM#&. ``~o. + . ,HMMMMMMMMMMMM*"'-` &b. + . .MMMMMMMMMMMMH' `"&\ + - RMMMMM#H##R' 4Mb + - |7MMM' ?:: `|MMb + / HMM__#|`"\>?v.. `MMML +. `"'#Hd| ` 9MMM: +- |\,\?HH#bbL `9MMb +: !MMMMMMMH#b, `""T +. . ,MMMMMMMMMMMbo. | +: 4MMMMMMMMMMMMMMMHo | +: ?MMMMMMMMMMMMMMM? : +-. `#MMMMMMMMMMMM: .- + : |MMMMMMMMMM? . + - JMMMMMMMT' : + `. MMMMMMH' - + -. |MMM#*` - + . HMH' . ' + -. #H:. .- + ` . .\ .- + '-..-+oodHL_,--/-` +[H _,\?dZkMHF&$*q#b.. + .//9MMMMMMM?:'HM\\"`-''`.. + ..` :MMMMMMMMMMHMMMMH?_ `-\ + . .dMMMMMMMMMMMMMM'"'" `\. + . |MMMMMMMMMMMMMR \\ + - T9MMMMMHH##M" `? + : (9MMM' !':. &k + .: HMM\_?p "":-b\. `ML +- "'"H&#, : |M| +: ?\,\dMH#b#. 9b +: |MMMMMMM##, `* +: . +MMMMMMMMMMMo_ - +: HMMMMMMMMMMMMMM#, : +: 9MMMMMMMMMMMMMH' . +: . *HMMMMMMMMMMP .' + : MMMMMMMMMH' . + - :MMMMMMM'` . + `. 9MMMMM*' - + -. {MMM#' : + - |MM" .' + `. &M'.. . ..' + ' . ._ .- + '-. -voboo#&:,-.-` +[H _oo:\bk99M[<$$+b\. + .$*"MMMMMMMM[:"\Mb\?^" . + . '` HMMMMMMMMMMHMMMM+?. `. + . .HMMMMMMMMMMMMMMP"'' . + . `MMMMMMMMMMMMMM| -`. + - `&MMMMMMHH##H: : + : `(*MMM} `|\ | + : `- ?MMb__#|""`|+v.. \ +. `''*H#b - :| +: `*\v,#M#b#, \ +. 9MMMMMMHb. : +: . #MMMMMMMMMb\ - +- .HMMMMMMMMMMMMb : +: `MMMMMMMMMMMMH . +-: . `#MMMMMMMMMP ' + : ]MMMMMMMH' : + - ,MMMMMM?' . + `: HMMMMH" - + -. .HMM#* .- + `. .HH*' . + `-. &R". .- + -. ._ .- + '-. .voodoodc?..-` +[H _\oo\?ddk9MRbS>v\_ + ..:>*""MMMMMMMMM:?|H?$?-. + ..- - "HMMMMMMMMMMHMMMH\_-. + . dMMMMMMMMMMMMMMT" . + . TMMMMMMMMMMMMMM `. + - `&HMMMMMM#H#H: . + - `\7HMMH |\. . + : ` HMM\_?c`""+?\.. : +- "``#&#| . - +: `?,\#MHdb. . +: |MMMMMH#. : +: . ,HMMMMMMMb, - +: ' 4MMMMMMMMMMH` +: . 9MMMMMMMMMT- +:.` `#MMMMMMMH ' + : ' HMMMMMH': + - |MMMMH" - + `: |MMMH*' .' + '? dMM#' . + \. .dH" .' + -. ,M'- ..' + ` . .. ..-` + '-. .\ooooboo<^.-` +[H _o,:o?\?dM&MHcc~,. + ..^':&#""HMMMMMMMM$:?&&?. + .` -` 'HMMMMMMMMMHMMMp\. + . ' |MMMMMMMMMMMMMM"' . + . `9MMMMMMMMMMMMM -. + - `*9MMMMMHH##[ . + - `\Z9MMM `~\ . + : '| ?MMb_?p""-?v.. : +- `"'*&#, - . +: `?,oHH#? . +-- |MMMMH,: +: . |MMMMMM6, +: - |MMMMMMMM +? HMMMMMMP +-- . ' |HMMMMM' + :.` . ' JMMMM+ + \ ,MMMP: + : |MMH?: + -:\. dM#" . + \ ,H*' .' + -. d':..' + ` . .,.- + '-.. .\oooodov~^-` +[H _o\:,??\??MR9#cb\_ + .v/''':&#""#HMMMMMMM$?*d\. + ..~' - -` `"#MMMMMMMMMMMHv. + .-' HMMMMMMMMMMMR!. + : `9MMMMMMMMMMM| -. + . `*9MMMMMH##| . + - `(#MMH `:, . + : '| `HMb_>/"|\,.: +.' `"'#&b - . +: ?\oHH?. +: !MMM& +: . . HMMMM +/. - -MMMMM +\`. 9MMMP +:. . . - |MMM' + \... ' .MMT + &. .dMP + \, .HM* + \. `\. ,H&' + `- `| - ,&': + `. ,/\ ' + '-.. _.- + "---.._\o,oov+--'" +[H _,d?,:?o?:?HM>#b\_ + ..H*"''`'H#*"**MMMMMM6$$v_ + v//" - `` `'#MMMMMMMMHo. + /"` |MMMMMMMMMM:. + ,> `HMMMMMMMMH:. + : `#HMMMMHH\ - + ' `Z#MM, `,: + : '\ ?HH_>:`\, +: "'*&| `: +. <\Hb +: MM +: . iMM +Mb\. {MM +::.`- - !MP +`&. . . - :M' + 9H, \ ' |T + HM? ,P + *ML ?? + :&. `o .d' + ': |T /" + -. .<'' + `... ..- + "`-=.,_,,,oov-~.-` +[H _,oc>?_:b?o?HH#b\_ + .v/99*""" '*H#""*HMMMMMZ,_ + oH* /" - ' "`#MMMMM#o. + ./*>- `MMMMMMMb + ,b/' `#MMMMMMM\ + :' ``HMMMMb: + /- `|&MH `\ + / `-. |Hb??\ +,- ' "`&,. +1 \} +!. T +$,. . 1 +?`M??. M +?.::| '\ - ? + M?&. . . - ,' + 9MMH\ .. ' ` . + HMMM#. :' + 9#MMb .. + -:"# `b. .- + . ` {! / + - ,-' + ' . .- + ```^==\_.,,,ov--\-` +[H _\o##??,:io??$#b\_ + .oH#"H9*""" "`#H*"*#MMMHo_ + oHMM- -' - '' ``*HMMHo. + dM#S>-` ?MMMM?. + ,&&,/' "#MMMH\ + d?-" `*HMMb + H? "ZHb: + /: \ H?L +|:| . `*: +:?: \ +>" : +M|\,_ | +!|":HH?-'. : +:^'_:?"\ `-- - . +- |ML?b . .. - - + :HMMMMH\ \ ` : + >MMMMMM#. . + ^M*HMMM| - + `. `"#+ `?v .` + . `- +?' - + ` . ..' + - . .- + "`\b=p?.._\\vv---` +[H _,o#bH\??::?o?cbo_ + .o#MH#**SH""' "`*H#"*#MHo_ + oHMMMH^ ^" - ` '*HHo. + .dMMM#">>- `HM?. + ,MH:R_o/ `*MH\ + dMM' ' "ML + HMR! ' `#k + d&'. -. `L +:M :: ` `- +/| !| - +k.$-" : +}9R:!,,_. . +\::\':`*M#\-'. - +: "''..:"!`\ '- - ` +- ,HMb.H| . _ - .' + : ,MMMMMMMb. .. . + .`HMMMMMMMM? . + `.`9M#*HMMMM : + -.' "##* `b, . + . ` ,/' .' + ` . ..' + - . ..- + "`*#d##c.._\v----` +[H _,o#&oHb?\o::d?>\_ + .oHHMMM#**$M""` "`*HH"#&o_ + oHMMMMMMD' .'' - ' ``bo. + .dMMMMMH*'/|- `\b. + ,MMMM?T|_o/ `\\ + dMMMMP '' `| + HMMMH& - `\ + /MH7' : -- : +-:MM {. . . +:i?' .!& . +:{, o| ' : +-T?9M\:-'o,_ . +: \?::``"`?9MHo./.. - +. '"`'^ _.`"!"^. `- - ` +- ,bMM?.M\ . . - . .' + : .oMMMMMMMMb. .. ` . + . `HMMMMMMMMMMb - + - 9MH*#HMMMMH .' + '. ' `"*##' `b. : + . ` .d'' .' + -. . ' + -. .-` + "`*##H###:._\--.-` +[H _oo#H&d#b?\b:_>>\_ + .oHMMMMMMH*"*9R"'-``*#P\-_ + oHMMMMMMMMM$ ." ' `^- + .dMMMMMMMMH*",?- '\. + ,MMMMMMM:?}.,d' `. + dMMMMMMMH /'' : + HMMMMMMM&' - - + dPTMMP>' : -. : +|? -MM} .\ . +J' ::*' -$L . +: ?b .,H- ' : +- |6.&MP:: !.,_. - +: `\:: "' "`:"MM#,-^, - : +- ````:' _.:"?``\ `- . +: .?bMML.]# - _ ` . .' + - .o#MMMMMMMMH\ \. . . + - `HMMMMMMMMMMMH : + `. `HMM#*#MMMMMH' - + -. ' ``##*' i+ : + - `' v/' .' + `- ..' + ' . .- + "`*##HMH##:__,-.-` +[H _oo##Mbb&bo??o_>\_ + .oHMMMMMMMMM**#?M*' "?*&.. + oHMMMMMMMMMMMM4 `" - `. + .dMMMMMMMMMMMM#"\?.- . + ,MMMMMMMMMM}"9:_,d' -. + dMMMMMMMMMMM| ^'' . + &MMMMMMMMMMH\ - . + :{M*"MMMPT"' : `-. : +.'M' 'MMM. -T, . . +- k i:?'' -|& . +: ` -o& .,H- " : +- `M:`HMP|:'!.o._. . +: "<:::'<^ '"``9MH#,-^ . - +- '''``''._.`"?`^| ^ - : +: ?#dMM_.M? . . - ..' + : ,ddMMMMMMMMMb. .. ' . + . TMMMMMMMMMMMMM, : + - ?MMH**#MMMMMH' : + '. ' "`##*' &. : + -. `' ,~" .' + -. ..' + ` . .- + ```*##HMMMH#<:,..-` +[H _,dd#HMb&dHo?\?:\_ + .oHMMMMMMMMMMMH***9P'`"\v. + oHMMMMMMMMMMMMMMM> `' -. + .dMMMMMMMMMMMMMMMH*'|~-' . + ,MMMMMMMMMMMMM6>`H._,& -. + dMMMMMMMMMMMMMMM| `" . + H*MMMMMMMMMMMMMH&. - . + d' HMM""&MMMPT'' :. `.- +,' MP `TMMM, |: . - +| #: ? *" : &L : +! `' /?H ,#r `' : +. ?M: HMM^<~->,o._ : +: `9:::'`*-``':`9MHb,|-, ' : +. `"''':' :_ ""!"^. `| : +`. _dbHM6_|H. . . ' .' + \ _odHMMMMMMMMH, .. ` : + `- |MMMMMMMMMMMMM| : + `. 9MMH**#MMMMMH' : + -. ' "?##" d : + . ' ,/" .' + `.. ..' + ` . .- + '`"#HHMMMMM#<>..-` +[H _oo##bHMb&d#bd,>\_ + .oHMMMMMMMMMMMMMM***9R"-.. + oHMMMMMMMMMMMMMMMMMH\ ? `-. + .dMMMMMMMMMMMMMMMMMMM#".}-' . + ,MMMMMMMMMMMMMMMMM6/`H _o} -. + dMMMMMMMMMMMMMMMMMMML `'' . + HbP*HMMMMMMMMMMMMMMM*: - , + dMH' `MMMP'"HMMMR'T" : : +|H' -MR' `?MMMb P, . . +1& *| |.`*" .-`&| . +M' " |\&| .,#~ "' : +T :HL.|HMH\c~`|v,\_ : +| `"|:::':`-`` '"MM#\-'. -: +% ``'``'`' :_ '?'`| ``. : +||, ,#dMM?.M? . .` - + ?\ .,odMMMMMMMMM? \ ` : + / |MMMMMMMMMMMMM: .' + `. TMMH#*9MMMMM* : + -. ` "*#*' ,: . + . ` .v'' .' + `. ..' + '- . .- + "`\+HHMMMMMMHr~.-` +[H _,,>#b&HMHd&&bb>\_ + _oHMMMMMMMMMMMMMMMMH**H:. + oHMMMMMMMMMMMMMMMMMMMM#v`? `. + .dMMMMMMMMMMMMMMMMMMMMMMH*`+| . + ,MMMMMMMMMMMMMMMMMMMMMb|?+.,H -. + ddHMMMMMMMMMMMMMMMMMMMMMb `' . + HMMkZ**HMMMMMMMMMMMMMMMMH\ - . : + dTMMM* `9MMMP'"*MMMMPT"` .. : +|M6H'' 4MP' `"HMMM| !|. . . +1MHp' #L $ *"' .-:&. . +MMM' " q:H. .o#-``' : +MM' ?H?.|MMH::::-o,_. - +M[ `*?:::'|` `"`:9MH\~-. ` +&M. ""'`'^'.:.`?'`. '| -: +`M|d, .dbHM[.1? .. : + 9||| . _obMMMMMMMMH, . : + H.^ MMMMMMMMMMMM} - + \ |MMH#*HMMMMH' .' + . ` `#*' ,:- + ` '' .-'. + `. .- + '- . .-` + '`\bqHMMMMMMHHb--` +[H .,:,#&6dHHHb&##o\_ + .oHHMMMMMMMMMMMMMMMMMH*\,. + oHMMMMMMMMMMMMMMMMMMMMMMHb:'-. + .dMMMMMMMMMMMMMMMMMMMMMMMMMH|\/' . + ,&HMMMMMMMMMMMMMMMMMMMMMMM/"&.,d. -. + dboMMHMMMMMMMMMMMMMMMMMMMMMML `' . + HMHMMM$Z***MMMMMMMMMMMMMMMMMM|.- . + dMM}MMMM#' `9MMMH?"`MMMMR'T' _ : +|MMMbM#'' |MM" ``MMMH. <_ . +dMMMM#& *&. .?`*" .'&: . +MMMMMH- `' -v/H .dD "' ' : +MMMM* `*M: 4MM*::-!v,_ : +MMMM `*?::" "'``"?9Mb::. : +&MMM, `"'"'|"._ "?`| - : +`MMM}.H ,#dM[_H ..: + 9MMi`M: . .ooHMMMMMMM, .. + 9Mb `- 1MMMMMMMMMM| : + ?M |MM#*#MMMM* . + -. ` |#"' ,' + . -" v` + -. .- + - . . ` + '-*#d#HHMMMMHH#"-' +[H _,<_:&S6dHHHb&bb\_ + .odHMMMMMMMMMMMMMMMMMMM}-_ + .oHMMMMMMMMMMMMMMMMMMMMMMMM#d:. + ?9MMMMMMMMMMMMMMMMMMMMMMMMMMMH-$ . + ,::dHMMMMMMMMMMMMMMMMMMMMMMMMH:\.?? -. + dMdboHMMHMMMMMMMMMMMMMMMMMMMMMMH, ' . + HMMMM7MMMb$R***MMMMMMMMMMMMMMMMMH\ - . + dMMMMM/MMMMM* `$MMMM*'"*MMMM?&' . : +|MMMMMMb1H*' HMP' '9MMM| &. . . +dMMMMMMM##~` `#\ |.`*" .-9. : +9MMMMMMMM* ` |v7? .,H `' ` : +SMMMMMMH' '9M_-MMH::-\v_ : +:HMMMMM `\_:"'|'`':9Mv\. +-|MMMMM, ""`'`':.`?\ \ +`:MMMMM}.d} .?bM6,| | + :?MMM6 M| . .,oHMMMMM| / + .?MMM- `' &MMMMMMMM|. + -`HM- HMH#*MMM?: + '. ' `#*:` + - -'/ + ` . . ' + ` . . ` + '--##HH#HMMMHH#""` +[H _o,d_?dZdoHHHb#b\_ + .vdMMMMMMMMMMMMMMMMMMMMH\. + .,HHMMMMMMMMMMMMMMMMMMMMMMMMH&,. + /?RMMMMMMMMMMMMMMMMMMMMMMMMMMMMH|.. + ,\?>`T#RMMMMMMMMMMMMMMMMMMMMMMMM6`\|/ + dMMbd#ooHMMMHMMMMMMMMMMMMMMMMMMMMMH,`' ' + HMMMMMMMTMMMMb$ZP**HMMMMMMMMMMMMMMMM|. : + dMMMMMMMM}$MMMMMH' `HMMMH?"`MMMM?T' . : +|MMMMMMMMMMoMH*'' `MM? ``MMM| +\ . +1MMMMMMMMMMMb#/ ?#? |`#" -T: : +*'HMMMMMMMMMM*' " ~?& .?} ' ' . +- 4MMMMMMMMP" `M? HMTc:\\.: +: `MMMMMMM[ "#:::`>`"?M{ +. |MMMMMMH. ``'``'_`:- +- |MMMMMMM|.dD ,#Mb\' + : *MMMMM: iM| . _oHMMMM: + . ?MMMM' "' ,MMMMMMP + : `HMH JM#*MMT + -. ' ` #' + . / + -. - .' + -. . ` + '--=&&MH##HMHH#""" +[H .-:?,Z?:&$dHH##b\_ + ,:bqRMMMMMMMMMMMMMMMMMHo. + .?HHHMMMMMMMMMMMMMMMMMMMMMMMHo. + -o/*M9MMMMMMMMMMMMMMMMMMMMMMMMMMMv + .:H\b\'|?#HHMMMMMMMMMMMMMMMMMMMMMM6?Z\ + .?MMMHbdbbodMMMMHMMMMMMMMMMMMMMMMMMMM\': + :MMMMMMMMMMM7MMMMb?6P**#MMMMMMMMMMMMMMM_ : + \MMMMMMMMMMMMb^MMMMMM? `*MMMM*"`MMMR<' . - +.1MMMMMMMMMMMMMb]M#"" 9MR' `?MMb \. : +-MMMMMMMMMMMMMMMH##|` *&. |`*' .\ . +-?""*MMMMMMMMMMMMM' ' |?b ,}" : +: MMMMMMMMMMH' `M_|M}r\? +. `MMMMMMMMM' `$_:`'"H +- TMMMMMMMM, '"``:: +: {MMMMMMMM| oH| .#M- + : `9MMMMMM' .MP . ,oMMT + . HMMMMP' `' ,MMMP + - `MMH' HH9* + '. ` ` .' + - . ' + ` . - .- + ` . .- + ' -==pHMMH##HH#""" +[H _..-:b&::&?&&##bo_ + ...?-#&9MMMMMMMMMMMMMMMHo_ + .. .1&#MMHMMMMMMMMMMMMMMMMMMMHo. + . .o/##R9MMMMMMMMMMMMMMMMMMMMMMMM?. + .- |MSd?|'`$?#HMMMMMMMMMMMMMMMMMMMMMH\ + - dMMMMHbd##oodMMMM#MMMMMMMMMMMMMMMMMH: + - JMMMMMMMMMMMMM7HMMMH$SR***MMMMMMMMMMMMb> + : {MMMMMMMMMMMMMMM`9MMMMMH' ``HMMM?"*MM[| : +- |MMMMMMMMMMMMMMMMM<MH*'' `MM' 'HM? |. +: `MMMMMMMMMMMMMMMMMM##H-' `#, ` |`? /| +. ?"""?HMMMMMMMMMMMMMH' " v& .}? +- |MMMMMMMMMMMP' `H:&H& +i `9MMMMMMMMMT `|?"? +: MMMMMMMMMH "`\ +: MMMMMMMMMH-.dH ,| + : ?MMMMMMM? {M' . .dT + . ?MMMMMR' `' ,MP + - `HMM#' .&* + '. ' `. + - . ' + `.. .- + -. .- + '-.==p##HMMHp&#""" +[H _v---:?&?:?&?&#b\_ + ..' i: #M$MMMMMMMMMMMMMHo_ + .. -]M#HMHMMMMMMMMMMMMMMMMMHo. + . ooP*&6&MMMMMMMMMMMMMMMMMMMMM?. + . - &Rbbd-/`?:##HMMMMMMMMMMMMMMMMMH? + - ,HMMMMM#od#boodMMMMHMMMMMMMMMMMMMMb + - iMMMMMMMMMMMMMMM[*MMMH&$R***MMMMMMMMMb + : |MMMMMMMMMMMMMMMMML"MMMMMM' ``MMMP"HMM: +. HMMMMMMMMMMMMMMMMMMb/MH"" `MR *M,| +: TMMMMMMMMMMMMMMMMMMMMd#&` `D. ?|\ +. `*"'"*HMMMMMMMMMMMMMMP' ' -d,J +: |MMMMMMMMMMMMP' ||M +M, ?MMMMMMMMMM| `\? +&| HMMMMMMMMM} `` +`L .MMMMMMMMMMP ,d| : + *. ?MMMMMMMF' .MP / + | TMMMMMM' `"' / + `. `MMMP' ./ + -. ` . + . . ' + - . .- + -\ ..- + '-..=p####HMH&=""" +[H _vo~^'':&b::d,#b\_ + ..`" `:v +9P]MMMMMMMMMMHo_ + ,- ?Mb#MMMMMMMMMMMMMMMMMHo. + . " ,ooM*&&&HMMMMMMMMMMMMMMMMHb. + . - 99Soo?|'`*?##HMMMMMMMMMMMMMH\ + - .HMMMMMM#od#boodMMMMHMMMMMMMMMMb + - :MMMMMMMMMMMMMMMM67HMMH&$R**HMMMMMb + : .MMMMMMMMMMMMMMMMMMM/HMMMMM| `9MM'HL +: {MMMMMMMMMMMMMMMMMMMM\MM*'' `H[ `9| +| `HMMMMMMMMMMMMMMMMMMMMb##| `F. :? +H `"*"'"`#MMMMMMMMMMMMMMM? ' k +M. MMMMMMMMMMMMM"' H +MMH. `HMMMMMMMMMM: | +&MM| `MMMMMMMMMM, - +`MM| dMMMMMMMMMM|.oH : + 9ML `HMMMMMMM? dH' - + Hi |MMMMMMP "' .' + T. `MMM#' - + `. ` .` + ` - + `.. . ..' + ... .- + '-. //######M#b~"" +[H _ooq=""''$b$_&?b\_ + .-`^" "'o |&M:MMMMMMMMHo_ + o/' -$Mb#MMMMMMMMMMMMMMHo. + /' .ooHP*&R&MMMMMMMMMMMMMM?. + .' `MRbod?|'`+?##9MMMMMMMMMH\ + .` .,MMMMMMH#od##obdMMMMHMMMMMMb + - ?MMMMMMMMMMMMMMMMM$HMMH$ZP*HMMb + ? |MMMMMMMMMMMMMMMMMMM|9MMMMP "M6\ +.- dMMMMMMMMMMMMMMMMMMMMb]M*' |R | +1| `HMMMMMMMMMMMMMMMMMMMMMd#| ?,: +MH, ``*""'"*#MMMMMMMMMMMMMM* '` +MM6_ |MMMMMMMMMMMMH" : +MMMMMb. "MMMMMMMMMMT - +&MMMMM' |MMMMMMMMMH ` +!MMMMb .HMMMMMMMMM+.?& : + TMMMM *MMMMMMMP dH' . : + 9MM' `MMMMMMP' "' . + 9ML `MMM#' - + `H ` : + `\. .' + `-\ . .- + ' ._ .-` + '-\. ,b#####p&**^` diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/interact.py b/lldb/third_party/Python/module/pexpect-4.6/tests/interact.py new file mode 100755 index 00000000000..a839e9502f9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/interact.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +try: + # This allows coverage to measure code run in this process + import coverage + coverage.process_startup() +except ImportError: + pass + +from utils import no_coverage_env +import pexpect +import sys + + +def main(): + p = pexpect.spawn('{sys.executable} getch.py'.format(sys=sys), + env=no_coverage_env()) + + # defaults matches api + escape_character = chr(29) + encoding = None + + if len(sys.argv) > 1 and '--no-escape' in sys.argv: + escape_character = None + + if len(sys.argv) > 1 and '--utf8' in sys.argv: + encoding = 'utf8' + + p.interact(escape_character=escape_character) + + print("Escaped interact") + +if __name__ == '__main__': + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/list100.py b/lldb/third_party/Python/module/pexpect-4.6/tests/list100.py new file mode 100644 index 00000000000..3b2b6ec3581 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/list100.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +print(list(range(100))) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/needs_kill.py b/lldb/third_party/Python/module/pexpect-4.6/tests/needs_kill.py new file mode 100755 index 00000000000..810236bdad6 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/needs_kill.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +"""This script can only be killed by SIGKILL.""" +import signal, time + +# Ignore interrupt, hangup and continue signals - only SIGKILL will work +signal.signal(signal.SIGINT, signal.SIG_IGN) +signal.signal(signal.SIGHUP, signal.SIG_IGN) +signal.signal(signal.SIGCONT, signal.SIG_IGN) + +print('READY') +while True: + time.sleep(10) +
\ No newline at end of file diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/pexpectTest.py b/lldb/third_party/Python/module/pexpect-4.6/tests/pexpectTest.py new file mode 100755 index 00000000000..6839a2f7053 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/pexpectTest.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +import time +import pexpect +import sys + +def getProcessResults(cmd, timeLimit=20): + ''' + executes 'cmd' as a child process and returns the child's output, + the duration of execution, and the process exit status. Aborts if + child process does not generate output for 'timeLimit' seconds. + ''' + output = "" + startTime = time.time() + child = pexpect.spawn(cmd, timeout=10) + child.logfile = sys.stdout + + while 1: + try: + # read_nonblocking will add to 'outout' one byte at a time + # newlines can show up as '\r\n' so we kill any '\r's which + # will mess up the formatting for the viewer + output += child.read_nonblocking(timeout=timeLimit).replace("\r","") + except pexpect.EOF as e: + print(str(e)) + # process terminated normally + break + except pexpect.TIMEOUT as e: + print(str(e)) + output += "\nProcess aborted by FlashTest after %s seconds.\n" % timeLimit + print(child.isalive()) + child.kill(9) + break + + endTime = time.time() + child.close(force=True) + + duration = endTime - startTime + exitStatus = child.exitstatus + + return (output, duration, exitStatus) + +cmd = "./ticker.py" + +result, duration, exitStatus = getProcessResults(cmd) + +print("result: %s" % result) +print("duration: %s" % duration) +print("exit-status: %s" % exitStatus) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/CSIGNALTEST/test.c b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/CSIGNALTEST/test.c new file mode 100644 index 00000000000..86bcc17fab5 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/CSIGNALTEST/test.c @@ -0,0 +1,90 @@ +/* I built this with "gcc -lutil test.c -otest" */ +#include <sys/types.h> /* include this before any other sys headers */ +#include <sys/wait.h> /* header for waitpid() and various macros */ +#include <signal.h> /* header for signal functions */ +#include <stdio.h> /* header for fprintf() */ +#include <unistd.h> /* header for fork() */ +#ifdef LINUX +#include <pty.h> +#else +#include <util.h> /* header for forkpty, compile with -lutil */ +#endif + +void sig_chld(int); /* prototype for our SIGCHLD handler */ + +int main() +{ + struct sigaction act; + int pid; + int fdm; + char slave_name [20]; + + + /* Assign sig_chld as our SIGCHLD handler. + We don't want to block any other signals in this example + We're only interested in children that have terminated, not ones + which have been stopped (eg user pressing control-Z at terminal). + Finally, make these values effective. If we were writing a real + application, we would save the old value instead of passing NULL. + */ + act.sa_handler = sig_chld; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_NOCLDSTOP; + if (sigaction(SIGCHLD, &act, NULL) < 0) + { + fprintf(stderr, "sigaction failed\n"); + return 1; + } + + /* Do the Fork thing. + */ + pid = forkpty (&fdm, slave_name, NULL, NULL); + /* pid = fork(); */ + + switch (pid) + { + case -1: + fprintf(stderr, "fork failed\n"); + return 1; + break; + + case 0: /* Child process. */ + printf ("This child output will cause trouble.\n"); + _exit(7); + break; + + default: /* Parent process. */ + sleep(1); + printf ("Child pid: %d\n", pid); + sleep(10); /* let child finish -- crappy way to avoid race. */ + break; + } + + return 0; +} + +void sig_chld(int signo) +{ + int status, wpid, child_val; + + printf ("In sig_chld signal handler.\n"); + + /* Wait for any child without blocking */ + wpid = waitpid (-1, & status, WNOHANG); + printf ("\tWaitpid found status for pid: %d\n", wpid); + if (wpid < 0) + { + fprintf(stderr, "\twaitpid failed\n"); + return; + } + printf("\tWaitpid status: %d\n", status); + + if (WIFEXITED(status)) /* did child exit normally? */ + { + child_val = WEXITSTATUS(status); + printf("\tchild exited normally with status %d\n", child_val); + } + printf ("End of sig_chld.\n"); +} + + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/README b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/README new file mode 100644 index 00000000000..d50f94cd620 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/README @@ -0,0 +1,2 @@ +These scripts are for checking how the underlying system behaves, not for +testing Pexpect itself.
\ No newline at end of file diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check.py b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check.py new file mode 100755 index 00000000000..b41755a9635 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +import signal +import os +import time +import pty + +def signal_handler (signum, frame): + print 'Signal handler called with signal:', signum + print 'signal.SIGCHLD=', signal.SIGKILL + +# First thing we do is set up a handler for SIGCHLD. +signal.signal (signal.SIGCHLD, signal.SIG_IGN) + +print 'PART 1 -- Test signal handling with empty pipe.' +# Create a child process for us to kill. +try: + pid, fd = pty.fork() +except Exception as e: + print str(e) + +if pid == 0: +# os.write (sys.stdout.fileno(), 'This is a test.\n This is a test.') + time.sleep(10000) + +print 'Sending SIGKILL to child pid:', pid +os.kill (pid, signal.SIGKILL) + +# SIGCHLD should interrupt sleep. +# Note that this is a race. +# It is possible that the signal handler will get called +# before we try to sleep, but this has not happened yet. +# But in that case we can only tell by order of printed output. +print 'Entering sleep...' +try: + time.sleep(10) +except: + print 'sleep was interrupted by signal.' + +# Just for fun let's see if the process is alive. +try: + os.kill(pid, 0) + print 'Child is alive. This is ambiguous because it may be a Zombie.' +except OSError as e: + print 'Child appears to be dead.' + +print 'PART 2 -- Test signal handling with full pipe.' +# Create a child process for us to kill. +try: + pid, fd = pty.fork() +except Exception as e: + print str(e) + +if pid == 0: + os.write (sys.stdout.fileno(), 'This is a test.\n This is a test.') + time.sleep(10000) + +print 'Sending SIGKILL to child pid:', pid +os.kill (pid, signal.SIGKILL) + +# SIGCHLD should interrupt sleep. +# Note that this is a race. +# It is possible that the signal handler will get called +# before we try to sleep, but this has not happened yet. +# But in that case we can only tell by order of printed output. +print 'Entering sleep...' +try: + time.sleep(10) +except: + print 'sleep was interrupted by signal.' + +# Just for fun let's see if the process is alive. +try: + os.kill(pid, 0) + print 'Child is alive. This is ambiguous because it may be a Zombie.' +except OSError as e: + print 'Child appears to be dead.' + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check2.py b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check2.py new file mode 100755 index 00000000000..0a7d5f89ca8 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check2.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +import signal +import os +import time + +def signal_handler (signum, frame): + print 'Signal handler called with signal:', signum + print 'signal.SIGCHLD=', signal.SIGKILL + +# Create a child process for us to kill. +pid = os.fork() +if pid == 0: + time.sleep(10000) + +#signal.signal (signal.SIGCHLD, signal.SIG_IGN) +signal.signal (signal.SIGCHLD, signal_handler) + +print 'Sending SIGKILL to child pid:', pid +os.kill (pid, signal.SIGKILL) + +# SIGCHLD should interrupt sleep. +# Note that this is a race. +# It is possible that the signal handler will get called +# before we try to sleep, but this has not happened yet. +# But in that case we can only tell by order of printed output. +interrupted = 0 +try: + time.sleep(10) +except: + print 'sleep was interrupted by signal.' + interrupted = 1 + +if not interrupted: + print 'ERROR. Signal did not interrupt sleep.' +else: + print 'Signal interrupted sleep. This is good.' + +# Let's see if the process is alive. +try: + os.kill(pid, 0) + print 'Child is alive. This is ambiguous because it may be a Zombie.' +except OSError as e: + print 'Child appears to be dead.' + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_control_terminal.py b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_control_terminal.py new file mode 100755 index 00000000000..9598fd7ca6b --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_control_terminal.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +import termios, fcntl, struct, os, sys + +def getwinsize(): + s = struct.pack("HHHH", 0, 0, 0, 0) + x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, s) + rows, cols = struct.unpack("HHHH", x)[:2] + return rows, cols + +def setwinsize(r,c): + # Assume ws_xpixel and ws_ypixel are zero. + s = struct.pack("HHHH", r,c,0,0) + x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCSWINSZ, s) +print 'stdin tty:', os.ttyname(0) +print 'stdout tty:', os.ttyname(1) +print 'controlling terminal:', os.ctermid() +print 'winsize %d,%d' % getwinsize() +print 'ENDTEST' diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_handler.py b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_handler.py new file mode 100755 index 00000000000..c0633eb80e0 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_handler.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +import signal +import os +import time +import pty +import sys +import fcntl +import tty +GLOBAL_SIGCHLD_RECEIVED = 0 + +def nonblock (fd): + # if O_NDELAY is set read() returns 0 (ambiguous with EOF). + # if O_NONBLOCK is set read() returns -1 and sets errno to EAGAIN + original_flags = fcntl.fcntl (fd, fcntl.F_GETFL, 0) + flags = original_flags | os.O_NONBLOCK + fcntl.fcntl(fd, fcntl.F_SETFL, flags) + return original_flags + +def signal_handler (signum, frame): + print '<HANDLER>' + global GLOBAL_SIGCHLD_RECEIVED + status = os.waitpid (-1, os.WNOHANG) + if status[0] == 0: + print 'No process for waitpid:', status + else: + print 'Status:', status + print 'WIFEXITED(status):', os.WIFEXITED(status[1]) + print 'WEXITSTATUS(status):', os.WEXITSTATUS(status[1]) + GLOBAL_SIGCHLD_RECEIVED = 1 + +def main (): + signal.signal (signal.SIGCHLD, signal_handler) + pid, fd = pty.fork() + if pid == 0: + os.write (sys.stdout.fileno(), 'This is a test.\nThis is a test.') + time.sleep(10000) + nonblock (fd) + tty.setraw(fd) #STDIN_FILENO) + print 'Sending SIGKILL to child pid:', pid + time.sleep(2) + os.kill (pid, signal.SIGKILL) + + print 'Entering to sleep...' + try: + time.sleep(2) + except: + print 'Sleep interrupted' + try: + os.kill(pid, 0) + print '\tChild is alive. This is ambiguous because it may be a Zombie.' + except OSError as e: + print '\tChild appears to be dead.' +# print str(e) + print + print 'Reading from master fd:', os.read (fd, 1000) + + + +if __name__ == '__main__': + main () diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_read.py b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_read.py new file mode 100755 index 00000000000..9598aa765eb --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_read.py @@ -0,0 +1,35 @@ +import os + +filename = os.tmpnam() +print 'filename:', filename + +fd_out = os.open(filename, os.O_CREAT | os.O_WRONLY) +print 'fd_out:', fd_out +os.write (fd_out, 'This is a test.\n') +os.close(fd_out) +print +print 'testing read on good fd...' +fd_in = os.open (filename, os.O_RDONLY) +print 'fd_in:', fd_in +while 1: + data_in = os.read(fd_in, 1) + print 'data_in:', data_in + if data_in == '': + print 'data_in was empty' + break #sys.exit(1) +os.close(fd_in) +print +print +print 'testing read on closed fd...' +fd_in = os.open ('test_read.py', os.O_RDONLY) +print 'fd_in:', fd_in +while 1: + data_in = os.read(fd_in, 1) + print 'data_in:', data_in + if data_in == '': + print 'data_in was empty' + break +os.close(fd_in) +d = os.read(fd_in, 1) # fd_in should be closed now... +if s == '': + print 'd is empty. good.' diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_signals.py b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_signals.py new file mode 100755 index 00000000000..d45bc8a3bd4 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/platform_checks/check_signals.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +import signal +import os +import time +import pty +import sys +GLOBAL_SIGCHLD_RECEIVED = 0 + +def signal_handler (signum, frame): + print '<HANDLER>' + global GLOBAL_SIGCHLD_RECEIVED + status = os.waitpid (-1, os.WNOHANG) + print 'WIFEXITED(status):', os.WIFEXITED(status) + print 'WEXITSTATUS(status):', os.WEXITSTATUS(status) + GLOBAL_SIGCHLD_RECEIVED = 1 + +def main (): +# sig_test ('SIG_IGN', 'ptyfork', 'yes') + sig_test ('handler', 'ptyfork', 'yes') +# sig_test ('SIG_IGN', 'ptyfork', 'no') +# sig_test ('handler', 'ptyfork', 'no') +# sig_test ('SIG_IGN', 'osfork', 'yes') +# sig_test ('handler', 'osfork', 'yes') +# sig_test ('SIG_IGN', 'osfork', 'no') +# sig_test ('handler', 'osfork', 'no') + +def sig_test (sig_handler_type, fork_type, child_output): + print 'Testing with:' + print '\tsig_handler_type:', sig_handler_type + print '\tfork_type:', fork_type + print '\tchild_output:', child_output + + if sig_handler_type == 'SIG_IGN': + signal.signal (signal.SIGCHLD, signal.SIG_IGN) + else: + signal.signal (signal.SIGCHLD, signal_handler) + pid = -1 + fd = -1 + if fork_type == 'ptyfork': + pid, fd = pty.fork() + else: + pid = os.fork() + + if pid == 0: + if child_output == 'yes': + os.write (sys.stdout.fileno(), 'This is a test.\nThis is a test.') + time.sleep(10000) + + #print 'Sending SIGKILL to child pid:', pid + time.sleep(2) + os.kill (pid, signal.SIGKILL) + + #print 'Entering to sleep...' + try: + time.sleep(2) + except: + pass + try: + os.kill(pid, 0) + print '\tChild is alive. This is ambiguous because it may be a Zombie.' + except OSError as e: + print '\tChild appears to be dead.' +# print str(e) + print + +if __name__ == '__main__': + main () diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/qa.py b/lldb/third_party/Python/module/pexpect-4.6/tests/qa.py new file mode 100755 index 00000000000..f50e3ed7726 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/qa.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import commands +import signal + +signal.signal(signal.SIGCHLD, signal.SIG_IGN) +print(commands.getoutput('/bin/ls -l')) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/sigwinch_report.py b/lldb/third_party/Python/module/pexpect-4.6/tests/sigwinch_report.py new file mode 100755 index 00000000000..f10956ab1c9 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/sigwinch_report.py @@ -0,0 +1,50 @@ +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from __future__ import print_function + +import signal, time, struct, fcntl, termios, sys + +def getwinsize(): + '''This returns the window size of the child tty. + The return value is a tuple of (rows, cols). + ''' + if 'TIOCGWINSZ' in dir(termios): + TIOCGWINSZ = termios.TIOCGWINSZ + else: + TIOCGWINSZ = 1074295912 # Assume + s = struct.pack('HHHH', 0, 0, 0, 0) + x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s) + return struct.unpack('HHHH', x)[0:2] + +def handler(signum, frame): + print('signal') + sys.stdout.flush() + print('SIGWINCH:', getwinsize ()) + sys.stdout.flush() + +print("Initial Size:", getwinsize()) +print("setting handler for SIGWINCH") +signal.signal(signal.SIGWINCH, handler) +print("READY") + +while 1: + sys.stdout.flush() + time.sleep(1) + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/sleep_for.py b/lldb/third_party/Python/module/pexpect-4.6/tests/sleep_for.py new file mode 100755 index 00000000000..902710576be --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/sleep_for.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +from __future__ import print_function + +import time +import sys + +def main(): + """ + This script sleeps for the number of seconds (float) specified by the + command line argument. + """ + if len(sys.argv) < 2: + print("Usage: %s seconds_to_sleep" % (sys.argv[0],)) + sys.exit(1) + timeout = float(sys.argv[1]) + print("READY") + time.sleep(timeout) + print("END") + +if __name__ == '__main__': + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/swapcase_echo.py b/lldb/third_party/Python/module/pexpect-4.6/tests/swapcase_echo.py new file mode 100755 index 00000000000..aaac442dbaf --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/swapcase_echo.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import sys, time +while True: + x = raw_input () + time.sleep(1) # without this delay the test would fail about 75% of the time. Why? + print(x.swapcase()) + sys.stdout.flush() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_FSM.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_FSM.py new file mode 100644 index 00000000000..3425fd2110e --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_FSM.py @@ -0,0 +1,34 @@ +import io +import sys +import unittest +try: + import builtins +except ImportError: + import __builtin__ as builtins + +PY3 = (sys.version_info[0] >= 3) +input_name = 'input' if PY3 else 'raw_input' + +from pexpect import FSM + +class FSMTestCase(unittest.TestCase): + def test_run_fsm(self): + def _input(prompt): + return "167 3 2 2 * * * 1 - =" + orig_input = getattr(builtins, input_name) + orig_stdout = sys.stdout + setattr(builtins, input_name, _input) + sys.stdout = sio = (io.StringIO if PY3 else io.BytesIO)() + + try: + FSM.main() + finally: + setattr(builtins, input_name, orig_input) + sys.stdout = orig_stdout + + printed = sio.getvalue() + assert '2003' in printed, printed + + +if __name__ == '__main__': + unittest.main()
\ No newline at end of file diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_ansi.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_ansi.py new file mode 100755 index 00000000000..a9d445ed7de --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_ansi.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from pexpect import ANSI +import unittest +from . import PexpectTestCase +import sys + +PY3 = (sys.version_info[0] >= 3) + +write_target = 'I\'ve got a ferret sticking up my nose. \n' +\ +'(He\'s got a ferret sticking up his nose.) \n' +\ +'How it got there I can\'t tell \n' +\ +'But now it\'s there it hurts like hell \n' +\ +'And what is more it radically affects my sense of smell. \n' +\ +'(His sense of smell.) ' + +write_text = 'I\'ve got a ferret sticking up my nose.\n' + \ +'(He\'s got a ferret sticking up his nose.)\n' + \ +'How it got there I can\'t tell\n' + \ +'But now it\'s there it hurts like hell\n' + \ +'And what is more it radically affects my sense of smell.\n' + \ +'(His sense of smell.)\n' + \ +'I can see a bare-bottomed mandril.\n' + \ +'(Slyly eyeing his other nostril.)\n' + \ +'If it jumps inside there too I really don\'t know what to do\n' + \ +'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \ +'(A nasal zoo.)\n' + \ +'I\'ve got a ferret sticking up my nose.\n' + \ +'(And what is worst of all it constantly explodes.)\n' + \ +'"Ferrets don\'t explode," you say\n' + \ +'But it happened nine times yesterday\n' + \ +'And I should know for each time I was standing in the way.\n' + \ +'I\'ve got a ferret sticking up my nose.\n' + \ +'(He\'s got a ferret sticking up his nose.)\n' + \ +'How it got there I can\'t tell\n' + \ +'But now it\'s there it hurts like hell\n' + \ +'And what is more it radically affects my sense of smell.\n' + \ +'(His sense of smell.)' + +tetris_target=' XX XXXX XX \n' +\ +' XXXXXX XXXXXXXX XX \n' +\ +' XXXXXX XXXXXXXX XX \n' +\ +' XX XX XX XXXX XX \n' +\ +' XXXXXX XXXX XXXX XX \n' +\ +' XXXXXXXXXX XXXX XX \n' +\ +' XX XXXXXX XX XX \n' +\ +' XXXXXX XX XX \n' +\ +' XXXX XXXXXX XX XX \n' +\ +' XXXXXX XXXX XX XX \n' +\ +' XX XX XXXX XX XX \n' +\ +' XX XX XX XX XX \n' +\ +' XX XX XXXX XXXX XX \n' +\ +' XXXXXXXX XXXX XXXX XX \n' +\ +' XXXXXXXXXXXXXX XXXXXXXX \n' +\ +' XX XXXXXXXX XX XX \n' +\ +' XXXXXXXXXXXXXX XX XX \n' +\ +' XX XXXX XXXXXX XX \n' +\ +' XXXXXX XXXXXXXX \n' +\ +' XXXXXXXXXX XX XX \n' +\ +' XXXXXXXXXXXXXXXXXXXXXXXX \n' +\ +' \n' +\ +' J->LEFT K->ROTATE L->RIGHT SPACE->DROP P->PAUSE Q->QUIT \n' +\ +' ' + +torture_target='+--------------------------------------------------------------------------------+\n' +\ +'|a`opqrs` This is the `srqpo`a |\n' +\ +'|VT100 series Torture Test Demonstration. |\n' +\ +'|VT100 series Torture Test Demonstration. |\n' +\ +'|This is a normal line __________________________________________________y_ |\n' +\ +'|This is a bold line (normal unless the Advanced Video Option is installed) |\n' +\ +'|This line is underlined _ " " " " " " _y_ |\n' +\ +'|This is a blinking line _ " " " " " " _y_ |\n' +\ +'|This is inverse video _ (underlined if no AVO and cursor is underline) _y_ |\n' +\ +'|Normal gjpqy Underline Blink Underline+Blink gjpqy |\n' +\ +'|Bold gjpqy Underline Blink Underline+Blink gjpqy |\n' +\ +'|Inverse Underline Blink Underline+Blink |\n' +\ +'|Bold+Inverse Underline Blink Underline+Blink |\n' +\ +'|This is double width |\n' +\ +'|This is double height |\n' +\ +'|This is double height |\n' +\ +'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\ +'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\ +'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\ +'|`abcdefghijklmnopqrstuvwxyz{|}~ lqwqk |\n' +\ +'|`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu |\n' +\ +'|`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu |\n' +\ +'|`abcdefghijklmnopqrstuvwxyz{|}~ mqvqj |\n' +\ +'| This test created by Joe Smith, 8-May-85 |\n' +\ +'| |\n' +\ +'+--------------------------------------------------------------------------------+\n' + +class ansiTestCase (PexpectTestCase.PexpectTestCase): + def test_write (self): + s = ANSI.ANSI (6,65) + s.fill('.') + s.cursor_home() + for c in write_text: + s.write (c) + assert str(s) == write_target + + def test_torturet (self): + s = ANSI.ANSI (24,80) + with open('torturet.vt') as f: + sample_text = f.read() + for c in sample_text: + s.process (c) + assert s.pretty() == torture_target, 'processed: \n' + s.pretty() + '\nexpected:\n' + torture_target + + def test_tetris (self): + s = ANSI.ANSI (24,80) + with open('tetris.data') as f: + tetris_text = f.read() + for c in tetris_text: + s.process (c) + assert str(s) == tetris_target + + def test_lines(self): + s = ANSI.ANSI(5, 5) + s.write('a'*6 + '\n') + s.write('ab\bcd\n') + s.write('ab\rcd\n') + assert str(s) == ('aaaaa\n' + 'a \n' + 'acd \n' + 'cd \n' + ' ') + + def test_number_x(self): + """Test the FSM state used to handle more than 2 numeric parameters.""" + class TestANSI(ANSI.ANSI): + captured_memory = None + def do_sgr(self, fsm): + assert self.captured_memory is None + self.captured_memory = fsm.memory + + s = TestANSI(1, 20) + s.write('\x1b[0;1;32;45mtest') + assert str(s) == ('test ') + assert s.captured_memory is not None + assert s.captured_memory == [s, '0', '1', '32', '45'] + + def test_fsm_memory(self): + """Test the FSM stack/memory does not have numbers left on it + after some sequences with numbers are passed in.""" + s = ANSI.ANSI(1, 20) + s.write('\x1b[0;1;2;3m\x1b[4;5;6;7q\x1b[?8h\x1b[?9ltest') + assert str(s) == ('test ') + assert s.state.memory == [s] + + def test_utf8_bytes(self): + """Test that when bytes are passed in containing UTF-8 encoded + characters, where the encoding of each character consists of + multiple bytes, the characters are correctly decoded. + Incremental decoding is also tested.""" + s = ANSI.ANSI(2, 10, encoding='utf-8') + # This is the UTF-8 encoding of the UCS character "HOURGLASS" + # followed by the UTF-8 encoding of the UCS character + # "KEYBOARD". These characters can't be encoded in cp437 or + # latin-1. The "KEYBOARD" character is split into two + # separate writes. + s.write(b'\xe2\x8c\x9b') + s.write(b'\xe2\x8c') + s.write(b'\xa8') + if PY3: + assert str(s) == u'\u231b\u2328 \n ' + else: + assert unicode(s) == u'\u231b\u2328 \n ' + assert str(s) == b'\xe2\x8c\x9b\xe2\x8c\xa8 \n ' + assert s.dump() == u'\u231b\u2328 ' + assert s.pretty() == u'+----------+\n|\u231b\u2328 |\n| |\n+----------+\n' + assert s.get_abs(1, 1) == u'\u231b' + assert s.get_region(1, 1, 1, 5) == [u'\u231b\u2328 '] + + def test_unicode(self): + """Test passing in of a unicode string.""" + s = ANSI.ANSI(2, 10, encoding="utf-8") + s.write(u'\u231b\u2328') + if PY3: + assert str(s) == u'\u231b\u2328 \n ' + else: + assert unicode(s) == u'\u231b\u2328 \n ' + assert str(s) == b'\xe2\x8c\x9b\xe2\x8c\xa8 \n ' + assert s.dump() == u'\u231b\u2328 ' + assert s.pretty() == u'+----------+\n|\u231b\u2328 |\n| |\n+----------+\n' + assert s.get_abs(1, 1) == u'\u231b' + assert s.get_region(1, 1, 1, 5) == [u'\u231b\u2328 '] + + def test_decode_error(self): + """Test that default handling of decode errors replaces the + invalid characters.""" + s = ANSI.ANSI(2, 10, encoding="ascii") + s.write(b'\xff') # a non-ASCII character + # In unicode, the non-ASCII character is replaced with + # REPLACEMENT CHARACTER. + if PY3: + assert str(s) == u'\ufffd \n ' + else: + assert unicode(s) == u'\ufffd \n ' + assert str(s) == b'? \n ' + assert s.dump() == u'\ufffd ' + assert s.pretty() == u'+----------+\n|\ufffd |\n| |\n+----------+\n' + assert s.get_abs(1, 1) == u'\ufffd' + assert s.get_region(1, 1, 1, 5) == [u'\ufffd '] + + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(ansiTestCase,'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_async.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_async.py new file mode 100644 index 00000000000..1cc32361fe2 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_async.py @@ -0,0 +1,70 @@ +try: + import asyncio +except ImportError: + asyncio = None + +import gc +import sys +import unittest + +import pexpect +from .PexpectTestCase import PexpectTestCase + +def run(coro): + return asyncio.get_event_loop().run_until_complete(coro) + +@unittest.skipIf(asyncio is None, "Requires asyncio") +class AsyncTests(PexpectTestCase): + def test_simple_expect(self): + p = pexpect.spawn('cat') + p.sendline('Hello asyncio') + coro = p.expect(['Hello', pexpect.EOF] , async_=True) + assert run(coro) == 0 + print('Done') + + def test_timeout(self): + p = pexpect.spawn('cat') + coro = p.expect('foo', timeout=1, async_=True) + with self.assertRaises(pexpect.TIMEOUT): + run(coro) + + p = pexpect.spawn('cat') + coro = p.expect(['foo', pexpect.TIMEOUT], timeout=1, async_=True) + assert run(coro) == 1 + + def test_eof(self): + p = pexpect.spawn('cat') + p.sendline('Hi') + coro = p.expect(pexpect.EOF, async_=True) + p.sendeof() + assert run(coro) == 0 + + p = pexpect.spawn('cat') + p.sendeof() + coro = p.expect('Blah', async_=True) + with self.assertRaises(pexpect.EOF): + run(coro) + + def test_expect_exact(self): + p = pexpect.spawn('%s list100.py' % sys.executable) + assert run(p.expect_exact(b'5', async_=True)) == 0 + assert run(p.expect_exact(['wpeok', b'11'], async_=True)) == 1 + assert run(p.expect_exact([b'foo', pexpect.EOF], async_=True)) == 1 + + def test_async_utf8(self): + p = pexpect.spawn('%s list100.py' % sys.executable, encoding='utf8') + assert run(p.expect_exact(u'5', async_=True)) == 0 + assert run(p.expect_exact([u'wpeok', u'11'], async_=True)) == 1 + assert run(p.expect_exact([u'foo', pexpect.EOF], async_=True)) == 1 + + def test_async_and_gc(self): + p = pexpect.spawn('%s sleep_for.py 1' % sys.executable, encoding='utf8') + assert run(p.expect_exact(u'READY', async_=True)) == 0 + gc.collect() + assert run(p.expect_exact(u'END', async_=True)) == 0 + + def test_async_and_sync(self): + p = pexpect.spawn('echo 1234', encoding='utf8', maxread=1) + assert run(p.expect_exact(u'1', async_=True)) == 0 + assert p.expect_exact(u'2') == 0 + assert run(p.expect_exact(u'3', async_=True)) == 0 diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_command_list_split.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_command_list_split.py new file mode 100755 index 00000000000..370f46e5b49 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_command_list_split.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +from . import PexpectTestCase + +class SplitCommandLineTestCase(PexpectTestCase.PexpectTestCase): + def testSplitSizes(self): + assert len(pexpect.split_command_line(r'')) == 0 + assert len(pexpect.split_command_line(r'one')) == 1 + assert len(pexpect.split_command_line(r'one two')) == 2 + assert len(pexpect.split_command_line(r'one two')) == 2 + assert len(pexpect.split_command_line(r'one two')) == 2 + assert len(pexpect.split_command_line(r'one\ one')) == 1 + assert len(pexpect.split_command_line('\'one one\'')) == 1 + assert len(pexpect.split_command_line(r'one\"one')) == 1 + assert len(pexpect.split_command_line(r'This\' is a\'\ test')) == 3 + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(SplitCommandLineTestCase,'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_constructor.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_constructor.py new file mode 100755 index 00000000000..98c473ae584 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_constructor.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +from . import PexpectTestCase + +class TestCaseConstructor(PexpectTestCase.PexpectTestCase): + def test_constructor (self): + '''This tests that the constructor will work and give + the same results for different styles of invoking __init__(). + This assumes that the root directory / is static during the test. + ''' + p1 = pexpect.spawn('uname -m -n -p -r -s -v') + p2 = pexpect.spawn('uname', ['-m', '-n', '-p', '-r', '-s', '-v']) + p1.expect(pexpect.EOF) + p2.expect(pexpect.EOF) + assert p1.before == p2.before + + def test_named_parameters (self): + '''This tests that named parameters work. + ''' + p = pexpect.spawn ('/bin/ls',timeout=10) + p = pexpect.spawn (timeout=10, command='/bin/ls') + p = pexpect.spawn (args=[], command='/bin/ls') + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(TestCaseConstructor,'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_ctrl_chars.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_ctrl_chars.py new file mode 100755 index 00000000000..10d03dbc2af --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_ctrl_chars.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from __future__ import print_function + +import pexpect +import unittest +from . import PexpectTestCase +import time +import sys + +from ptyprocess import ptyprocess +ptyprocess._make_eof_intr() + +if sys.version_info[0] >= 3: + def byte(i): + return bytes([i]) +else: + byte = chr + +class TestCtrlChars(PexpectTestCase.PexpectTestCase): + + def test_control_chars(self): + '''This tests that we can send all 256 8-bit characters to a child + process.''' + child = pexpect.spawn('python getch.py', echo=False, timeout=5) + child.expect('READY') + for i in range(1, 256): + child.send(byte(i)) + child.expect ('%d<STOP>' % (i,)) + + # This needs to be last, as getch.py exits on \x00 + child.send(byte(0)) + child.expect('0<STOP>') + child.expect(pexpect.EOF) + assert not child.isalive() + assert child.exitstatus == 0 + + def test_sendintr (self): + child = pexpect.spawn('python getch.py', echo=False, timeout=5) + child.expect('READY') + child.sendintr() + child.expect(str(ord(ptyprocess._INTR)) + '<STOP>') + + child.send(byte(0)) + child.expect('0<STOP>') + child.expect(pexpect.EOF) + assert not child.isalive() + assert child.exitstatus == 0 + + def test_sendeof(self): + child = pexpect.spawn('python getch.py', echo=False, timeout=5) + child.expect('READY') + child.sendeof() + child.expect(str(ord(ptyprocess._EOF)) + '<STOP>') + + child.send(byte(0)) + child.expect('0<STOP>') + child.expect(pexpect.EOF) + assert not child.isalive() + assert child.exitstatus == 0 + + def test_bad_sendcontrol_chars (self): + '''This tests that sendcontrol will return 0 for an unknown char. ''' + + child = pexpect.spawn('python getch.py', echo=False, timeout=5) + child.expect('READY') + assert 0 == child.sendcontrol('1') + + def test_sendcontrol(self): + '''This tests that we can send all special control codes by name. + ''' + child = pexpect.spawn('python getch.py', echo=False, timeout=5) + child.expect('READY') + for ctrl in 'abcdefghijklmnopqrstuvwxyz': + assert child.sendcontrol(ctrl) == 1 + val = ord(ctrl) - ord('a') + 1 + child.expect_exact(str(val)+'<STOP>') + + # escape character + assert child.sendcontrol('[') == 1 + child.expect('27<STOP>') + assert child.sendcontrol('\\') == 1 + child.expect('28<STOP>') + # telnet escape character + assert child.sendcontrol(']') == 1 + child.expect('29<STOP>') + assert child.sendcontrol('^') == 1 + child.expect('30<STOP>') + # irc protocol uses this to underline ... + assert child.sendcontrol('_') == 1 + child.expect('31<STOP>') + # the real "backspace is delete" + assert child.sendcontrol('?') == 1 + child.expect('127<STOP>') + + # NUL, same as ctrl + ' ' + assert child.sendcontrol('@') == 1 + child.expect('0<STOP>') + child.expect(pexpect.EOF) + assert not child.isalive() + assert child.exitstatus == 0 + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(TestCtrlChars,'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_delay.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_delay.py new file mode 100644 index 00000000000..1e4dba687df --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_delay.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- + +from . import PexpectTestCase +import pexpect + + +class TestCaseDelay(PexpectTestCase.PexpectTestCase): + """ + Tests for various delay attributes. + """ + def test_delaybeforesend(self): + """ + Test various values for delaybeforesend. + """ + p = pexpect.spawn("cat") + + p.delaybeforesend = 1 + p.sendline("line 1") + p.expect("line 1") + + p.delaybeforesend = 0.0 + p.sendline("line 2") + p.expect("line 2") + + p.delaybeforesend = None + p.sendline("line 3") + p.expect("line 3") + + def test_delayafterread(self): + """ + Test various values for delayafterread. + """ + p = pexpect.spawn("cat") + + p.delayafterread = 1 + p.sendline("line 1") + p.expect("line 1") + + p.delayafterread = 0.0 + p.sendline("line 2") + p.expect("line 2") + + p.delayafterread = None + p.sendline("line 3") + p.expect("line 3") diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_destructor.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_destructor.py new file mode 100755 index 00000000000..d27b6f6251e --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_destructor.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +from . import PexpectTestCase +import gc +import platform +import time + +class TestCaseDestructor(PexpectTestCase.PexpectTestCase): + def test_destructor (self): + if platform.python_implementation() != 'CPython': + # Details of garbage collection are different on other implementations + return 'SKIP' + gc.collect() + time.sleep(3) + p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + fd_t1 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd) + p1.expect(pexpect.EOF) + p2.expect(pexpect.EOF) + p3.expect(pexpect.EOF) + p4.expect(pexpect.EOF) + p1.kill(9) + p2.kill(9) + p3.kill(9) + p4.kill(9) + p1 = None + p2 = None + p3 = None + p4 = None + gc.collect() + time.sleep(3) # Some platforms are slow at gc... Solaris! + + p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + fd_t2 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd) + p1.kill(9) + p2.kill(9) + p3.kill(9) + p4.kill(9) + del (p1) + del (p2) + del (p3) + del (p4) + gc.collect() + time.sleep(3) + + p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN) + fd_t3 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd) + + assert (fd_t1 == fd_t2 == fd_t3), "pty file descriptors not properly garbage collected (fd_t1,fd_t2,fd_t3)=(%s,%s,%s)" % (str(fd_t1),str(fd_t2),str(fd_t3)) + + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(TestCaseDestructor,'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_dotall.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_dotall.py new file mode 100755 index 00000000000..68aef3f50b7 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_dotall.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +import re +from . import PexpectTestCase + +testdata = 'BEGIN\nHello world\nEND' +class TestCaseDotall(PexpectTestCase.PexpectTestCase): + def test_dotall (self): + p = pexpect.spawn('echo "%s"' % testdata) + i = p.expect ([b'BEGIN(.*)END', pexpect.EOF]) + assert i==0, 'DOTALL does not seem to be working.' + + def test_precompiled (self): + p = pexpect.spawn('echo "%s"' % testdata) + pat = re.compile(b'BEGIN(.*)END') # This overrides the default DOTALL. + i = p.expect ([pat, pexpect.EOF]) + assert i==1, 'Precompiled pattern to override DOTALL does not seem to be working.' + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(TestCaseDotall,'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_env.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_env.py new file mode 100755 index 00000000000..ecaaa4bea26 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_env.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2016, Martin Packman <martin.packman@canonical.com> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import contextlib +import os +import tempfile +import unittest + +import pexpect +from . import PexpectTestCase + + +@contextlib.contextmanager +def example_script(name, output='success'): + " helper to create a temporary shell script that tests can run " + tempdir = tempfile.mkdtemp(prefix='tmp-pexpect-test') + try: + script_path = os.path.join(tempdir, name) + with open(script_path, 'w') as f: + f.write('#!/bin/sh\necho "%s"' % (output,)) + try: + os.chmod(script_path, 0o755) + yield tempdir + finally: + os.remove(script_path) + finally: + os.rmdir(tempdir) + + +class TestCaseEnv(PexpectTestCase.PexpectTestCase): + " tests for the env argument to pexpect.spawn and pexpect.run " + + def test_run_uses_env(self): + " pexpect.run uses env argument when running child process " + script_name = 'run_uses_env.sh' + environ = {'PEXPECT_TEST_KEY': 'pexpect test value'} + with example_script(script_name, '$PEXPECT_TEST_KEY') as script_dir: + script = os.path.join(script_dir, script_name) + out = pexpect.run(script, env=environ) + self.assertEqual(out.rstrip(), b'pexpect test value') + + def test_spawn_uses_env(self): + " pexpect.spawn uses env argument when running child process " + script_name = 'spawn_uses_env.sh' + environ = {'PEXPECT_TEST_KEY': 'pexpect test value'} + with example_script(script_name, '$PEXPECT_TEST_KEY') as script_dir: + script = os.path.join(script_dir, script_name) + child = pexpect.spawn(script, env=environ) + out = child.readline() + child.expect(pexpect.EOF) + self.assertEqual(child.exitstatus, 0) + self.assertEqual(out.rstrip(), b'pexpect test value') + + def test_run_uses_env_path(self): + " pexpect.run uses binary from PATH when given in env argument " + script_name = 'run_uses_env_path.sh' + with example_script(script_name) as script_dir: + out = pexpect.run(script_name, env={'PATH': script_dir}) + self.assertEqual(out.rstrip(), b'success') + + def test_run_uses_env_path_over_path(self): + " pexpect.run uses PATH from env over os.environ " + script_name = 'run_uses_env_path_over_path.sh' + with example_script(script_name, output='failure') as wrong_dir: + with example_script(script_name) as right_dir: + orig_path = os.environ['PATH'] + os.environ['PATH'] = wrong_dir + try: + out = pexpect.run(script_name, env={'PATH': right_dir}) + finally: + os.environ['PATH'] = orig_path + self.assertEqual(out.rstrip(), b'success') + + +if __name__ == '__main__': + unittest.main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_expect.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_expect.py new file mode 100755 index 00000000000..795518ab2fc --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_expect.py @@ -0,0 +1,602 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import multiprocessing +import unittest +import subprocess +import time +import signal +import sys +import os + +import pexpect +from . import PexpectTestCase +from .utils import no_coverage_env + +# Many of these test cases blindly assume that sequential directory +# listings of the /bin directory will yield the same results. +# This may not be true, but seems adequate for testing now. +# I should fix this at some point. + +FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)]) +def hex_dump(src, length=16): + result=[] + for i in xrange(0, len(src), length): + s = src[i:i+length] + hexa = ' '.join(["%02X"%ord(x) for x in s]) + printable = s.translate(FILTER) + result.append("%04X %-*s %s\n" % (i, length*3, hexa, printable)) + return ''.join(result) + +def hex_diff(left, right): + diff = ['< %s\n> %s' % (_left, _right,) for _left, _right in zip( + hex_dump(left).splitlines(), hex_dump(right).splitlines()) + if _left != _right] + return '\n' + '\n'.join(diff,) + + +class ExpectTestCase (PexpectTestCase.PexpectTestCase): + + def test_expect_basic (self): + p = pexpect.spawn('cat', echo=False, timeout=5) + p.sendline (b'Hello') + p.sendline (b'there') + p.sendline (b'Mr. Python') + p.expect (b'Hello') + p.expect (b'there') + p.expect (b'Mr. Python') + p.sendeof () + p.expect (pexpect.EOF) + + def test_expect_exact_basic (self): + p = pexpect.spawn('cat', echo=False, timeout=5) + p.sendline (b'Hello') + p.sendline (b'there') + p.sendline (b'Mr. Python') + p.expect_exact (b'Hello') + p.expect_exact (b'there') + p.expect_exact (b'Mr. Python') + p.sendeof () + p.expect_exact (pexpect.EOF) + + def test_expect_ignore_case(self): + '''This test that the ignorecase flag will match patterns + even if case is different using the regex (?i) directive. + ''' + p = pexpect.spawn('cat', echo=False, timeout=5) + p.sendline (b'HELLO') + p.sendline (b'there') + p.expect (b'(?i)hello') + p.expect (b'(?i)THERE') + p.sendeof () + p.expect (pexpect.EOF) + + def test_expect_ignore_case_flag(self): + '''This test that the ignorecase flag will match patterns + even if case is different using the ignorecase flag. + ''' + p = pexpect.spawn('cat', echo=False, timeout=5) + p.ignorecase = True + p.sendline (b'HELLO') + p.sendline (b'there') + p.expect (b'hello') + p.expect (b'THERE') + p.sendeof () + p.expect (pexpect.EOF) + + def test_expect_order (self): + '''This tests that patterns are matched in the same order as given in the pattern_list. + + (Or does it? Doesn't it also pass if expect() always chooses + (one of the) the leftmost matches in the input? -- grahn) + ... agreed! -jquast, the buffer ptr isn't forwarded on match, see first two test cases + ''' + p = pexpect.spawn('cat', echo=False, timeout=5) + self._expect_order(p) + + def test_expect_order_exact (self): + '''Like test_expect_order(), but using expect_exact(). + ''' + p = pexpect.spawn('cat', echo=False, timeout=5) + p.expect = p.expect_exact + self._expect_order(p) + + def _expect_order (self, p): + p.sendline (b'1234') + p.sendline (b'abcd') + p.sendline (b'wxyz') + p.sendline (b'7890') + p.sendeof () + index = p.expect ([ + b'1234', + b'abcd', + b'wxyz', + pexpect.EOF, + b'7890' ]) + assert index == 0, (index, p.before, p.after) + index = p.expect ([ + b'54321', + pexpect.TIMEOUT, + b'1234', + b'abcd', + b'wxyz', + pexpect.EOF], timeout=5) + assert index == 3, (index, p.before, p.after) + index = p.expect ([ + b'54321', + pexpect.TIMEOUT, + b'1234', + b'abcd', + b'wxyz', + pexpect.EOF], timeout=5) + assert index == 4, (index, p.before, p.after) + index = p.expect ([ + pexpect.EOF, + b'abcd', + b'wxyz', + b'7890' ]) + assert index == 3, (index, p.before, p.after) + + index = p.expect ([ + b'abcd', + b'wxyz', + b'7890', + pexpect.EOF]) + assert index == 3, (index, p.before, p.after) + + def test_expect_setecho_off(self): + '''This tests that echo may be toggled off. + ''' + p = pexpect.spawn('cat', echo=True, timeout=5) + try: + self._expect_echo_toggle(p) + except IOError: + if sys.platform.lower().startswith('sunos'): + if hasattr(unittest, 'SkipTest'): + raise unittest.SkipTest("Not supported on this platform.") + return 'skip' + raise + + def test_expect_setecho_off_exact(self): + p = pexpect.spawn('cat', echo=True, timeout=5) + p.expect = p.expect_exact + try: + self._expect_echo_toggle(p) + except IOError: + if sys.platform.lower().startswith('sunos'): + if hasattr(unittest, 'SkipTest'): + raise unittest.SkipTest("Not supported on this platform.") + return 'skip' + raise + + def test_waitnoecho(self): + " Tests setecho(False) followed by waitnoecho() " + p = pexpect.spawn('cat', echo=False, timeout=5) + try: + p.setecho(False) + p.waitnoecho() + except IOError: + if sys.platform.lower().startswith('sunos'): + if hasattr(unittest, 'SkipTest'): + raise unittest.SkipTest("Not supported on this platform.") + return 'skip' + raise + + def test_waitnoecho_order(self): + + ''' This tests that we can wait on a child process to set echo mode. + For example, this tests that we could wait for SSH to set ECHO False + when asking of a password. This makes use of an external script + echo_wait.py. ''' + + p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN) + start = time.time() + try: + p1.waitnoecho(timeout=10) + except IOError: + if sys.platform.lower().startswith('sunos'): + if hasattr(unittest, 'SkipTest'): + raise unittest.SkipTest("Not supported on this platform.") + return 'skip' + raise + + + end_time = time.time() - start + assert end_time < 10 and end_time > 2, "waitnoecho did not set ECHO off in the expected window of time." + + # test that we actually timeout and return False if ECHO is never set off. + p1 = pexpect.spawn('cat') + start = time.time() + retval = p1.waitnoecho(timeout=4) + end_time = time.time() - start + assert end_time > 3, "waitnoecho should have waited longer than 2 seconds. retval should be False, retval=%d"%retval + assert retval==False, "retval should be False, retval=%d"%retval + + # This one is mainly here to test default timeout for code coverage. + p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN) + start = time.time() + p1.waitnoecho() + end_time = time.time() - start + assert end_time < 10, "waitnoecho did not set ECHO off in the expected window of time." + + def test_expect_echo (self): + '''This tests that echo is on by default. + ''' + p = pexpect.spawn('cat', echo=True, timeout=5) + self._expect_echo(p) + + def test_expect_echo_exact (self): + '''Like test_expect_echo(), but using expect_exact(). + ''' + p = pexpect.spawn('cat', echo=True, timeout=5) + p.expect = p.expect_exact + self._expect_echo(p) + + def _expect_echo (self, p): + p.sendline (b'1234') # Should see this twice (once from tty echo and again from cat). + index = p.expect ([ + b'1234', + b'abcd', + b'wxyz', + pexpect.EOF, + pexpect.TIMEOUT]) + assert index == 0, "index="+str(index)+"\n"+p.before + index = p.expect ([ + b'1234', + b'abcd', + b'wxyz', + pexpect.EOF]) + assert index == 0, "index="+str(index) + + def _expect_echo_toggle(self, p): + p.sendline (b'1234') # Should see this twice (once from tty echo and again from cat). + index = p.expect ([ + b'1234', + b'abcd', + b'wxyz', + pexpect.EOF, + pexpect.TIMEOUT]) + assert index == 0, "index="+str(index)+"\n"+p.before + index = p.expect ([ + b'1234', + b'abcd', + b'wxyz', + pexpect.EOF]) + assert index == 0, "index="+str(index) + p.setecho(0) # Turn off tty echo + p.waitnoecho() + p.sendline (b'abcd') # Now, should only see this once. + p.sendline (b'wxyz') # Should also be only once. + index = p.expect ([ + pexpect.EOF, + pexpect.TIMEOUT, + b'abcd', + b'wxyz', + b'1234']) + assert index == 2, "index="+str(index) + index = p.expect ([ + pexpect.EOF, + b'abcd', + b'wxyz', + b'7890']) + assert index == 2, "index="+str(index) + p.setecho(1) # Turn on tty echo + p.sendline (b'7890') # Should see this twice. + index = p.expect ([pexpect.EOF,b'abcd',b'wxyz',b'7890']) + assert index == 3, "index="+str(index) + index = p.expect ([pexpect.EOF,b'abcd',b'wxyz',b'7890']) + assert index == 3, "index="+str(index) + p.sendeof() + + def test_expect_index (self): + '''This tests that mixed list of regex strings, TIMEOUT, and EOF all + return the correct index when matched. + ''' + p = pexpect.spawn('cat', echo=False, timeout=5) + self._expect_index(p) + + def test_expect_index_exact (self): + '''Like test_expect_index(), but using expect_exact(). + ''' + p = pexpect.spawn('cat', echo=False, timeout=5) + p.expect = p.expect_exact + self._expect_index(p) + + def _expect_index (self, p): + p.sendline (b'1234') + index = p.expect ([b'abcd',b'wxyz',b'1234',pexpect.EOF]) + assert index == 2, "index="+str(index) + p.sendline (b'abcd') + index = p.expect ([pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF]) + assert index == 1, "index="+str(index)+str(p) + p.sendline (b'wxyz') + index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF]) + assert index == 3, "index="+str(index) # Expect 'wxyz' + p.sendline (b'$*!@?') + index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF], + timeout=1) + assert index == 1, "index="+str(index) # Expect TIMEOUT + p.sendeof () + index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF]) + assert index == 5, "index="+str(index) # Expect EOF + + def test_expect (self): + the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'], + stdout=subprocess.PIPE).communicate()[0].rstrip() + p = pexpect.spawn('ls -l /bin') + the_new_way = b'' + while 1: + i = p.expect ([b'\n', pexpect.EOF]) + the_new_way = the_new_way + p.before + if i == 1: + break + the_new_way = the_new_way.rstrip() + the_new_way = the_new_way.replace(b'\r\n', b'\n' + ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip() + the_old_way = the_old_way.replace(b'\r\n', b'\n' + ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip() + assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way) + + def test_expect_exact (self): + the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'], + stdout=subprocess.PIPE).communicate()[0].rstrip() + p = pexpect.spawn('ls -l /bin') + the_new_way = b'' + while 1: + i = p.expect_exact ([b'\n', pexpect.EOF]) + the_new_way = the_new_way + p.before + if i == 1: + break + the_new_way = the_new_way.replace(b'\r\n', b'\n' + ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip() + the_old_way = the_old_way.replace(b'\r\n', b'\n' + ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip() + assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way) + p = pexpect.spawn('echo hello.?world') + i = p.expect_exact(b'.?') + self.assertEqual(p.before, b'hello') + self.assertEqual(p.after, b'.?') + + def test_expect_eof (self): + the_old_way = subprocess.Popen(args=['/bin/ls', '-l', '/bin'], + stdout=subprocess.PIPE).communicate()[0].rstrip() + p = pexpect.spawn('/bin/ls -l /bin') + p.expect(pexpect.EOF) # This basically tells it to read everything. Same as pexpect.run() function. + the_new_way = p.before + the_new_way = the_new_way.replace(b'\r\n', b'\n' + ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip() + the_old_way = the_old_way.replace(b'\r\n', b'\n' + ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip() + assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way) + + def test_expect_timeout (self): + p = pexpect.spawn('cat', timeout=5) + p.expect(pexpect.TIMEOUT) # This tells it to wait for timeout. + self.assertEqual(p.after, pexpect.TIMEOUT) + + def test_unexpected_eof (self): + p = pexpect.spawn('ls -l /bin') + try: + p.expect('_Z_XY_XZ') # Probably never see this in ls output. + except pexpect.EOF: + pass + else: + self.fail ('Expected an EOF exception.') + + def test_buffer_interface(self): + p = pexpect.spawn('cat', timeout=5) + p.sendline (b'Hello') + p.expect (b'Hello') + assert len(p.buffer) + p.buffer = b'Testing' + p.sendeof () + + def test_before_across_chunks(self): + # https://github.com/pexpect/pexpect/issues/478 + child = pexpect.spawn( + '''/bin/bash -c "openssl rand -base64 {} | head -500 | nl --number-format=rz --number-width=5 2>&1 ; echo 'PATTERN!!!'"'''.format(1024 * 1024 * 2), + searchwindowsize=128 + ) + child.expect(['PATTERN']) + assert len(child.before.splitlines()) == 500 + assert child.after == b'PATTERN' + assert child.buffer == b'!!!\r\n' + + def _before_after(self, p): + p.timeout = 5 + + p.expect(b'5') + self.assertEqual(p.after, b'5') + assert p.before.startswith(b'[0, 1, 2'), p.before + + p.expect(b'50') + self.assertEqual(p.after, b'50') + assert p.before.startswith(b', 6, 7, 8'), p.before[:20] + assert p.before.endswith(b'48, 49, '), p.before[-20:] + + p.expect(pexpect.EOF) + self.assertEqual(p.after, pexpect.EOF) + assert p.before.startswith(b', 51, 52'), p.before[:20] + assert p.before.endswith(b', 99]\r\n'), p.before[-20:] + + def test_before_after(self): + '''This tests expect() for some simple before/after things. + ''' + p = pexpect.spawn('%s -Wi list100.py' % self.PYTHONBIN, env=no_coverage_env()) + self._before_after(p) + + def test_before_after_exact(self): + '''This tests some simple before/after things, for + expect_exact(). (Grahn broke it at one point.) + ''' + p = pexpect.spawn('%s -Wi list100.py' % self.PYTHONBIN, env=no_coverage_env()) + # mangle the spawn so we test expect_exact() instead + p.expect = p.expect_exact + self._before_after(p) + + def _ordering(self, p): + p.timeout = 20 + p.expect(b'>>> ') + + p.sendline('list(range(4*3))') + self.assertEqual(p.expect([b'5,', b'5,']), 0) + p.expect(b'>>> ') + + p.sendline(b'list(range(4*3))') + self.assertEqual(p.expect([b'7,', b'5,']), 1) + p.expect(b'>>> ') + + p.sendline(b'list(range(4*3))') + self.assertEqual(p.expect([b'5,', b'7,']), 0) + p.expect(b'>>> ') + + p.sendline(b'list(range(4*5))') + self.assertEqual(p.expect([b'2,', b'12,']), 0) + p.expect(b'>>> ') + + p.sendline(b'list(range(4*5))') + self.assertEqual(p.expect([b'12,', b'2,']), 1) + + def test_ordering(self): + '''This tests expect() for which pattern is returned + when many may eventually match. I (Grahn) am a bit + confused about what should happen, but this test passes + with pexpect 2.1. + ''' + p = pexpect.spawn(self.PYTHONBIN) + self._ordering(p) + + def test_ordering_exact(self): + '''This tests expect_exact() for which pattern is returned + when many may eventually match. I (Grahn) am a bit + confused about what should happen, but this test passes + for the expect() method with pexpect 2.1. + ''' + p = pexpect.spawn(self.PYTHONBIN) + # mangle the spawn so we test expect_exact() instead + p.expect = p.expect_exact + self._ordering(p) + + def _greed(self, expect): + # End at the same point: the one with the earliest start should win + self.assertEqual(expect([b'3, 4', b'2, 3, 4']), 1) + + # Start at the same point: first pattern passed wins + self.assertEqual(expect([b'5,', b'5, 6']), 0) + + # Same pattern passed twice: first instance wins + self.assertEqual(expect([b'7, 8', b'7, 8, 9', b'7, 8']), 0) + + def _greed_read1(self, expect): + # Here, one has an earlier start and a later end. When processing + # one character at a time, the one that finishes first should win, + # because we don't know about the other match when it wins. + # If maxread > 1, this behaviour is currently undefined, although in + # most cases the one that starts first will win. + self.assertEqual(expect([b'1, 2, 3', b'2,']), 1) + + def test_greed(self): + p = pexpect.spawn(self.PYTHONBIN + ' list100.py') + self._greed(p.expect) + + p = pexpect.spawn(self.PYTHONBIN + ' list100.py', maxread=1) + self._greed_read1(p.expect) + + def test_greed_exact(self): + p = pexpect.spawn(self.PYTHONBIN + ' list100.py') + self._greed(p.expect_exact) + + p = pexpect.spawn(self.PYTHONBIN + ' list100.py', maxread=1) + self._greed_read1(p.expect_exact) + + def test_bad_arg(self): + p = pexpect.spawn('cat') + with self.assertRaisesRegexp(TypeError, '.*must be one of'): + p.expect(1) + with self.assertRaisesRegexp(TypeError, '.*must be one of'): + p.expect([1, b'2']) + with self.assertRaisesRegexp(TypeError, '.*must be one of'): + p.expect_exact(1) + with self.assertRaisesRegexp(TypeError, '.*must be one of'): + p.expect_exact([1, b'2']) + + def test_timeout_none(self): + p = pexpect.spawn('echo abcdef', timeout=None) + p.expect('abc') + p.expect_exact('def') + p.expect(pexpect.EOF) + + def test_signal_handling(self): + ''' + This tests the error handling of a signal interrupt (usually a + SIGWINCH generated when a window is resized), but in this test, we + are substituting an ALARM signal as this is much easier for testing + and is treated the same as a SIGWINCH. + + To ensure that the alarm fires during the expect call, we are + setting the signal to alarm after 1 second while the spawned process + sleeps for 2 seconds prior to sending the expected output. + ''' + def noop(x, y): + pass + signal.signal(signal.SIGALRM, noop) + + p1 = pexpect.spawn('%s sleep_for.py 2' % self.PYTHONBIN, timeout=5) + p1.expect('READY') + signal.alarm(1) + p1.expect('END') + + def test_stdin_closed(self): + ''' + Ensure pexpect continues to operate even when stdin is closed + ''' + class Closed_stdin_proc(multiprocessing.Process): + def run(self): + sys.__stdin__.close() + cat = pexpect.spawn('cat') + cat.sendeof() + cat.expect(pexpect.EOF) + + proc = Closed_stdin_proc() + proc.start() + proc.join() + assert proc.exitcode == 0 + + def test_stdin_stdout_closed(self): + ''' + Ensure pexpect continues to operate even when stdin and stdout is closed + ''' + class Closed_stdin_stdout_proc(multiprocessing.Process): + def run(self): + sys.__stdin__.close() + sys.__stdout__.close() + cat = pexpect.spawn('cat') + cat.sendeof() + cat.expect(pexpect.EOF) + + proc = Closed_stdin_stdout_proc() + proc.start() + proc.join() + assert proc.exitcode == 0 + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(ExpectTestCase, 'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_filedescriptor.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_filedescriptor.py new file mode 100755 index 00000000000..d9164e1d50b --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_filedescriptor.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +from pexpect import fdpexpect +import unittest +from . import PexpectTestCase +import os + +class ExpectTestCase(PexpectTestCase.PexpectTestCase): + def setUp(self): + print(self.id()) + PexpectTestCase.PexpectTestCase.setUp(self) + + def test_fd (self): + fd = os.open ('TESTDATA.txt', os.O_RDONLY) + s = fdpexpect.fdspawn (fd) + s.expect(b'This is the end of test data:') + s.expect(pexpect.EOF) + self.assertEqual(s.before, b' END\n') + + def test_maxread (self): + fd = os.open ('TESTDATA.txt', os.O_RDONLY) + s = fdpexpect.fdspawn (fd) + s.maxread = 100 + s.expect('2') + s.expect ('This is the end of test data:') + s.expect (pexpect.EOF) + self.assertEqual(s.before, b' END\n') + + def test_fd_isalive (self): + fd = os.open ('TESTDATA.txt', os.O_RDONLY) + s = fdpexpect.fdspawn(fd) + assert s.isalive() + os.close(fd) + assert not s.isalive(), "Should not be alive after close()" + + def test_fd_isatty (self): + fd = os.open ('TESTDATA.txt', os.O_RDONLY) + s = fdpexpect.fdspawn (fd) + assert not s.isatty() + s.close() + + def test_fileobj(self): + f = open('TESTDATA.txt', 'r') + s = fdpexpect.fdspawn(f) # Should get the fileno from the file handle + s.expect('2') + s.close() + assert not s.isalive() + s.close() # Smoketest - should be able to call this again + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(ExpectTestCase, 'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_interact.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_interact.py new file mode 100755 index 00000000000..865353b7151 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_interact.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from __future__ import print_function +from __future__ import unicode_literals + +import os +import pexpect +import unittest +import sys +from . import PexpectTestCase + + +class InteractTestCase (PexpectTestCase.PexpectTestCase): + def setUp(self): + super(InteractTestCase, self).setUp() + self.env = env = os.environ.copy() + + # Ensure 'import pexpect' works in subprocess interact*.py + if 'PYTHONPATH' in env: + env['PYTHONPATH'] = os.pathsep.join((self.project_dir, + env['PYTHONPATH'])) + else: + env['PYTHONPATH'] = self.project_dir + + self.interact_py = ('{sys.executable} interact.py'.format(sys=sys)) + + def test_interact_escape(self): + " Ensure `escape_character' value exits interactive mode. " + p = pexpect.spawn(self.interact_py, timeout=5, env=self.env) + p.expect('READY') + p.sendcontrol(']') # chr(29), the default `escape_character' + # value of pexpect.interact(). + p.expect_exact('Escaped interact') + p.expect(pexpect.EOF) + assert not p.isalive() + assert p.exitstatus == 0 + + def test_interact_escape_None(self): + " Return only after Termination when `escape_character=None'. " + p = pexpect.spawn('{self.interact_py} --no-escape'.format(self=self), + timeout=5, env=self.env) + p.expect('READY') + p.sendcontrol(']') + p.expect('29<STOP>') + p.send('\x00') + if not os.environ.get('TRAVIS', None): + # on Travis-CI, we sometimes miss trailing stdout from the + # chain of child processes, not entirely sure why. So this + # is skipped on such systems. + p.expect('0<STOP>') + p.expect_exact('Escaped interact') + p.expect(pexpect.EOF) + assert not p.isalive() + assert p.exitstatus == 0 + + def test_interact_exit_unicode(self): + " Ensure subprocess receives utf8. " + p = pexpect.spawnu('{self.interact_py} --utf8'.format(self=self), + timeout=5, env=self.env) + p.expect('READY') + p.send('ɑ') # >>> map(ord, u'ɑ'.encode('utf8')) + p.expect('201<STOP>') # [201, 145] + p.expect('145<STOP>') + p.send('Β') # >>> map(ord, u'Β'.encode('utf8')) + p.expect('206<STOP>') # [206, 146] + p.expect('146<STOP>') + p.send('\x00') + if not os.environ.get('TRAVIS', None): + # on Travis-CI, we sometimes miss trailing stdout from the + # chain of child processes, not entirely sure why. So this + # is skipped on such systems. + p.expect('0<STOP>') + p.expect_exact('Escaped interact') + p.expect(pexpect.EOF) + assert not p.isalive() + assert p.exitstatus == 0 + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(InteractTestCase, 'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_isalive.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_isalive.py new file mode 100755 index 00000000000..cd79d09a4d3 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_isalive.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +import signal +import sys +import time +from . import PexpectTestCase + + +class IsAliveTestCase(PexpectTestCase.PexpectTestCase): + """Various tests for the running status of processes.""" + + def test_expect_wait(self): + """Ensure consistency in wait() and isalive().""" + p = pexpect.spawn('sleep 1') + assert p.isalive() + assert p.wait() == 0 + assert not p.isalive() + # In previous versions of ptyprocess/pexpect, calling wait() a second + # time would raise an exception, but not since v4.0 + assert p.wait() == 0 + + def test_expect_wait_after_termination(self): + """Ensure wait on a process terminated by kill -9.""" + p = pexpect.spawn('sleep 3') + assert p.isalive() + p.kill(9) + time.sleep(1) + + # when terminated, the exitstatus is None, but p.signalstatus + # and p.terminated reflects that the kill -9 nature. + assert p.wait() is None + assert p.signalstatus == 9 + assert p.terminated == True + assert not p.isalive() + + def test_signal_wait(self): + '''Test calling wait with a process terminated by a signal.''' + if not hasattr(signal, 'SIGALRM'): + return 'SKIP' + p = pexpect.spawn(sys.executable, ['alarm_die.py']) + p.wait() + assert p.exitstatus is None + self.assertEqual(p.signalstatus, signal.SIGALRM) + + def test_expect_isalive_dead_after_normal_termination (self): + p = pexpect.spawn('ls', timeout=15) + p.expect(pexpect.EOF) + assert not p.isalive() + + def test_expect_isalive_dead_after_SIGHUP(self): + p = pexpect.spawn('cat', timeout=5, ignore_sighup=False) + assert p.isalive() + force = False + if sys.platform.lower().startswith('sunos'): + # On Solaris (SmartOs), and only when executed from cron(1), SIGKILL + # is required to end the sub-process. This is done using force=True + force = True + assert p.terminate(force) == True + p.expect(pexpect.EOF) + assert not p.isalive() + + def test_expect_isalive_dead_after_SIGINT(self): + p = pexpect.spawn('cat', timeout=5) + assert p.isalive() + force = False + if sys.platform.lower().startswith('sunos'): + # On Solaris (SmartOs), and only when executed from cron(1), SIGKILL + # is required to end the sub-process. This is done using force=True + force = True + assert p.terminate(force) == True + p.expect(pexpect.EOF) + assert not p.isalive() + + def test_expect_isalive_dead_after_SIGKILL(self): + p = pexpect.spawn('cat', timeout=5) + assert p.isalive() + p.kill(9) + p.expect(pexpect.EOF) + assert not p.isalive() + + def test_forced_terminate(self): + p = pexpect.spawn(sys.executable, ['needs_kill.py']) + p.expect('READY') + assert p.terminate(force=True) == True + p.expect(pexpect.EOF) + assert not p.isalive() + +### Some platforms allow this. Some reset status after call to waitpid. +### probably not necessary, isalive() returns early when terminate is False. + def test_expect_isalive_consistent_multiple_calls (self): + '''This tests that multiple calls to isalive() return same value. + ''' + p = pexpect.spawn('cat') + assert p.isalive() + assert p.isalive() + p.sendeof() + p.expect(pexpect.EOF) + assert not p.isalive() + assert not p.isalive() + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(IsAliveTestCase, 'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_log.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_log.py new file mode 100755 index 00000000000..4ad225697d8 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_log.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +import os +import tempfile +from . import PexpectTestCase + +# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent +_CAT_EOF = b'^D\x08\x08' + +class TestCaseLog(PexpectTestCase.PexpectTestCase): + + def test_log (self): + log_message = 'This is a test.' + filename = tempfile.mktemp() + mylog = open(filename, 'wb') + p = pexpect.spawn('echo', [log_message]) + p.logfile = mylog + p.expect(pexpect.EOF) + p.logfile = None + mylog.close() + with open(filename, 'rb') as f: + lf = f.read() + os.unlink(filename) + self.assertEqual(lf.rstrip(), log_message.encode('ascii')) + + def test_log_logfile_read (self): + log_message = 'This is a test.' + filename = tempfile.mktemp() + mylog = open(filename, 'wb') + p = pexpect.spawn('cat') + p.logfile_read = mylog + p.sendline(log_message) + p.sendeof() + p.expect(pexpect.EOF) + p.logfile = None + mylog.close() + with open(filename, 'rb') as f: + lf = f.read() + os.unlink (filename) + lf = lf.replace(_CAT_EOF, b'') + self.assertEqual(lf, b'This is a test.\r\nThis is a test.\r\n') + + def test_log_logfile_send (self): + log_message = b'This is a test.' + filename = tempfile.mktemp() + mylog = open (filename, 'wb') + p = pexpect.spawn('cat') + p.logfile_send = mylog + p.sendline(log_message) + p.sendeof() + p.expect (pexpect.EOF) + p.logfile = None + mylog.close() + with open(filename, 'rb') as f: + lf = f.read() + os.unlink(filename) + lf = lf.replace(b'\x04', b'') + self.assertEqual(lf.rstrip(), log_message) + + def test_log_send_and_received (self): + + '''The logfile should have the test message three time -- once for the + data we sent. Once for the data that cat echos back as characters are + typed. And once for the data that cat prints after we send a linefeed + (sent by sendline). ''' + + log_message = 'This is a test.' + filename = tempfile.mktemp() + mylog = open(filename, 'wb') + p = pexpect.spawn('cat') + p.logfile = mylog + p.sendline(log_message) + p.sendeof() + p.expect (pexpect.EOF) + p.logfile = None + mylog.close() + with open(filename, 'rb') as f: + lf = f.read() + os.unlink(filename) + lf = lf.replace(b'\x04', b'').replace(_CAT_EOF, b'') + self.assertEqual(lf, + b'This is a test.\nThis is a test.\r\nThis is a test.\r\n') + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(TestCaseLog,'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_misc.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_misc.py new file mode 100755 index 00000000000..6052b6aee13 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_misc.py @@ -0,0 +1,373 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import unittest +import sys +import re +import signal +import time +import tempfile +import os + +import pexpect +from . import PexpectTestCase + +# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent +_CAT_EOF = b'^D\x08\x08' + + +if (sys.version_info[0] >= 3): + def _u(s): + return s.decode('utf-8') +else: + def _u(s): + return s + + +class TestCaseMisc(PexpectTestCase.PexpectTestCase): + + def test_isatty(self): + " Test isatty() is True after spawning process on most platforms. " + child = pexpect.spawn('cat') + if not child.isatty() and sys.platform.lower().startswith('sunos'): + if hasattr(unittest, 'SkipTest'): + raise unittest.SkipTest("Not supported on this platform.") + return 'skip' + assert child.isatty() + + def test_isatty_poll(self): + " Test isatty() is True after spawning process on most platforms. " + child = pexpect.spawn('cat', use_poll=True) + if not child.isatty() and sys.platform.lower().startswith('sunos'): + if hasattr(unittest, 'SkipTest'): + raise unittest.SkipTest("Not supported on this platform.") + return 'skip' + assert child.isatty() + + def test_read(self): + " Test spawn.read by calls of various size. " + child = pexpect.spawn('cat') + child.sendline("abc") + child.sendeof() + self.assertEqual(child.read(0), b'') + self.assertEqual(child.read(1), b'a') + self.assertEqual(child.read(1), b'b') + self.assertEqual(child.read(1), b'c') + self.assertEqual(child.read(2), b'\r\n') + remaining = child.read().replace(_CAT_EOF, b'') + self.assertEqual(remaining, b'abc\r\n') + + def test_read_poll(self): + " Test spawn.read by calls of various size. " + child = pexpect.spawn('cat', use_poll=True) + child.sendline("abc") + child.sendeof() + self.assertEqual(child.read(0), b'') + self.assertEqual(child.read(1), b'a') + self.assertEqual(child.read(1), b'b') + self.assertEqual(child.read(1), b'c') + self.assertEqual(child.read(2), b'\r\n') + remaining = child.read().replace(_CAT_EOF, b'') + self.assertEqual(remaining, b'abc\r\n') + + def test_read_poll_timeout(self): + " Test use_poll properly times out " + child = pexpect.spawn('sleep 5', use_poll=True) + with self.assertRaises(pexpect.TIMEOUT): + child.expect(pexpect.EOF, timeout=1) + + def test_readline_bin_echo(self): + " Test spawn('echo'). " + # given, + child = pexpect.spawn('echo', ['alpha', 'beta']) + + # exercise, + assert child.readline() == b'alpha beta' + child.crlf + + def test_readline(self): + " Test spawn.readline(). " + # when argument 0 is sent, nothing is returned. + # Otherwise the argument value is meaningless. + child = pexpect.spawn('cat', echo=False) + child.sendline("alpha") + child.sendline("beta") + child.sendline("gamma") + child.sendline("delta") + child.sendeof() + assert child.readline(0) == b'' + assert child.readline().rstrip() == b'alpha' + assert child.readline(1).rstrip() == b'beta' + assert child.readline(2).rstrip() == b'gamma' + assert child.readline().rstrip() == b'delta' + child.expect(pexpect.EOF) + assert not child.isalive() + assert child.exitstatus == 0 + + def test_iter(self): + " iterating over lines of spawn.__iter__(). " + child = pexpect.spawn('cat', echo=False) + child.sendline("abc") + child.sendline("123") + child.sendeof() + # Don't use ''.join() because we want to test __iter__(). + page = b'' + for line in child: + page += line + page = page.replace(_CAT_EOF, b'') + assert page == b'abc\r\n123\r\n' + + def test_readlines(self): + " reading all lines of spawn.readlines(). " + child = pexpect.spawn('cat', echo=False) + child.sendline("abc") + child.sendline("123") + child.sendeof() + page = b''.join(child.readlines()).replace(_CAT_EOF, b'') + assert page == b'abc\r\n123\r\n' + child.expect(pexpect.EOF) + assert not child.isalive() + assert child.exitstatus == 0 + + def test_write(self): + " write a character and return it in return. " + child = pexpect.spawn('cat', echo=False) + child.write('a') + child.write('\r') + self.assertEqual(child.readline(), b'a\r\n') + + def test_writelines(self): + " spawn.writelines() " + child = pexpect.spawn('cat') + # notice that much like file.writelines, we do not delimit by newline + # -- it is equivalent to calling write(''.join([args,])) + child.writelines(['abc', '123', 'xyz', '\r']) + child.sendeof() + line = child.readline() + assert line == b'abc123xyz\r\n' + + def test_eof(self): + " call to expect() after EOF is received raises pexpect.EOF " + child = pexpect.spawn('cat') + child.sendeof() + with self.assertRaises(pexpect.EOF): + child.expect('the unexpected') + + def test_with(self): + "spawn can be used as a context manager" + with pexpect.spawn(sys.executable + ' echo_w_prompt.py') as p: + p.expect('<in >') + p.sendline(b'alpha') + p.expect(b'<out>alpha') + assert p.isalive() + + assert not p.isalive() + + def test_terminate(self): + " test force terminate always succeeds (SIGKILL). " + child = pexpect.spawn('cat') + child.terminate(force=1) + assert child.terminated + + def test_sighup(self): + " validate argument `ignore_sighup=True` and `ignore_sighup=False`. " + getch = sys.executable + ' getch.py' + child = pexpect.spawn(getch, ignore_sighup=True) + child.expect('READY') + child.kill(signal.SIGHUP) + for _ in range(10): + if not child.isalive(): + self.fail('Child process should not have exited.') + time.sleep(0.1) + + child = pexpect.spawn(getch, ignore_sighup=False) + child.expect('READY') + child.kill(signal.SIGHUP) + for _ in range(10): + if not child.isalive(): + break + time.sleep(0.1) + else: + self.fail('Child process should have exited.') + + def test_bad_child_pid(self): + " assert bad condition error in isalive(). " + expect_errmsg = re.escape("isalive() encountered condition where ") + child = pexpect.spawn('cat') + child.terminate(force=1) + # Force an invalid state to test isalive + child.ptyproc.terminated = 0 + try: + with self.assertRaisesRegexp(pexpect.ExceptionPexpect, + ".*" + expect_errmsg): + child.isalive() + finally: + # Force valid state for child for __del__ + child.terminated = 1 + + def test_bad_arguments_suggest_fdpsawn(self): + " assert custom exception for spawn(int). " + expect_errmsg = "maybe you want to use fdpexpect.fdspawn" + with self.assertRaisesRegexp(pexpect.ExceptionPexpect, + ".*" + expect_errmsg): + pexpect.spawn(1) + + def test_bad_arguments_second_arg_is_list(self): + " Second argument to spawn, if used, must be only a list." + with self.assertRaises(TypeError): + pexpect.spawn('ls', '-la') + + with self.assertRaises(TypeError): + # not even a tuple, + pexpect.spawn('ls', ('-la',)) + + def test_read_after_close_raises_value_error(self): + " Calling read_nonblocking after close raises ValueError. " + # as read_nonblocking underlies all other calls to read, + # ValueError should be thrown for all forms of read. + with self.assertRaises(ValueError): + p = pexpect.spawn('cat') + p.close() + p.read_nonblocking() + + with self.assertRaises(ValueError): + p = pexpect.spawn('cat') + p.close() + p.read() + + with self.assertRaises(ValueError): + p = pexpect.spawn('cat') + p.close() + p.readline() + + with self.assertRaises(ValueError): + p = pexpect.spawn('cat') + p.close() + p.readlines() + + def test_isalive(self): + " check isalive() before and after EOF. (True, False) " + child = pexpect.spawn('cat') + assert child.isalive() is True + child.sendeof() + child.expect(pexpect.EOF) + assert child.isalive() is False + + def test_bad_type_in_expect(self): + " expect() does not accept dictionary arguments. " + child = pexpect.spawn('cat') + with self.assertRaises(TypeError): + child.expect({}) + + def test_cwd(self): + " check keyword argument `cwd=' of pexpect.run() " + tmp_dir = os.path.realpath(tempfile.gettempdir()) + default = pexpect.run('pwd') + pwd_tmp = pexpect.run('pwd', cwd=tmp_dir).rstrip() + assert default != pwd_tmp + assert tmp_dir == _u(pwd_tmp) + + def _test_searcher_as(self, searcher, plus=None): + # given, + given_words = ['alpha', 'beta', 'gamma', 'delta', ] + given_search = given_words + if searcher == pexpect.searcher_re: + given_search = [re.compile(word) for word in given_words] + if plus is not None: + given_search = given_search + [plus] + search_string = searcher(given_search) + basic_fmt = '\n {0}: {1}' + fmt = basic_fmt + if searcher is pexpect.searcher_re: + fmt = '\n {0}: re.compile({1})' + expected_output = '{0}:'.format(searcher.__name__) + idx = 0 + for word in given_words: + expected_output += fmt.format(idx, "'{0}'".format(word)) + idx += 1 + if plus is not None: + if plus == pexpect.EOF: + expected_output += basic_fmt.format(idx, 'EOF') + elif plus == pexpect.TIMEOUT: + expected_output += basic_fmt.format(idx, 'TIMEOUT') + + # exercise, + assert search_string.__str__() == expected_output + + def test_searcher_as_string(self): + " check searcher_string(..).__str__() " + self._test_searcher_as(pexpect.searcher_string) + + def test_searcher_as_string_with_EOF(self): + " check searcher_string(..).__str__() that includes EOF " + self._test_searcher_as(pexpect.searcher_string, plus=pexpect.EOF) + + def test_searcher_as_string_with_TIMEOUT(self): + " check searcher_string(..).__str__() that includes TIMEOUT " + self._test_searcher_as(pexpect.searcher_string, plus=pexpect.TIMEOUT) + + def test_searcher_re_as_string(self): + " check searcher_re(..).__str__() " + self._test_searcher_as(pexpect.searcher_re) + + def test_searcher_re_as_string_with_EOF(self): + " check searcher_re(..).__str__() that includes EOF " + self._test_searcher_as(pexpect.searcher_re, plus=pexpect.EOF) + + def test_searcher_re_as_string_with_TIMEOUT(self): + " check searcher_re(..).__str__() that includes TIMEOUT " + self._test_searcher_as(pexpect.searcher_re, plus=pexpect.TIMEOUT) + + def test_nonnative_pty_fork(self): + " test forced self.__fork_pty() and __pty_make_controlling_tty " + # given, + class spawn_ourptyfork(pexpect.spawn): + def _spawn(self, command, args=[], preexec_fn=None, + dimensions=None): + self.use_native_pty_fork = False + pexpect.spawn._spawn(self, command, args, preexec_fn, + dimensions) + + # exercise, + p = spawn_ourptyfork('cat', echo=False) + # verify, + p.sendline('abc') + p.expect('abc') + p.sendeof() + p.expect(pexpect.EOF) + assert not p.isalive() + + def test_exception_tb(self): + " test get_trace() filters away pexpect/__init__.py calls. " + p = pexpect.spawn('sleep 1') + try: + p.expect('BLAH') + except pexpect.ExceptionPexpect as e: + # get_trace should filter out frames in pexpect's own code + tb = e.get_trace() + # exercise, + assert 'raise ' not in tb + assert 'pexpect/__init__.py' not in tb + else: + assert False, "Should have raised an exception." + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(TestCaseMisc,'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_missing_command.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_missing_command.py new file mode 100755 index 00000000000..92e47335e5a --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_missing_command.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +from . import PexpectTestCase + +class MissingCommandTestCase (PexpectTestCase.PexpectTestCase): + def testMissingCommand(self): + try: + i = pexpect.spawn ('ZXQYQZX') + except Exception: + pass + else: + self.fail('Expected an Exception.') + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(MissingCommandTestCase,'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_performance.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_performance.py new file mode 100755 index 00000000000..63778af672f --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_performance.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from __future__ import print_function + +import unittest, time, sys +import platform +import pexpect +import re +from . import PexpectTestCase + +# This isn't exactly a unit test, but it fits in nicely with the rest of the tests. + +class PerformanceTestCase (PexpectTestCase.PexpectTestCase): + + '''Testing the performance of expect, with emphasis on wading through long + inputs. ''' + + if sys.version_info[0] >= 3: + @staticmethod + def _iter_n(n): + s = 'for n in range(1, %d+1): print(n)' % n + return s.encode('ascii') + + else: + @staticmethod + def _iter_n(n): + return 'for n in range(1, %d+1): print(n)' % n + + def plain_range(self, n): + e = pexpect.spawn('python', timeout=100) + self.assertEqual(e.expect(b'>>>'), 0) + e.sendline(self._iter_n(n)) + self.assertEqual(e.expect(br'\.{3}'), 0) + e.sendline(b'') + self.assertEqual(e.expect([b'inquisition', '%d' % n]), 1) + + def window_range(self, n): + e = pexpect.spawn('python', timeout=100) + self.assertEqual(e.expect(b'>>>'), 0) + e.sendline(self._iter_n(n)) + self.assertEqual(e.expect(r'\.{3}'), 0) + e.sendline(b'') + self.assertEqual(e.expect([b'inquisition', '%d' % n], searchwindowsize=20), 1) + + def exact_range(self, n): + e = pexpect.spawn('python', timeout=100) + self.assertEqual(e.expect_exact([b'>>>']), 0) + e.sendline(self._iter_n(n)) + self.assertEqual(e.expect_exact([b'...']), 0) + e.sendline(b'') + self.assertEqual(e.expect_exact([b'inquisition', '%d' % n],timeout=520), 1) + + def ewin_range(self, n): + e = pexpect.spawn('python', timeout=100) + self.assertEqual(e.expect_exact([b'>>>']), 0) + e.sendline(self._iter_n(n)) + self.assertEqual(e.expect_exact([b'...']), 0) + e.sendline(b'') + self.assertEqual(e.expect_exact([b'inquisition', '%d' % n], searchwindowsize=20), 1) + + def faster_range(self, n): + e = pexpect.spawn('python', timeout=100) + self.assertEqual(e.expect(b'>>>'), 0) + e.sendline(('list(range(1, %d+1))' % n).encode('ascii')) + self.assertEqual(e.expect([b'inquisition', '%d' % n]), 1) + + def test_100000(self): + if platform.python_implementation() == 'PyPy': + raise unittest.SkipTest("This test fails on PyPy because of REPL differences") + print() + start_time = time.time() + self.plain_range (100000) + print("100000 calls to plain_range:", (time.time() - start_time)) + start_time = time.time() + self.window_range(100000) + print("100000 calls to window_range:", (time.time() - start_time)) + start_time = time.time() + self.exact_range (100000) + print("100000 calls to exact_range:", (time.time() - start_time)) + start_time = time.time() + self.ewin_range (100000) + print("100000 calls to ewin_range:", (time.time() - start_time)) + start_time = time.time() + self.faster_range(100000) + print("100000 calls to faster_range:", (time.time() - start_time)) + + def test_large_stdout_stream(self): + e = pexpect.spawn('openssl rand -base64 {}'.format(1024*1024*25), searchwindowsize=1000) + resp = e.expect(['Password:', pexpect.EOF, pexpect.TIMEOUT]) + assert resp == 1 # index 1 == EOF + +if __name__ == "__main__": + unittest.main() + +suite = unittest.makeSuite(PerformanceTestCase,'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_pickling.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_pickling.py new file mode 100644 index 00000000000..6538677075a --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_pickling.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +import pickle +import unittest + +from pexpect import ExceptionPexpect + +class PickleTest(unittest.TestCase): + def test_picking(self): + e = ExceptionPexpect('Oh noes!') + clone = pickle.loads(pickle.dumps(e)) + self.assertEqual(e.value, clone.value) + +if __name__ == '__main__': + unittest.main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_popen_spawn.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_popen_spawn.py new file mode 100644 index 00000000000..fca7493d3be --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_popen_spawn.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import unittest +import subprocess + + +import pexpect +from pexpect.popen_spawn import PopenSpawn +from . import PexpectTestCase + + +class ExpectTestCase (PexpectTestCase.PexpectTestCase): + + def test_expect_basic(self): + p = PopenSpawn('cat', timeout=5) + p.sendline(b'Hello') + p.sendline(b'there') + p.sendline(b'Mr. Python') + p.expect(b'Hello') + p.expect(b'there') + p.expect(b'Mr. Python') + p.sendeof() + p.expect(pexpect.EOF) + + def test_expect_exact_basic(self): + p = PopenSpawn('cat', timeout=5) + p.sendline(b'Hello') + p.sendline(b'there') + p.sendline(b'Mr. Python') + p.expect_exact(b'Hello') + p.expect_exact(b'there') + p.expect_exact(b'Mr. Python') + p.sendeof() + p.expect_exact(pexpect.EOF) + + def test_expect(self): + the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'], + stdout=subprocess.PIPE).communicate()[0].rstrip() + p = PopenSpawn('ls -l /bin') + the_new_way = b'' + while 1: + i = p.expect([b'\n', pexpect.EOF]) + the_new_way = the_new_way + p.before + if i == 1: + break + the_new_way += b'\n' + the_new_way = the_new_way.rstrip() + assert the_old_way == the_new_way, len(the_old_way) - len(the_new_way) + + def test_expect_exact(self): + the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'], + stdout=subprocess.PIPE).communicate()[0].rstrip() + p = PopenSpawn('ls -l /bin') + the_new_way = b'' + while 1: + i = p.expect_exact([b'\n', pexpect.EOF]) + the_new_way = the_new_way + p.before + if i == 1: + break + the_new_way += b'\n' + the_new_way = the_new_way.rstrip() + + assert the_old_way == the_new_way, len(the_old_way) - len(the_new_way) + p = PopenSpawn('echo hello.?world') + i = p.expect_exact(b'.?') + self.assertEqual(p.before, b'hello') + self.assertEqual(p.after, b'.?') + + def test_expect_eof(self): + the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'], + stdout=subprocess.PIPE).communicate()[0].rstrip() + p = PopenSpawn('ls -l /bin') + # This basically tells it to read everything. Same as pexpect.run() + # function. + p.expect(pexpect.EOF) + the_new_way = p.before.rstrip() + assert the_old_way == the_new_way, len(the_old_way) - len(the_new_way) + + def test_expect_timeout(self): + p = PopenSpawn('cat', timeout=5) + p.expect(pexpect.TIMEOUT) # This tells it to wait for timeout. + self.assertEqual(p.after, pexpect.TIMEOUT) + + def test_unexpected_eof(self): + p = PopenSpawn('ls -l /bin') + try: + p.expect('_Z_XY_XZ') # Probably never see this in ls output. + except pexpect.EOF: + pass + else: + self.fail('Expected an EOF exception.') + + def test_bad_arg(self): + p = PopenSpawn('cat') + with self.assertRaisesRegexp(TypeError, '.*must be one of'): + p.expect(1) + with self.assertRaisesRegexp(TypeError, '.*must be one of'): + p.expect([1, b'2']) + with self.assertRaisesRegexp(TypeError, '.*must be one of'): + p.expect_exact(1) + with self.assertRaisesRegexp(TypeError, '.*must be one of'): + p.expect_exact([1, b'2']) + + def test_timeout_none(self): + p = PopenSpawn('echo abcdef', timeout=None) + p.expect('abc') + p.expect_exact('def') + p.expect(pexpect.EOF) + + def test_crlf(self): + p = PopenSpawn('echo alpha beta') + assert p.read() == b'alpha beta' + p.crlf + + def test_crlf_encoding(self): + p = PopenSpawn('echo alpha beta', encoding='utf-8') + assert p.read() == 'alpha beta' + p.crlf + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(ExpectTestCase, 'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_pxssh.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_pxssh.py new file mode 100644 index 00000000000..5f82302ebeb --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_pxssh.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +import os +import tempfile +import unittest + +from pexpect import pxssh + +class SSHTestBase(unittest.TestCase): + def setUp(self): + self.orig_path = os.environ.get('PATH') + fakessh_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'fakessh')) + os.environ['PATH'] = fakessh_dir + \ + ((os.pathsep + self.orig_path) if self.orig_path else '') + + def tearDown(self): + if self.orig_path: + os.environ['PATH'] = self.orig_path + else: + del os.environ['PATH'] + +class PxsshTestCase(SSHTestBase): + def test_fake_ssh(self): + ssh = pxssh.pxssh() + #ssh.logfile_read = sys.stdout # DEBUG + ssh.login('server', 'me', password='s3cret') + ssh.sendline('ping') + ssh.expect('pong', timeout=10) + assert ssh.prompt(timeout=10) + ssh.logout() + + def test_wrong_pw(self): + ssh = pxssh.pxssh() + try: + ssh.login('server', 'me', password='wr0ng') + except pxssh.ExceptionPxssh: + pass + else: + assert False, 'Password should have been refused' + + def test_failed_set_unique_prompt(self): + ssh = pxssh.pxssh() + ssh.set_unique_prompt = lambda: False + try: + ssh.login('server', 'me', password='s3cret', + auto_prompt_reset=True) + except pxssh.ExceptionPxssh: + pass + else: + assert False, 'should have raised exception, pxssh.ExceptionPxssh' + + def test_connection_refused(self): + ssh = pxssh.pxssh() + try: + ssh.login('noserver', 'me', password='s3cret') + except pxssh.ExceptionPxssh: + pass + else: + assert False, 'should have raised exception, pxssh.ExceptionPxssh' + + def test_ssh_tunnel_string(self): + ssh = pxssh.pxssh(debug_command_string=True) + tunnels = { 'local': ['2424:localhost:22'],'remote': ['2525:localhost:22'], + 'dynamic': [8888] } + confirmation_strings = 0 + confirmation_array = ['-R 2525:localhost:22','-L 2424:localhost:22','-D 8888'] + string = ssh.login('server', 'me', password='s3cret', ssh_tunnels=tunnels) + for confirmation in confirmation_array: + if confirmation in string: + confirmation_strings+=1 + + if confirmation_strings!=len(confirmation_array): + assert False, 'String generated from tunneling is incorrect.' + + def test_remote_ssh_tunnel_string(self): + ssh = pxssh.pxssh(debug_command_string=True) + tunnels = { 'local': ['2424:localhost:22'],'remote': ['2525:localhost:22'], + 'dynamic': [8888] } + confirmation_strings = 0 + confirmation_array = ['-R 2525:localhost:22','-L 2424:localhost:22','-D 8888'] + string = ssh.login('server', 'me', password='s3cret', ssh_tunnels=tunnels, spawn_local_ssh=False) + for confirmation in confirmation_array: + if confirmation in string: + confirmation_strings+=1 + + if confirmation_strings!=len(confirmation_array): + assert False, 'String generated from remote tunneling is incorrect.' + + def test_ssh_config_passing_string(self): + ssh = pxssh.pxssh(debug_command_string=True) + (temp_file,config_path) = tempfile.mkstemp() + string = ssh.login('server', 'me', password='s3cret', spawn_local_ssh=False, ssh_config=config_path) + if not '-F '+config_path in string: + assert False, 'String generated from SSH config passing is incorrect.' + + def test_ssh_key_string(self): + ssh = pxssh.pxssh(debug_command_string=True) + confirmation_strings = 0 + confirmation_array = [' -A'] + string = ssh.login('server', 'me', password='s3cret', ssh_key=True) + for confirmation in confirmation_array: + if confirmation in string: + confirmation_strings+=1 + + if confirmation_strings!=len(confirmation_array): + assert False, 'String generated from forcing the SSH agent sock is incorrect.' + + confirmation_strings = 0 + (temp_file,ssh_key) = tempfile.mkstemp() + confirmation_array = [' -i '+ssh_key] + string = ssh.login('server', 'me', password='s3cret', ssh_key=ssh_key) + for confirmation in confirmation_array: + if confirmation in string: + confirmation_strings+=1 + + if confirmation_strings!=len(confirmation_array): + assert False, 'String generated from adding an SSH key is incorrect.' + + +if __name__ == '__main__': + unittest.main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_replwrap.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_replwrap.py new file mode 100644 index 00000000000..d0fe8e21753 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_replwrap.py @@ -0,0 +1,114 @@ +import platform +import unittest +import re +import os + +import pexpect +from pexpect import replwrap + +skip_pypy = "This test fails on PyPy because of REPL differences" + + +class REPLWrapTestCase(unittest.TestCase): + def setUp(self): + super(REPLWrapTestCase, self).setUp() + self.save_ps1 = os.getenv('PS1', r'\$') + self.save_ps2 = os.getenv('PS2', '>') + os.putenv('PS1', r'\$') + os.putenv('PS2', '>') + + def tearDown(self): + super(REPLWrapTestCase, self).tearDown() + os.putenv('PS1', self.save_ps1) + os.putenv('PS2', self.save_ps2) + + def test_bash(self): + bash = replwrap.bash() + res = bash.run_command("time") + assert 'real' in res, res + + def test_pager_as_cat(self): + " PAGER is set to cat, to prevent timeout in ``man sleep``. " + bash = replwrap.bash() + res = bash.run_command('man sleep', timeout=5) + assert 'SLEEP' in res, res + + def test_bash_env(self): + """env, which displays PS1=..., should not mess up finding the prompt. + """ + bash = replwrap.bash() + res = bash.run_command("env") + self.assertIn('PS1', res) + res = bash.run_command("echo $HOME") + assert res.startswith('/'), res + + def test_long_running_multiline(self): + " ensure the default timeout is used for multi-line commands. " + bash = replwrap.bash() + res = bash.run_command("echo begin\r\nsleep 2\r\necho done") + self.assertEqual(res.strip().splitlines(), ['begin', 'done']) + + def test_long_running_continuation(self): + " also ensure timeout when used within continuation prompts. " + bash = replwrap.bash() + # The two extra '\\' in the following expression force a continuation + # prompt: + # $ echo begin\ + # + ; + # $ sleep 2 + # $ echo done + res = bash.run_command("echo begin\\\n;sleep 2\r\necho done") + self.assertEqual(res.strip().splitlines(), ['begin', 'done']) + + def test_multiline(self): + bash = replwrap.bash() + res = bash.run_command("echo '1 2\n3 4'") + self.assertEqual(res.strip().splitlines(), ['1 2', '3 4']) + + # Should raise ValueError if input is incomplete + try: + bash.run_command("echo '5 6") + except ValueError: + pass + else: + assert False, "Didn't raise ValueError for incomplete input" + + # Check that the REPL was reset (SIGINT) after the incomplete input + res = bash.run_command("echo '1 2\n3 4'") + self.assertEqual(res.strip().splitlines(), ['1 2', '3 4']) + + def test_existing_spawn(self): + child = pexpect.spawn("bash", timeout=5, echo=False, encoding='utf-8') + repl = replwrap.REPLWrapper(child, re.compile('[$#]'), + "PS1='{0}' PS2='{1}' " + "PROMPT_COMMAND=''") + + res = repl.run_command("echo $HOME") + assert res.startswith('/'), res + + def test_python(self): + if platform.python_implementation() == 'PyPy': + raise unittest.SkipTest(skip_pypy) + + p = replwrap.python() + res = p.run_command('4+7') + assert res.strip() == '11' + + res = p.run_command('for a in range(3): print(a)\n') + assert res.strip().splitlines() == ['0', '1', '2'] + + def test_no_change_prompt(self): + if platform.python_implementation() == 'PyPy': + raise unittest.SkipTest(skip_pypy) + + child = pexpect.spawn('python', echo=False, timeout=5, encoding='utf-8') + # prompt_change=None should mean no prompt change + py = replwrap.REPLWrapper(child, u">>> ", prompt_change=None, + continuation_prompt=u"... ") + assert py.prompt == ">>> " + + res = py.run_command("for a in range(3): print(a)\n") + assert res.strip().splitlines() == ['0', '1', '2'] + +if __name__ == '__main__': + unittest.main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_repr.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_repr.py new file mode 100644 index 00000000000..ac337160d7e --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_repr.py @@ -0,0 +1,37 @@ +""" Test __str__ methods. """ +import pexpect + +from . import PexpectTestCase + + +class TestCaseMisc(PexpectTestCase.PexpectTestCase): + + def test_str_spawnu(self): + """ Exercise spawnu.__str__() """ + # given, + p = pexpect.spawnu('cat') + # exercise, + value = str(p) + # verify + assert isinstance(value, str) + + def test_str_spawn(self): + """ Exercise spawn.__str__() """ + # given, + p = pexpect.spawn('cat') + # exercise, + value = str(p) + # verify + assert isinstance(value, str) + + def test_str_before_spawn(self): + """ Exercise derived spawn.__str__() """ + # given, + child = pexpect.spawn(None, None) + child.read_nonblocking = lambda size, timeout: b'' + try: + child.expect('alpha', timeout=0.1) + except pexpect.TIMEOUT as e: + str(e) # Smoketest + else: + assert False, 'TIMEOUT exception expected. No exception raised.' diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_run.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_run.py new file mode 100755 index 00000000000..1b3c92ff602 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_run.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python +# encoding: utf-8 +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +import subprocess +import tempfile +import sys +import os +from . import PexpectTestCase + +unicode_type = str if pexpect.PY3 else unicode + + +def timeout_callback(values): + if values["event_count"] > 3: + return 1 + return 0 + + +def function_events_callback(values): + try: + previous_echoed = (values["child_result_list"][-1] + .decode().split("\n")[-2].strip()) + if previous_echoed.endswith("stage-1"): + return "echo stage-2\n" + elif previous_echoed.endswith("stage-2"): + return "echo stage-3\n" + elif previous_echoed.endswith("stage-3"): + return "exit\n" + else: + raise Exception("Unexpected output {0}".format(previous_echoed)) + except IndexError: + return "echo stage-1\n" + + +class RunFuncTestCase(PexpectTestCase.PexpectTestCase): + runfunc = staticmethod(pexpect.run) + cr = b'\r' + empty = b'' + prep_subprocess_out = staticmethod(lambda x: x) + + def setUp(self): + fd, self.rcfile = tempfile.mkstemp() + os.write(fd, b'PS1=GO: \n') + os.close(fd) + super(RunFuncTestCase, self).setUp() + + def tearDown(self): + os.unlink(self.rcfile) + super(RunFuncTestCase, self).tearDown() + + def test_run_exit(self): + (data, exitstatus) = self.runfunc('python exit1.py', withexitstatus=1) + assert exitstatus == 1, "Exit status of 'python exit1.py' should be 1." + + def test_run(self): + the_old_way = subprocess.Popen( + args=['uname', '-m', '-n'], + stdout=subprocess.PIPE + ).communicate()[0].rstrip() + + (the_new_way, exitstatus) = self.runfunc( + 'uname -m -n', withexitstatus=1) + the_new_way = the_new_way.replace(self.cr, self.empty).rstrip() + + self.assertEqual(self.prep_subprocess_out(the_old_way), the_new_way) + self.assertEqual(exitstatus, 0) + + def test_run_callback(self): + # TODO it seems like this test could block forever if run fails... + events = {pexpect.TIMEOUT: timeout_callback} + self.runfunc("cat", timeout=1, events=events) + + def test_run_bad_exitstatus(self): + (the_new_way, exitstatus) = self.runfunc( + 'ls -l /najoeufhdnzkxjd', withexitstatus=1) + assert exitstatus != 0 + + def test_run_event_as_string(self): + events = [ + # second match on 'abc', echo 'def' + ('abc\r\n.*GO:', 'echo "def"\n'), + # final match on 'def': exit + ('def\r\n.*GO:', 'exit\n'), + # first match on 'GO:' prompt, echo 'abc' + ('GO:', 'echo "abc"\n') + ] + + (data, exitstatus) = pexpect.run( + 'bash --rcfile {0}'.format(self.rcfile), + withexitstatus=True, + events=events, + timeout=10) + assert exitstatus == 0 + + def test_run_event_as_function(self): + events = [ + ('GO:', function_events_callback) + ] + + (data, exitstatus) = pexpect.run( + 'bash --rcfile {0}'.format(self.rcfile), + withexitstatus=True, + events=events, + timeout=10) + assert exitstatus == 0 + + def test_run_event_as_method(self): + events = [ + ('GO:', self._method_events_callback) + ] + + (data, exitstatus) = pexpect.run( + 'bash --rcfile {0}'.format(self.rcfile), + withexitstatus=True, + events=events, + timeout=10) + assert exitstatus == 0 + + def test_run_event_typeerror(self): + events = [('GO:', -1)] + with self.assertRaises(TypeError): + pexpect.run('bash --rcfile {0}'.format(self.rcfile), + withexitstatus=True, + events=events, + timeout=10) + + def _method_events_callback(self, values): + try: + previous_echoed = (values["child_result_list"][-1].decode() + .split("\n")[-2].strip()) + if previous_echoed.endswith("foo1"): + return "echo foo2\n" + elif previous_echoed.endswith("foo2"): + return "echo foo3\n" + elif previous_echoed.endswith("foo3"): + return "exit\n" + else: + raise Exception("Unexpected output {0!r}" + .format(previous_echoed)) + except IndexError: + return "echo foo1\n" + + +class RunUnicodeFuncTestCase(RunFuncTestCase): + runfunc = staticmethod(pexpect.runu) + cr = b'\r'.decode('ascii') + empty = b''.decode('ascii') + prep_subprocess_out = staticmethod(lambda x: x.decode('utf-8', 'replace')) + + def test_run_unicode(self): + if pexpect.PY3: + char = chr(254) # þ + pattern = '<in >' + else: + char = unichr(254) # analysis:ignore + pattern = '<in >'.decode('ascii') + + def callback(values): + if values['event_count'] == 0: + return char + '\n' + else: + return True # Stop the child process + + output = pexpect.runu(sys.executable + ' echo_w_prompt.py', + env={'PYTHONIOENCODING': 'utf-8'}, + events={pattern: callback}) + assert isinstance(output, unicode_type), type(output) + assert ('<out>' + char) in output, output + +if __name__ == '__main__': + unittest.main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_run_out_of_pty.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_run_out_of_pty.py new file mode 100755 index 00000000000..309014761df --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_run_out_of_pty.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +from . import PexpectTestCase + +class ExpectTestCase(PexpectTestCase.PexpectTestCase): + # This takes too long to run and isn't all that interesting of a test. + def OFF_test_run_out_of_pty (self): + '''This assumes that the tested platform has < 10000 pty devices. + This test currently does not work under Solaris. + Under Solaris it runs out of file descriptors first and + ld.so starts to barf: + ld.so.1: pt_chmod: fatal: /usr/lib/libc.so.1: Too many open files + ''' + plist=[] + for count in range (0,10000): + try: + plist.append (pexpect.spawn('ls -l')) + except pexpect.ExceptionPexpect: + for c in range (0, count): + plist[c].close() + return + except Exception: + err = sys.exc_info()[1] + self.fail ('Expected ExceptionPexpect. ' + str(err)) + self.fail ('Could not run out of pty devices. This may be OK.') + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(ExpectTestCase,'test') + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_screen.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_screen.py new file mode 100755 index 00000000000..2429e57a90a --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_screen.py @@ -0,0 +1,287 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +import sys + +from pexpect import screen +import unittest +from . import PexpectTestCase + +PY3 = (sys.version_info[0] >= 3) + +fill1_target='XXXXXXXXXX\n' + \ +'XOOOOOOOOX\n' + \ +'XO::::::OX\n' + \ +'XO:oooo:OX\n' + \ +'XO:o..o:OX\n' + \ +'XO:o..o:OX\n' + \ +'XO:oooo:OX\n' + \ +'XO::::::OX\n' + \ +'XOOOOOOOOX\n' + \ +'XXXXXXXXXX' +fill2_target = 'XXXXXXXXXXX\n' + \ +'XOOOOOOOOOX\n' + \ +'XO:::::::OX\n' + \ +'XO:ooooo:OX\n' + \ +'XO:o...o:OX\n' + \ +'XO:o.+.o:OX\n' + \ +'XO:o...o:OX\n' + \ +'XO:ooooo:OX\n' + \ +'XO:::::::OX\n' + \ +'XOOOOOOOOOX\n' + \ +'XXXXXXXXXXX' +put_target = '\\.3.5.7.9/\n' + \ +'.........2\n' + \ +'3.........\n' + \ +'.........4\n' + \ +'5...\\/....\n' + \ +'..../\\...6\n' + \ +'7.........\n' + \ +'.........8\n' + \ +'9.........\n' + \ +'/2.4.6.8.\\' +scroll_target = '\\.3.5.7.9/\n' + \ +'\\.3.5.7.9/\n' + \ +'\\.3.5.7.9/\n' + \ +'\\.3.5.7.9/\n' + \ +'5...\\/....\n' + \ +'..../\\...6\n' + \ +'/2.4.6.8.\\\n' + \ +'/2.4.6.8.\\\n' + \ +'/2.4.6.8.\\\n' + \ +'/2.4.6.8.\\' +insert_target = 'ZXZZZZZZXZ\n' +\ +'.........2\n' +\ +'3.........\n' +\ +'.........4\n' +\ +'Z5...\\/...\n' +\ +'..../Z\\...\n' +\ +'7.........\n' +\ +'.........8\n' +\ +'9.........\n' +\ +'ZZ/2.4.6ZZ' +get_region_target = ['......', '.\\/...', './\\...', '......'] + +unicode_box_unicode_result = u'\u2554\u2557\n\u255A\u255D' +unicode_box_pretty_result = u'''\ ++--+ +|\u2554\u2557| +|\u255A\u255D| ++--+ +''' +unicode_box_ascii_bytes_result = b'??\n??' +unicode_box_cp437_bytes_result = b'\xc9\xbb\n\xc8\xbc' +unicode_box_utf8_bytes_result = b'\xe2\x95\x94\xe2\x95\x97\n\xe2\x95\x9a\xe2\x95\x9d' + +class screenTestCase (PexpectTestCase.PexpectTestCase): + def make_screen_with_put (self): + s = screen.screen(10,10) + s.fill ('.') + for r in range (1,s.rows + 1): + if r % 2: + s.put_abs (r, 1, str(r)) + else: + s.put_abs (r, s.cols, str(r)) + for c in range (1,s.cols + 1): + if c % 2: + s.put_abs (1, c, str(c)) + else: + s.put_abs (s.rows, c, str(c)) + s.put_abs(1,1, '\\') + s.put_abs(1,s.cols, '/') + s.put_abs(s.rows,1,'/') + s.put_abs(s.rows, s.cols, '\\') + s.put_abs(5,5,'\\') + s.put_abs(5,6,'/') + s.put_abs(6,5,'/') + s.put_abs(6,6,'\\') + return s + + def test_fill (self): + s = screen.screen (10,10) + s.fill_region (10,1,1,10,'X') + s.fill_region (2,2,9,9,'O') + s.fill_region (8,8,3,3,':') + s.fill_region (4,7,7,4,'o') + s.fill_region (6,5,5,6,'.') + assert str(s) == fill1_target + + s = screen.screen (11,11) + s.fill_region (1,1,11,11,'X') + s.fill_region (2,2,10,10,'O') + s.fill_region (9,9,3,3,':') + s.fill_region (4,8,8,4,'o') + s.fill_region (7,5,5,7,'.') + s.fill_region (6,6,6,6,'+') + assert str(s) == fill2_target + def test_put (self): + s = self.make_screen_with_put() + assert str(s) == put_target + def test_get_region (self): + s = self.make_screen_with_put() + r = s.get_region (4,4,7,9) + assert r == get_region_target + + def test_cursor_save (self): + s = self.make_screen_with_put() + s.cursor_home (5,5) + c = s.get() + s.cursor_save() + s.cursor_home() + s.cursor_forward() + s.cursor_down() + s.cursor_unsave() + assert s.cur_r == 5 and s.cur_c == 5 + assert c == s.get() + def test_scroll (self): + s = self.make_screen_with_put() + s.scroll_screen_rows (1,4) + s.scroll_down(); s.scroll_down(); s.scroll_down() + s.scroll_down(); s.scroll_down(); s.scroll_down() + s.scroll_screen_rows (7,10) + s.scroll_up(); s.scroll_up(); s.scroll_up() + s.scroll_up(); s.scroll_up(); s.scroll_up() + assert str(s) == scroll_target + def test_insert (self): + s = self.make_screen_with_put() + s.insert_abs (10,1,'Z') + s.insert_abs (1,1,'Z') + s.insert_abs (1,1,'Z') + s.insert_abs (1,1,'Z') + s.insert_abs (1,1,'Z') + s.insert_abs (1,1,'Z') + s.insert_abs (10,1,'Z') + s.insert_abs (1,1,'Z') + s.insert_abs (1,1,'Z') + s.insert_abs (5,1,'Z') + s.insert_abs (6,6,'Z') + s.cursor_home (1,1) # Also test relative insert. + s.insert ('Z') + s.insert ('Z') + s.insert ('Z') + s.insert ('Z') + s.insert_abs (1,8,'X') + s.insert_abs (1,2,'X') + s.insert_abs (10,9,'Z') + s.insert_abs (10,9,'Z') + assert str(s) == insert_target + + def make_screen_with_box_unicode(self, *args, **kwargs): + '''Creates a screen containing a box drawn using double-line + line drawing characters. The characters are fed in as + unicode. ''' + s = screen.screen (2,2,*args,**kwargs) + s.put_abs (1,1,u'\u2554') + s.put_abs (1,2,u'\u2557') + s.put_abs (2,1,u'\u255A') + s.put_abs (2,2,u'\u255D') + return s + + def make_screen_with_box_cp437(self, *args, **kwargs): + '''Creates a screen containing a box drawn using double-line + line drawing characters. The characters are fed in as + CP437. ''' + s = screen.screen (2,2,*args,**kwargs) + s.put_abs (1,1,b'\xc9') + s.put_abs (1,2,b'\xbb') + s.put_abs (2,1,b'\xc8') + s.put_abs (2,2,b'\xbc') + return s + + def make_screen_with_box_utf8(self, *args, **kwargs): + '''Creates a screen containing a box drawn using double-line + line drawing characters. The characters are fed in as + UTF-8. ''' + s = screen.screen (2,2,*args,**kwargs) + s.put_abs (1,1,b'\xe2\x95\x94') + s.put_abs (1,2,b'\xe2\x95\x97') + s.put_abs (2,1,b'\xe2\x95\x9a') + s.put_abs (2,2,b'\xe2\x95\x9d') + return s + + def test_unicode_ascii (self): + # With the default encoding set to ASCII, we should still be + # able to feed in unicode strings and get them back out: + s = self.make_screen_with_box_unicode('ascii') + if PY3: + assert str(s) == unicode_box_unicode_result + else: + assert unicode(s) == unicode_box_unicode_result + # And we should still get something for Python 2 str(), though + # it might not be very useful + str(s) + + assert s.pretty() == unicode_box_pretty_result + + def test_decoding_errors(self): + # With strict error handling, it should reject bytes it can't decode + with self.assertRaises(UnicodeDecodeError): + self.make_screen_with_box_cp437('ascii', 'strict') + + # replace should turn them into unicode replacement characters, U+FFFD + s = self.make_screen_with_box_cp437('ascii', 'replace') + expected = u'\ufffd\ufffd\n\ufffd\ufffd' + if PY3: + assert str(s) == expected + else: + assert unicode(s) == expected + + def test_unicode_cp437 (self): + # Verify decoding from and re-encoding to CP437. + s = self.make_screen_with_box_cp437('cp437','strict') + if PY3: + assert str(s) == unicode_box_unicode_result + else: + assert unicode(s) == unicode_box_unicode_result + assert str(s) == unicode_box_cp437_bytes_result + assert s.pretty() == unicode_box_pretty_result + + def test_unicode_utf8 (self): + # Verify decoding from and re-encoding to UTF-8. + s = self.make_screen_with_box_utf8('utf-8','strict') + if PY3: + assert str(s) == unicode_box_unicode_result + else: + assert unicode(s) == unicode_box_unicode_result + assert str(s) == unicode_box_utf8_bytes_result + assert s.pretty() == unicode_box_pretty_result + + def test_no_bytes(self): + s = screen.screen(2, 2, encoding=None) + s.put_abs(1, 1, u'A') + s.put_abs(2, 2, u'D') + + with self.assertRaises(TypeError): + s.put_abs(1, 2, b'B') + + if PY3: + assert str(s) == u'A \n D' + else: + assert unicode(s) == u'A \n D' + # This will still work if it's limited to ascii + assert str(s) == b'A \n D' + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(screenTestCase,'test') + + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_socket.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_socket.py new file mode 100644 index 00000000000..21648f4a0f6 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_socket.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +from pexpect import fdpexpect +import unittest +from . import PexpectTestCase +import multiprocessing +import os +import signal +import socket +import time +import errno + + +class SocketServerError(Exception): + pass + + +class ExpectTestCase(PexpectTestCase.PexpectTestCase): + + def setUp(self): + print(self.id()) + PexpectTestCase.PexpectTestCase.setUp(self) + self.host = '127.0.0.1' + self.port = 49152 + 10000 + self.motd = b"""\ +------------------------------------------------------------------------------ +* Welcome to the SOCKET UNIT TEST code! * +------------------------------------------------------------------------------ +* * +* This unit test code is our best effort at testing the ability of the * +* pexpect library to handle sockets. We need some text to test buffer size * +* handling. * +* * +* A page is 1024 bytes or 1K. 80 x 24 = 1920. So a standard terminal window * +* contains more than one page. We actually want more than a page for our * +* tests. * +* * +* This is the twelfth line, and we need 24. So we need a few more paragraphs.* +* We can keep them short and just put lines between them. * +* * +* The 80 x 24 terminal size comes from the ancient past when computers were * +* only able to display text in cuneiform writing. * +* * +* The cunieform writing system used the edge of a reed to make marks on clay * +* tablets. * +* * +* It was the forerunner of the style of handwriting used by doctors to write * +* prescriptions. Thus the name: pre (before) script (writing) ion (charged * +* particle). * +------------------------------------------------------------------------------ +""".replace(b'\n', b'\n\r') + b"\r\n" + self.prompt1 = b'Press Return to continue:' + self.prompt2 = b'Rate this unit test>' + self.prompt3 = b'Press X to exit:' + self.enter = b'\r\n' + self.exit = b'X\r\n' + self.server_up = multiprocessing.Event() + self.server_process = multiprocessing.Process(target=self.socket_server, args=(self.server_up,)) + self.server_process.daemon = True + self.server_process.start() + counter = 0 + while not self.server_up.is_set(): + time.sleep(0.250) + counter += 1 + if counter > (10 / 0.250): + raise SocketServerError("Could not start socket server") + + def tearDown(self): + os.kill(self.server_process.pid, signal.SIGINT) + self.server_process.join(timeout=5.0) + PexpectTestCase.PexpectTestCase.tearDown(self) + + def socket_server(self, server_up): + sock = None + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((self.host, self.port)) + sock.listen(5) + server_up.set() + while True: + (conn, addr) = sock.accept() + conn.send(self.motd) + conn.send(self.prompt1) + result = conn.recv(1024) + if result != self.enter: + break + conn.send(self.prompt2) + result = conn.recv(1024) + if result != self.enter: + break + conn.send(self.prompt3) + result = conn.recv(1024) + if result.startswith(self.exit[0]): + conn.shutdown(socket.SHUT_RDWR) + conn.close() + except KeyboardInterrupt: + pass + if sock is not None: + try: + sock.shutdown(socket.SHUT_RDWR) + sock.close() + except socket.error: + pass + exit(0) + + def socket_fn(self, timed_out, all_read): + result = 0 + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock, timeout=10) + # Get all data from server + session.read_nonblocking(size=4096) + all_read.set() + # This read should timeout + session.read_nonblocking(size=4096) + except pexpect.TIMEOUT: + timed_out.set() + result = errno.ETIMEDOUT + exit(result) + + def test_socket(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock.fileno(), timeout=10) + session.expect(self.prompt1) + self.assertEqual(session.before, self.motd) + session.send(self.enter) + session.expect(self.prompt2) + session.send(self.enter) + session.expect(self.prompt3) + session.send(self.exit) + session.expect(pexpect.EOF) + self.assertEqual(session.before, b'') + + def test_socket_with_write(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock.fileno(), timeout=10) + session.expect(self.prompt1) + self.assertEqual(session.before, self.motd) + session.write(self.enter) + session.expect(self.prompt2) + session.write(self.enter) + session.expect(self.prompt3) + session.write(self.exit) + session.expect(pexpect.EOF) + self.assertEqual(session.before, b'') + + def test_not_int(self): + with self.assertRaises(pexpect.ExceptionPexpect): + session = fdpexpect.fdspawn('bogus', timeout=10) + + def test_not_file_descriptor(self): + with self.assertRaises(pexpect.ExceptionPexpect): + session = fdpexpect.fdspawn(-1, timeout=10) + + def test_timeout(self): + with self.assertRaises(pexpect.TIMEOUT): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock, timeout=10) + session.expect(b'Bogus response') + + def test_interrupt(self): + timed_out = multiprocessing.Event() + all_read = multiprocessing.Event() + test_proc = multiprocessing.Process(target=self.socket_fn, args=(timed_out, all_read)) + test_proc.daemon = True + test_proc.start() + while not all_read.is_set(): + time.sleep(1.0) + os.kill(test_proc.pid, signal.SIGWINCH) + while not timed_out.is_set(): + time.sleep(1.0) + test_proc.join(timeout=5.0) + self.assertEqual(test_proc.exitcode, errno.ETIMEDOUT) + + def test_multiple_interrupts(self): + timed_out = multiprocessing.Event() + all_read = multiprocessing.Event() + test_proc = multiprocessing.Process(target=self.socket_fn, args=(timed_out, all_read)) + test_proc.daemon = True + test_proc.start() + while not all_read.is_set(): + time.sleep(1.0) + while not timed_out.is_set(): + os.kill(test_proc.pid, signal.SIGWINCH) + time.sleep(1.0) + test_proc.join(timeout=5.0) + self.assertEqual(test_proc.exitcode, errno.ETIMEDOUT) + + def test_maxread(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock.fileno(), timeout=10) + session.maxread = 1100 + session.expect(self.prompt1) + self.assertEqual(session.before, self.motd) + session.send(self.enter) + session.expect(self.prompt2) + session.send(self.enter) + session.expect(self.prompt3) + session.send(self.exit) + session.expect(pexpect.EOF) + self.assertEqual(session.before, b'') + + def test_fd_isalive(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock.fileno(), timeout=10) + assert session.isalive() + sock.close() + assert not session.isalive(), "Should not be alive after close()" + + def test_fd_isalive_poll(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock.fileno(), timeout=10, use_poll=True) + assert session.isalive() + sock.close() + assert not session.isalive(), "Should not be alive after close()" + + def test_fd_isatty(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock.fileno(), timeout=10) + assert not session.isatty() + session.close() + + def test_fd_isatty_poll(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock.fileno(), timeout=10, use_poll=True) + assert not session.isatty() + session.close() + + def test_fileobj(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = fdpexpect.fdspawn(sock, timeout=10) # Should get the fileno from the socket + session.expect(self.prompt1) + session.close() + assert not session.isalive() + session.close() # Smoketest - should be able to call this again + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(ExpectTestCase, 'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_timeout_pattern.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_timeout_pattern.py new file mode 100755 index 00000000000..5f610ef03ed --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_timeout_pattern.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +from __future__ import with_statement # bring 'with' stmt to py25 +import pexpect +import unittest +from . import PexpectTestCase +import sys + +class Exp_TimeoutTestCase(PexpectTestCase.PexpectTestCase): + def test_matches_exp_timeout (self): + '''This tests that we can raise and catch TIMEOUT. + ''' + try: + raise pexpect.TIMEOUT("TIMEOUT match test") + except pexpect.TIMEOUT: + pass + #print "Correctly caught TIMEOUT when raising TIMEOUT." + else: + self.fail('TIMEOUT not caught by an except TIMEOUT clause.') + + def test_pattern_printout (self): + '''Verify that a TIMEOUT returns the proper patterns it is trying to match against. + Make sure it is returning the pattern from the correct call.''' + try: + p = pexpect.spawn('cat') + p.sendline('Hello') + p.expect('Hello') + p.expect('Goodbye',timeout=5) + except pexpect.TIMEOUT: + assert p.match_index == None + else: + self.fail("Did not generate a TIMEOUT exception.") + + def test_exp_timeout_notThrown (self): + '''Verify that a TIMEOUT is not thrown when we match what we expect.''' + try: + p = pexpect.spawn('cat') + p.sendline('Hello') + p.expect('Hello') + except pexpect.TIMEOUT: + self.fail("TIMEOUT caught when it shouldn't be raised because we match the proper pattern.") + + def test_stacktraceMunging (self): + '''Verify that the stack trace returned with a TIMEOUT instance does not contain references to pexpect.''' + try: + p = pexpect.spawn('cat') + p.sendline('Hello') + p.expect('Goodbye',timeout=5) + except pexpect.TIMEOUT: + err = sys.exc_info()[1] + if err.get_trace().count("pexpect/__init__.py") != 0: + self.fail("The TIMEOUT get_trace() referenced pexpect.py. " + "It should only reference the caller.\n" + err.get_trace()) + + def test_correctStackTrace (self): + '''Verify that the stack trace returned with a TIMEOUT instance correctly handles function calls.''' + def nestedFunction (spawnInstance): + spawnInstance.expect("junk", timeout=3) + + try: + p = pexpect.spawn('cat') + p.sendline('Hello') + nestedFunction(p) + except pexpect.TIMEOUT: + err = sys.exc_info()[1] + if err.get_trace().count("nestedFunction") == 0: + self.fail("The TIMEOUT get_trace() did not show the call " + "to the nestedFunction function.\n" + str(err) + "\n" + + err.get_trace()) + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(Exp_TimeoutTestCase,'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_unicode.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_unicode.py new file mode 100644 index 00000000000..9b5b988a497 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_unicode.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import platform +import tempfile +import sys +import time + +import pexpect +import unittest +from . import PexpectTestCase + +# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent +_CAT_EOF = '^D\x08\x08' + +class UnicodeTests(PexpectTestCase.PexpectTestCase): + def test_expect_basic (self): + p = pexpect.spawnu('cat') + p.sendline('Hello') + p.sendline('there') + p.sendline('Mr. þython') # þ is more like th than p, but never mind + p.expect('Hello') + p.expect('there') + p.expect('Mr. þython') + p.sendeof () + p.expect (pexpect.EOF) + + def test_expect_exact_basic (self): + p = pexpect.spawnu('cat') + p.sendline('Hello') + p.sendline('there') + p.sendline('Mr. þython') + p.expect_exact('Hello') + p.expect_exact('there') + p.expect_exact('Mr. þython') + p.sendeof() + p.expect_exact (pexpect.EOF) + + def test_expect_setecho_toggle(self): + '''This tests that echo may be toggled off. + ''' + p = pexpect.spawnu('cat', timeout=5) + try: + self._expect_echo_toggle_off(p) + except IOError: + if sys.platform.lower().startswith('sunos'): + if hasattr(unittest, 'SkipTest'): + raise unittest.SkipTest("Not supported on this platform.") + return 'skip' + raise + self._expect_echo_toggle_on(p) + + def test_expect_echo_exact (self): + '''Like test_expect_echo(), but using expect_exact(). + ''' + p = pexpect.spawnu('cat', timeout=5) + p.expect = p.expect_exact + self._expect_echo(p) + + def test_expect_setecho_toggle_exact(self): + p = pexpect.spawnu('cat', timeout=5) + p.expect = p.expect_exact + try: + self._expect_echo_toggle_off(p) + except IOError: + if sys.platform.lower().startswith('sunos'): + if hasattr(unittest, 'SkipTest'): + raise unittest.SkipTest("Not supported on this platform.") + return 'skip' + raise + self._expect_echo_toggle_on(p) + + def _expect_echo (self, p): + p.sendline('1234') # Should see this twice (once from tty echo and again from cat). + index = p.expect (['1234', 'abcdé', 'wxyz', pexpect.EOF, pexpect.TIMEOUT]) + assert index == 0, (index, p.before) + index = p.expect (['1234', 'abcdé', 'wxyz', pexpect.EOF]) + assert index == 0, index + + def _expect_echo_toggle_off(self, p): + p.setecho(0) # Turn off tty echo + p.waitnoecho() + p.sendline('abcdé') # Now, should only see this once. + p.sendline('wxyz') # Should also be only once. + index = p.expect ([pexpect.EOF,pexpect.TIMEOUT, 'abcdé', 'wxyz', '1234']) + assert index == 2, index + index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890']) + assert index == 2, index + + def _expect_echo_toggle_on(self, p): + p.setecho(1) # Turn on tty echo + time.sleep(0.2) # there is no waitecho() ! + p.sendline('7890') # Should see this twice. + index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890']) + assert index == 3, index + index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890']) + assert index == 3, index + p.sendeof() + + def test_log_unicode(self): + msg = "abcΩ÷" + filename_send = tempfile.mktemp() + filename_read = tempfile.mktemp() + p = pexpect.spawnu('cat') + if platform.python_version_tuple() < ('3', '0', '0'): + import codecs + def open(fname, mode, **kwargs): + if 'newline' in kwargs: + del kwargs['newline'] + return codecs.open(fname, mode, **kwargs) + else: + import io + open = io.open + + p.logfile_send = open(filename_send, 'w', encoding='utf-8') + p.logfile_read = open(filename_read, 'w', encoding='utf-8') + p.sendline(msg) + p.sendeof() + p.expect(pexpect.EOF) + p.close() + p.logfile_send.close() + p.logfile_read.close() + + # ensure the 'send' log is correct, + with open(filename_send, 'r', encoding='utf-8') as f: + self.assertEqual(f.read(), msg + '\n\x04') + + # ensure the 'read' log is correct, + with open(filename_read, 'r', encoding='utf-8', newline='') as f: + output = f.read().replace(_CAT_EOF, '') + self.assertEqual(output, (msg + '\r\n')*2 ) + + + def test_spawn_expect_ascii_unicode(self): + # A bytes-based spawn should be able to handle ASCII-only unicode, for + # backwards compatibility. + p = pexpect.spawn('cat') + p.sendline('Camelot') + p.expect('Camelot') + + p.sendline('Aargh') + p.sendline('Aårgh') + p.expect_exact('Aargh') + + p.sendeof() + p.expect(pexpect.EOF) + + def test_spawn_send_unicode(self): + # A bytes-based spawn should be able to send arbitrary unicode + p = pexpect.spawn('cat') + p.sendline('3½') + p.sendeof() + p.expect(pexpect.EOF) + + def test_spawn_utf8_incomplete(self): + # This test case ensures correct incremental decoding, which + # otherwise fails when the stream inspected by os.read() + # does not align exactly at a utf-8 multibyte boundary: + # UnicodeDecodeError: 'utf8' codec can't decode byte 0xe2 in + # position 0: unexpected end of data + p = pexpect.spawnu('cat', maxread=1) + p.sendline('▁▂▃▄▅▆▇█') + p.sendeof() + p.expect('▁▂▃▄▅▆▇█') + + def test_readline_bin_echo(self): + # Test using readline() with spawnu objects. pexpect 3.2 had threw + # a TypeError when concatenating a bytestring to a unicode type. + + # given, + child = pexpect.spawnu('echo', ['input', ]) + + # exercise, + assert child.readline() == 'input' + child.crlf + + def test_unicode_argv(self): + """ Ensure a program can be executed with unicode arguments. """ + p = pexpect.spawn(u'echo ǝpoɔıun', timeout=5, encoding='utf8') + p.expect(u'ǝpoɔıun') + p.expect(pexpect.EOF) + assert not p.isalive() + assert p.exitstatus == 0 + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(UnicodeTests, 'test') diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_which.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_which.py new file mode 100644 index 00000000000..15a8944153d --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_which.py @@ -0,0 +1,291 @@ +# -*- coding: utf-8 -*- +import subprocess +import tempfile +import shutil +import errno +import os + +import pexpect +from . import PexpectTestCase + +import pytest + + +class TestCaseWhich(PexpectTestCase.PexpectTestCase): + " Tests for pexpect.which(). " + + def test_which_finds_ls(self): + " which() can find ls(1). " + exercise = pexpect.which("ls") + assert exercise is not None + assert exercise.startswith('/') + + def test_path_from_env(self): + " executable found from optional env argument " + bin_name = 'pexpect-test-path-from-env' + tempdir = tempfile.mkdtemp() + try: + bin_path = os.path.join(tempdir, bin_name) + with open(bin_path, 'w') as f: + f.write('# test file not to be run') + try: + os.chmod(bin_path, 0o700) + found_path = pexpect.which(bin_name, env={'PATH': tempdir}) + finally: + os.remove(bin_path) + self.assertEqual(bin_path, found_path) + finally: + os.rmdir(tempdir) + + def test_os_defpath_which(self): + " which() finds an executable in $PATH and returns its abspath. " + + bin_dir = tempfile.mkdtemp() + temp_obj = tempfile.NamedTemporaryFile( + suffix=u'.sh', prefix=u'ǝpoɔıun-', + dir=bin_dir, delete=False) + bin_path = temp_obj.name + fname = os.path.basename(temp_obj.name) + save_path = os.environ['PATH'] + save_defpath = os.defpath + + try: + # setup + os.environ['PATH'] = '' + os.defpath = bin_dir + with open(bin_path, 'w') as fp: + pass + + # given non-executable, + os.chmod(bin_path, 0o400) + + # exercise absolute and relative, + assert pexpect.which(bin_path) is None + assert pexpect.which(fname) is None + + # given executable, + os.chmod(bin_path, 0o700) + + # exercise absolute and relative, + assert pexpect.which(bin_path) == bin_path + assert pexpect.which(fname) == bin_path + + finally: + # restore, + os.environ['PATH'] = save_path + os.defpath = save_defpath + + # destroy scratch files and folders, + if os.path.exists(bin_path): + os.unlink(bin_path) + if os.path.exists(bin_dir): + os.rmdir(bin_dir) + + def test_path_search_which(self): + " which() finds an executable in $PATH and returns its abspath. " + fname = 'gcc' + bin_dir = tempfile.mkdtemp() + bin_path = os.path.join(bin_dir, fname) + save_path = os.environ['PATH'] + try: + # setup + os.environ['PATH'] = bin_dir + with open(bin_path, 'w') as fp: + pass + + # given non-executable, + os.chmod(bin_path, 0o400) + + # exercise absolute and relative, + assert pexpect.which(bin_path) is None + assert pexpect.which(fname) is None + + # given executable, + os.chmod(bin_path, 0o700) + + # exercise absolute and relative, + assert pexpect.which(bin_path) == bin_path + assert pexpect.which(fname) == bin_path + + finally: + # restore, + os.environ['PATH'] = save_path + + # destroy scratch files and folders, + if os.path.exists(bin_path): + os.unlink(bin_path) + if os.path.exists(bin_dir): + os.rmdir(bin_dir) + + def test_which_follows_symlink(self): + " which() follows symlinks and returns its path. " + fname = 'original' + symname = 'extra-crispy' + bin_dir = tempfile.mkdtemp() + bin_path = os.path.join(bin_dir, fname) + sym_path = os.path.join(bin_dir, symname) + save_path = os.environ['PATH'] + try: + # setup + os.environ['PATH'] = bin_dir + with open(bin_path, 'w') as fp: + pass + os.chmod(bin_path, 0o400) + os.symlink(bin_path, sym_path) + + # should not be found because symlink points to non-executable + assert pexpect.which(symname) is None + + # but now it should -- because it is executable + os.chmod(bin_path, 0o700) + assert pexpect.which(symname) == sym_path + + finally: + # restore, + os.environ['PATH'] = save_path + + # destroy scratch files, symlinks, and folders, + if os.path.exists(sym_path): + os.unlink(sym_path) + if os.path.exists(bin_path): + os.unlink(bin_path) + if os.path.exists(bin_dir): + os.rmdir(bin_dir) + + def test_which_should_not_match_folders(self): + " Which does not match folders, even though they are executable. " + # make up a path and insert a folder that is 'executable', a naive + # implementation might match (previously pexpect versions 3.2 and + # sh versions 1.0.8, reported by @lcm337.) + fname = 'g++' + bin_dir = tempfile.mkdtemp() + bin_dir2 = os.path.join(bin_dir, fname) + save_path = os.environ['PATH'] + try: + os.environ['PATH'] = bin_dir + os.mkdir(bin_dir2, 0o755) + # should not be found because it is not executable *file*, + # but rather, has the executable bit set, as a good folder + # should -- it should not be returned because it fails isdir() + exercise = pexpect.which(fname) + assert exercise is None + + finally: + # restore, + os.environ['PATH'] = save_path + # destroy scratch folders, + for _dir in (bin_dir2, bin_dir,): + if os.path.exists(_dir): + os.rmdir(_dir) + + def test_which_should_match_other_group_user(self): + " which() returns executables by other, group, and user ownership. " + # create an executable and test that it is found using which() for + # each of the 'other', 'group', and 'user' permission bits. + fname = 'g77' + bin_dir = tempfile.mkdtemp() + bin_path = os.path.join(bin_dir, fname) + save_path = os.environ['PATH'] + try: + # setup + os.environ['PATH'] = bin_dir + + # an interpreted script requires the ability to read, + # whereas a binary program requires only to be executable. + # + # to gain access to a binary program, we make a copy of + # the existing system program echo(1). + bin_echo = None + for pth in ('/bin/echo', '/usr/bin/echo'): + if os.path.exists(pth): + bin_echo = pth + break + bin_which = None + for pth in ('/bin/which', '/usr/bin/which'): + if os.path.exists(pth): + bin_which = pth + break + if not bin_echo or not bin_which: + pytest.skip('needs `echo` and `which` binaries') + shutil.copy(bin_echo, bin_path) + isroot = os.getuid() == 0 + for should_match, mode in ( + # note that although the file may have matching 'group' or + # 'other' executable permissions, it is *not* executable + # because the current uid is the owner of the file -- which + # takes precedence + (False, 0o000), # ----------, no + (isroot, 0o001), # ---------x, no + (isroot, 0o010), # ------x---, no + (True, 0o100), # ---x------, yes + (False, 0o002), # --------w-, no + (False, 0o020), # -----w----, no + (False, 0o200), # --w-------, no + (isroot, 0o003), # --------wx, no + (isroot, 0o030), # -----wx---, no + (True, 0o300), # --wx------, yes + (False, 0o004), # -------r--, no + (False, 0o040), # ----r-----, no + (False, 0o400), # -r--------, no + (isroot, 0o005), # -------r-x, no + (isroot, 0o050), # ----r-x---, no + (True, 0o500), # -r-x------, yes + (False, 0o006), # -------rw-, no + (False, 0o060), # ----rw----, no + (False, 0o600), # -rw-------, no + (isroot, 0o007), # -------rwx, no + (isroot, 0o070), # ----rwx---, no + (True, 0o700), # -rwx------, yes + (isroot, 0o4001), # ---S-----x, no + (isroot, 0o4010), # ---S--x---, no + (True, 0o4100), # ---s------, yes + (isroot, 0o4003), # ---S----wx, no + (isroot, 0o4030), # ---S-wx---, no + (True, 0o4300), # --ws------, yes + (isroot, 0o2001), # ------S--x, no + (isroot, 0o2010), # ------s---, no + (True, 0o2100), # ---x--S---, yes + + ): + mode_str = '{0:0>4o}'.format(mode) + + # given file mode, + os.chmod(bin_path, mode) + + # exercise whether we may execute + can_execute = True + try: + subprocess.Popen(fname).wait() == 0 + except OSError as err: + if err.errno != errno.EACCES: + raise + # permission denied + can_execute = False + + assert should_match == can_execute, ( + should_match, can_execute, mode_str) + + # exercise whether which(1) would match + proc = subprocess.Popen((bin_which, fname), + env={'PATH': bin_dir}, + stdout=subprocess.PIPE) + bin_which_match = bool(not proc.wait()) + assert should_match == bin_which_match, ( + should_match, bin_which_match, mode_str) + + # finally, exercise pexpect's which(1) matches + # the same. + pexpect_match = bool(pexpect.which(fname)) + + assert should_match == pexpect_match == bin_which_match, ( + should_match, pexpect_match, bin_which_match, mode_str) + + finally: + # restore, + os.environ['PATH'] = save_path + + # destroy scratch files and folders, + if os.path.exists(bin_path): + os.unlink(bin_path) + if os.path.exists(bin_dir): + os.rmdir(bin_dir) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/test_winsize.py b/lldb/third_party/Python/module/pexpect-4.6/tests/test_winsize.py new file mode 100755 index 00000000000..be16773b756 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/test_winsize.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' +import pexpect +import unittest +from . import PexpectTestCase +import time + +class TestCaseWinsize(PexpectTestCase.PexpectTestCase): + + def test_initial_winsize(self): + """ Assert initial window dimension size (24, 80). """ + p = pexpect.spawn('{self.PYTHONBIN} sigwinch_report.py' + .format(self=self), timeout=3) + # default size by PtyProcess class is 24 rows by 80 columns. + p.expect_exact('Initial Size: (24, 80)') + p.close() + + def test_initial_winsize_by_dimension(self): + """ Assert user-parameter window dimension size is initial. """ + p = pexpect.spawn('{self.PYTHONBIN} sigwinch_report.py' + .format(self=self), timeout=3, + dimensions=(40, 100)) + p.expect_exact('Initial Size: (40, 100)') + p.close() + + def test_setwinsize(self): + """ Ensure method .setwinsize() sends signal caught by child. """ + p = pexpect.spawn('{self.PYTHONBIN} sigwinch_report.py' + .format(self=self), timeout=3) + # Note that we must await the installation of the child process' + # signal handler, + p.expect_exact('READY') + p.setwinsize(19, 84) + p.expect_exact('SIGWINCH: (19, 84)') + p.close() + +if __name__ == '__main__': + unittest.main() + +suite = unittest.makeSuite(TestCaseWinsize,'test') + + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/tetris.data b/lldb/third_party/Python/module/pexpect-4.6/tests/tetris.data new file mode 100644 index 00000000000..06b6ce6ed2f --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/tetris.data @@ -0,0 +1,3 @@ +[2J +[24;1H J->LEFT K->ROTATE L->RIGHT SPACE->DROP P->PAUSE Q->QUIT +[1;28HXX[1;36HXXXXXXXX[1;50HXX[2;28HXX[2;50HXX[3;28HXX[3;50HXX[4;28HXX[4;50HXX[5;28HXX[5;50HXX[6;28HXX[6;50HXX[7;28HXX[7;50HXX[8;28HXX[8;50HXX[9;28HXX[9;50HXX[10;28HXX[10;50HXX[11;28HXX[11;50HXX[12;28HXX[12;50HXX[13;28HXX[13;50HXX[14;28HXX[14;50HXX[15;28HXX[15;50HXX[16;28HXX[16;50HXX[17;28HXX[17;50HXX[18;28HXX[18;50HXX[19;28HXX[19;50HXX[20;28HXX[20;50HXX[21;28HXXXXXXXXXXXXXXXXXXXXXXXX[1;36H [2;36HXXXXXXXX[21;50HXX[2;36H [3;36HXXXXXXXX[21;50HXX[3;36H [4;36HXXXXXXXX[21;50HXX[4;36H [5;36HXXXXXXXX[21;50HXX[5;34HXX[5;42H [21;50HXX[5;34H [6;34HXXXXXXXX[21;50HXX[6;32HXX[6;40H [21;50HXX[6;30HXX[6;38H [21;50HXX[6;30H [7;30HXXXXXXXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[7;30H [8;30HXXXXXXXX[21;50HXX[8;30H [20;30HXXXXXXXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [2;38HXXXX[3;36HXX[21;50HXX[2;36H [2;42HXX[3;36H XX[21;50HXX[2;38H [3;40HXXXX[4;38HXX[21;50HXX[3;38H [3;44HXX[4;38H XX[21;50HXX[3;40H [3;46HXX[4;40H XX[21;50HXX[3;42H [3;48HXX[4;42H XX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[3;44H [4;46HXXXX[5;44HXX[21;50HXX[4;44H [5;46HXXXX[6;44HXX[21;50HXX[5;44H [6;44H [19;44HXXXXXX[20;44HXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [2;38HXXXX[3;36HXX[21;50HXX[2;36H [2;42HXX[3;36H XX[21;50HXX[2;38H [2;44HXX[3;38H XX[21;50HXX[2;40H [3;42HXXXX[4;40HXX[21;50HXX[2;42HXX[3;40H [3;44H [4;40H XXXX[21;50HXX[2;42H XX[3;40HXX[3;44HXX[4;42H [21;50HXX[2;44H [3;40H [4;40HXXXXXX[21;50HXX[3;44H [4;40H [17;44HXX[18;40HXXXXXX[21;50HXX[1;36HXXXX[21;50HXX[1;36H [1;40HXX[2;36HXXXX[21;50HXX[1;36HXX[1;40H [2;34HXX[2;38H [21;50HXX[1;36H [2;34H [2;38HXX[3;34HXXXX[21;50HXX[2;34HXX[2;38H [3;32HXX[3;36H [21;50HXX[2;32HXX[2;36H [3;30HXX[3;34H [21;50HXX[21;50HXX[2;32H [3;30H [3;34HXX[4;30HXXXX[21;50HXX[21;50HXX[3;32H [4;30H [18;32HXXXX[19;30HXXXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [1;42HXX[2;36H XX[21;50HXX[1;38H [2;40HXXXX[3;38HXX[21;50HXX[2;38H [2;44HXX[3;38H XX[21;50HXX[2;40H [2;46HXX[3;40H XX[21;50HXX[2;42H [2;48HXX[3;42H XX[21;50HXX[2;44H [3;46HXXXX[4;44HXX[21;50HXX[21;50HXX[21;50HXX[3;44H [4;44H [15;44HXXXXXX[16;44HXX[21;50HXX[1;36HXXXXXXXX[21;50HXX[1;34HXX[1;42H [21;50HXX[1;34H [2;34HXXXXXXXX[21;50HXX[2;32HXX[2;40H [21;50HXX[2;30HXX[2;38H [21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[2;30H [3;30HXXXXXXXX[21;50HXX[3;30H [17;30HXXXXXXXX[21;50HXX[1;38HXXXX[21;50HXX[1;38H [16;36HXXXX[17;38HXXXX[21;50HXX[21;50HXX[1;36HXXXX[21;50HXX[1;36H [1;40HXX[21;50HXX[2;38HXXXX[21;50HXX[1;38H [1;42HXX[2;38H [2;42HXX[21;50HXX[1;40H [1;44HXX[2;40H [2;44HXX[21;50HXX[1;42H [1;46HXX[2;42H [2;46HXX[21;50HXX[1;44H [3;44HXXXX[21;50HXX[2;44H [3;44H [13;44HXXXX[14;44HXXXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;34HXX[1;40H [2;38HXX [21;50HXX[1;34H [2;34HXXXX[3;38HXX[21;50HXX[2;32HXX[2;38H [3;36HXX [21;50HXX[2;30HXX[2;36H [3;34HXX [21;50HXX[21;50HXX[21;50HXX[21;50HXX[2;30H [3;34H [15;30HXXXXXX[16;34HXX[21;50HXX[1;36HXXXXXXXX[21;50HXX[1;36H [1;44HXX[21;50HXX[1;38H [2;38HXXXXXXXX[21;50HXX[1;40HXX[2;38H [2;42H [3;40HXX[4;40HXX[21;50HXX[1;40H [5;40HXX[21;50HXX[2;40H [3;38HXX[3;42HXXXX[4;40H [5;40H [21;50HXX[2;40HXX[3;38H [3;42H [4;40HXX[5;40HXX[21;50HXX[2;40H [6;40HXX[21;50HXX[3;40H [4;40H [5;40H [6;40H [13;40HXX[14;40HXX[15;40HXX[16;40HXX[21;50HXX[1;36HXXXXXX[2;38HXX[21;50HXX[1;34HXX[1;40H [2;36HXX [21;50HXX[1;32HXX[1;38H [2;34HXX [21;50HXX[1;32H [21;50HXX[1;36H [2;36HXX[3;34HXX[21;50HXX[1;32HXX [2;32HXX[2;36H [3;32HXX [21;50HXX[2;30HXX[3;32H [21;50HXX[1;32H [2;30H [2;34H [3;30HXXXXXX[21;50HXX[2;32H [3;30H [13;32HXX[14;30HXXXXXX[21;50HXX[1;36HXXXXXXXX[21;50HXX[1;36H [1;44HXX[21;50HXX[1;38H [1;42H [2;40HXX[3;40HXX[21;50HXX[1;40H XX[2;40H XX[3;40H XX[21;50HXX[4;42HXX[21;50HXX[1;42H [2;40HXX[2;44HXXXX[3;42H [4;42H [21;50HXX[2;40H [2;48HXX[21;50HXX[1;44HXX[2;42H [2;46H [3;44HXX[4;44HXX[21;50HXX[1;44H [5;44HXX[21;50HXX[2;44H [3;44H [4;44H [5;44H [9;44HXX[10;44HXX[11;44HXX[12;44HXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [1;40H [2;36H XXXX[21;50HXX[1;36HXX [2;36HXX[2;40H [21;50HXX[1;34HXX[1;38HXX[2;36H [21;50HXX[1;34H [2;34HXXXXXX[21;50HXX[1;36HXX [2;32HXX[2;38H [21;50HXX[1;32HXXXX [2;32H [2;36H [3;34HXX[21;50HXX[1;30HXX[1;34H [2;32HXX [3;32HXX [21;50HXX[1;30H [2;30HXX[4;32HXX[21;50HXX[2;30H [3;32H [4;32H [10;30HXXXX[11;32HXX[12;32HXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;36H [1;40H [2;38HXX [21;50HXX[1;36HXX[1;40HXX[2;38H [21;50HXX[1;38H [2;36HXXXXXX[21;50HXX[1;36H XX[2;36H [2;40H [3;36HXXXX[21;50HXX[1;38H [2;38H [3;36H [13;38HXX[14;38HXX[15;36HXXXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [1;42HXX[2;36H XX[21;50HXX[1;38H [2;40HXXXX[3;38HXX[21;50HXX[1;40HXX[2;38H [2;42H [3;38H XXXX[21;50HXX[1;40H XX[2;40H XX[3;40H [3;44HXX[21;50HXX[1;42H XX[2;40HXX[2;44HXX[3;42H [21;50HXX[1;44H XX[2;40H [2;46HXX[21;50HXX[1;46H [2;42H [3;42HXXXXXX[21;50HXX[2;42HXXXX [3;42H [3;46H [4;44HXX[21;50HXX[2;42H [3;44H [4;44H [6;42HXXXX[7;44HXX[8;44HXX[21;50HXX[1;38HXXXX[21;50HXX[1;36HXX[1;40H [2;36HXX[21;50HXX[1;34HXX[1;38H [2;34HXX [21;50HXX[1;34H [2;36HXX[3;34HXX[21;50HXX[1;34HXX[2;34H [2;38HXX[3;34H [21;50HXX[1;32HXX[1;36H [2;34HXX[2;38H [21;50HXX[1;32H [2;32HXX[2;36H [3;32HXX[21;50HXX[1;32HXX [2;30HXX[2;34H [3;30HXX [21;50HXX[1;32H [2;30H [3;32HXX[4;30HXX[21;50HXX[2;32H [3;30H [4;30H [7;32HXX[8;30HXXXX[9;30HXX[21;50HXX[1;36HXXXX[21;50HXX[21;50HXX[1;36H [1;40HXX[21;50HXX[21;50HXX[2;38HXXXX[21;50HXX[1;38H [1;42HXX[2;38H [2;42HXX[21;50HXX[21;50HXX[1;40H [1;44HXX[2;40H [2;44HXX[21;50HXX[21;50HXX[1;42H [3;42HXXXX[21;50HXX[2;42H [3;42H [4;42HXXXX[5;42HXXXX[21;50HXX[1;36HXXXX[21;50HXX[1;36H [1;40HXX[2;40HXX[21;50HXX[1;36HXX[1;40H [2;40H [21;50HXX[1;36H [1;40HXX[2;40HXX[21;50HXX[1;40H [2;38HXX[3;40HXX[21;50HXX[1;38H [2;38H [3;40H [10;38HXX[11;38HXXXX[12;40HXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;36H [2;40H [9;36HXXXXXX[10;40HXX[21;50HXX[21;50HXX[1;38HXXXX[21;50HXX[1;36HXX[1;40H [2;36HXX[21;50HXX[1;34HXX[1;38H [2;34HXX [21;50HXX[1;34H [2;36HXX[3;34HXX[21;50HXX[1;34HXX[2;34H [2;38HXX[3;34H [21;50HXX[1;32HXX[1;36H [2;34HXX[2;38H [21;50HXX[1;32H [2;34H [6;32HXXXX[7;34HXXXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;36H [1;42HXX[2;40H XX[21;50HXX[1;38H [1;42H [2;40HXX [21;50HXX[1;40H XX[2;40H XX[21;50HXX[1;40HXX[1;44HXX[2;42H [21;50HXX[1;42H [2;40HXXXXXX[21;50HXX[1;40H XX[2;40H [2;46HXX[21;50HXX[1;42H XX[2;42H [2;46H [3;42HXXXX[21;50HXX[21;50HXX[1;38HXXXX[21;50HXX[1;36HXX[1;40H [2;36HXX[21;50HXX[1;36H [2;38HXX[3;36HXX[21;50HXX[1;36HXX [2;34HXX[2;38H [3;34HXX [21;50HXX[1;34HXX[2;34H [2;38HXX[3;34H [21;50HXX[1;32HXX[1;36H [2;34HXX[2;38H [21;50HXX[1;32H [2;32HXX[2;36H [3;32HXX[21;50HXX[1;34H [2;32H [3;34HXX[4;32HXX[21;50HXX[2;32HXX [3;30HXX[3;34H [4;30HXX [21;50HXX[2;32H [3;30H [4;30H XX[5;30HXXXX[6;30HXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;36H [1;42HXX[2;40H XX[21;50HXX[1;38H [1;42H [2;40HXX [21;50HXX[1;40H XX[2;40H XX[21;50HXX[21;50HXX[1;38HXXXX[21;50HXX[21;50HXX[1;36HXX[1;40H [2;36HXX[21;50HXX[1;36H [2;36H [4;38HXX[5;36HXXXX[6;36HXX[21;50HXX[1;36HXXXX[21;50HXX[21;50HXX[1;34HXX[1;38H [21;50HXX[2;34HXXXX[21;50HXX[21;50HXX[1;32HXX[1;36H [2;32HXX[2;36H [21;50HXX[21;50HXX[1;30HXX[1;34H [2;30HXX[2;34H [21;50HXX[1;30H [3;30HXXXX[21;50HXX[21;50HXX[1;36HXXXX[21;50HXX[1;36H [1;40HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[2;38HXXXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[1;38H [3;38HXXXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/ticker.py b/lldb/third_party/Python/module/pexpect-4.6/tests/ticker.py new file mode 100755 index 00000000000..5ecc1c21be0 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/ticker.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +''' +PEXPECT LICENSE + + This license is approved by the OSI and FSF as GPL-compatible. + http://opensource.org/licenses/isc-license.txt + + Copyright (c) 2012, Noah Spurrier <noah@noah.org> + PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY + PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE + COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +''' + +import time, sys + +for i in range(5): + print "tick" + time.sleep(1) + +sys.exit(0) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/torturet.vt b/lldb/third_party/Python/module/pexpect-4.6/tests/torturet.vt new file mode 100644 index 00000000000..65f965b505d --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/torturet.vt @@ -0,0 +1,61 @@ +\<>[H[1;2;3;4qPrEM1\[?4h[0m +[H[J[7m#6(0a`opqrs`(B This is the (0`srqpo`a(B[1m +#3VT100 series Torture Test Demonstration. +#4VT100 series Torture Test Demonstration. +#6[1;5m Watch the blinking lights [4;24r[0m +[0q[1q[0q[2q[0q[3q[0q[4q[0q +[0q[1q[0q[2q[0q[3q[0q[4q[0q +[0q[1q[0q[2q[0q[3q[0q[4q[0q +PrEM0\[4;1H[J[24;1H + +This file is a VT100-series Torture Test. It demonstrates all the visual +attributes of the VT100 terminal. + +The top line is double-width/single-height with inverse-video line-drawing +characters. The 2nd and 3rd lines are double-width/double-height in bold +inverse video. They also show the limited scrolling region. + +The remaining lines will show NORMAL, BOLD, BLINK, INVERSE, and all 16 +combinations of those 4 attributes. They show that there is a difference +between an underscore character and the underline attribute, and that +lower-case decenders go below the underline. + +A window pane is drawn in the lower right to show how the line-drawing set +can be used. At the lower left is the character set double-wide/double-high +to show the dot-matrix used. Upper-case characters are 8 by 7 in a 10 by 10 +character cell, with 1 blank row on top and 2 on the bottom. The underline +attribute uses the first bottom blank row, lower-case decenders use both. + + + +[0mThis is a normal line __________________________________________________y_ +[1mThis is a bold line (normal unless the Advanced Video Option is installed) +[0;4mThis line is underlined _ " " " " " " _y_ +[0;5mThis is a blinking line _ " " " " " " _y_ +[0;7mThis is inverse video _ (underlined if no AVO and cursor is underline) _y_ +[0mNormal gjpqy [4mUnderline[0;0m [5m Blink [4mUnderline+Blink gjpqy[0m +[1mBold gjpqy [4mUnderline[0;1m [5m Blink [4mUnderline+Blink gjpqy[0m +[7mInverse [4mUnderline[0;7m [5m Blink [4mUnderline+Blink[0;7m +[1mBold+Inverse [4mUnderline[0;1;7m [5m Blink [4mUnderline+Blink[0m +PrEM1\[A +#6This is double [1mwidth[0m +#3This is double [1mheight[0m +#4This is double [1mheight[0m +#6[7;4m_[0;7mABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy +#3[7;4m_[0;7mABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy +#4[7;4m_[0;7mABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy[3A +[0m[CA[CC[CE[CG[CI[CK[CM[CO[CQ[CS[CU[CW[CY[C0[C2[C4[C6[C8[Ci[Cy +[4m_[0m[CB[CD[CF[CH[CJ[CL[CN[CP[CR[CT[CV[CX[CZ[C1[C3[C5[C7[C9[Co +[4m_[0m[CB[CD[CF[CH[CJ[CL[CN[CP[CR[CT[CV[CX[CZ[C1[C3[C5[C7[C9[Co +(0#6[7m`abcdefghijklmnopqrstuvwxyz{|}~[0m lqwqk +#3[7m`abcdefghijklmnopqrstuvwxyz{|}~[0m tqnqu +#4[7m`abcdefghijklmnopqrstuvwxyz{|}~[0m tqnqu[3A[0m +[Ca[Cc[Ce[Cg[Ci[Ck[Cm[Co[Cq[Cs[Cu[Cw[Cy[C{[C} +`[Cb[Cd[Cf[Ch[Cj[Cl[Cn[Cp[Cr[Ct[Cv[Cx[Cz[C|[C~ +`[Cb[Cd[Cf[Ch[Cj[Cl[Cn[Cp[Cr[Ct[Cv[Cx[Cz[C|[C~(B +#6[7m`abcdefghijklmnopqrstuvwxyz{|}~(0[0m mqvqj[A(B +[0m[Ca[Cc[Ce[Cg[Ci[Ck[Cm[Co[Cq[Cs[Cu[Cw[Cy[C{[C} +PrEM0\ $PrEM0 works on GIGI [A[1;7m + This test created by Joe Smith, 8-May-85 [0m +[1;r[22;1H + diff --git a/lldb/third_party/Python/module/pexpect-4.6/tests/utils.py b/lldb/third_party/Python/module/pexpect-4.6/tests/utils.py new file mode 100644 index 00000000000..dcd3aa017da --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tests/utils.py @@ -0,0 +1,7 @@ +import os + +def no_coverage_env(): + "Return a copy of os.environ that won't trigger coverage measurement." + env = os.environ.copy() + env.pop('COV_CORE_SOURCE', None) + return env
\ No newline at end of file diff --git a/lldb/third_party/Python/module/pexpect-4.6/tools/display-fpathconf.py b/lldb/third_party/Python/module/pexpect-4.6/tools/display-fpathconf.py new file mode 100644 index 00000000000..d40cbae206f --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tools/display-fpathconf.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +"""Displays os.fpathconf values related to terminals. """ +from __future__ import print_function +import sys +import os + + +def display_fpathconf(): + DISP_VALUES = ( + ('PC_MAX_CANON', ('Max no. of bytes in a ' + 'terminal canonical input line.')), + ('PC_MAX_INPUT', ('Max no. of bytes for which ' + 'space is available in a terminal input queue.')), + ('PC_PIPE_BUF', ('Max no. of bytes which will ' + 'be written atomically to a pipe.')), + ('PC_VDISABLE', 'Terminal character disabling value.') + ) + FMT = '{name:<13} {value:<5} {description}' + + # column header + print(FMT.format(name='name', value='value', description='description')) + print(FMT.format(name=('-' * 13), value=('-' * 5), description=('-' * 11))) + + fd = sys.stdin.fileno() + for name, description in DISP_VALUES: + key = os.pathconf_names.get(name, None) + if key is None: + value = 'UNDEF' + else: + try: + value = os.fpathconf(fd, name) + except OSError as err: + value = 'OSErrno {0.errno}'.format(err) + if name == 'PC_VDISABLE': + value = hex(value) + print(FMT.format(name=name, value=value, description=description)) + print() + + +if __name__ == '__main__': + display_fpathconf() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tools/display-maxcanon.py b/lldb/third_party/Python/module/pexpect-4.6/tools/display-maxcanon.py new file mode 100644 index 00000000000..cbd664ffec7 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tools/display-maxcanon.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +""" +This tool uses pexpect to test expected Canonical mode length. + +All systems use the value of MAX_CANON which can be found using +fpathconf(3) value PC_MAX_CANON -- with the exception of Linux +and FreeBSD. + +Linux, though defining a value of 255, actually honors the value +of 4096 from linux kernel include file tty.h definition +N_TTY_BUF_SIZE. + +Linux also does not honor IMAXBEL. termios(3) states, "Linux does not +implement this bit, and acts as if it is always set." Although these +tests ensure it is enabled, this is a non-op for Linux. + +FreeBSD supports neither, and instead uses a fraction (1/5) of the tty +speed which is always 9600. Therefor, the maximum limited input line +length is 9600 / 5 = 1920. + +These tests only ensure the correctness of the behavior described by +the sendline() docstring -- the values listed there, and above should +be equal to the output of the given OS described, but no promises! +""" +# std import +from __future__ import print_function +import sys +import os + + +def detect_maxcanon(): + import pexpect + bashrc = os.path.join( + # re-use pexpect/replwrap.py's bashrc file, + os.path.dirname(__file__), os.path.pardir, 'pexpect', 'bashrc.sh') + + child = pexpect.spawn('bash', ['--rcfile', bashrc], + echo=True, encoding='utf8', timeout=3) + + child.sendline(u'echo -n READY_; echo GO') + child.expect_exact(u'READY_GO') + + child.sendline(u'stty icanon imaxbel erase ^H; echo -n retval: $?') + child.expect_exact(u'retval: 0') + + child.sendline(u'echo -n GO_; echo AGAIN') + child.expect_exact(u'GO_AGAIN') + child.sendline(u'cat') + + child.delaybeforesend = 0 + + column, blocksize = 0, 64 + ch_marker = u'_' + + print('auto-detecting MAX_CANON: ', end='') + sys.stdout.flush() + + while True: + child.send(ch_marker * blocksize) + result = child.expect([ch_marker * blocksize, u'\a']) + if result == 0: + # entire block fit without emitting bel + column += blocksize + elif result == 1: + # an '\a' was emitted, count the number of ch_markers + # found since last blocksize, determining our MAX_CANON + column += child.before.count(ch_marker) + break + print(column) + +if __name__ == '__main__': + try: + detect_maxcanon() + except ImportError: + # we'd like to use this with CI -- but until we integrate + # with tox, we can't determine a period in testing when + # the pexpect module has been installed + print('warning: pexpect not in module path, MAX_CANON ' + 'could not be determined by systems test.', + file=sys.stderr) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tools/display-sighandlers.py b/lldb/third_party/Python/module/pexpect-4.6/tools/display-sighandlers.py new file mode 100755 index 00000000000..f3559f72e31 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tools/display-sighandlers.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# Displays all signals, their values, and their handlers. +from __future__ import print_function +import signal +FMT = '{name:<10} {value:<5} {description}' + +# header +print(FMT.format(name='name', value='value', description='description')) +print('-' * (33)) + +for name, value in [(signal_name, getattr(signal, signal_name)) + for signal_name in dir(signal) + if signal_name.startswith('SIG') + and not signal_name.startswith('SIG_')]: + try: + handler = signal.getsignal(value) + except ValueError: + # FreeBSD: signal number out of range + handler = 'out of range' + description = { + signal.SIG_IGN: "ignored(SIG_IGN)", + signal.SIG_DFL: "default(SIG_DFL)" + }.get(handler, handler) + print(FMT.format(name=name, value=value, description=description)) diff --git a/lldb/third_party/Python/module/pexpect-4.6/tools/display-terminalinfo.py b/lldb/third_party/Python/module/pexpect-4.6/tools/display-terminalinfo.py new file mode 100755 index 00000000000..1288397acbb --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tools/display-terminalinfo.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python +""" Display known information about our terminal. """ +from __future__ import print_function +import termios +import locale +import sys +import os + +BITMAP_IFLAG = { + 'IGNBRK': 'ignore BREAK condition', + 'BRKINT': 'map BREAK to SIGINTR', + 'IGNPAR': 'ignore (discard) parity errors', + 'PARMRK': 'mark parity and framing errors', + 'INPCK': 'enable checking of parity errors', + 'ISTRIP': 'strip 8th bit off chars', + 'INLCR': 'map NL into CR', + 'IGNCR': 'ignore CR', + 'ICRNL': 'map CR to NL (ala CRMOD)', + 'IXON': 'enable output flow control', + 'IXOFF': 'enable input flow control', + 'IXANY': 'any char will restart after stop', + 'IMAXBEL': 'ring bell on input queue full', + 'IUCLC': 'translate upper case to lower case', +} + +BITMAP_OFLAG = { + 'OPOST': 'enable following output processing', + 'ONLCR': 'map NL to CR-NL (ala CRMOD)', + 'OXTABS': 'expand tabs to spaces', + 'ONOEOT': 'discard EOT\'s `^D\' on output)', + 'OCRNL': 'map CR to NL', + 'OLCUC': 'translate lower case to upper case', + 'ONOCR': 'No CR output at column 0', + 'ONLRET': 'NL performs CR function', +} + +BITMAP_CFLAG = { + 'CSIZE': 'character size mask', + 'CS5': '5 bits (pseudo)', + 'CS6': '6 bits', + 'CS7': '7 bits', + 'CS8': '8 bits', + 'CSTOPB': 'send 2 stop bits', + 'CREAD': 'enable receiver', + 'PARENB': 'parity enable', + 'PARODD': 'odd parity, else even', + 'HUPCL': 'hang up on last close', + 'CLOCAL': 'ignore modem status lines', + 'CCTS_OFLOW': 'CTS flow control of output', + 'CRTSCTS': 'same as CCTS_OFLOW', + 'CRTS_IFLOW': 'RTS flow control of input', + 'MDMBUF': 'flow control output via Carrier', +} + +BITMAP_LFLAG = { + 'ECHOKE': 'visual erase for line kill', + 'ECHOE': 'visually erase chars', + 'ECHO': 'enable echoing', + 'ECHONL': 'echo NL even if ECHO is off', + 'ECHOPRT': 'visual erase mode for hardcopy', + 'ECHOCTL': 'echo control chars as ^(Char)', + 'ISIG': 'enable signals INTR, QUIT, [D]SUSP', + 'ICANON': 'canonicalize input lines', + 'ALTWERASE': 'use alternate WERASE algorithm', + 'IEXTEN': 'enable DISCARD and LNEXT', + 'EXTPROC': 'external processing', + 'TOSTOP': 'stop background jobs from output', + 'FLUSHO': 'output being flushed (state)', + 'NOKERNINFO': 'no kernel output from VSTATUS', + 'PENDIN': 'XXX retype pending input (state)', + 'NOFLSH': 'don\'t flush after interrupt', +} + +CTLCHAR_INDEX = { + 'VEOF': 'EOF', + 'VEOL': 'EOL', + 'VEOL2': 'EOL2', + 'VERASE': 'ERASE', + 'VWERASE': 'WERASE', + 'VKILL': 'KILL', + 'VREPRINT': 'REPRINT', + 'VINTR': 'INTR', + 'VQUIT': 'QUIT', + 'VSUSP': 'SUSP', + 'VDSUSP': 'DSUSP', + 'VSTART': 'START', + 'VSTOP': 'STOP', + 'VLNEXT': 'LNEXT', + 'VDISCARD': 'DISCARD', + 'VMIN': '---', + 'VTIME': '---', + 'VSTATUS': 'STATUS', +} + + +def display_bitmask(kind, bitmap, value): + """ Display all matching bitmask values for ``value`` given ``bitmap``. """ + col1_width = max(map(len, list(bitmap.keys()) + [kind])) + col2_width = 7 + FMT = '{name:>{col1_width}} {value:>{col2_width}} {description}' + print(FMT.format(name=kind, + value='Value', + description='Description', + col1_width=col1_width, + col2_width=col2_width)) + print('{0} {1} {2}'.format('-' * col1_width, + '-' * col2_width, + '-' * max(map(len, bitmap.values())))) + for flag_name, description in bitmap.items(): + try: + bitmask = getattr(termios, flag_name) + bit_val = 'on' if bool(value & bitmask) else 'off' + except AttributeError: + bit_val = 'undef' + print(FMT.format(name=flag_name, + value=bit_val, + description=description, + col1_width=col1_width, + col2_width=col2_width)) + print() + + +def display_ctl_chars(index, cc): + """ Display all control character indicies, names, and values. """ + title = 'Special Character' + col1_width = len(title) + col2_width = max(map(len, index.values())) + FMT = '{idx:<{col1_width}} {name:<{col2_width}} {value}' + print('Special line Characters'.center(40).rstrip()) + print(FMT.format(idx='Index', + name='Name', + value='Value', + col1_width=col1_width, + col2_width=col2_width)) + print('{0} {1} {2}'.format('-' * col1_width, + '-' * col2_width, + '-' * 10)) + for index_name, name in index.items(): + try: + index = getattr(termios, index_name) + value = cc[index] + if value == b'\xff': + value = '_POSIX_VDISABLE' + else: + value = repr(value) + except AttributeError: + value = 'undef' + print(FMT.format(idx=index_name, + name=name, + value=value, + col1_width=col1_width, + col2_width=col2_width)) + print() + + +def display_conf(kind, names, getter): + col1_width = max(map(len, names)) + FMT = '{name:>{col1_width}} {value}' + print(FMT.format(name=kind, + value='value', + col1_width=col1_width)) + print('{0} {1}'.format('-' * col1_width, '-' * 27)) + for name in names: + try: + value = getter(name) + except OSError as err: + value = err + print(FMT.format(name=name, value=value, col1_width=col1_width)) + print() + + +def main(): + fd = sys.stdin.fileno() + locale.setlocale(locale.LC_ALL, '') + encoding = locale.getpreferredencoding() + + print('os.isatty({0}) => {1}'.format(fd, os.isatty(fd))) + print('locale.getpreferredencoding() => {0}'.format(encoding)) + + display_conf(kind='pathconf', + names=os.pathconf_names, + getter=lambda name: os.fpathconf(fd, name)) + + try: + (iflag, oflag, cflag, lflag, ispeed, ospeed, cc + ) = termios.tcgetattr(fd) + except termios.error as err: + print('stdin is not a typewriter: {0}'.format(err)) + else: + display_bitmask(kind='Input Mode', + bitmap=BITMAP_IFLAG, + value=iflag) + display_bitmask(kind='Output Mode', + bitmap=BITMAP_OFLAG, + value=oflag) + display_bitmask(kind='Control Mode', + bitmap=BITMAP_CFLAG, + value=cflag) + display_bitmask(kind='Local Mode', + bitmap=BITMAP_LFLAG, + value=lflag) + display_ctl_chars(index=CTLCHAR_INDEX, + cc=cc) + try: + print('os.ttyname({0}) => {1}'.format(fd, os.ttyname(fd))) + print('os.ctermid() => {0}'.format(os.ctermid())) + except OSError as e: + # Travis fails on ttyname with errno 0 'Error'. + print("Error inspecting TTY: {0}".format(e)) + +if __name__ == '__main__': + main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/tools/teamcity-coverage-report.sh b/lldb/third_party/Python/module/pexpect-4.6/tools/teamcity-coverage-report.sh new file mode 100755 index 00000000000..2e32241b7b7 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tools/teamcity-coverage-report.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# This is to be executed by each individual OS test. It only +# combines coverage files and reports locally to the given +# TeamCity build configuration. +set -e +set -o pipefail +[ -z ${TEMP} ] && TEMP=/tmp + +# combine all .coverage* files, +coverage combine + +# create ascii report, +report_file=$(mktemp $TEMP/coverage.XXXXX) +coverage report --rcfile=`dirname $0`/../.coveragerc > "${report_file}" 2>/dev/null + +# Report Code Coverage for TeamCity, using 'Service Messages', +# https://confluence.jetbrains.com/display/TCD8/How+To...#HowTo...-ImportcoverageresultsinTeamCity +# https://confluence.jetbrains.com/display/TCD8/Custom+Chart#CustomChart-DefaultStatisticsValuesProvidedbyTeamCity +total_no_lines=$(awk '/TOTAL/{printf("%s",$2)}' < "${report_file}") +total_no_misses=$(awk '/TOTAL/{printf("%s",$3)}' < "${report_file}") +total_no_covered=$((${total_no_lines} - ${total_no_misses})) +echo "##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value='""${total_no_lines}""']" +echo "##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='""${total_no_covered}""']" + +# Display for human consumption and remove ascii file. +cat "${report_file}" +rm "${report_file}" diff --git a/lldb/third_party/Python/module/pexpect-4.6/tools/teamcity-runtests.sh b/lldb/third_party/Python/module/pexpect-4.6/tools/teamcity-runtests.sh new file mode 100755 index 00000000000..bcb28f78aa6 --- /dev/null +++ b/lldb/third_party/Python/module/pexpect-4.6/tools/teamcity-runtests.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# +# This script assumes that the project 'ptyprocess' is +# available in the parent of the project's folder. +set -e +set -o pipefail + +if [ -z $1 ]; then + echo "$0 (2.6|2.7|3.3|3.4)" + exit 1 +fi + +export PYTHONIOENCODING=UTF8 +export LANG=en_US.UTF-8 + +pyversion=$1 +shift +here=$(cd `dirname $0`; pwd) +osrel=$(uname -s) +venv=teamcity-pexpect +venv_wrapper=$(which virtualenvwrapper.sh) + +if [ -z $venv_wrapper ]; then + echo "virtualenvwrapper.sh not found in PATH." >&2 + exit 1 +fi + +. ${venv_wrapper} +rmvirtualenv ${venv} || true +mkvirtualenv -p `which python${pyversion}` ${venv} || true +workon ${venv} + +# install ptyprocess +cd $here/../../ptyprocess +pip uninstall --yes ptyprocess || true +python setup.py install + +# install all test requirements +pip install --upgrade pytest-cov coverage coveralls pytest-capturelog + +# run tests +cd $here/.. +ret=0 +py.test \ + --cov pexpect \ + --cov-config .coveragerc \ + --junit-xml=results.${osrel}.py${pyversion}.xml \ + --verbose \ + --verbose \ + "$@" || ret=$? + +if [ $ret -ne 0 ]; then + # we always exit 0, preferring instead the jUnit XML + # results to be the dominate cause of a failed build. + echo "py.test returned exit code ${ret}." >&2 + echo "the build should detect and report these failing tests." >&2 +fi + +# combine all coverage to single file, report for this build, +# then move into ./build-output/ as a unique artifact to allow +# the final "Full build" step to combine and report to coveralls.io +`dirname $0`/teamcity-coverage-report.sh +mkdir -p build-output +mv .coverage build-output/.coverage.${osrel}.py{$pyversion}.$RANDOM.$$ |