author | Andreea Pavel <apavel@mozilla.com> |
Fri, 18 May 2018 21:17:33 +0300 | |
changeset 418841 | 2375438b837c39405dd2c3fa143c12611be82e02 |
parent 418840 | 07344dd474326a185413c934db93331b1edda24a |
child 418842 | 266c78fab1d6b9950a0ae2f5fb176cbe37d045ea |
push id | 34014 |
push user | aciure@mozilla.com |
push date | Fri, 18 May 2018 22:04:52 +0000 |
treeherder | mozilla-central@b54f574a1dd2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1408051 |
milestone | 62.0a1 |
backs out | 5afad9b7fd2114e7fd63d6b3674e7d9f169c2565 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/python/mozbuild/mozbuild/action/test_archive.py +++ b/python/mozbuild/mozbuild/action/test_archive.py @@ -365,22 +365,16 @@ ARCHIVE_FILES = { } ], 'mozharness': [ { 'source': buildconfig.topsrcdir, 'base': 'testing', 'pattern': 'mozharness/**', }, - { - 'source': buildconfig.topsrcdir, - 'base': 'third_party/python/virtualenv', - 'dest': 'mozharness/third_party/python/virtualenv', - 'pattern': '**', - }, ], 'reftest': [ { 'source': buildconfig.topobjdir, 'base': '_tests', 'pattern': 'reftest/**', }, {
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/AUTHORS.txt @@ -0,0 +1,91 @@ +Author +------ + +Ian Bicking + +Maintainers +----------- + +Brian Rosner +Carl Meyer +Jannis Leidel +Paul Moore +Paul Nasrat +Marcus Smith + +Contributors +------------ + +Alex Grönholm +Anatoly Techtonik +Antonio Cuni +Antonio Valentino +Armin Ronacher +Barry Warsaw +Benjamin Root +Bradley Ayers +Branden Rolston +Brandon Carl +Brian Kearns +Cap Petschulat +CBWhiz +Chris Adams +Chris McDonough +Christos Kontas +Christian Hudon +Christian Stefanescu +Christopher Nilsson +Cliff Xuan +Curt Micol +Damien Nozay +Dan Sully +Daniel Hahler +Daniel Holth +David Schoonover +Denis Costa +Doug Hellmann +Doug Napoleone +Douglas Creager +Eduard-Cristian Stefan +Erik M. Bray +Ethan Jucovy +Gabriel de Perthuis +Gunnlaugur Thor Briem +Graham Dennis +Greg Haskins +Jason Penney +Jason R. Coombs +Jeff Hammel +Jeremy Orem +Jason Penney +Jason R. Coombs +John Kleint +Jonathan Griffin +Jonathan Hitchcock +Jorge Vargas +Josh Bronson +Kamil Kisiel +Kyle Gibson +Konstantin Zemlyak +Kumar McMillan +Lars Francke +Marc Abramowitz +Mika Laitio +Mike Hommey +Miki Tebeka +Philip Jenvey +Philippe Ombredanne +Piotr Dobrogost +Preston Holmes +Ralf Schmitt +Raul Leal +Ronny Pfannschmidt +Satrajit Ghosh +Sergio de Carvalho +Stefano Rivera +Tarek Ziadé +Thomas Aglassinger +Vinay Sajip +Vitaly Babiy +Vladimir Rutsky +Wang Xuerui \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2007 Ian Bicking and Contributors +Copyright (c) 2009 Ian Bicking, The Open Planning Project +Copyright (c) 2011-2016 The virtualenv developers + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/MANIFEST.in @@ -0,0 +1,12 @@ +recursive-include docs * +recursive-include tests *.py *.sh *.expected +recursive-include virtualenv_support *.whl +recursive-include virtualenv_embedded * +recursive-exclude docs/_templates * +recursive-exclude docs/_build * +include virtualenv_support/__init__.py +include bin/* +include scripts/* +include *.py +include AUTHORS.txt +include LICENSE.txt
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/PKG-INFO @@ -0,0 +1,87 @@ +Metadata-Version: 1.1 +Name: virtualenv +Version: 15.0.1 +Summary: Virtual Python Environment builder +Home-page: https://virtualenv.pypa.io/ +Author: Jannis Leidel, Carl Meyer and Brian Rosner +Author-email: python-virtualenv@groups.google.com +License: MIT +Description: Virtualenv + ========== + + `Mailing list <http://groups.google.com/group/python-virtualenv>`_ | + `Issues <https://github.com/pypa/virtualenv/issues>`_ | + `Github <https://github.com/pypa/virtualenv>`_ | + `PyPI <https://pypi.python.org/pypi/virtualenv/>`_ | + User IRC: #pypa + Dev IRC: #pypa-dev + + Introduction + ------------ + + ``virtualenv`` is a tool to create isolated Python environments. + + The basic problem being addressed is one of dependencies and versions, + and indirectly permissions. Imagine you have an application that + needs version 1 of LibFoo, but another application requires version + 2. How can you use both these applications? If you install + everything into ``/usr/lib/python2.7/site-packages`` (or whatever your + platform's standard location is), it's easy to end up in a situation + where you unintentionally upgrade an application that shouldn't be + upgraded. + + Or more generally, what if you want to install an application *and + leave it be*? If an application works, any change in its libraries or + the versions of those libraries can break the application. + + Also, what if you can't install packages into the global + ``site-packages`` directory? For instance, on a shared host. + + In all these cases, ``virtualenv`` can help you. It creates an + environment that has its own installation directories, that doesn't + share libraries with other virtualenv environments (and optionally + doesn't access the globally installed libraries either). + + .. comment: + + Release History + =============== + + 15.0.1 (2016-03-17) + ------------------- + + * Print error message when DEST_DIR exists and is a file + + * Upgrade setuptools to 20.3 + + * Upgrade pip to 8.1.1. + + + 15.0.0 (2016-03-05) + ------------------- + + * Remove the `virtualenv-N.N` script from the package; this can no longer be + correctly created from a wheel installation. + Resolves #851, #692 + + * Remove accidental runtime dependency on pip by extracting certificate in the + subprocess. + + * Upgrade setuptools 20.2.2. + + * Upgrade pip to 8.1.0. + + + `Full Changelog <https://virtualenv.pypa.io/en/latest/changes.html>`_. +Keywords: setuptools deployment installation distutils +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/README.rst @@ -0,0 +1,31 @@ +virtualenv +========== + +A tool for creating isolated 'virtual' python environments. + +.. image:: https://img.shields.io/pypi/v/virtualenv.svg + :target: https://pypi.python.org/pypi/virtualenv + +.. image:: https://img.shields.io/travis/pypa/virtualenv/develop.svg + :target: http://travis-ci.org/pypa/virtualenv + +* `Installation <https://virtualenv.pypa.io/en/latest/installation.html>`_ +* `Documentation <https://virtualenv.pypa.io/>`_ +* `Changelog <https://virtualenv.pypa.io/en/latest/changes.html>`_ +* `Issues <https://github.com/pypa/virtualenv/issues>`_ +* `PyPI <https://pypi.python.org/pypi/virtualenv/>`_ +* `Github <https://github.com/pypa/virtualenv>`_ +* `User mailing list <http://groups.google.com/group/python-virtualenv>`_ +* `Dev mailing list <http://groups.google.com/group/pypa-dev>`_ +* User IRC: #pypa on Freenode. +* Dev IRC: #pypa-dev on Freenode. + + +Code of Conduct +--------------- + +Everyone interacting in the virtualenv project's codebases, issue trackers, +chat rooms, and mailing lists is expected to follow the +`PyPA Code of Conduct`_. + +.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/
new file mode 100755 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/bin/rebuild-script.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +""" +Helper script to rebuild virtualenv.py from virtualenv_support +""" +from __future__ import print_function + +import os +import re +import codecs +from zlib import crc32 + +here = os.path.dirname(__file__) +script = os.path.join(here, '..', 'virtualenv.py') + +gzip = codecs.lookup('zlib') +b64 = codecs.lookup('base64') + +file_regex = re.compile( + br'##file (.*?)\n([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*convert\("""\n(.*?)"""\)', + re.S) +file_template = b'##file %(filename)s\n%(varname)s = convert("""\n%(data)s""")' + +def rebuild(script_path): + with open(script_path, 'rb') as f: + script_content = f.read() + parts = [] + last_pos = 0 + match = None + for match in file_regex.finditer(script_content): + parts += [script_content[last_pos:match.start()]] + last_pos = match.end() + filename, fn_decoded = match.group(1), match.group(1).decode() + varname = match.group(2) + data = match.group(3) + + print('Found file %s' % fn_decoded) + pathname = os.path.join(here, '..', 'virtualenv_embedded', fn_decoded) + + with open(pathname, 'rb') as f: + embedded = f.read() + new_crc = crc32(embedded) + new_data = b64.encode(gzip.encode(embedded)[0])[0] + + if new_data == data: + print(' File up to date (crc: %s)' % new_crc) + parts += [match.group(0)] + continue + # Else: content has changed + crc = crc32(gzip.decode(b64.decode(data)[0])[0]) + print(' Content changed (crc: %s -> %s)' % + (crc, new_crc)) + new_match = file_template % { + b'filename': filename, + b'varname': varname, + b'data': new_data + } + parts += [new_match] + + parts += [script_content[last_pos:]] + new_content = b''.join(parts) + + if new_content != script_content: + print('Content updated; overwriting... ', end='') + with open(script_path, 'wb') as f: + f.write(new_content) + print('done.') + else: + print('No changes in content') + if match is None: + print('No variables were matched/found') + +if __name__ == '__main__': + rebuild(script)
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/Makefile @@ -0,0 +1,130 @@ +# 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) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +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 " 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/django-compressor.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-compressor.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/django-compressor" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-compressor" + @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." + +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."
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/changes.rst @@ -0,0 +1,985 @@ +Release History +=============== + +15.0.1 (2016-03-17) +------------------- + +* Print error message when DEST_DIR exists and is a file + +* Upgrade setuptools to 20.3 + +* Upgrade pip to 8.1.1. + + +15.0.0 (2016-03-05) +------------------- + +* Remove the `virtualenv-N.N` script from the package; this can no longer be + correctly created from a wheel installation. + Resolves :issue:`851`, :issue:`692` + +* Remove accidental runtime dependency on pip by extracting certificate in the + subprocess. + +* Upgrade setuptools 20.2.2. + +* Upgrade pip to 8.1.0. + + +14.0.6 (2016-02-07) +------------------- + +* Upgrade setuptools to 20.0 + +* Upgrade wheel to 0.29.0 + +* Fix an error where virtualenv didn't pass in a working ssl certificate for + pip, causing "weird" errors related to ssl. + + +14.0.5 (2016-02-01) +------------------- + +* Homogenize drive letter casing for both prefixes and filenames. :issue:`858` + + +14.0.4 (2016-01-31) +------------------- + +* Upgrade setuptools to 19.6.2 + +* Revert ac4ea65; only correct drive letter case. + Fixes :issue:`856`, :issue:`815` + + +14.0.3 (2016-01-28) +------------------- + +* Upgrade setuptools to 19.6.1 + + +14.0.2 (2016-01-28) +------------------- + +* Upgrade setuptools to 19.6 + +* Suppress any errors from `unset` on different shells (:pull:`843`) + +* Normalize letter case for prefix path checking. Fixes :issue:`837` + + +14.0.1 (2016-01-21) +------------------- + +* Upgrade from pip 8.0.0 to 8.0.2. + +* Fix the default of ``--(no-)download`` to default to downloading. + + +14.0.0 (2016-01-19) +------------------- + +* **BACKWARDS INCOMPATIBLE** Drop support for Python 3.2. + +* Upgrade setuptools to 19.4 + +* Upgrade wheel to 0.26.0 + +* Upgrade pip to 8.0.0 + +* Upgrade argparse to 1.4.0 + +* Added support for ``python-config`` script (:pull:`798`) + +* Updated activate.fish (:pull:`589`) (:pull:`799`) + +* Account for a ``site.pyo`` correctly in some python implementations (:pull:`759`) + +* Properly restore an empty PS1 (:issue:`407`) + +* Properly remove ``pydoc`` when deactivating + +* Remove workaround for very old Mageia / Mandriva linuxes (:pull:`472`) + +* Added a space after virtualenv name in the prompt: ``(env) $PS1`` + +* Make sure not to run a --user install when creating the virtualenv (:pull:`803`) + +* Remove virtualenv.py's path from sys.path when executing with a new + python. Fixes issue :issue:`779`, :issue:`763` (:pull:`805`) + +* Remove use of () in .bat files so ``Program Files (x86)`` works :issue:`35` + +* Download new releases of the preinstalled software from PyPI when there are + new releases available. This behavior can be disabled using + ``--no-download``. + +* Make ``--no-setuptools``, ``--no-pip``, and ``--no-wheel`` independent of + each other. + + +13.1.2 (2015-08-23) +------------------- + +* Upgrade pip to 7.1.2. + + +13.1.1 (2015-08-20) +------------------- + +* Upgrade pip to 7.1.1. + +* Upgrade setuptools to 18.2. + +* Make the activate script safe to use when bash is running with ``-u``. + + +13.1.0 (2015-06-30) +------------------- + +* Upgrade pip to 7.1.0 + +* Upgrade setuptools to 18.0.1 + + +13.0.3 (2015-06-01) +------------------- + +* Upgrade pip to 7.0.3 + + +13.0.2 (2015-06-01) +------------------- + +* Upgrade pip to 7.0.2 + +* Upgrade setuptools to 17.0 + + +13.0.1 (2015-05-22) +------------------- + +* Upgrade pip to 7.0.1 + + +13.0.0 (2015-05-21) +------------------- + +* Automatically install wheel when creating a new virutalenv. This can be + disabled by using the ``--no-wheel`` option. + +* Don't trust the current directory as a location to discover files to install + packages from. + +* Upgrade setuptools to 16.0. + +* Upgrade pip to 7.0.0. + + +12.1.1 (2015-04-07) +------------------- + +* Upgrade pip to 6.1.1 + + +12.1.0 (2015-04-07) +------------------- + +* Upgrade setuptools to 15.0 + +* Upgrade pip to 6.1.0 + + +12.0.7 (2015-02-04) +------------------- + +* Upgrade pip to 6.0.8 + + +12.0.6 (2015-01-28) +------------------- + +* Upgrade pip to 6.0.7 + +* Upgrade setuptools to 12.0.5 + + +12.0.5 (2015-01-03) +------------------- + +* Upgrade pip to 6.0.6 + +* Upgrade setuptools to 11.0 + + +12.0.4 (2014-12-23) +------------------- + +* Revert the fix to ``-p`` on Debian based pythons as it was broken in other + situations. + +* Revert several sys.path changes new in 12.0 which were breaking virtualenv. + +12.0.3 (2014-12-23) +------------------- + +* Fix an issue where Debian based Pythons would fail when using -p with the + host Python. + +* Upgrade pip to 6.0.3 + +12.0.2 (2014-12-23) +------------------- + +* Upgraded pip to 6.0.2 + +12.0.1 (2014-12-22) +------------------- + +* Upgraded pip to 6.0.1 + + +12.0 (2014-12-22) +----------------- + +* **PROCESS** Version numbers are now simply ``X.Y`` where the leading ``1`` + has been dropped. +* Split up documentation into structured pages +* Now using pytest framework +* Correct sys.path ordering for debian, issue #461 +* Correctly throws error on older Pythons, issue #619 +* Allow for empty $PATH, pull #601 +* Don't set prompt if $env:VIRTUAL_ENV_DISABLE_PROMPT is set for Powershell +* Updated setuptools to 7.0 + +1.11.6 (2014-05-16) +------------------- + +* Updated setuptools to 3.6 +* Updated pip to 1.5.6 + +1.11.5 (2014-05-03) +------------------- + +* Updated setuptools to 3.4.4 +* Updated documentation to use https://virtualenv.pypa.io/ +* Updated pip to 1.5.5 + +1.11.4 (2014-02-21) +------------------- + +* Updated pip to 1.5.4 + + +1.11.3 (2014-02-20) +------------------- + +* Updated setuptools to 2.2 +* Updated pip to 1.5.3 + + +1.11.2 (2014-01-26) +------------------- + +* Fixed easy_install installed virtualenvs by updated pip to 1.5.2 + +1.11.1 (2014-01-20) +------------------- + +* Fixed an issue where pip and setuptools were not getting installed when using + the ``--system-site-packages`` flag. +* Updated setuptools to fix an issue when installed with easy_install +* Fixed an issue with Python 3.4 and sys.stdout encoding being set to ascii +* Upgraded pip to v1.5.1 +* Upgraded setuptools to v2.1 + +1.11 (2014-01-02) +----------------- + +* **BACKWARDS INCOMPATIBLE** Switched to using wheels for the bundled copies of + setuptools and pip. Using sdists is no longer supported - users supplying + their own versions of pip/setuptools will need to provide wheels. +* **BACKWARDS INCOMPATIBLE** Modified the handling of ``--extra-search-dirs``. + This option now works like pip's ``--find-links`` option, in that it adds + extra directories to search for compatible wheels for pip and setuptools. + The actual wheel selected is chosen based on version and compatibility, using + the same algorithm as ``pip install setuptools``. +* Fixed #495, --always-copy was failing (#PR 511) +* Upgraded pip to v1.5 +* Upgraded setuptools to v1.4 + +1.10.1 (2013-08-07) +------------------- + +* **New Signing Key** Release 1.10.1 is using a different key than normal with + fingerprint: 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA +* Upgraded pip to v1.4.1 +* Upgraded setuptools to v0.9.8 + + +1.10 (2013-07-23) +----------------- + +* **BACKWARDS INCOMPATIBLE** Dropped support for Python 2.5. The minimum + supported Python version is now Python 2.6. + +* **BACKWARDS INCOMPATIBLE** Using ``virtualenv.py`` as an isolated script + (i.e. without an associated ``virtualenv_support`` directory) is no longer + supported for security reasons and will fail with an error. + + Along with this, ``--never-download`` is now always pinned to ``True``, and + is only being maintained in the short term for backward compatibility + (Pull #412). + +* **IMPORTANT** Switched to the new setuptools (v0.9.7) which has been merged + with Distribute_ again and works for Python 2 and 3 with one codebase. + The ``--distribute`` and ``--setuptools`` options are now no-op. + +* Updated to pip 1.4. + +* Added support for PyPy3k + +* Added the option to use a version number with the ``-p`` option to get the + system copy of that Python version (Windows only) + +* Removed embedded ``ez_setup.py``, ``distribute_setup.py`` and + ``distribute_from_egg.py`` files as part of switching to merged setuptools. + +* Fixed ``--relocatable`` to work better on Windows. + +* Fixed issue with readline on Windows. + +.. _Distribute: https://pypi.python.org/pypi/distribute + +1.9.1 (2013-03-08) +------------------ + +* Updated to pip 1.3.1 that fixed a major backward incompatible change of + parsing URLs to externally hosted packages that got accidentally included + in pip 1.3. + +1.9 (2013-03-07) +---------------- + +* Unset VIRTUAL_ENV environment variable in deactivate.bat (Pull #364) +* Upgraded distribute to 0.6.34. +* Added ``--no-setuptools`` and ``--no-pip`` options (Pull #336). +* Fixed Issue #373. virtualenv-1.8.4 was failing in cygwin (Pull #382). +* Fixed Issue #378. virtualenv is now "multiarch" aware on debian/ubuntu (Pull #379). +* Fixed issue with readline module path on pypy and OSX (Pull #374). +* Made 64bit detection compatible with Python 2.5 (Pull #393). + + +1.8.4 (2012-11-25) +------------------ + +* Updated distribute to 0.6.31. This fixes #359 (numpy install regression) on + UTF-8 platforms, and provides a workaround on other platforms: + ``PYTHONIOENCODING=utf8 pip install numpy``. + +* When installing virtualenv via curl, don't forget to filter out arguments + the distribute setup script won't understand. Fixes #358. + +* Added some more integration tests. + +* Removed the unsupported embedded setuptools egg for Python 2.4 to reduce + file size. + +1.8.3 (2012-11-21) +------------------ + +* Fixed readline on OS X. Thanks minrk + +* Updated distribute to 0.6.30 (improves our error reporting, plus new + distribute features and fixes). Thanks Gabriel (g2p) + +* Added compatibility with multiarch Python (Python 3.3 for example). Added an + integration test. Thanks Gabriel (g2p) + +* Added ability to install distribute from a user-provided egg, rather than the + bundled sdist, for better speed. Thanks Paul Moore. + +* Make the creation of lib64 symlink smarter about already-existing symlink, + and more explicit about full paths. Fixes #334 and #330. Thanks Jeremy Orem. + +* Give lib64 site-dir preference over lib on 64-bit systems, to avoid wrong + 32-bit compiles in the venv. Fixes #328. Thanks Damien Nozay. + +* Fix a bug with prompt-handling in ``activate.csh`` in non-interactive csh + shells. Fixes #332. Thanks Benjamin Root for report and patch. + +* Make it possible to create a virtualenv from within a Python + 3.3. pyvenv. Thanks Chris McDonough for the report. + +* Add optional --setuptools option to be able to switch to it in case + distribute is the default (like in Debian). + +1.8.2 (2012-09-06) +------------------ + +* Updated the included pip version to 1.2.1 to fix regressions introduced + there in 1.2. + + +1.8.1 (2012-09-03) +------------------ + +* Fixed distribute version used with `--never-download`. Thanks michr for + report and patch. + +* Fix creating Python 3.3 based virtualenvs by unsetting the + ``__PYVENV_LAUNCHER__`` environment variable in subprocesses. + + +1.8 (2012-09-01) +---------------- + +* **Dropped support for Python 2.4** The minimum supported Python version is + now Python 2.5. + +* Fix `--relocatable` on systems that use lib64. Fixes #78. Thanks Branden + Rolston. + +* Symlink some additional modules under Python 3. Fixes #194. Thanks Vinay + Sajip, Ian Clelland, and Stefan Holek for the report. + +* Fix ``--relocatable`` when a script uses ``__future__`` imports. Thanks + Branden Rolston. + +* Fix a bug in the config option parser that prevented setting negative + options with environment variables. Thanks Ralf Schmitt. + +* Allow setting ``--no-site-packages`` from the config file. + +* Use ``/usr/bin/multiarch-platform`` if available to figure out the include + directory. Thanks for the patch, Mika Laitio. + +* Fix ``install_name_tool`` replacement to work on Python 3.X. + +* Handle paths of users' site-packages on Mac OS X correctly when changing + the prefix. + +* Updated the embedded version of distribute to 0.6.28 and pip to 1.2. + + +1.7.2 (2012-06-22) +------------------ + +* Updated to distribute 0.6.27. + +* Fix activate.fish on OS X. Fixes #8. Thanks David Schoonover. + +* Create a virtualenv-x.x script with the Python version when installing, so + virtualenv for multiple Python versions can be installed to the same + script location. Thanks Miki Tebeka. + +* Restored ability to create a virtualenv with a path longer than 78 + characters, without breaking creation of virtualenvs with non-ASCII paths. + Thanks, Bradley Ayers. + +* Added ability to create virtualenvs without having installed Apple's + developers tools (using an own implementation of ``install_name_tool``). + Thanks Mike Hommey. + +* Fixed PyPy and Jython support on Windows. Thanks Konstantin Zemlyak. + +* Added pydoc script to ease use. Thanks Marc Abramowitz. Fixes #149. + +* Fixed creating a bootstrap script on Python 3. Thanks Raul Leal. Fixes #280. + +* Fixed inconsistency when having set the ``PYTHONDONTWRITEBYTECODE`` env var + with the --distribute option or the ``VIRTUALENV_USE_DISTRIBUTE`` env var. + ``VIRTUALENV_USE_DISTRIBUTE`` is now considered again as a legacy alias. + + +1.7.1.2 (2012-02-17) +-------------------- + +* Fixed minor issue in `--relocatable`. Thanks, Cap Petschulat. + + +1.7.1.1 (2012-02-16) +-------------------- + +* Bumped the version string in ``virtualenv.py`` up, too. + +* Fixed rST rendering bug of long description. + + +1.7.1 (2012-02-16) +------------------ + +* Update embedded pip to version 1.1. + +* Fix `--relocatable` under Python 3. Thanks Doug Hellmann. + +* Added environ PATH modification to activate_this.py. Thanks Doug + Napoleone. Fixes #14. + +* Support creating virtualenvs directly from a Python build directory on + Windows. Thanks CBWhiz. Fixes #139. + +* Use non-recursive symlinks to fix things up for posix_local install + scheme. Thanks michr. + +* Made activate script available for use with msys and cygwin on Windows. + Thanks Greg Haskins, Cliff Xuan, Jonathan Griffin and Doug Napoleone. + Fixes #176. + +* Fixed creation of virtualenvs on Windows when Python is not installed for + all users. Thanks Anatoly Techtonik for report and patch and Doug + Napoleone for testing and confirmation. Fixes #87. + +* Fixed creation of virtualenvs using -p in installs where some modules + that ought to be in the standard library (e.g. `readline`) are actually + installed in `site-packages` next to `virtualenv.py`. Thanks Greg Haskins + for report and fix. Fixes #167. + +* Added activation script for Powershell (signed by Jannis Leidel). Many + thanks to Jason R. Coombs. + + +1.7 (2011-11-30) +---------------- + +* Gave user-provided ``--extra-search-dir`` priority over default dirs for + finding setuptools/distribute (it already had priority for finding pip). + Thanks Ethan Jucovy. + +* Updated embedded Distribute release to 0.6.24. Thanks Alex Gronholm. + +* Made ``--no-site-packages`` behavior the default behavior. The + ``--no-site-packages`` flag is still permitted, but displays a warning when + used. Thanks Chris McDonough. + +* New flag: ``--system-site-packages``; this flag should be passed to get the + previous default global-site-package-including behavior back. + +* Added ability to set command options as environment variables and options + in a ``virtualenv.ini`` file. + +* Fixed various encoding related issues with paths. Thanks Gunnlaugur Thor Briem. + +* Made ``virtualenv.py`` script executable. + + +1.6.4 (2011-07-21) +------------------ + +* Restored ability to run on Python 2.4, too. + + +1.6.3 (2011-07-16) +------------------ + +* Restored ability to run on Python < 2.7. + + +1.6.2 (2011-07-16) +------------------ + +* Updated embedded distribute release to 0.6.19. + +* Updated embedded pip release to 1.0.2. + +* Fixed #141 - Be smarter about finding pkg_resources when using the + non-default Python interpreter (by using the ``-p`` option). + +* Fixed #112 - Fixed path in docs. + +* Fixed #109 - Corrected doctests of a Logger method. + +* Fixed #118 - Fixed creating virtualenvs on platforms that use the + "posix_local" install scheme, such as Ubuntu with Python 2.7. + +* Add missing library to Python 3 virtualenvs (``_dummy_thread``). + + +1.6.1 (2011-04-30) +------------------ + +* Start to use git-flow. + +* Added support for PyPy 1.5 + +* Fixed #121 -- added sanity-checking of the -p argument. Thanks Paul Nasrat. + +* Added progress meter for pip installation as well as setuptools. Thanks Ethan + Jucovy. + +* Added --never-download and --search-dir options. Thanks Ethan Jucovy. + + +1.6 +--- + +* Added Python 3 support! Huge thanks to Vinay Sajip and Vitaly Babiy. + +* Fixed creation of virtualenvs on Mac OS X when standard library modules + (readline) are installed outside the standard library. + +* Updated bundled pip to 1.0. + + +1.5.2 +----- + +* Moved main repository to Github: https://github.com/pypa/virtualenv + +* Transferred primary maintenance from Ian to Jannis Leidel, Carl Meyer and Brian Rosner + +* Fixed a few more pypy related bugs. + +* Updated bundled pip to 0.8.2. + +* Handed project over to new team of maintainers. + +* Moved virtualenv to Github at https://github.com/pypa/virtualenv + + +1.5.1 +----- + +* Added ``_weakrefset`` requirement for Python 2.7.1. + +* Fixed Windows regression in 1.5 + + +1.5 +--- + +* Include pip 0.8.1. + +* Add support for PyPy. + +* Uses a proper temporary dir when installing environment requirements. + +* Add ``--prompt`` option to be able to override the default prompt prefix. + +* Fix an issue with ``--relocatable`` on Windows. + +* Fix issue with installing the wrong version of distribute. + +* Add fish and csh activate scripts. + + +1.4.9 +----- + +* Include pip 0.7.2 + + +1.4.8 +----- + +* Fix for Mac OS X Framework builds that use + ``--universal-archs=intel`` + +* Fix ``activate_this.py`` on Windows. + +* Allow ``$PYTHONHOME`` to be set, so long as you use ``source + bin/activate`` it will get unset; if you leave it set and do not + activate the environment it will still break the environment. + +* Include pip 0.7.1 + + +1.4.7 +----- + +* Include pip 0.7 + + +1.4.6 +----- + +* Allow ``activate.sh`` to skip updating the prompt (by setting + ``$VIRTUAL_ENV_DISABLE_PROMPT``). + + +1.4.5 +----- + +* Include pip 0.6.3 + +* Fix ``activate.bat`` and ``deactivate.bat`` under Windows when + ``PATH`` contained a parenthesis + + +1.4.4 +----- + +* Include pip 0.6.2 and Distribute 0.6.10 + +* Create the ``virtualenv`` script even when Setuptools isn't + installed + +* Fix problem with ``virtualenv --relocate`` when ``bin/`` has + subdirectories (e.g., ``bin/.svn/``); from Alan Franzoni. + +* If you set ``$VIRTUALENV_DISTRIBUTE`` then virtualenv will use + Distribute by default (so you don't have to remember to use + ``--distribute``). + + +1.4.3 +----- + +* Include pip 0.6.1 + + +1.4.2 +----- + +* Fix pip installation on Windows + +* Fix use of stand-alone ``virtualenv.py`` (and boot scripts) + +* Exclude ~/.local (user site-packages) from environments when using + ``--no-site-packages`` + + +1.4.1 +----- + +* Include pip 0.6 + + +1.4 +--- + +* Updated setuptools to 0.6c11 + +* Added the --distribute option + +* Fixed packaging problem of support-files + + +1.3.4 +----- + +* Virtualenv now copies the actual embedded Python binary on + Mac OS X to fix a hang on Snow Leopard (10.6). + +* Fail more gracefully on Windows when ``win32api`` is not installed. + +* Fix site-packages taking precedent over Jython's ``__classpath__`` + and also specially handle the new ``__pyclasspath__`` entry in + ``sys.path``. + +* Now copies Jython's ``registry`` file to the virtualenv if it exists. + +* Better find libraries when compiling extensions on Windows. + +* Create ``Scripts\pythonw.exe`` on Windows. + +* Added support for the Debian/Ubuntu + ``/usr/lib/pythonX.Y/dist-packages`` directory. + +* Set ``distutils.sysconfig.get_config_vars()['LIBDIR']`` (based on + ``sys.real_prefix``) which is reported to help building on Windows. + +* Make ``deactivate`` work on ksh + +* Fixes for ``--python``: make it work with ``--relocatable`` and the + symlink created to the exact Python version. + + +1.3.3 +----- + +* Use Windows newlines in ``activate.bat``, which has been reported to help + when using non-ASCII directory names. + +* Fixed compatibility with Jython 2.5b1. + +* Added a function ``virtualenv.install_python`` for more fine-grained + access to what ``virtualenv.create_environment`` does. + +* Fix `a problem <https://bugs.launchpad.net/virtualenv/+bug/241581>`_ + with Windows and paths that contain spaces. + +* If ``/path/to/env/.pydistutils.cfg`` exists (or + ``/path/to/env/pydistutils.cfg`` on Windows systems) then ignore + ``~/.pydistutils.cfg`` and use that other file instead. + +* Fix ` a problem + <https://bugs.launchpad.net/virtualenv/+bug/340050>`_ picking up + some ``.so`` libraries in ``/usr/local``. + + +1.3.2 +----- + +* Remove the ``[install] prefix = ...`` setting from the virtualenv + ``distutils.cfg`` -- this has been causing problems for a lot of + people, in rather obscure ways. + +* If you use a boot script it will attempt to import ``virtualenv`` + and find a pre-downloaded Setuptools egg using that. + +* Added platform-specific paths, like ``/usr/lib/pythonX.Y/plat-linux2`` + + +1.3.1 +----- + +* Real Python 2.6 compatibility. Backported the Python 2.6 updates to + ``site.py``, including `user directories + <http://docs.python.org/dev/whatsnew/2.6.html#pep-370-per-user-site-packages-directory>`_ + (this means older versions of Python will support user directories, + whether intended or not). + +* Always set ``[install] prefix`` in ``distutils.cfg`` -- previously + on some platforms where a system-wide ``distutils.cfg`` was present + with a ``prefix`` setting, packages would be installed globally + (usually in ``/usr/local/lib/pythonX.Y/site-packages``). + +* Sometimes Cygwin seems to leave ``.exe`` off ``sys.executable``; a + workaround is added. + +* Fix ``--python`` option. + +* Fixed handling of Jython environments that use a + jython-complete.jar. + + +1.3 +--- + +* Update to Setuptools 0.6c9 +* Added an option ``virtualenv --relocatable EXISTING_ENV``, which + will make an existing environment "relocatable" -- the paths will + not be absolute in scripts, ``.egg-info`` and ``.pth`` files. This + may assist in building environments that can be moved and copied. + You have to run this *after* any new packages installed. +* Added ``bin/activate_this.py``, a file you can use like + ``execfile("path_to/activate_this.py", + dict(__file__="path_to/activate_this.py"))`` -- this will activate + the environment in place, similar to what `the mod_wsgi example + does <http://code.google.com/p/modwsgi/wiki/VirtualEnvironments>`_. +* For Mac framework builds of Python, the site-packages directory + ``/Library/Python/X.Y/site-packages`` is added to ``sys.path``, from + Andrea Rech. +* Some platform-specific modules in Macs are added to the path now + (``plat-darwin/``, ``plat-mac/``, ``plat-mac/lib-scriptpackages``), + from Andrea Rech. +* Fixed a small Bashism in the ``bin/activate`` shell script. +* Added ``__future__`` to the list of required modules, for Python + 2.3. You'll still need to backport your own ``subprocess`` module. +* Fixed the ``__classpath__`` entry in Jython's ``sys.path`` taking + precedent over virtualenv's libs. + + +1.2 +--- + +* Added a ``--python`` option to select the Python interpreter. +* Add ``warnings`` to the modules copied over, for Python 2.6 support. +* Add ``sets`` to the module copied over for Python 2.3 (though Python + 2.3 still probably doesn't work). + + +1.1.1 +----- + +* Added support for Jython 2.5. + + +1.1 +--- + +* Added support for Python 2.6. +* Fix a problem with missing ``DLLs/zlib.pyd`` on Windows. Create +* ``bin/python`` (or ``bin/python.exe``) even when you run virtualenv + with an interpreter named, e.g., ``python2.4`` +* Fix MacPorts Python +* Added --unzip-setuptools option +* Update to Setuptools 0.6c8 +* If the current directory is not writable, run ez_setup.py in ``/tmp`` +* Copy or symlink over the ``include`` directory so that packages will + more consistently compile. + + +1.0 +--- + +* Fix build on systems that use ``/usr/lib64``, distinct from + ``/usr/lib`` (specifically CentOS x64). +* Fixed bug in ``--clear``. +* Fixed typos in ``deactivate.bat``. +* Preserve ``$PYTHONPATH`` when calling subprocesses. + + +0.9.2 +----- + +* Fix include dir copying on Windows (makes compiling possible). +* Include the main ``lib-tk`` in the path. +* Patch ``distutils.sysconfig``: ``get_python_inc`` and + ``get_python_lib`` to point to the global locations. +* Install ``distutils.cfg`` before Setuptools, so that system + customizations of ``distutils.cfg`` won't effect the installation. +* Add ``bin/pythonX.Y`` to the virtualenv (in addition to + ``bin/python``). +* Fixed an issue with Mac Framework Python builds, and absolute paths + (from Ronald Oussoren). + + +0.9.1 +----- + +* Improve ability to create a virtualenv from inside a virtualenv. +* Fix a little bug in ``bin/activate``. +* Actually get ``distutils.cfg`` to work reliably. + + +0.9 +--- + +* Added ``lib-dynload`` and ``config`` to things that need to be + copied over in an environment. +* Copy over or symlink the ``include`` directory, so that you can + build packages that need the C headers. +* Include a ``distutils`` package, so you can locally update + ``distutils.cfg`` (in ``lib/pythonX.Y/distutils/distutils.cfg``). +* Better avoid downloading Setuptools, and hitting PyPI on environment + creation. +* Fix a problem creating a ``lib64/`` directory. +* Should work on MacOSX Framework builds (the default Python + installations on Mac). Thanks to Ronald Oussoren. + + +0.8.4 +----- + +* Windows installs would sometimes give errors about ``sys.prefix`` that + were inaccurate. +* Slightly prettier output. + + +0.8.3 +----- + +* Added support for Windows. + + +0.8.2 +----- + +* Give a better warning if you are on an unsupported platform (Mac + Framework Pythons, and Windows). +* Give error about running while inside a workingenv. +* Give better error message about Python 2.3. + + +0.8.1 +----- + +Fixed packaging of the library. + + +0.8 +--- + +Initial release. Everything is changed and new!
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/conf.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# +# Paste documentation build configuration file, created by +# sphinx-quickstart on Tue Apr 22 22:08:49 2008. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default value; values that are commented out +# serve to show the default value. + +import os +import sys + +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +# If your extensions are in another directory, add it here. +sys.path.insert(0, os.path.abspath(os.pardir)) + +# General configuration +# --------------------- + +# 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.extlinks'] + +# Add any paths that contain templates here, relative to this directory. +#templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General substitutions. +project = 'virtualenv' +copyright = '2007-2014, Ian Bicking, The Open Planning Project, PyPA' + +# The default replacements for |version| and |release|, also used in various +# other places throughout the built documents. +try: + from virtualenv import __version__ + # The short X.Y version. + version = '.'.join(__version__.split('.')[:2]) + # The full version, including alpha/beta/rc tags. + release = __version__ +except ImportError: + version = release = 'dev' + +# 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 documents that shouldn't be included in the build. +unused_docs = [] + +# 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' + +extlinks = { + 'issue': ('https://github.com/pypa/virtualenv/issues/%s', '#'), + 'pull': ('https://github.com/pypa/virtualenv/pull/%s', 'PR #'), +} + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +#html_style = 'default.css' + +html_theme = 'default' +if not on_rtd: + try: + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + except ImportError: + pass + + +# 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 + +# Content template for the index page. +#html_index = '' + +# 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_use_modindex = True + +# If true, the reST sources are included in the HTML build as _sources/<name>. +#html_copy_source = True + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Pastedoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +#latex_documents = [] + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/development.rst @@ -0,0 +1,61 @@ +Development +=========== + +Contributing +------------ + +Refer to the `pip development`_ documentation - it applies equally to +virtualenv, except that virtualenv issues should filed on the `virtualenv +repo`_ at GitHub. + +Virtualenv's release schedule is tied to pip's -- each time there's a new pip +release, there will be a new virtualenv release that bundles the new version of +pip. + +Files in the `virtualenv_embedded/` subdirectory are embedded into +`virtualenv.py` itself as base64-encoded strings (in order to support +single-file use of `virtualenv.py` without installing it). If your patch +changes any file in `virtualenv_embedded/`, run `bin/rebuild-script.py` to +update the embedded version of that file in `virtualenv.py`; commit that and +submit it as part of your patch / pull request. + +.. _pip development: http://www.pip-installer.org/en/latest/development.html +.. _virtualenv repo: https://github.com/pypa/virtualenv/ + +Running the tests +----------------- + +Virtualenv's test suite is small and not yet at all comprehensive, but we aim +to grow it. + +The easy way to run tests (handles test dependencies automatically):: + + $ python setup.py test + +If you want to run only a selection of the tests, you'll need to run them +directly with pytest instead. Create a virtualenv, and install required +packages:: + + $ pip install pytest mock + +Run pytest:: + + $ pytest + +Or select just a single test file to run:: + + $ pytest tests/test_virtualenv + +Status and License +------------------ + +``virtualenv`` is a successor to `workingenv +<http://cheeseshop.python.org/pypi/workingenv.py>`_, and an extension +of `virtual-python +<http://peak.telecommunity.com/DevCenter/EasyInstall#creating-a-virtual-python>`_. + +It was written by Ian Bicking, sponsored by the `Open Planning +Project <http://openplans.org>`_ and is now maintained by a +`group of developers <https://github.com/pypa/virtualenv/raw/master/AUTHORS.txt>`_. +It is licensed under an +`MIT-style permissive license <https://github.com/pypa/virtualenv/raw/master/LICENSE.txt>`_.
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/index.rst @@ -0,0 +1,137 @@ +Virtualenv +========== + +`Mailing list <http://groups.google.com/group/python-virtualenv>`_ | +`Issues <https://github.com/pypa/virtualenv/issues>`_ | +`Github <https://github.com/pypa/virtualenv>`_ | +`PyPI <https://pypi.python.org/pypi/virtualenv/>`_ | +User IRC: #pypa +Dev IRC: #pypa-dev + +Introduction +------------ + +``virtualenv`` is a tool to create isolated Python environments. + +The basic problem being addressed is one of dependencies and versions, +and indirectly permissions. Imagine you have an application that +needs version 1 of LibFoo, but another application requires version +2. How can you use both these applications? If you install +everything into ``/usr/lib/python2.7/site-packages`` (or whatever your +platform's standard location is), it's easy to end up in a situation +where you unintentionally upgrade an application that shouldn't be +upgraded. + +Or more generally, what if you want to install an application *and +leave it be*? If an application works, any change in its libraries or +the versions of those libraries can break the application. + +Also, what if you can't install packages into the global +``site-packages`` directory? For instance, on a shared host. + +In all these cases, ``virtualenv`` can help you. It creates an +environment that has its own installation directories, that doesn't +share libraries with other virtualenv environments (and optionally +doesn't access the globally installed libraries either). + +.. comment: split here + +.. toctree:: + :maxdepth: 2 + + installation + userguide + reference + development + changes + +.. warning:: + + Python bugfix releases 2.6.8, 2.7.3, 3.1.5 and 3.2.3 include a change that + will cause "import random" to fail with "cannot import name urandom" on any + virtualenv created on a Unix host with an earlier release of Python + 2.6/2.7/3.1/3.2, if the underlying system Python is upgraded. This is due to + the fact that a virtualenv uses the system Python's standard library but + contains its own copy of the Python interpreter, so an upgrade to the system + Python results in a mismatch between the version of the Python interpreter + and the version of the standard library. It can be fixed by removing + ``$ENV/bin/python`` and re-running virtualenv on the same target directory + with the upgraded Python. + +Other Documentation and Links +----------------------------- + +* `Blog announcement of virtualenv`__. + + .. __: http://blog.ianbicking.org/2007/10/10/workingenv-is-dead-long-live-virtualenv/ + +* James Gardner has written a tutorial on using `virtualenv with + Pylons + <http://wiki.pylonshq.com/display/pylonscookbook/Using+a+Virtualenv+Sandbox>`_. + +* Chris Perkins created a `showmedo video including virtualenv + <http://showmedo.com/videos/video?name=2910000&fromSeriesID=291>`_. + +* Doug Hellmann's `virtualenvwrapper`_ is a useful set of scripts to make + your workflow with many virtualenvs even easier. `His initial blog post on it`__. + He also wrote `an example of using virtualenv to try IPython`__. + + .. _virtualenvwrapper: https://pypi.python.org/pypi/virtualenvwrapper/ + .. __: https://doughellmann.com/blog/2008/05/01/virtualenvwrapper/ + .. __: https://doughellmann.com/blog/2008/02/01/ipython-and-virtualenv/ + +* `Pew`_ is another wrapper for virtualenv that makes use of a different + activation technique. + + .. _Pew: https://pypi.python.org/pypi/pew/ + +* `Using virtualenv with mod_wsgi + <http://code.google.com/p/modwsgi/wiki/VirtualEnvironments>`_. + +* `virtualenv commands + <https://github.com/thisismedium/virtualenv-commands>`_ for some more + workflow-related tools around virtualenv. + +* PyCon US 2011 talk: `Reverse-engineering Ian Bicking's brain: inside pip and virtualenv + <http://pyvideo.org/video/568/reverse-engineering-ian-bicking--39-s-brain--insi>`_. + By the end of the talk, you'll have a good idea exactly how pip + and virtualenv do their magic, and where to go looking in the source + for particular behaviors or bug fixes. + +Compare & Contrast with Alternatives +------------------------------------ + +There are several alternatives that create isolated environments: + +* ``workingenv`` (which I do not suggest you use anymore) is the + predecessor to this library. It used the main Python interpreter, + but relied on setting ``$PYTHONPATH`` to activate the environment. + This causes problems when running Python scripts that aren't part of + the environment (e.g., a globally installed ``hg`` or ``bzr``). It + also conflicted a lot with Setuptools. + +* `virtual-python + <http://peak.telecommunity.com/DevCenter/EasyInstall#creating-a-virtual-python>`_ + is also a predecessor to this library. It uses only symlinks, so it + couldn't work on Windows. It also symlinks over the *entire* + standard library and global ``site-packages``. As a result, it + won't see new additions to the global ``site-packages``. + + This script only symlinks a small portion of the standard library + into the environment, and so on Windows it is feasible to simply + copy these files over. Also, it creates a new/empty + ``site-packages`` and also adds the global ``site-packages`` to the + path, so updates are tracked separately. This script also installs + Setuptools automatically, saving a step and avoiding the need for + network access. + +* `zc.buildout <http://pypi.python.org/pypi/zc.buildout>`_ doesn't + create an isolated Python environment in the same style, but + achieves similar results through a declarative config file that sets + up scripts with very particular packages. As a declarative system, + it is somewhat easier to repeat and manage, but more difficult to + experiment with. ``zc.buildout`` includes the ability to setup + non-Python systems (e.g., a database server or an Apache instance). + +I *strongly* recommend anyone doing application development or +deployment use one of these tools.
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/installation.rst @@ -0,0 +1,58 @@ +Installation +============ + +.. warning:: + + We advise installing virtualenv-1.9 or greater. Prior to version 1.9, the + pip included in virtualenv did not download from PyPI over SSL. + +.. warning:: + + When using pip to install virtualenv, we advise using pip 1.3 or greater. + Prior to version 1.3, pip did not download from PyPI over SSL. + +.. warning:: + + We advise against using easy_install to install virtualenv when using + setuptools < 0.9.7, because easy_install didn't download from PyPI over SSL + and was broken in some subtle ways. + +To install globally with `pip` (if you have pip 1.3 or greater installed globally): + +:: + + $ [sudo] pip install virtualenv + +Or to get the latest unreleased dev version: + +:: + + $ [sudo] pip install https://github.com/pypa/virtualenv/tarball/develop + + +To install version X.X globally from source: + +:: + + $ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-X.X.tar.gz + $ tar xvfz virtualenv-X.X.tar.gz + $ cd virtualenv-X.X + $ [sudo] python setup.py install + + +To *use* locally from source: + +:: + + $ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-X.X.tar.gz + $ tar xvfz virtualenv-X.X.tar.gz + $ cd virtualenv-X.X + $ python virtualenv.py myVE + +.. note:: + + The ``virtualenv.py`` script is *not* supported if run without the + necessary pip/setuptools/virtualenv distributions available locally. All + of the installation methods above include a ``virtualenv_support`` + directory alongside ``virtualenv.py`` which contains a complete set of + pip and setuptools distributions, and so are fully supported.
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/make.bat @@ -0,0 +1,170 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% +) + +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. 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\django-compressor.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\django-compressor.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" == "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
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/reference.rst @@ -0,0 +1,261 @@ +Reference Guide +=============== + +``virtualenv`` Command +---------------------- + +.. _usage: + +Usage +~~~~~ + +:command:`virtualenv [OPTIONS] ENV_DIR` + + Where ``ENV_DIR`` is an absolute or relative path to a directory to create + the virtual environment in. + +.. _options: + +Options +~~~~~~~ + +.. program: virtualenv + +.. option:: --version + + show program's version number and exit + +.. option:: -h, --help + + show this help message and exit + +.. option:: -v, --verbose + + Increase verbosity. + +.. option:: -q, --quiet + + Decrease verbosity. + +.. option:: -p PYTHON_EXE, --python=PYTHON_EXE + + The Python interpreter to use, e.g., + --python=python2.5 will use the python2.5 interpreter + to create the new environment. The default is the + interpreter that virtualenv was installed with + (like ``/usr/bin/python``) + +.. option:: --clear + + Clear out the non-root install and start from scratch. + +.. option:: --system-site-packages + + Give the virtual environment access to the global + site-packages. + +.. option:: --always-copy + + Always copy files rather than symlinking. + +.. option:: --relocatable + + Make an EXISTING virtualenv environment relocatable. + This fixes up scripts and makes all .pth files relative. + +.. option:: --unzip-setuptools + + Unzip Setuptools when installing it. + +.. option:: --no-setuptools + + Do not install setuptools in the new virtualenv. + +.. option:: --no-pip + + Do not install pip in the new virtualenv. + +.. option:: --no-wheel + + Do not install wheel in the new virtualenv. + +.. option:: --extra-search-dir=DIR + + Directory to look for setuptools/pip distributions in. + This option can be specified multiple times. + +.. option:: --prompt=PROMPT + + Provides an alternative prompt prefix for this + environment. + +.. option:: --download + + Download preinstalled packages from PyPI. + +.. option:: --no-download + + Do not download preinstalled packages from PyPI. + +.. option:: --no-site-packages + + DEPRECATED. Retained only for backward compatibility. + Not having access to global site-packages is now the + default behavior. + +.. option:: --distribute +.. option:: --setuptools + + Legacy; now have no effect. Before version 1.10 these could be used + to choose whether to install Distribute_ or Setuptools_ into the created + virtualenv. Distribute has now been merged into Setuptools, and the + latter is always installed. + +.. _Distribute: https://pypi.python.org/pypi/distribute +.. _Setuptools: https://pypi.python.org/pypi/setuptools + + +Configuration +------------- + +Environment Variables +~~~~~~~~~~~~~~~~~~~~~ + +Each command line option is automatically used to look for environment +variables with the name format ``VIRTUALENV_<UPPER_NAME>``. That means +the name of the command line options are capitalized and have dashes +(``'-'``) replaced with underscores (``'_'``). + +For example, to automatically use a custom Python binary instead of the +one virtualenv is run with you can also set an environment variable:: + + $ export VIRTUALENV_PYTHON=/opt/python-3.3/bin/python + $ virtualenv ENV + +It's the same as passing the option to virtualenv directly:: + + $ virtualenv --python=/opt/python-3.3/bin/python ENV + +This also works for appending command line options, like ``--find-links``. +Just leave an empty space between the passed values, e.g.:: + + $ export VIRTUALENV_EXTRA_SEARCH_DIR="/path/to/dists /path/to/other/dists" + $ virtualenv ENV + +is the same as calling:: + + $ virtualenv --extra-search-dir=/path/to/dists --extra-search-dir=/path/to/other/dists ENV + +.. envvar:: VIRTUAL_ENV_DISABLE_PROMPT + + Any virtualenv created when this is set to a non-empty value will not have + it's :ref:`activate` modify the shell prompt. + + +Configuration File +~~~~~~~~~~~~~~~~~~ + +virtualenv also looks for a standard ini config file. On Unix and Mac OS X +that's ``$HOME/.virtualenv/virtualenv.ini`` and on Windows, it's +``%APPDATA%\virtualenv\virtualenv.ini``. + +The names of the settings are derived from the long command line option, +e.g. the option :option:`--python <-p>` would look like this:: + + [virtualenv] + python = /opt/python-3.3/bin/python + +Appending options like :option:`--extra-search-dir` can be written on multiple +lines:: + + [virtualenv] + extra-search-dir = + /path/to/dists + /path/to/other/dists + +Please have a look at the output of :option:`--help <-h>` for a full list +of supported options. + + +Extending Virtualenv +-------------------- + + +Creating Your Own Bootstrap Scripts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +While this creates an environment, it doesn't put anything into the +environment. Developers may find it useful to distribute a script +that sets up a particular environment, for example a script that +installs a particular web application. + +To create a script like this, call +:py:func:`virtualenv.create_bootstrap_script`, and write the +result to your new bootstrapping script. + +.. py:function:: create_bootstrap_script(extra_text) + + Creates a bootstrap script from ``extra_text``, which is like + this script but with extend_parser, adjust_options, and after_install hooks. + +This returns a string that (written to disk of course) can be used +as a bootstrap script with your own customizations. The script +will be the standard virtualenv.py script, with your extra text +added (your extra text should be Python code). + +If you include these functions, they will be called: + +.. py:function:: extend_parser(optparse_parser) + + You can add or remove options from the parser here. + +.. py:function:: adjust_options(options, args) + + You can change options here, or change the args (if you accept + different kinds of arguments, be sure you modify ``args`` so it is + only ``[DEST_DIR]``). + +.. py:function:: after_install(options, home_dir) + + After everything is installed, this function is called. This + is probably the function you are most likely to use. An + example would be:: + + def after_install(options, home_dir): + if sys.platform == 'win32': + bin = 'Scripts' + else: + bin = 'bin' + subprocess.call([join(home_dir, bin, 'easy_install'), + 'MyPackage']) + subprocess.call([join(home_dir, bin, 'my-package-script'), + 'setup', home_dir]) + + This example immediately installs a package, and runs a setup + script from that package. + +Bootstrap Example +~~~~~~~~~~~~~~~~~ + +Here's a more concrete example of how you could use this:: + + import virtualenv, textwrap + output = virtualenv.create_bootstrap_script(textwrap.dedent(""" + import os, subprocess + def after_install(options, home_dir): + etc = join(home_dir, 'etc') + if not os.path.exists(etc): + os.makedirs(etc) + subprocess.call([join(home_dir, 'bin', 'easy_install'), + 'BlogApplication']) + subprocess.call([join(home_dir, 'bin', 'paster'), + 'make-config', 'BlogApplication', + join(etc, 'blog.ini')]) + subprocess.call([join(home_dir, 'bin', 'paster'), + 'setup-app', join(etc, 'blog.ini')]) + """)) + f = open('blog-bootstrap.py', 'w').write(output) + +Another example is available `here`__. + +.. __: https://github.com/socialplanning/fassembler/blob/master/fassembler/create-venv-script.py
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/docs/userguide.rst @@ -0,0 +1,258 @@ +User Guide +========== + + +Usage +----- + +Virtualenv has one basic command:: + + $ virtualenv ENV + +Where ``ENV`` is a directory to place the new virtual environment. It has +a number of usual effects (modifiable by many :ref:`options`): + + - :file:`ENV/lib/` and :file:`ENV/include/` are created, containing supporting + library files for a new virtualenv python. Packages installed in this + environment will live under :file:`ENV/lib/pythonX.X/site-packages/`. + + - :file:`ENV/bin` is created, where executables live - noticeably a new + :command:`python`. Thus running a script with ``#! /path/to/ENV/bin/python`` + would run that script under this virtualenv's python. + + - The crucial packages pip_ and setuptools_ are installed, which allow other + packages to be easily installed to the environment. This associated pip + can be run from :file:`ENV/bin/pip`. + +The python in your new virtualenv is effectively isolated from the python that +was used to create it. + +.. _pip: https://pypi.python.org/pypi/pip +.. _setuptools: https://pypi.python.org/pypi/setuptools + + +.. _activate: + +activate script +~~~~~~~~~~~~~~~ + +In a newly created virtualenv there will also be a :command:`activate` shell +script. For Windows systems, activation scripts are provided for +the Command Prompt and Powershell. + +On Posix systems, this resides in :file:`/ENV/bin/`, so you can run:: + + $ source bin/activate + +For some shells (e.g. the original Bourne Shell) you may need to use the +:command:`.` command, when :command:`source` does not exist. There are also +separate activate files for some other shells, like csh and fish. +:file:`bin/activate` should work for bash/zsh/dash. + +This will change your ``$PATH`` so its first entry is the virtualenv's +``bin/`` directory. (You have to use ``source`` because it changes your +shell environment in-place.) This is all it does; it's purely a +convenience. If you directly run a script or the python interpreter +from the virtualenv's ``bin/`` directory (e.g. ``path/to/ENV/bin/pip`` +or ``/path/to/ENV/bin/python-script.py``) there's no need for +activation. + +The ``activate`` script will also modify your shell prompt to indicate +which environment is currently active. To disable this behaviour, see +:envvar:`VIRTUAL_ENV_DISABLE_PROMPT`. + +To undo these changes to your path (and prompt), just run:: + + $ deactivate + +On Windows, the equivalent `activate` script is in the ``Scripts`` folder:: + + > \path\to\env\Scripts\activate + +And type ``deactivate`` to undo the changes. + +Based on your active shell (CMD.exe or Powershell.exe), Windows will use +either activate.bat or activate.ps1 (as appropriate) to activate the +virtual environment. If using Powershell, see the notes about code signing +below. + +.. note:: + + If using Powershell, the ``activate`` script is subject to the + `execution policies`_ on the system. By default on Windows 7, the system's + excution policy is set to ``Restricted``, meaning no scripts like the + ``activate`` script are allowed to be executed. But that can't stop us + from changing that slightly to allow it to be executed. + + In order to use the script, you can relax your system's execution + policy to ``AllSigned``, meaning all scripts on the system must be + digitally signed to be executed. Since the virtualenv activation + script is signed by one of the authors (Jannis Leidel) this level of + the execution policy suffices. As an administrator run:: + + PS C:\> Set-ExecutionPolicy AllSigned + + Then you'll be asked to trust the signer, when executing the script. + You will be prompted with the following:: + + PS C:\> virtualenv .\foo + New python executable in C:\foo\Scripts\python.exe + Installing setuptools................done. + Installing pip...................done. + PS C:\> .\foo\scripts\activate + + Do you want to run software from this untrusted publisher? + File C:\foo\scripts\activate.ps1 is published by E=jannis@leidel.info, + CN=Jannis Leidel, L=Berlin, S=Berlin, C=DE, Description=581796-Gh7xfJxkxQSIO4E0 + and is not trusted on your system. Only run scripts from trusted publishers. + [V] Never run [D] Do not run [R] Run once [A] Always run [?] Help + (default is "D"):A + (foo) PS C:\> + + If you select ``[A] Always Run``, the certificate will be added to the + Trusted Publishers of your user account, and will be trusted in this + user's context henceforth. If you select ``[R] Run Once``, the script will + be run, but you will be prometed on a subsequent invocation. Advanced users + can add the signer's certificate to the Trusted Publishers of the Computer + account to apply to all users (though this technique is out of scope of this + document). + + Alternatively, you may relax the system execution policy to allow running + of local scripts without verifying the code signature using the following:: + + PS C:\> Set-ExecutionPolicy RemoteSigned + + Since the ``activate.ps1`` script is generated locally for each virtualenv, + it is not considered a remote script and can then be executed. + +.. _`execution policies`: http://technet.microsoft.com/en-us/library/dd347641.aspx + +Removing an Environment +~~~~~~~~~~~~~~~~~~~~~~~ + +Removing a virtual environment is simply done by deactivating it and deleting the +environment folder with all its contents:: + + (ENV)$ deactivate + $ rm -r /path/to/ENV + +The :option:`--system-site-packages` Option +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you build with ``virtualenv --system-site-packages ENV``, your virtual +environment will inherit packages from ``/usr/lib/python2.7/site-packages`` +(or wherever your global site-packages directory is). + +This can be used if you have control over the global site-packages directory, +and you want to depend on the packages there. If you want isolation from the +global system, do not use this flag. + +Windows Notes +~~~~~~~~~~~~~ + +Some paths within the virtualenv are slightly different on Windows: scripts and +executables on Windows go in ``ENV\Scripts\`` instead of ``ENV/bin/`` and +libraries go in ``ENV\Lib\`` rather than ``ENV/lib/``. + +To create a virtualenv under a path with spaces in it on Windows, you'll need +the `win32api <http://sourceforge.net/projects/pywin32/>`_ library installed. + + +Using Virtualenv without ``bin/python`` +--------------------------------------- + +Sometimes you can't or don't want to use the Python interpreter +created by the virtualenv. For instance, in a `mod_python +<http://www.modpython.org/>`_ or `mod_wsgi <http://www.modwsgi.org/>`_ +environment, there is only one interpreter. + +Luckily, it's easy. You must use the custom Python interpreter to +*install* libraries. But to *use* libraries, you just have to be sure +the path is correct. A script is available to correct the path. You +can setup the environment like:: + + activate_this = '/path/to/env/bin/activate_this.py' + execfile(activate_this, dict(__file__=activate_this)) + +This will change ``sys.path`` and even change ``sys.prefix``, but also allow +you to use an existing interpreter. Items in your environment will show up +first on ``sys.path``, before global items. However, global items will +always be accessible (as if the :option:`--system-site-packages` flag had been +used in creating the environment, whether it was or not). Also, this cannot undo +the activation of other environments, or modules that have been imported. +You shouldn't try to, for instance, activate an environment before a web +request; you should activate *one* environment as early as possible, and not +do it again in that process. + +Making Environments Relocatable +------------------------------- + +**Note:** this option is somewhat experimental, and there are probably +caveats that have not yet been identified. + +.. warning:: + + The ``--relocatable`` option currently has a number of issues, + and is not guaranteed to work in all circumstances. It is possible + that the option will be deprecated in a future version of ``virtualenv``. + +Normally environments are tied to a specific path. That means that +you cannot move an environment around or copy it to another computer. +You can fix up an environment to make it relocatable with the +command:: + + $ virtualenv --relocatable ENV + +This will make some of the files created by setuptools use relative paths, +and will change all the scripts to use ``activate_this.py`` instead of using +the location of the Python interpreter to select the environment. + +**Note:** scripts which have been made relocatable will only work if +the virtualenv is activated, specifically the python executable from +the virtualenv must be the first one on the system PATH. Also note that +the activate scripts are not currently made relocatable by +``virtualenv --relocatable``. + +**Note:** you must run this after you've installed *any* packages into +the environment. If you make an environment relocatable, then +install a new package, you must run ``virtualenv --relocatable`` +again. + +Also, this **does not make your packages cross-platform**. You can +move the directory around, but it can only be used on other similar +computers. Some known environmental differences that can cause +incompatibilities: a different version of Python, when one platform +uses UCS2 for its internal unicode representation and another uses +UCS4 (a compile-time option), obvious platform changes like Windows +vs. Linux, or Intel vs. ARM, and if you have libraries that bind to C +libraries on the system, if those C libraries are located somewhere +different (either different versions, or a different filesystem +layout). + +If you use this flag to create an environment, currently, the +:option:`--system-site-packages` option will be implied. + +The :option:`--extra-search-dir` option +--------------------------------------- + +This option allows you to provide your own versions of setuptools and/or +pip to use instead of the embedded versions that come with virtualenv. + +To use this feature, pass one or more ``--extra-search-dir`` options to +virtualenv like this:: + + $ virtualenv --extra-search-dir=/path/to/distributions ENV + +The ``/path/to/distributions`` path should point to a directory that contains +setuptools and/or pip wheels. + +virtualenv will look for wheels in the specified directories, but will use +pip's standard algorithm for selecting the wheel to install, which looks for +the latest compatible wheel. + +As well as the extra directories, the search order includes: + +#. The ``virtualenv_support`` directory relative to virtualenv.py +#. The directory where virtualenv.py is located. +#. The current directory. +
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/scripts/virtualenv @@ -0,0 +1,3 @@ +#!/usr/bin/env python +import virtualenv +virtualenv.main()
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/setup.cfg @@ -0,0 +1,8 @@ +[bdist_wheel] +universal = 1 + +[egg_info] +tag_date = 0 +tag_build = +tag_svn_revision = 0 +
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/setup.py @@ -0,0 +1,123 @@ +import os +import re +import shutil +import sys + +if sys.version_info[:2] < (2, 6): + sys.exit('virtualenv requires Python 2.6 or higher.') + +try: + from setuptools import setup + from setuptools.command.test import test as TestCommand + + class PyTest(TestCommand): + user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")] + + def initialize_options(self): + TestCommand.initialize_options(self) + self.pytest_args = [] + + def finalize_options(self): + TestCommand.finalize_options(self) + #self.test_args = [] + #self.test_suite = True + + def run_tests(self): + # import here, because outside the eggs aren't loaded + import pytest + sys.exit(pytest.main(self.pytest_args)) + + setup_params = { + 'entry_points': { + 'console_scripts': ['virtualenv=virtualenv:main'], + }, + 'zip_safe': False, + 'cmdclass': {'test': PyTest}, + 'tests_require': ['pytest', 'mock'], + } +except ImportError: + from distutils.core import setup + if sys.platform == 'win32': + print('Note: without Setuptools installed you will ' + 'have to use "python -m virtualenv ENV"') + setup_params = {} + else: + script = 'scripts/virtualenv' + setup_params = {'scripts': [script]} + + +def read_file(*paths): + here = os.path.dirname(os.path.abspath(__file__)) + with open(os.path.join(here, *paths)) as f: + return f.read() + +# Get long_description from index.rst: +long_description = read_file('docs', 'index.rst') +long_description = long_description.strip().split('split here', 1)[0] +# Add release history +changes = read_file('docs', 'changes.rst') +# Only report last two releases for brevity +releases_found = 0 +change_lines = [] +for line in changes.splitlines(): + change_lines.append(line) + if line.startswith('--------------'): + releases_found += 1 + if releases_found > 2: + break + +changes = '\n'.join(change_lines[:-2]) + '\n' +changes += '`Full Changelog <https://virtualenv.pypa.io/en/latest/changes.html>`_.' +# Replace issue/pull directives +changes = re.sub(r':pull:`(\d+)`', r'PR #\1', changes) +changes = re.sub(r':issue:`(\d+)`', r'#\1', changes) + +long_description += '\n\n' + changes + + +def get_version(): + version_file = read_file('virtualenv.py') + version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", + version_file, re.M) + if version_match: + return version_match.group(1) + raise RuntimeError("Unable to find version string.") + + +# Hack to prevent stupid TypeError: 'NoneType' object is not callable error on +# exit of python setup.py test # in multiprocessing/util.py _exit_function when +# running python setup.py test (see +# http://www.eby-sarna.com/pipermail/peak/2010-May/003357.html) +try: + import multiprocessing # noqa +except ImportError: + pass + +setup( + name='virtualenv', + version=get_version(), + description="Virtual Python Environment builder", + long_description=long_description, + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + ], + keywords='setuptools deployment installation distutils', + author='Ian Bicking', + author_email='ianb@colorstudy.com', + maintainer='Jannis Leidel, Carl Meyer and Brian Rosner', + maintainer_email='python-virtualenv@groups.google.com', + url='https://virtualenv.pypa.io/', + license='MIT', + py_modules=['virtualenv'], + packages=['virtualenv_support'], + package_data={'virtualenv_support': ['*.whl']}, + **setup_params)
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/site.py @@ -0,0 +1,760 @@ +"""Append module search paths for third-party packages to sys.path. + +**************************************************************** +* This module is automatically imported during initialization. * +**************************************************************** + +In earlier versions of Python (up to 1.5a3), scripts or modules that +needed to use site-specific modules would place ``import site'' +somewhere near the top of their code. Because of the automatic +import, this is no longer necessary (but code that does it still +works). + +This will append site-specific paths to the module search path. On +Unix, it starts with sys.prefix and sys.exec_prefix (if different) and +appends lib/python<version>/site-packages as well as lib/site-python. +It also supports the Debian convention of +lib/python<version>/dist-packages. On other platforms (mainly Mac and +Windows), it uses just sys.prefix (and sys.exec_prefix, if different, +but this is unlikely). The resulting directories, if they exist, are +appended to sys.path, and also inspected for path configuration files. + +FOR DEBIAN, this sys.path is augmented with directories in /usr/local. +Local addons go into /usr/local/lib/python<version>/site-packages +(resp. /usr/local/lib/site-python), Debian addons install into +/usr/{lib,share}/python<version>/dist-packages. + +A path configuration file is a file whose name has the form +<package>.pth; its contents are additional directories (one per line) +to be added to sys.path. Non-existing directories (or +non-directories) are never added to sys.path; no directory is added to +sys.path more than once. Blank lines and lines beginning with +'#' are skipped. Lines starting with 'import' are executed. + +For example, suppose sys.prefix and sys.exec_prefix are set to +/usr/local and there is a directory /usr/local/lib/python2.X/site-packages +with three subdirectories, foo, bar and spam, and two path +configuration files, foo.pth and bar.pth. Assume foo.pth contains the +following: + + # foo package configuration + foo + bar + bletch + +and bar.pth contains: + + # bar package configuration + bar + +Then the following directories are added to sys.path, in this order: + + /usr/local/lib/python2.X/site-packages/bar + /usr/local/lib/python2.X/site-packages/foo + +Note that bletch is omitted because it doesn't exist; bar precedes foo +because bar.pth comes alphabetically before foo.pth; and spam is +omitted because it is not mentioned in either path configuration file. + +After these path manipulations, an attempt is made to import a module +named sitecustomize, which can perform arbitrary additional +site-specific customizations. If this import fails with an +ImportError exception, it is silently ignored. + +""" + +import sys +import os + +try: + import __builtin__ as builtins +except ImportError: + import builtins +try: + set +except NameError: + from sets import Set as set + +# Prefixes for site-packages; add additional prefixes like /usr/local here +PREFIXES = [sys.prefix, sys.exec_prefix] +# Enable per user site-packages directory +# set it to False to disable the feature or True to force the feature +ENABLE_USER_SITE = None +# for distutils.commands.install +USER_SITE = None +USER_BASE = None + +_is_64bit = (getattr(sys, 'maxsize', None) or getattr(sys, 'maxint')) > 2**32 +_is_pypy = hasattr(sys, 'pypy_version_info') +_is_jython = sys.platform[:4] == 'java' +if _is_jython: + ModuleType = type(os) + +def makepath(*paths): + dir = os.path.join(*paths) + if _is_jython and (dir == '__classpath__' or + dir.startswith('__pyclasspath__')): + return dir, dir + dir = os.path.abspath(dir) + return dir, os.path.normcase(dir) + +def abs__file__(): + """Set all module' __file__ attribute to an absolute path""" + for m in sys.modules.values(): + if ((_is_jython and not isinstance(m, ModuleType)) or + hasattr(m, '__loader__')): + # only modules need the abspath in Jython. and don't mess + # with a PEP 302-supplied __file__ + continue + f = getattr(m, '__file__', None) + if f is None: + continue + m.__file__ = os.path.abspath(f) + +def removeduppaths(): + """ Remove duplicate entries from sys.path along with making them + absolute""" + # This ensures that the initial path provided by the interpreter contains + # only absolute pathnames, even if we're running from the build directory. + L = [] + known_paths = set() + for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in known_paths: + L.append(dir) + known_paths.add(dircase) + sys.path[:] = L + return known_paths + +# XXX This should not be part of site.py, since it is needed even when +# using the -S option for Python. See http://www.python.org/sf/586680 +def addbuilddir(): + """Append ./build/lib.<platform> in case we're running in the build dir + (especially for Guido :-)""" + from distutils.util import get_platform + s = "build/lib.%s-%.3s" % (get_platform(), sys.version) + if hasattr(sys, 'gettotalrefcount'): + s += '-pydebug' + s = os.path.join(os.path.dirname(sys.path[-1]), s) + sys.path.append(s) + +def _init_pathinfo(): + """Return a set containing all existing directory entries from sys.path""" + d = set() + for dir in sys.path: + try: + if os.path.isdir(dir): + dir, dircase = makepath(dir) + d.add(dircase) + except TypeError: + continue + return d + +def addpackage(sitedir, name, known_paths): + """Add a new path to known_paths by combining sitedir and 'name' or execute + sitedir if it starts with 'import'""" + if known_paths is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + f = open(fullname, "rU") + except IOError: + return + try: + for line in f: + if line.startswith("#"): + continue + if line.startswith("import"): + exec(line) + continue + line = line.rstrip() + dir, dircase = makepath(sitedir, line) + if not dircase in known_paths and os.path.exists(dir): + sys.path.append(dir) + known_paths.add(dircase) + finally: + f.close() + if reset: + known_paths = None + return known_paths + +def addsitedir(sitedir, known_paths=None): + """Add 'sitedir' argument to sys.path if missing and handle .pth files in + 'sitedir'""" + if known_paths is None: + known_paths = _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in known_paths: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + names.sort() + for name in names: + if name.endswith(os.extsep + "pth"): + addpackage(sitedir, name, known_paths) + if reset: + known_paths = None + return known_paths + +def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix): + """Add site-packages (and possibly site-python) to sys.path""" + prefixes = [os.path.join(sys_prefix, "local"), sys_prefix] + if exec_prefix != sys_prefix: + prefixes.append(os.path.join(exec_prefix, "local")) + + for prefix in prefixes: + if prefix: + if sys.platform in ('os2emx', 'riscos') or _is_jython: + sitedirs = [os.path.join(prefix, "Lib", "site-packages")] + elif _is_pypy: + sitedirs = [os.path.join(prefix, 'site-packages')] + elif sys.platform == 'darwin' and prefix == sys_prefix: + + if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python + + sitedirs = [os.path.join("/Library/Python", sys.version[:3], "site-packages"), + os.path.join(prefix, "Extras", "lib", "python")] + + else: # any other Python distros on OSX work this way + sitedirs = [os.path.join(prefix, "lib", + "python" + sys.version[:3], "site-packages")] + + elif os.sep == '/': + sitedirs = [os.path.join(prefix, + "lib", + "python" + sys.version[:3], + "site-packages"), + os.path.join(prefix, "lib", "site-python"), + os.path.join(prefix, "python" + sys.version[:3], "lib-dynload")] + lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages") + if (os.path.exists(lib64_dir) and + os.path.realpath(lib64_dir) not in [os.path.realpath(p) for p in sitedirs]): + if _is_64bit: + sitedirs.insert(0, lib64_dir) + else: + sitedirs.append(lib64_dir) + try: + # sys.getobjects only available in --with-pydebug build + sys.getobjects + sitedirs.insert(0, os.path.join(sitedirs[0], 'debug')) + except AttributeError: + pass + # Debian-specific dist-packages directories: + sitedirs.append(os.path.join(prefix, "local/lib", + "python" + sys.version[:3], + "dist-packages")) + if sys.version[0] == '2': + sitedirs.append(os.path.join(prefix, "lib", + "python" + sys.version[:3], + "dist-packages")) + else: + sitedirs.append(os.path.join(prefix, "lib", + "python" + sys.version[0], + "dist-packages")) + sitedirs.append(os.path.join(prefix, "lib", "dist-python")) + else: + sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] + if sys.platform == 'darwin': + # for framework builds *only* we add the standard Apple + # locations. Currently only per-user, but /Library and + # /Network/Library could be added too + if 'Python.framework' in prefix: + home = os.environ.get('HOME') + if home: + sitedirs.append( + os.path.join(home, + 'Library', + 'Python', + sys.version[:3], + 'site-packages')) + for sitedir in sitedirs: + if os.path.isdir(sitedir): + addsitedir(sitedir, known_paths) + return None + +def check_enableusersite(): + """Check if user site directory is safe for inclusion + + The function tests for the command line flag (including environment var), + process uid/gid equal to effective uid/gid. + + None: Disabled for security reasons + False: Disabled by user (command line option) + True: Safe and enabled + """ + if hasattr(sys, 'flags') and getattr(sys.flags, 'no_user_site', False): + return False + + if hasattr(os, "getuid") and hasattr(os, "geteuid"): + # check process uid == effective uid + if os.geteuid() != os.getuid(): + return None + if hasattr(os, "getgid") and hasattr(os, "getegid"): + # check process gid == effective gid + if os.getegid() != os.getgid(): + return None + + return True + +def addusersitepackages(known_paths): + """Add a per user site-package to sys.path + + Each user has its own python directory with site-packages in the + home directory. + + USER_BASE is the root directory for all Python versions + + USER_SITE is the user specific site-packages directory + + USER_SITE/.. can be used for data. + """ + global USER_BASE, USER_SITE, ENABLE_USER_SITE + env_base = os.environ.get("PYTHONUSERBASE", None) + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + #if sys.platform in ('os2emx', 'riscos'): + # # Don't know what to put here + # USER_BASE = '' + # USER_SITE = '' + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + if env_base: + USER_BASE = env_base + else: + USER_BASE = joinuser(base, "Python") + USER_SITE = os.path.join(USER_BASE, + "Python" + sys.version[0] + sys.version[2], + "site-packages") + else: + if env_base: + USER_BASE = env_base + else: + USER_BASE = joinuser("~", ".local") + USER_SITE = os.path.join(USER_BASE, "lib", + "python" + sys.version[:3], + "site-packages") + + if ENABLE_USER_SITE and os.path.isdir(USER_SITE): + addsitedir(USER_SITE, known_paths) + if ENABLE_USER_SITE: + for dist_libdir in ("lib", "local/lib"): + user_site = os.path.join(USER_BASE, dist_libdir, + "python" + sys.version[:3], + "dist-packages") + if os.path.isdir(user_site): + addsitedir(user_site, known_paths) + return known_paths + + + +def setBEGINLIBPATH(): + """The OS/2 EMX port has optional extension modules that do double duty + as DLLs (and must use the .DLL file extension) for other extensions. + The library search path needs to be amended so these will be found + during module import. Use BEGINLIBPATH so that these are at the start + of the library search path. + + """ + dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") + libpath = os.environ['BEGINLIBPATH'].split(';') + if libpath[-1]: + libpath.append(dllpath) + else: + libpath[-1] = dllpath + os.environ['BEGINLIBPATH'] = ';'.join(libpath) + + +def setquit(): + """Define new built-ins 'quit' and 'exit'. + These are simply strings that display a hint on how to exit. + + """ + if os.sep == ':': + eof = 'Cmd-Q' + elif os.sep == '\\': + eof = 'Ctrl-Z plus Return' + else: + eof = 'Ctrl-D (i.e. EOF)' + + class Quitter(object): + def __init__(self, name): + self.name = name + def __repr__(self): + return 'Use %s() or %s to exit' % (self.name, eof) + def __call__(self, code=None): + # Shells like IDLE catch the SystemExit, but listen when their + # stdin wrapper is closed. + try: + sys.stdin.close() + except: + pass + raise SystemExit(code) + builtins.quit = Quitter('quit') + builtins.exit = Quitter('exit') + + +class _Printer(object): + """interactive prompt objects for printing the license text, a list of + contributors and the copyright notice.""" + + MAXLINES = 23 + + def __init__(self, name, data, files=(), dirs=()): + self.__name = name + self.__data = data + self.__files = files + self.__dirs = dirs + self.__lines = None + + def __setup(self): + if self.__lines: + return + data = None + for dir in self.__dirs: + for filename in self.__files: + filename = os.path.join(dir, filename) + try: + fp = open(filename, "rU") + data = fp.read() + fp.close() + break + except IOError: + pass + if data: + break + if not data: + data = self.__data + self.__lines = data.split('\n') + self.__linecnt = len(self.__lines) + + def __repr__(self): + self.__setup() + if len(self.__lines) <= self.MAXLINES: + return "\n".join(self.__lines) + else: + return "Type %s() to see the full %s text" % ((self.__name,)*2) + + def __call__(self): + self.__setup() + prompt = 'Hit Return for more, or q (and Return) to quit: ' + lineno = 0 + while 1: + try: + for i in range(lineno, lineno + self.MAXLINES): + print(self.__lines[i]) + except IndexError: + break + else: + lineno += self.MAXLINES + key = None + while key is None: + try: + key = raw_input(prompt) + except NameError: + key = input(prompt) + if key not in ('', 'q'): + key = None + if key == 'q': + break + +def setcopyright(): + """Set 'copyright' and 'credits' in __builtin__""" + builtins.copyright = _Printer("copyright", sys.copyright) + if _is_jython: + builtins.credits = _Printer( + "credits", + "Jython is maintained by the Jython developers (www.jython.org).") + elif _is_pypy: + builtins.credits = _Printer( + "credits", + "PyPy is maintained by the PyPy developers: http://pypy.org/") + else: + builtins.credits = _Printer("credits", """\ + Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands + for supporting Python development. See www.python.org for more information.""") + here = os.path.dirname(os.__file__) + builtins.license = _Printer( + "license", "See http://www.python.org/%.3s/license.html" % sys.version, + ["LICENSE.txt", "LICENSE"], + [os.path.join(here, os.pardir), here, os.curdir]) + + +class _Helper(object): + """Define the built-in 'help'. + This is a wrapper around pydoc.help (with a twist). + + """ + + def __repr__(self): + return "Type help() for interactive help, " \ + "or help(object) for help about object." + def __call__(self, *args, **kwds): + import pydoc + return pydoc.help(*args, **kwds) + +def sethelper(): + builtins.help = _Helper() + +def aliasmbcs(): + """On Windows, some default encodings are not provided by Python, + while they are always available as "mbcs" in each locale. Make + them usable by aliasing to "mbcs" in such a case.""" + if sys.platform == 'win32': + import locale, codecs + enc = locale.getdefaultlocale()[1] + if enc.startswith('cp'): # "cp***" ? + try: + codecs.lookup(enc) + except LookupError: + import encodings + encodings._cache[enc] = encodings._unknown + encodings.aliases.aliases[enc] = 'mbcs' + +def setencoding(): + """Set the string encoding used by the Unicode implementation. The + default is 'ascii', but if you're willing to experiment, you can + change this.""" + encoding = "ascii" # Default value set by _PyUnicode_Init() + if 0: + # Enable to support locale aware default string encodings. + import locale + loc = locale.getdefaultlocale() + if loc[1]: + encoding = loc[1] + if 0: + # Enable to switch off string to Unicode coercion and implicit + # Unicode to string conversion. + encoding = "undefined" + if encoding != "ascii": + # On Non-Unicode builds this will raise an AttributeError... + sys.setdefaultencoding(encoding) # Needs Python Unicode build ! + + +def execsitecustomize(): + """Run custom site specific code, if available.""" + try: + import sitecustomize + except ImportError: + pass + +def virtual_install_main_packages(): + f = open(os.path.join(os.path.dirname(__file__), 'orig-prefix.txt')) + sys.real_prefix = f.read().strip() + f.close() + pos = 2 + hardcoded_relative_dirs = [] + if sys.path[0] == '': + pos += 1 + if _is_jython: + paths = [os.path.join(sys.real_prefix, 'Lib')] + elif _is_pypy: + if sys.version_info > (3, 2): + cpyver = '%d' % sys.version_info[0] + elif sys.pypy_version_info >= (1, 5): + cpyver = '%d.%d' % sys.version_info[:2] + else: + cpyver = '%d.%d.%d' % sys.version_info[:3] + paths = [os.path.join(sys.real_prefix, 'lib_pypy'), + os.path.join(sys.real_prefix, 'lib-python', cpyver)] + if sys.pypy_version_info < (1, 9): + paths.insert(1, os.path.join(sys.real_prefix, + 'lib-python', 'modified-%s' % cpyver)) + hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below + # + # This is hardcoded in the Python executable, but relative to sys.prefix: + for path in paths[:]: + plat_path = os.path.join(path, 'plat-%s' % sys.platform) + if os.path.exists(plat_path): + paths.append(plat_path) + # MOZ: The MSYS2 and MinGW versions of Python have their main packages in the UNIX directory this checks specifically for the native win32 python + elif sys.platform == 'win32' and os.sep == '\\': + paths = [os.path.join(sys.real_prefix, 'Lib'), os.path.join(sys.real_prefix, 'DLLs')] + else: + paths = [os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3])] + hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below + lib64_path = os.path.join(sys.real_prefix, 'lib64', 'python'+sys.version[:3]) + if os.path.exists(lib64_path): + if _is_64bit: + paths.insert(0, lib64_path) + else: + paths.append(lib64_path) + # This is hardcoded in the Python executable, but relative to + # sys.prefix. Debian change: we need to add the multiarch triplet + # here, which is where the real stuff lives. As per PEP 421, in + # Python 3.3+, this lives in sys.implementation, while in Python 2.7 + # it lives in sys. + try: + arch = getattr(sys, 'implementation', sys)._multiarch + except AttributeError: + # This is a non-multiarch aware Python. Fallback to the old way. + arch = sys.platform + plat_path = os.path.join(sys.real_prefix, 'lib', + 'python'+sys.version[:3], + 'plat-%s' % arch) + if os.path.exists(plat_path): + paths.append(plat_path) + # This is hardcoded in the Python executable, but + # relative to sys.prefix, so we have to fix up: + for path in list(paths): + tk_dir = os.path.join(path, 'lib-tk') + if os.path.exists(tk_dir): + paths.append(tk_dir) + + # These are hardcoded in the Apple's Python executable, + # but relative to sys.prefix, so we have to fix them up: + if sys.platform == 'darwin': + hardcoded_paths = [os.path.join(relative_dir, module) + for relative_dir in hardcoded_relative_dirs + for module in ('plat-darwin', 'plat-mac', 'plat-mac/lib-scriptpackages')] + + for path in hardcoded_paths: + if os.path.exists(path): + paths.append(path) + + sys.path.extend(paths) + +def force_global_eggs_after_local_site_packages(): + """ + Force easy_installed eggs in the global environment to get placed + in sys.path after all packages inside the virtualenv. This + maintains the "least surprise" result that packages in the + virtualenv always mask global packages, never the other way + around. + + """ + egginsert = getattr(sys, '__egginsert', 0) + for i, path in enumerate(sys.path): + if i > egginsert and path.startswith(sys.prefix): + egginsert = i + sys.__egginsert = egginsert + 1 + +def virtual_addsitepackages(known_paths): + force_global_eggs_after_local_site_packages() + return addsitepackages(known_paths, sys_prefix=sys.real_prefix) + +def fixclasspath(): + """Adjust the special classpath sys.path entries for Jython. These + entries should follow the base virtualenv lib directories. + """ + paths = [] + classpaths = [] + for path in sys.path: + if path == '__classpath__' or path.startswith('__pyclasspath__'): + classpaths.append(path) + else: + paths.append(path) + sys.path = paths + sys.path.extend(classpaths) + +def execusercustomize(): + """Run custom user specific code, if available.""" + try: + import usercustomize + except ImportError: + pass + + +def main(): + global ENABLE_USER_SITE + virtual_install_main_packages() + abs__file__() + paths_in_sys = removeduppaths() + if (os.name == "posix" and sys.path and + os.path.basename(sys.path[-1]) == "Modules"): + addbuilddir() + if _is_jython: + fixclasspath() + GLOBAL_SITE_PACKAGES = not os.path.exists(os.path.join(os.path.dirname(__file__), 'no-global-site-packages.txt')) + if not GLOBAL_SITE_PACKAGES: + ENABLE_USER_SITE = False + if ENABLE_USER_SITE is None: + ENABLE_USER_SITE = check_enableusersite() + paths_in_sys = addsitepackages(paths_in_sys) + paths_in_sys = addusersitepackages(paths_in_sys) + if GLOBAL_SITE_PACKAGES: + paths_in_sys = virtual_addsitepackages(paths_in_sys) + if sys.platform == 'os2emx': + setBEGINLIBPATH() + setquit() + setcopyright() + sethelper() + aliasmbcs() + setencoding() + execsitecustomize() + if ENABLE_USER_SITE: + execusercustomize() + # Remove sys.setdefaultencoding() so that users cannot change the + # encoding after initialization. The test for presence is needed when + # this module is run as a script, because this code is executed twice. + if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding + +main() + +def _script(): + help = """\ + %s [--user-base] [--user-site] + + Without arguments print some useful information + With arguments print the value of USER_BASE and/or USER_SITE separated + by '%s'. + + Exit codes with --user-base or --user-site: + 0 - user site directory is enabled + 1 - user site directory is disabled by user + 2 - uses site directory is disabled by super user + or for security reasons + >2 - unknown error + """ + args = sys.argv[1:] + if not args: + print("sys.path = [") + for dir in sys.path: + print(" %r," % (dir,)) + print("]") + def exists(path): + if os.path.isdir(path): + return "exists" + else: + return "doesn't exist" + print("USER_BASE: %r (%s)" % (USER_BASE, exists(USER_BASE))) + print("USER_SITE: %r (%s)" % (USER_SITE, exists(USER_BASE))) + print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE) + sys.exit(0) + + buffer = [] + if '--user-base' in args: + buffer.append(USER_BASE) + if '--user-site' in args: + buffer.append(USER_SITE) + + if buffer: + print(os.pathsep.join(buffer)) + if ENABLE_USER_SITE: + sys.exit(0) + elif ENABLE_USER_SITE is False: + sys.exit(1) + elif ENABLE_USER_SITE is None: + sys.exit(2) + else: + sys.exit(3) + else: + import textwrap + print(textwrap.dedent(help % (sys.argv[0], os.pathsep))) + sys.exit(10) + +if __name__ == '__main__': + _script()
new file mode 100755 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/tests/test_activate.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +set -u + +ROOT="$(dirname $0)/.." +VIRTUALENV="${ROOT}/virtualenv.py" +TESTENV="/tmp/test_virtualenv_activate.venv" + +rm -rf ${TESTENV} + +echo "$0: Creating virtualenv ${TESTENV}..." 1>&2 + +${VIRTUALENV} ${TESTENV} | tee ${ROOT}/tests/test_activate_output.actual +if ! diff ${ROOT}/tests/test_activate_output.expected ${ROOT}/tests/test_activate_output.actual; then + echo "$0: Failed to get expected output from ${VIRTUALENV}!" 1>&2 + exit 1 +fi + +echo "$0: Created virtualenv ${TESTENV}." 1>&2 + +echo "$0: Activating ${TESTENV}..." 1>&2 +. ${TESTENV}/bin/activate +echo "$0: Activated ${TESTENV}." 1>&2 + +echo "$0: Checking value of \$VIRTUAL_ENV..." 1>&2 + +if [ "$VIRTUAL_ENV" != "${TESTENV}" ]; then + echo "$0: Expected \$VIRTUAL_ENV to be set to \"${TESTENV}\"; actual value: \"${VIRTUAL_ENV}\"!" 1>&2 + exit 2 +fi + +echo "$0: \$VIRTUAL_ENV = \"${VIRTUAL_ENV}\" -- OK." 1>&2 + +echo "$0: Checking output of \$(which python)..." 1>&2 + +if [ "$(which python)" != "${TESTENV}/bin/python" ]; then + echo "$0: Expected \$(which python) to return \"${TESTENV}/bin/python\"; actual value: \"$(which python)\"!" 1>&2 + exit 3 +fi + +echo "$0: Output of \$(which python) is OK." 1>&2 + +echo "$0: Checking output of \$(which pip)..." 1>&2 + +if [ "$(which pip)" != "${TESTENV}/bin/pip" ]; then + echo "$0: Expected \$(which pip) to return \"${TESTENV}/bin/pip\"; actual value: \"$(which pip)\"!" 1>&2 + exit 4 +fi + +echo "$0: Output of \$(which pip) is OK." 1>&2 + +echo "$0: Checking output of \$(which easy_install)..." 1>&2 + +if [ "$(which easy_install)" != "${TESTENV}/bin/easy_install" ]; then + echo "$0: Expected \$(which easy_install) to return \"${TESTENV}/bin/easy_install\"; actual value: \"$(which easy_install)\"!" 1>&2 + exit 5 +fi + +echo "$0: Output of \$(which easy_install) is OK." 1>&2 + +echo "$0: Executing a simple Python program..." 1>&2 + +TESTENV=${TESTENV} python <<__END__ +import os, sys + +expected_site_packages = os.path.join(os.environ['TESTENV'], 'lib','python%s' % sys.version[:3], 'site-packages') +site_packages = os.path.join(os.environ['VIRTUAL_ENV'], 'lib', 'python%s' % sys.version[:3], 'site-packages') + +assert site_packages == expected_site_packages, 'site_packages did not have expected value; actual value: %r' % site_packages + +open(os.path.join(site_packages, 'pydoc_test.py'), 'w').write('"""This is pydoc_test.py"""\n') +__END__ + +if [ $? -ne 0 ]; then + echo "$0: Python script failed!" 1>&2 + exit 6 +fi + +echo "$0: Execution of a simple Python program -- OK." 1>&2 + +echo "$0: Testing pydoc..." 1>&2 + +if ! PAGER=cat pydoc pydoc_test | grep 'This is pydoc_test.py' > /dev/null; then + echo "$0: pydoc test failed!" 1>&2 + exit 7 +fi + +echo "$0: pydoc is OK." 1>&2 + +echo "$0: Deactivating ${TESTENV}..." 1>&2 +deactivate +echo "$0: Deactivated ${TESTENV}." 1>&2 +echo "$0: OK!" 1>&2 + +rm -rf ${TESTENV} +
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/tests/test_activate_output.expected @@ -0,0 +1,2 @@ +New python executable in /tmp/test_virtualenv_activate.venv/bin/python +Installing setuptools, pip, wheel...done.
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/tests/test_cmdline.py @@ -0,0 +1,44 @@ +import sys +import subprocess +import virtualenv +import pytest + +VIRTUALENV_SCRIPT = virtualenv.__file__ + +def test_commandline_basic(tmpdir): + """Simple command line usage should work""" + subprocess.check_call([ + sys.executable, + VIRTUALENV_SCRIPT, + str(tmpdir.join('venv')) + ]) + +def test_commandline_explicit_interp(tmpdir): + """Specifying the Python interpreter should work""" + subprocess.check_call([ + sys.executable, + VIRTUALENV_SCRIPT, + '-p', sys.executable, + str(tmpdir.join('venv')) + ]) + +# The registry lookups to support the abbreviated "-p 3.5" form of specifying +# a Python interpreter on Windows don't seem to work with Python 3.5. The +# registry layout is not well documented, and it's not clear that the feature +# is sufficiently widely used to be worth fixing. +# See https://github.com/pypa/virtualenv/issues/864 +@pytest.mark.skipif("sys.platform == 'win32' and sys.version_info[:2] >= (3,5)") +def test_commandline_abbrev_interp(tmpdir): + """Specifying abbreviated forms of the Python interpreter should work""" + if sys.platform == 'win32': + fmt = '%s.%s' + else: + fmt = 'python%s.%s' + abbrev = fmt % (sys.version_info[0], sys.version_info[1]) + subprocess.check_call([ + sys.executable, + VIRTUALENV_SCRIPT, + '-p', abbrev, + str(tmpdir.join('venv')) + ]) +
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/tests/test_virtualenv.py @@ -0,0 +1,139 @@ +import virtualenv +import optparse +import os +import shutil +import sys +import tempfile +import pytest +import platform # noqa + +from mock import patch, Mock + + +def test_version(): + """Should have a version string""" + assert virtualenv.virtualenv_version, "Should have version" + + +@patch('os.path.exists') +def test_resolve_interpreter_with_absolute_path(mock_exists): + """Should return absolute path if given and exists""" + mock_exists.return_value = True + virtualenv.is_executable = Mock(return_value=True) + test_abs_path = os.path.abspath("/usr/bin/python53") + + exe = virtualenv.resolve_interpreter(test_abs_path) + + assert exe == test_abs_path, "Absolute path should return as is" + mock_exists.assert_called_with(test_abs_path) + virtualenv.is_executable.assert_called_with(test_abs_path) + + +@patch('os.path.exists') +def test_resolve_interpreter_with_nonexistent_interpreter(mock_exists): + """Should SystemExit with an nonexistent python interpreter path""" + mock_exists.return_value = False + + with pytest.raises(SystemExit): + virtualenv.resolve_interpreter("/usr/bin/python53") + + mock_exists.assert_called_with("/usr/bin/python53") + + +@patch('os.path.exists') +def test_resolve_interpreter_with_invalid_interpreter(mock_exists): + """Should exit when with absolute path if not exists""" + mock_exists.return_value = True + virtualenv.is_executable = Mock(return_value=False) + invalid = os.path.abspath("/usr/bin/pyt_hon53") + + with pytest.raises(SystemExit): + virtualenv.resolve_interpreter(invalid) + + mock_exists.assert_called_with(invalid) + virtualenv.is_executable.assert_called_with(invalid) + + +def test_activate_after_future_statements(): + """Should insert activation line after last future statement""" + script = [ + '#!/usr/bin/env python', + 'from __future__ import with_statement', + 'from __future__ import print_function', + 'print("Hello, world!")' + ] + assert virtualenv.relative_script(script) == [ + '#!/usr/bin/env python', + 'from __future__ import with_statement', + 'from __future__ import print_function', + '', + "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); exec(compile(open(activate_this).read(), activate_this, 'exec'), dict(__file__=activate_this)); del os, activate_this", + '', + 'print("Hello, world!")' + ] + + +def test_cop_update_defaults_with_store_false(): + """store_false options need reverted logic""" + class MyConfigOptionParser(virtualenv.ConfigOptionParser): + def __init__(self, *args, **kwargs): + self.config = virtualenv.ConfigParser.RawConfigParser() + self.files = [] + optparse.OptionParser.__init__(self, *args, **kwargs) + + def get_environ_vars(self, prefix='VIRTUALENV_'): + yield ("no_site_packages", "1") + + cop = MyConfigOptionParser() + cop.add_option( + '--no-site-packages', + dest='system_site_packages', + action='store_false', + help="Don't give access to the global site-packages dir to the " + "virtual environment (default)") + + defaults = {} + cop.update_defaults(defaults) + assert defaults == {'system_site_packages': 0} + +def test_install_python_bin(): + """Should create the right python executables and links""" + tmp_virtualenv = tempfile.mkdtemp() + try: + home_dir, lib_dir, inc_dir, bin_dir = \ + virtualenv.path_locations(tmp_virtualenv) + virtualenv.install_python(home_dir, lib_dir, inc_dir, bin_dir, False, + False) + + if virtualenv.is_win: + required_executables = [ 'python.exe', 'pythonw.exe'] + else: + py_exe_no_version = 'python' + py_exe_version_major = 'python%s' % sys.version_info[0] + py_exe_version_major_minor = 'python%s.%s' % ( + sys.version_info[0], sys.version_info[1]) + required_executables = [ py_exe_no_version, py_exe_version_major, + py_exe_version_major_minor ] + + for pth in required_executables: + assert os.path.exists(os.path.join(bin_dir, pth)), ("%s should " + "exist in bin_dir" % pth) + finally: + shutil.rmtree(tmp_virtualenv) + + +@pytest.mark.skipif("platform.python_implementation() == 'PyPy'") +def test_always_copy_option(): + """Should be no symlinks in directory tree""" + tmp_virtualenv = tempfile.mkdtemp() + ve_path = os.path.join(tmp_virtualenv, 'venv') + try: + virtualenv.create_environment(ve_path, symlink=False) + + for root, dirs, files in os.walk(tmp_virtualenv): + for f in files + dirs: + full_name = os.path.join(root, f) + assert not os.path.islink(full_name), "%s should not be a" \ + " symlink (to %s)" % (full_name, os.readlink(full_name)) + finally: + shutil.rmtree(tmp_virtualenv)
new file mode 100755 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv.py @@ -0,0 +1,2329 @@ +#!/usr/bin/env python +"""Create a "virtual" Python installation""" + +import os +import sys + +# If we are running in a new interpreter to create a virtualenv, +# we do NOT want paths from our existing location interfering with anything, +# So we remove this file's directory from sys.path - most likely to be +# the previous interpreter's site-packages. Solves #705, #763, #779 +if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): + for path in sys.path[:]: + if os.path.realpath(os.path.dirname(__file__)) == os.path.realpath(path): + sys.path.remove(path) + +import base64 +import codecs +import optparse +import re +import shutil +import logging +import zlib +import errno +import glob +import distutils.sysconfig +import struct +import subprocess +import pkgutil +import tempfile +import textwrap +from distutils.util import strtobool +from os.path import join + +try: + import ConfigParser +except ImportError: + import configparser as ConfigParser + +__version__ = "15.0.1" +virtualenv_version = __version__ # legacy + +if sys.version_info < (2, 6): + print('ERROR: %s' % sys.exc_info()[1]) + print('ERROR: this script requires Python 2.6 or greater.') + sys.exit(101) + +try: + basestring +except NameError: + basestring = str + +py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) + +is_jython = sys.platform.startswith('java') +is_pypy = hasattr(sys, 'pypy_version_info') +is_win = (sys.platform == 'win32' and os.sep == '\\') +is_cygwin = (sys.platform == 'cygwin') +is_msys2 = (sys.platform == 'win32' and os.sep == '/') +is_darwin = (sys.platform == 'darwin') +abiflags = getattr(sys, 'abiflags', '') + +user_dir = os.path.expanduser('~') +if is_win: + default_storage_dir = os.path.join(user_dir, 'virtualenv') +else: + default_storage_dir = os.path.join(user_dir, '.virtualenv') +default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini') + +if is_pypy: + expected_exe = 'pypy' +elif is_jython: + expected_exe = 'jython' +else: + expected_exe = 'python' + +# Return a mapping of version -> Python executable +# Only provided for Windows, where the information in the registry is used +if not is_win: + def get_installed_pythons(): + return {} +else: + try: + import winreg + except ImportError: + import _winreg as winreg + + def get_installed_pythons(): + try: + python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, + "Software\\Python\\PythonCore") + except WindowsError: + # No registered Python installations + return {} + i = 0 + versions = [] + while True: + try: + versions.append(winreg.EnumKey(python_core, i)) + i = i + 1 + except WindowsError: + break + exes = dict() + for ver in versions: + try: + path = winreg.QueryValue(python_core, "%s\\InstallPath" % ver) + except WindowsError: + continue + exes[ver] = join(path, "python.exe") + + winreg.CloseKey(python_core) + + # Add the major versions + # Sort the keys, then repeatedly update the major version entry + # Last executable (i.e., highest version) wins with this approach + for ver in sorted(exes): + exes[ver[0]] = exes[ver] + + return exes + +REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath', + 'fnmatch', 'locale', 'encodings', 'codecs', + 'stat', 'UserDict', 'readline', 'copy_reg', 'types', + 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile', + 'zlib'] + +REQUIRED_FILES = ['lib-dynload', 'config'] + +majver, minver = sys.version_info[:2] +if majver == 2: + if minver >= 6: + REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) + if minver >= 7: + REQUIRED_MODULES.extend(['_weakrefset']) + if is_msys2: + REQUIRED_MODULES.extend(['functools']) +elif majver == 3: + # Some extra modules are needed for Python 3, but different ones + # for different versions. + REQUIRED_MODULES.extend([ + '_abcoll', 'warnings', 'linecache', 'abc', 'io', '_weakrefset', + 'copyreg', 'tempfile', 'random', '__future__', 'collections', + 'keyword', 'tarfile', 'shutil', 'struct', 'copy', 'tokenize', + 'token', 'functools', 'heapq', 'bisect', 'weakref', 'reprlib' + ]) + if minver >= 2: + REQUIRED_FILES[-1] = 'config-%s' % majver + if minver >= 3: + import sysconfig + platdir = sysconfig.get_config_var('PLATDIR') + REQUIRED_FILES.append(platdir) + REQUIRED_MODULES.extend([ + 'base64', '_dummy_thread', 'hashlib', 'hmac', + 'imp', 'importlib', 'rlcompleter' + ]) + if minver >= 4: + REQUIRED_MODULES.extend([ + 'operator', + '_collections_abc', + '_bootlocale', + ]) + +if is_pypy: + # these are needed to correctly display the exceptions that may happen + # during the bootstrap + REQUIRED_MODULES.extend(['traceback', 'linecache']) + + +class Logger(object): + + """ + Logging object for use in command-line script. Allows ranges of + levels, to avoid some redundancy of displayed information. + """ + + DEBUG = logging.DEBUG + INFO = logging.INFO + NOTIFY = (logging.INFO+logging.WARN)/2 + WARN = WARNING = logging.WARN + ERROR = logging.ERROR + FATAL = logging.FATAL + + LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] + + def __init__(self, consumers): + self.consumers = consumers + self.indent = 0 + self.in_progress = None + self.in_progress_hanging = False + + def debug(self, msg, *args, **kw): + self.log(self.DEBUG, msg, *args, **kw) + + def info(self, msg, *args, **kw): + self.log(self.INFO, msg, *args, **kw) + + def notify(self, msg, *args, **kw): + self.log(self.NOTIFY, msg, *args, **kw) + + def warn(self, msg, *args, **kw): + self.log(self.WARN, msg, *args, **kw) + + def error(self, msg, *args, **kw): + self.log(self.ERROR, msg, *args, **kw) + + def fatal(self, msg, *args, **kw): + self.log(self.FATAL, msg, *args, **kw) + + def log(self, level, msg, *args, **kw): + if args: + if kw: + raise TypeError( + "You may give positional or keyword arguments, not both") + args = args or kw + rendered = None + for consumer_level, consumer in self.consumers: + if self.level_matches(level, consumer_level): + if (self.in_progress_hanging + and consumer in (sys.stdout, sys.stderr)): + self.in_progress_hanging = False + sys.stdout.write('\n') + sys.stdout.flush() + if rendered is None: + if args: + rendered = msg % args + else: + rendered = msg + rendered = ' '*self.indent + rendered + if hasattr(consumer, 'write'): + consumer.write(rendered+'\n') + else: + consumer(rendered) + + def start_progress(self, msg): + assert not self.in_progress, ( + "Tried to start_progress(%r) while in_progress %r" + % (msg, self.in_progress)) + if self.level_matches(self.NOTIFY, self._stdout_level()): + sys.stdout.write(msg) + sys.stdout.flush() + self.in_progress_hanging = True + else: + self.in_progress_hanging = False + self.in_progress = msg + + def end_progress(self, msg='done.'): + assert self.in_progress, ( + "Tried to end_progress without start_progress") + if self.stdout_level_matches(self.NOTIFY): + if not self.in_progress_hanging: + # Some message has been printed out since start_progress + sys.stdout.write('...' + self.in_progress + msg + '\n') + sys.stdout.flush() + else: + sys.stdout.write(msg + '\n') + sys.stdout.flush() + self.in_progress = None + self.in_progress_hanging = False + + def show_progress(self): + """If we are in a progress scope, and no log messages have been + shown, write out another '.'""" + if self.in_progress_hanging: + sys.stdout.write('.') + sys.stdout.flush() + + def stdout_level_matches(self, level): + """Returns true if a message at this level will go to stdout""" + return self.level_matches(level, self._stdout_level()) + + def _stdout_level(self): + """Returns the level that stdout runs at""" + for level, consumer in self.consumers: + if consumer is sys.stdout: + return level + return self.FATAL + + def level_matches(self, level, consumer_level): + """ + >>> l = Logger([]) + >>> l.level_matches(3, 4) + False + >>> l.level_matches(3, 2) + True + >>> l.level_matches(slice(None, 3), 3) + False + >>> l.level_matches(slice(None, 3), 2) + True + >>> l.level_matches(slice(1, 3), 1) + True + >>> l.level_matches(slice(2, 3), 1) + False + """ + if isinstance(level, slice): + start, stop = level.start, level.stop + if start is not None and start > consumer_level: + return False + if stop is not None and stop <= consumer_level: + return False + return True + else: + return level >= consumer_level + + #@classmethod + def level_for_integer(cls, level): + levels = cls.LEVELS + if level < 0: + return levels[0] + if level >= len(levels): + return levels[-1] + return levels[level] + + level_for_integer = classmethod(level_for_integer) + +# create a silent logger just to prevent this from being undefined +# will be overridden with requested verbosity main() is called. +logger = Logger([(Logger.LEVELS[-1], sys.stdout)]) + +def mkdir(path): + if not os.path.exists(path): + logger.info('Creating %s', path) + os.makedirs(path) + else: + logger.info('Directory %s already exists', path) + +def copyfileordir(src, dest, symlink=True): + if os.path.isdir(src): + shutil.copytree(src, dest, symlink) + else: + shutil.copy2(src, dest) + +def copyfile(src, dest, symlink=True): + if not os.path.exists(src): + # Some bad symlink in the src + logger.warn('Cannot find file %s (bad symlink)', src) + return + if os.path.exists(dest): + logger.debug('File %s already exists', dest) + return + if not os.path.exists(os.path.dirname(dest)): + logger.info('Creating parent directories for %s', os.path.dirname(dest)) + os.makedirs(os.path.dirname(dest)) + if not os.path.islink(src): + srcpath = os.path.abspath(src) + else: + srcpath = os.readlink(src) + if symlink and hasattr(os, 'symlink') and not is_win: + logger.info('Symlinking %s', dest) + try: + os.symlink(srcpath, dest) + except (OSError, NotImplementedError): + logger.info('Symlinking failed, copying to %s', dest) + copyfileordir(src, dest, symlink) + else: + logger.info('Copying to %s', dest) + copyfileordir(src, dest, symlink) + +def writefile(dest, content, overwrite=True): + if not os.path.exists(dest): + logger.info('Writing %s', dest) + with open(dest, 'wb') as f: + f.write(content.encode('utf-8')) + return + else: + with open(dest, 'rb') as f: + c = f.read() + if c != content.encode("utf-8"): + if not overwrite: + logger.notify('File %s exists with different content; not overwriting', dest) + return + logger.notify('Overwriting %s with new content', dest) + with open(dest, 'wb') as f: + f.write(content.encode('utf-8')) + else: + logger.info('Content %s already in place', dest) + +def rmtree(dir): + if os.path.exists(dir): + logger.notify('Deleting tree %s', dir) + shutil.rmtree(dir) + else: + logger.info('Do not need to delete %s; already gone', dir) + +def make_exe(fn): + if hasattr(os, 'chmod'): + oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777 + newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777 + os.chmod(fn, newmode) + logger.info('Changed mode of %s to %s', fn, oct(newmode)) + +def _find_file(filename, dirs): + for dir in reversed(dirs): + files = glob.glob(os.path.join(dir, filename)) + if files and os.path.isfile(files[0]): + return True, files[0] + return False, filename + +def file_search_dirs(): + here = os.path.dirname(os.path.abspath(__file__)) + dirs = [here, join(here, 'virtualenv_support')] + if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': + # Probably some boot script; just in case virtualenv is installed... + try: + import virtualenv + except ImportError: + pass + else: + dirs.append(os.path.join( + os.path.dirname(virtualenv.__file__), 'virtualenv_support')) + return [d for d in dirs if os.path.isdir(d)] + + +class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter): + """ + Custom help formatter for use in ConfigOptionParser that updates + the defaults before expanding them, allowing them to show up correctly + in the help listing + """ + def expand_default(self, option): + if self.parser is not None: + self.parser.update_defaults(self.parser.defaults) + return optparse.IndentedHelpFormatter.expand_default(self, option) + + +class ConfigOptionParser(optparse.OptionParser): + """ + Custom option parser which updates its defaults by checking the + configuration files and environmental variables + """ + def __init__(self, *args, **kwargs): + self.config = ConfigParser.RawConfigParser() + self.files = self.get_config_files() + self.config.read(self.files) + optparse.OptionParser.__init__(self, *args, **kwargs) + + def get_config_files(self): + config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False) + if config_file and os.path.exists(config_file): + return [config_file] + return [default_config_file] + + def update_defaults(self, defaults): + """ + Updates the given defaults with values from the config files and + the environ. Does a little special handling for certain types of + options (lists). + """ + # Then go and look for the other sources of configuration: + config = {} + # 1. config files + config.update(dict(self.get_config_section('virtualenv'))) + # 2. environmental variables + config.update(dict(self.get_environ_vars())) + # Then set the options with those values + for key, val in config.items(): + key = key.replace('_', '-') + if not key.startswith('--'): + key = '--%s' % key # only prefer long opts + option = self.get_option(key) + if option is not None: + # ignore empty values + if not val: + continue + # handle multiline configs + if option.action == 'append': + val = val.split() + else: + option.nargs = 1 + if option.action == 'store_false': + val = not strtobool(val) + elif option.action in ('store_true', 'count'): + val = strtobool(val) + try: + val = option.convert_value(key, val) + except optparse.OptionValueError: + e = sys.exc_info()[1] + print("An error occurred during configuration: %s" % e) + sys.exit(3) + defaults[option.dest] = val + return defaults + + def get_config_section(self, name): + """ + Get a section of a configuration + """ + if self.config.has_section(name): + return self.config.items(name) + return [] + + def get_environ_vars(self, prefix='VIRTUALENV_'): + """ + Returns a generator with all environmental vars with prefix VIRTUALENV + """ + for key, val in os.environ.items(): + if key.startswith(prefix): + yield (key.replace(prefix, '').lower(), val) + + def get_default_values(self): + """ + Overridding to make updating the defaults after instantiation of + the option parser possible, update_defaults() does the dirty work. + """ + if not self.process_default_values: + # Old, pre-Optik 1.5 behaviour. + return optparse.Values(self.defaults) + + defaults = self.update_defaults(self.defaults.copy()) # ours + for option in self._get_all_options(): + default = defaults.get(option.dest) + if isinstance(default, basestring): + opt_str = option.get_opt_string() + defaults[option.dest] = option.check_value(opt_str, default) + return optparse.Values(defaults) + + +def main(): + parser = ConfigOptionParser( + version=virtualenv_version, + usage="%prog [OPTIONS] DEST_DIR", + formatter=UpdatingDefaultsHelpFormatter()) + + parser.add_option( + '-v', '--verbose', + action='count', + dest='verbose', + default=0, + help="Increase verbosity.") + + parser.add_option( + '-q', '--quiet', + action='count', + dest='quiet', + default=0, + help='Decrease verbosity.') + + parser.add_option( + '-p', '--python', + dest='python', + metavar='PYTHON_EXE', + help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' + 'interpreter to create the new environment. The default is the interpreter that ' + 'virtualenv was installed with (%s)' % sys.executable) + + parser.add_option( + '--clear', + dest='clear', + action='store_true', + help="Clear out the non-root install and start from scratch.") + + parser.set_defaults(system_site_packages=False) + parser.add_option( + '--no-site-packages', + dest='system_site_packages', + action='store_false', + help="DEPRECATED. Retained only for backward compatibility. " + "Not having access to global site-packages is now the default behavior.") + + parser.add_option( + '--system-site-packages', + dest='system_site_packages', + action='store_true', + help="Give the virtual environment access to the global site-packages.") + + parser.add_option( + '--always-copy', + dest='symlink', + action='store_false', + default=True, + help="Always copy files rather than symlinking.") + + parser.add_option( + '--unzip-setuptools', + dest='unzip_setuptools', + action='store_true', + help="Unzip Setuptools when installing it.") + + parser.add_option( + '--relocatable', + dest='relocatable', + action='store_true', + help='Make an EXISTING virtualenv environment relocatable. ' + 'This fixes up scripts and makes all .pth files relative.') + + parser.add_option( + '--no-setuptools', + dest='no_setuptools', + action='store_true', + help='Do not install setuptools in the new virtualenv.') + + parser.add_option( + '--no-pip', + dest='no_pip', + action='store_true', + help='Do not install pip in the new virtualenv.') + + parser.add_option( + '--no-wheel', + dest='no_wheel', + action='store_true', + help='Do not install wheel in the new virtualenv.') + + default_search_dirs = file_search_dirs() + parser.add_option( + '--extra-search-dir', + dest="search_dirs", + action="append", + metavar='DIR', + default=default_search_dirs, + help="Directory to look for setuptools/pip distributions in. " + "This option can be used multiple times.") + + parser.add_option( + "--download", + dest="download", + default=True, + action="store_true", + help="Download preinstalled packages from PyPI.", + ) + + parser.add_option( + "--no-download", + '--never-download', + dest="download", + action="store_false", + help="Do not download preinstalled packages from PyPI.", + ) + + parser.add_option( + '--prompt', + dest='prompt', + help='Provides an alternative prompt prefix for this environment.') + + parser.add_option( + '--setuptools', + dest='setuptools', + action='store_true', + help="DEPRECATED. Retained only for backward compatibility. This option has no effect.") + + parser.add_option( + '--distribute', + dest='distribute', + action='store_true', + help="DEPRECATED. Retained only for backward compatibility. This option has no effect.") + + if 'extend_parser' in globals(): + extend_parser(parser) + + options, args = parser.parse_args() + + global logger + + if 'adjust_options' in globals(): + adjust_options(options, args) + + verbosity = options.verbose - options.quiet + logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)]) + + if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): + env = os.environ.copy() + interpreter = resolve_interpreter(options.python) + if interpreter == sys.executable: + logger.warn('Already using interpreter %s' % interpreter) + else: + logger.notify('Running virtualenv with interpreter %s' % interpreter) + env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true' + file = __file__ + if file.endswith('.pyc'): + file = file[:-1] + popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env) + raise SystemExit(popen.wait()) + + if not args: + print('You must provide a DEST_DIR') + parser.print_help() + sys.exit(2) + if len(args) > 1: + print('There must be only one argument: DEST_DIR (you gave %s)' % ( + ' '.join(args))) + parser.print_help() + sys.exit(2) + + home_dir = args[0] + + if os.path.exists(home_dir) and os.path.isfile(home_dir): + logger.fatal('ERROR: File already exists and is not a directory.') + logger.fatal('Please provide a different path or delete the file.') + sys.exit(3) + + if os.environ.get('WORKING_ENV'): + logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') + logger.fatal('Please deactivate your workingenv, then re-run this script') + sys.exit(3) + + if 'PYTHONHOME' in os.environ: + logger.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it') + del os.environ['PYTHONHOME'] + + if options.relocatable: + make_environment_relocatable(home_dir) + return + + create_environment(home_dir, + site_packages=options.system_site_packages, + clear=options.clear, + unzip_setuptools=options.unzip_setuptools, + prompt=options.prompt, + search_dirs=options.search_dirs, + download=options.download, + no_setuptools=options.no_setuptools, + no_pip=options.no_pip, + no_wheel=options.no_wheel, + symlink=options.symlink and hasattr(os, 'symlink')) # MOZ: Make sure we don't use symlink when we don't have it + if 'after_install' in globals(): + after_install(options, home_dir) + +def call_subprocess(cmd, show_stdout=True, + filter_stdout=None, cwd=None, + raise_on_returncode=True, extra_env=None, + remove_from_env=None, stdin=None): + cmd_parts = [] + for part in cmd: + if len(part) > 45: + part = part[:20]+"..."+part[-20:] + if ' ' in part or '\n' in part or '"' in part or "'" in part: + part = '"%s"' % part.replace('"', '\\"') + if hasattr(part, 'decode'): + try: + part = part.decode(sys.getdefaultencoding()) + except UnicodeDecodeError: + part = part.decode(sys.getfilesystemencoding()) + cmd_parts.append(part) + cmd_desc = ' '.join(cmd_parts) + if show_stdout: + stdout = None + else: + stdout = subprocess.PIPE + logger.debug("Running command %s" % cmd_desc) + if extra_env or remove_from_env: + env = os.environ.copy() + if extra_env: + env.update(extra_env) + if remove_from_env: + for varname in remove_from_env: + env.pop(varname, None) + else: + env = None + try: + proc = subprocess.Popen( + cmd, stderr=subprocess.STDOUT, + stdin=None if stdin is None else subprocess.PIPE, + stdout=stdout, + cwd=cwd, env=env) + except Exception: + e = sys.exc_info()[1] + logger.fatal( + "Error %s while executing command %s" % (e, cmd_desc)) + raise + all_output = [] + if stdout is not None: + if stdin is not None: + proc.stdin.write(stdin) + proc.stdin.close() + + stdout = proc.stdout + encoding = sys.getdefaultencoding() + fs_encoding = sys.getfilesystemencoding() + while 1: + line = stdout.readline() + try: + line = line.decode(encoding) + except UnicodeDecodeError: + line = line.decode(fs_encoding) + if not line: + break + line = line.rstrip() + all_output.append(line) + if filter_stdout: + level = filter_stdout(line) + if isinstance(level, tuple): + level, line = level + logger.log(level, line) + if not logger.stdout_level_matches(level): + logger.show_progress() + else: + logger.info(line) + else: + proc.communicate(stdin) + proc.wait() + if proc.returncode: + if raise_on_returncode: + if all_output: + logger.notify('Complete output from command %s:' % cmd_desc) + logger.notify('\n'.join(all_output) + '\n----------------------------------------') + raise OSError( + "Command %s failed with error code %s" + % (cmd_desc, proc.returncode)) + else: + logger.warn( + "Command %s had error code %s" + % (cmd_desc, proc.returncode)) + +def filter_install_output(line): + if line.strip().startswith('running'): + return Logger.INFO + return Logger.DEBUG + +def find_wheels(projects, search_dirs): + """Find wheels from which we can import PROJECTS. + + Scan through SEARCH_DIRS for a wheel for each PROJECT in turn. Return + a list of the first wheel found for each PROJECT + """ + + wheels = [] + + # Look through SEARCH_DIRS for the first suitable wheel. Don't bother + # about version checking here, as this is simply to get something we can + # then use to install the correct version. + for project in projects: + for dirname in search_dirs: + # This relies on only having "universal" wheels available. + # The pattern could be tightened to require -py2.py3-none-any.whl. + files = glob.glob(os.path.join(dirname, project + '-*.whl')) + if files: + wheels.append(os.path.abspath(files[0])) + break + else: + # We're out of luck, so quit with a suitable error + logger.fatal('Cannot find a wheel for %s' % (project,)) + + return wheels + +def install_wheel(project_names, py_executable, search_dirs=None, + download=False): + if search_dirs is None: + search_dirs = file_search_dirs() + + wheels = find_wheels(['setuptools', 'pip'], search_dirs) + pythonpath = os.pathsep.join(wheels) + + # PIP_FIND_LINKS uses space as the path separator and thus cannot have paths + # with spaces in them. Convert any of those to local file:// URL form. + try: + from urlparse import urljoin + from urllib import pathname2url + except ImportError: + from urllib.parse import urljoin + from urllib.request import pathname2url + def space_path2url(p): + if ' ' not in p: + return p + return urljoin('file:', pathname2url(os.path.abspath(p))) + findlinks = ' '.join(space_path2url(d) for d in search_dirs) + + SCRIPT = textwrap.dedent(""" + import sys + import pkgutil + import tempfile + import os + + import pip + + cert_data = pkgutil.get_data("pip._vendor.requests", "cacert.pem") + if cert_data is not None: + cert_file = tempfile.NamedTemporaryFile(delete=False) + cert_file.write(cert_data) + cert_file.close() + else: + cert_file = None + + try: + args = ["install", "--ignore-installed"] + if cert_file is not None: + args += ["--cert", cert_file.name] + args += sys.argv[1:] + + sys.exit(pip.main(args)) + finally: + if cert_file is not None: + os.remove(cert_file.name) + """).encode("utf8") + + cmd = [py_executable, '-'] + project_names + logger.start_progress('Installing %s...' % (', '.join(project_names))) + logger.indent += 2 + + env = { + "PYTHONPATH": pythonpath, + "JYTHONPATH": pythonpath, # for Jython < 3.x + "PIP_FIND_LINKS": findlinks, + "PIP_USE_WHEEL": "1", + "PIP_ONLY_BINARY": ":all:", + "PIP_PRE": "1", + "PIP_USER": "0", + } + + if not download: + env["PIP_NO_INDEX"] = "1" + + try: + call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=SCRIPT) + finally: + logger.indent -= 2 + logger.end_progress() + + +def create_environment(home_dir, site_packages=False, clear=False, + unzip_setuptools=False, + prompt=None, search_dirs=None, download=False, + no_setuptools=False, no_pip=False, no_wheel=False, + symlink=True): + """ + Creates a new environment in ``home_dir``. + + If ``site_packages`` is true, then the global ``site-packages/`` + directory will be on the path. + + If ``clear`` is true (default False) then the environment will + first be cleared. + """ + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) + + py_executable = os.path.abspath(install_python( + home_dir, lib_dir, inc_dir, bin_dir, + site_packages=site_packages, clear=clear, symlink=symlink)) + + install_distutils(home_dir) + + to_install = [] + + if not no_setuptools: + to_install.append('setuptools') + + if not no_pip: + to_install.append('pip') + + if not no_wheel: + to_install.append('wheel') + + if to_install: + install_wheel( + to_install, + py_executable, + search_dirs, + download=download, + ) + + install_activate(home_dir, bin_dir, prompt) + + install_python_config(home_dir, bin_dir, prompt) + +def is_executable_file(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + +def path_locations(home_dir): + """Return the path locations for the environment (where libraries are, + where scripts go, etc)""" + home_dir = os.path.abspath(home_dir) + # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its + # prefix arg is broken: http://bugs.python.org/issue3386 + if is_win: + # Windows has lots of problems with executables with spaces in + # the name; this function will remove them (using the ~1 + # format): + mkdir(home_dir) + if ' ' in home_dir: + import ctypes + GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW + size = max(len(home_dir)+1, 256) + buf = ctypes.create_unicode_buffer(size) + try: + u = unicode + except NameError: + u = str + ret = GetShortPathName(u(home_dir), buf, size) + if not ret: + print('Error: the path "%s" has a space in it' % home_dir) + print('We could not determine the short pathname for it.') + print('Exiting.') + sys.exit(3) + home_dir = str(buf.value) + lib_dir = join(home_dir, 'Lib') + inc_dir = join(home_dir, 'Include') + bin_dir = join(home_dir, 'Scripts') + if is_jython: + lib_dir = join(home_dir, 'Lib') + inc_dir = join(home_dir, 'Include') + bin_dir = join(home_dir, 'bin') + elif is_pypy: + lib_dir = home_dir + inc_dir = join(home_dir, 'include') + bin_dir = join(home_dir, 'bin') + elif not is_win: + lib_dir = join(home_dir, 'lib', py_version) + inc_dir = join(home_dir, 'include', py_version + abiflags) + bin_dir = join(home_dir, 'bin') + return home_dir, lib_dir, inc_dir, bin_dir + + +def change_prefix(filename, dst_prefix): + prefixes = [sys.prefix] + + if is_darwin: + prefixes.extend(( + os.path.join("/Library/Python", sys.version[:3], "site-packages"), + os.path.join(sys.prefix, "Extras", "lib", "python"), + os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"), + # Python 2.6 no-frameworks + os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"), + # System Python 2.7 on OSX Mountain Lion + os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages"))) + + if hasattr(sys, 'real_prefix'): + prefixes.append(sys.real_prefix) + if hasattr(sys, 'base_prefix'): + prefixes.append(sys.base_prefix) + prefixes = list(map(os.path.expanduser, prefixes)) + prefixes = list(map(os.path.abspath, prefixes)) + # Check longer prefixes first so we don't split in the middle of a filename + prefixes = sorted(prefixes, key=len, reverse=True) + filename = os.path.abspath(filename) + # On Windows, make sure drive letter is uppercase + if is_win and filename[0] in 'abcdefghijklmnopqrstuvwxyz': + filename = filename[0].upper() + filename[1:] + for i, prefix in enumerate(prefixes): + if is_win and prefix[0] in 'abcdefghijklmnopqrstuvwxyz': + prefixes[i] = prefix[0].upper() + prefix[1:] + for src_prefix in prefixes: + if filename.startswith(src_prefix): + _, relpath = filename.split(src_prefix, 1) + if src_prefix != os.sep: # sys.prefix == "/" + assert relpath[0] == os.sep + relpath = relpath[1:] + return join(dst_prefix, relpath) + assert False, "Filename %s does not start with any of these prefixes: %s" % \ + (filename, prefixes) + +def copy_required_modules(dst_prefix, symlink): + import imp + + for modname in REQUIRED_MODULES: + if modname in sys.builtin_module_names: + logger.info("Ignoring built-in bootstrap module: %s" % modname) + continue + try: + f, filename, _ = imp.find_module(modname) + except ImportError: + logger.info("Cannot import bootstrap module: %s" % modname) + else: + if f is not None: + f.close() + # special-case custom readline.so on OS X, but not for pypy: + if modname == 'readline' and sys.platform == 'darwin' and not ( + is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))): + dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so') + elif modname == 'readline' and sys.platform == 'win32': + # special-case for Windows, where readline is not a + # standard module, though it may have been installed in + # site-packages by a third-party package + pass + else: + dst_filename = change_prefix(filename, dst_prefix) + copyfile(filename, dst_filename, symlink) + if filename.endswith('.pyc'): + pyfile = filename[:-1] + if os.path.exists(pyfile): + copyfile(pyfile, dst_filename[:-1], symlink) + + +def subst_path(prefix_path, prefix, home_dir): + prefix_path = os.path.normpath(prefix_path) + prefix = os.path.normpath(prefix) + home_dir = os.path.normpath(home_dir) + if not prefix_path.startswith(prefix): + logger.warn('Path not in prefix %r %r', prefix_path, prefix) + return + return prefix_path.replace(prefix, home_dir, 1) + + +def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, symlink=True): + """Install just the base environment, no distutils patches etc""" + if sys.executable.startswith(bin_dir): + print('Please use the *system* python to run this script') + return + + if clear: + rmtree(lib_dir) + ## FIXME: why not delete it? + ## Maybe it should delete everything with #!/path/to/venv/python in it + logger.notify('Not deleting %s', bin_dir) + + if hasattr(sys, 'real_prefix'): + logger.notify('Using real prefix %r' % sys.real_prefix) + prefix = sys.real_prefix + elif hasattr(sys, 'base_prefix'): + logger.notify('Using base prefix %r' % sys.base_prefix) + prefix = sys.base_prefix + else: + prefix = sys.prefix + mkdir(lib_dir) + fix_lib64(lib_dir, symlink) + stdlib_dirs = [os.path.dirname(os.__file__)] + if is_win: + stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) + elif is_darwin: + stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages')) + if hasattr(os, 'symlink'): + logger.info('Symlinking Python bootstrap modules') + else: + logger.info('Copying Python bootstrap modules') + logger.indent += 2 + try: + # copy required files... + for stdlib_dir in stdlib_dirs: + if not os.path.isdir(stdlib_dir): + continue + for fn in os.listdir(stdlib_dir): + bn = os.path.splitext(fn)[0] + if fn != 'site-packages' and bn in REQUIRED_FILES: + copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink) + # ...and modules + copy_required_modules(home_dir, symlink) + finally: + logger.indent -= 2 + mkdir(join(lib_dir, 'site-packages')) + import site + site_filename = site.__file__ + if site_filename.endswith('.pyc') or site_filename.endswith('.pyo'): + site_filename = site_filename[:-1] + elif site_filename.endswith('$py.class'): + site_filename = site_filename.replace('$py.class', '.py') + site_filename_dst = change_prefix(site_filename, home_dir) + site_dir = os.path.dirname(site_filename_dst) + # MOZ: Copies a site.py if it exists instead of using the one hex encoded in + # this file. Necessary for some site.py fixes for MinGW64 version of python + site_py_src_path = os.path.join(os.path.dirname(__file__), 'site.py') + if os.path.isfile(site_py_src_path): + shutil.copy(site_py_src_path, site_filename_dst) + else: + writefile(site_filename_dst, SITE_PY) + writefile(join(site_dir, 'orig-prefix.txt'), prefix) + site_packages_filename = join(site_dir, 'no-global-site-packages.txt') + if not site_packages: + writefile(site_packages_filename, '') + + if is_pypy or is_win: + stdinc_dir = join(prefix, 'include') + else: + stdinc_dir = join(prefix, 'include', py_version + abiflags) + if os.path.exists(stdinc_dir): + copyfile(stdinc_dir, inc_dir, symlink) + else: + logger.debug('No include dir %s' % stdinc_dir) + + platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1) + if platinc_dir != stdinc_dir: + platinc_dest = distutils.sysconfig.get_python_inc( + plat_specific=1, prefix=home_dir) + if platinc_dir == platinc_dest: + # Do platinc_dest manually due to a CPython bug; + # not http://bugs.python.org/issue3386 but a close cousin + platinc_dest = subst_path(platinc_dir, prefix, home_dir) + if platinc_dest: + # PyPy's stdinc_dir and prefix are relative to the original binary + # (traversing virtualenvs), whereas the platinc_dir is relative to + # the inner virtualenv and ignores the prefix argument. + # This seems more evolved than designed. + copyfile(platinc_dir, platinc_dest, symlink) + + # pypy never uses exec_prefix, just ignore it + if sys.exec_prefix != prefix and not is_pypy: + if is_win: + exec_dir = join(sys.exec_prefix, 'lib') + elif is_jython: + exec_dir = join(sys.exec_prefix, 'Lib') + else: + exec_dir = join(sys.exec_prefix, 'lib', py_version) + for fn in os.listdir(exec_dir): + copyfile(join(exec_dir, fn), join(lib_dir, fn), symlink) + + if is_jython: + # Jython has either jython-dev.jar and javalib/ dir, or just + # jython.jar + for name in 'jython-dev.jar', 'javalib', 'jython.jar': + src = join(prefix, name) + if os.path.exists(src): + copyfile(src, join(home_dir, name), symlink) + # XXX: registry should always exist after Jython 2.5rc1 + src = join(prefix, 'registry') + if os.path.exists(src): + copyfile(src, join(home_dir, 'registry'), symlink=False) + copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'), + symlink=False) + + mkdir(bin_dir) + py_executable = join(bin_dir, os.path.basename(sys.executable)) + if 'Python.framework' in prefix: + # OS X framework builds cause validation to break + # https://github.com/pypa/virtualenv/issues/322 + if os.environ.get('__PYVENV_LAUNCHER__'): + del os.environ["__PYVENV_LAUNCHER__"] + if re.search(r'/Python(?:-32|-64)*$', py_executable): + # The name of the python executable is not quite what + # we want, rename it. + py_executable = os.path.join( + os.path.dirname(py_executable), 'python') + + logger.notify('New %s executable in %s', expected_exe, py_executable) + pcbuild_dir = os.path.dirname(sys.executable) + pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth') + if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')): + logger.notify('Detected python running from build directory %s', pcbuild_dir) + logger.notify('Writing .pth file linking to build directory for *.pyd files') + writefile(pyd_pth, pcbuild_dir) + else: + pcbuild_dir = None + if os.path.exists(pyd_pth): + logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth) + os.unlink(pyd_pth) + + if sys.executable != py_executable: + ## FIXME: could I just hard link? + executable = sys.executable + shutil.copyfile(executable, py_executable) + make_exe(py_executable) + if is_win or is_cygwin: + pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe') + if os.path.exists(pythonw): + logger.info('Also created pythonw.exe') + shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe')) + python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe') + python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe') + if os.path.exists(python_d): + logger.info('Also created python_d.exe') + shutil.copyfile(python_d, python_d_dest) + elif os.path.exists(python_d_dest): + logger.info('Removed python_d.exe as it is no longer at the source') + os.unlink(python_d_dest) + # we need to copy the DLL to enforce that windows will load the correct one. + # may not exist if we are cygwin. + py_executable_dll = 'python%s%s.dll' % ( + sys.version_info[0], sys.version_info[1]) + py_executable_dll_d = 'python%s%s_d.dll' % ( + sys.version_info[0], sys.version_info[1]) + pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll) + pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d) + pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d) + if os.path.exists(pythondll): + logger.info('Also created %s' % py_executable_dll) + shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll)) + if os.path.exists(pythondll_d): + logger.info('Also created %s' % py_executable_dll_d) + shutil.copyfile(pythondll_d, pythondll_d_dest) + elif os.path.exists(pythondll_d_dest): + logger.info('Removed %s as the source does not exist' % pythondll_d_dest) + os.unlink(pythondll_d_dest) + if is_pypy: + # make a symlink python --> pypy-c + python_executable = os.path.join(os.path.dirname(py_executable), 'python') + if sys.platform in ('win32', 'cygwin'): + python_executable += '.exe' + logger.info('Also created executable %s' % python_executable) + copyfile(py_executable, python_executable, symlink) + + if is_win: + for name in ['libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', + 'libeay32.dll', 'ssleay32.dll', 'sqlite3.dll', + 'tcl85.dll', 'tk85.dll']: + src = join(prefix, name) + if os.path.exists(src): + copyfile(src, join(bin_dir, name), symlink) + + for d in sys.path: + if d.endswith('lib_pypy'): + break + else: + logger.fatal('Could not find lib_pypy in sys.path') + raise SystemExit(3) + logger.info('Copying lib_pypy') + copyfile(d, os.path.join(home_dir, 'lib_pypy'), symlink) + + if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe: + secondary_exe = os.path.join(os.path.dirname(py_executable), + expected_exe) + py_executable_ext = os.path.splitext(py_executable)[1] + if py_executable_ext.lower() == '.exe': + # python2.4 gives an extension of '.4' :P + secondary_exe += py_executable_ext + if os.path.exists(secondary_exe): + logger.warn('Not overwriting existing %s script %s (you must use %s)' + % (expected_exe, secondary_exe, py_executable)) + else: + logger.notify('Also creating executable in %s' % secondary_exe) + shutil.copyfile(sys.executable, secondary_exe) + make_exe(secondary_exe) + + if '.framework' in prefix: + if 'Python.framework' in prefix: + logger.debug('MacOSX Python framework detected') + # Make sure we use the embedded interpreter inside + # the framework, even if sys.executable points to + # the stub executable in ${sys.prefix}/bin + # See http://groups.google.com/group/python-virtualenv/ + # browse_thread/thread/17cab2f85da75951 + original_python = os.path.join( + prefix, 'Resources/Python.app/Contents/MacOS/Python') + if 'EPD' in prefix: + logger.debug('EPD framework detected') + original_python = os.path.join(prefix, 'bin/python') + shutil.copy(original_python, py_executable) + + # Copy the framework's dylib into the virtual + # environment + virtual_lib = os.path.join(home_dir, '.Python') + + if os.path.exists(virtual_lib): + os.unlink(virtual_lib) + copyfile( + os.path.join(prefix, 'Python'), + virtual_lib, + symlink) + + # And then change the install_name of the copied python executable + try: + mach_o_change(py_executable, + os.path.join(prefix, 'Python'), + '@executable_path/../.Python') + except: + e = sys.exc_info()[1] + logger.warn("Could not call mach_o_change: %s. " + "Trying to call install_name_tool instead." % e) + try: + call_subprocess( + ["install_name_tool", "-change", + os.path.join(prefix, 'Python'), + '@executable_path/../.Python', + py_executable]) + except: + logger.fatal("Could not call install_name_tool -- you must " + "have Apple's development tools installed") + raise + + if not is_win: + # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist + py_exe_version_major = 'python%s' % sys.version_info[0] + py_exe_version_major_minor = 'python%s.%s' % ( + sys.version_info[0], sys.version_info[1]) + py_exe_no_version = 'python' + required_symlinks = [ py_exe_no_version, py_exe_version_major, + py_exe_version_major_minor ] + + py_executable_base = os.path.basename(py_executable) + + if py_executable_base in required_symlinks: + # Don't try to symlink to yourself. + required_symlinks.remove(py_executable_base) + + for pth in required_symlinks: + full_pth = join(bin_dir, pth) + if os.path.exists(full_pth): + os.unlink(full_pth) + if symlink: + os.symlink(py_executable_base, full_pth) + else: + copyfile(py_executable, full_pth, symlink) + + if is_win and ' ' in py_executable: + # There's a bug with subprocess on Windows when using a first + # argument that has a space in it. Instead we have to quote + # the value: + py_executable = '"%s"' % py_executable + # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks + cmd = [py_executable, '-c', 'import sys;out=sys.stdout;' + 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))'] + logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) + try: + proc = subprocess.Popen(cmd, + stdout=subprocess.PIPE) + proc_stdout, proc_stderr = proc.communicate() + except OSError: + e = sys.exc_info()[1] + if e.errno == errno.EACCES: + logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e)) + sys.exit(100) + else: + raise e + + proc_stdout = proc_stdout.strip().decode("utf-8") + proc_stdout = os.path.normcase(os.path.abspath(proc_stdout)) + norm_home_dir = os.path.normcase(os.path.abspath(home_dir)) + if hasattr(norm_home_dir, 'decode'): + norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding()) + if proc_stdout != norm_home_dir: + logger.fatal( + 'ERROR: The executable %s is not functioning' % py_executable) + logger.fatal( + 'ERROR: It thinks sys.prefix is %r (should be %r)' + % (proc_stdout, norm_home_dir)) + logger.fatal( + 'ERROR: virtualenv is not compatible with this system or executable') + if is_win: + logger.fatal( + 'Note: some Windows users have reported this error when they ' + 'installed Python for "Only this user" or have multiple ' + 'versions of Python installed. Copying the appropriate ' + 'PythonXX.dll to the virtualenv Scripts/ directory may fix ' + 'this problem.') + sys.exit(100) + else: + logger.info('Got sys.prefix result: %r' % proc_stdout) + + pydistutils = os.path.expanduser('~/.pydistutils.cfg') + if os.path.exists(pydistutils): + logger.notify('Please make sure you remove any previous custom paths from ' + 'your %s file.' % pydistutils) + ## FIXME: really this should be calculated earlier + + fix_local_scheme(home_dir, symlink) + + if site_packages: + if os.path.exists(site_packages_filename): + logger.info('Deleting %s' % site_packages_filename) + os.unlink(site_packages_filename) + + return py_executable + + +def install_activate(home_dir, bin_dir, prompt=None): + if is_win or is_jython and os._name == 'nt': + files = { + 'activate.bat': ACTIVATE_BAT, + 'deactivate.bat': DEACTIVATE_BAT, + 'activate.ps1': ACTIVATE_PS, + } + + # MSYS needs paths of the form /c/path/to/file + drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/')) + home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail) + + # Run-time conditional enables (basic) Cygwin compatibility + home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" % + (home_dir, home_dir_msys)) + files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh) + + else: + files = {'activate': ACTIVATE_SH} + + # suppling activate.fish in addition to, not instead of, the + # bash script support. + files['activate.fish'] = ACTIVATE_FISH + + # same for csh/tcsh support... + files['activate.csh'] = ACTIVATE_CSH + + files['activate_this.py'] = ACTIVATE_THIS + + install_files(home_dir, bin_dir, prompt, files) + +def install_files(home_dir, bin_dir, prompt, files): + if hasattr(home_dir, 'decode'): + home_dir = home_dir.decode(sys.getfilesystemencoding()) + vname = os.path.basename(home_dir) + for name, content in files.items(): + content = content.replace('__VIRTUAL_PROMPT__', prompt or '') + content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname) + content = content.replace('__VIRTUAL_ENV__', home_dir) + content = content.replace('__VIRTUAL_NAME__', vname) + content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) + writefile(os.path.join(bin_dir, name), content) + +def install_python_config(home_dir, bin_dir, prompt=None): + if sys.platform == 'win32' or is_jython and os._name == 'nt': + files = {} + else: + files = {'python-config': PYTHON_CONFIG} + install_files(home_dir, bin_dir, prompt, files) + for name, content in files.items(): + make_exe(os.path.join(bin_dir, name)) + +def install_distutils(home_dir): + distutils_path = change_prefix(distutils.__path__[0], home_dir) + mkdir(distutils_path) + ## FIXME: maybe this prefix setting should only be put in place if + ## there's a local distutils.cfg with a prefix setting? + home_dir = os.path.abspath(home_dir) + ## FIXME: this is breaking things, removing for now: + #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir + writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) + writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False) + +def fix_local_scheme(home_dir, symlink=True): + """ + Platforms that use the "posix_local" install scheme (like Ubuntu with + Python 2.7) need to be given an additional "local" location, sigh. + """ + try: + import sysconfig + except ImportError: + pass + else: + if sysconfig._get_default_scheme() == 'posix_local': + local_path = os.path.join(home_dir, 'local') + if not os.path.exists(local_path): + os.mkdir(local_path) + for subdir_name in os.listdir(home_dir): + if subdir_name == 'local': + continue + copyfile(os.path.abspath(os.path.join(home_dir, subdir_name)), \ + os.path.join(local_path, subdir_name), symlink) + +def fix_lib64(lib_dir, symlink=True): + """ + Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y + instead of lib/pythonX.Y. If this is such a platform we'll just create a + symlink so lib64 points to lib + """ + # PyPy's library path scheme is not affected by this. + # Return early or we will die on the following assert. + if is_pypy: + logger.debug('PyPy detected, skipping lib64 symlinking') + return + # Check we have a lib64 library path + if not [p for p in distutils.sysconfig.get_config_vars().values() + if isinstance(p, basestring) and 'lib64' in p]: + return + + logger.debug('This system uses lib64; symlinking lib64 to lib') + + assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( + "Unexpected python lib dir: %r" % lib_dir) + lib_parent = os.path.dirname(lib_dir) + top_level = os.path.dirname(lib_parent) + lib_dir = os.path.join(top_level, 'lib') + lib64_link = os.path.join(top_level, 'lib64') + assert os.path.basename(lib_parent) == 'lib', ( + "Unexpected parent dir: %r" % lib_parent) + if os.path.lexists(lib64_link): + return + if symlink: + os.symlink('lib', lib64_link) + else: + copyfile('lib', lib64_link) + +def resolve_interpreter(exe): + """ + If the executable given isn't an absolute path, search $PATH for the interpreter + """ + # If the "executable" is a version number, get the installed executable for + # that version + python_versions = get_installed_pythons() + if exe in python_versions: + exe = python_versions[exe] + + if os.path.abspath(exe) != exe: + paths = os.environ.get('PATH', '').split(os.pathsep) + for path in paths: + if os.path.exists(join(path, exe)): + exe = join(path, exe) + break + if not os.path.exists(exe): + logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe)) + raise SystemExit(3) + if not is_executable(exe): + logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe)) + raise SystemExit(3) + return exe + +def is_executable(exe): + """Checks a file is executable""" + return os.access(exe, os.X_OK) + +############################################################ +## Relocating the environment: + +def make_environment_relocatable(home_dir): + """ + Makes the already-existing environment use relative paths, and takes out + the #!-based environment selection in scripts. + """ + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) + activate_this = os.path.join(bin_dir, 'activate_this.py') + if not os.path.exists(activate_this): + logger.fatal( + 'The environment doesn\'t have a file %s -- please re-run virtualenv ' + 'on this environment to update it' % activate_this) + fixup_scripts(home_dir, bin_dir) + fixup_pth_and_egg_link(home_dir) + ## FIXME: need to fix up distutils.cfg + +OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3], + 'activate', 'activate.bat', 'activate_this.py', + 'activate.fish', 'activate.csh'] + +def fixup_scripts(home_dir, bin_dir): + if is_win: + new_shebang_args = ( + '%s /c' % os.path.normcase(os.environ.get('COMSPEC', 'cmd.exe')), + '', '.exe') + else: + new_shebang_args = ('/usr/bin/env', sys.version[:3], '') + + # This is what we expect at the top of scripts: + shebang = '#!%s' % os.path.normcase(os.path.join( + os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2])) + # This is what we'll put: + new_shebang = '#!%s python%s%s' % new_shebang_args + + for filename in os.listdir(bin_dir): + filename = os.path.join(bin_dir, filename) + if not os.path.isfile(filename): + # ignore subdirs, e.g. .svn ones. + continue + lines = None + with open(filename, 'rb') as f: + try: + lines = f.read().decode('utf-8').splitlines() + except UnicodeDecodeError: + # This is probably a binary program instead + # of a script, so just ignore it. + continue + if not lines: + logger.warn('Script %s is an empty file' % filename) + continue + + old_shebang = lines[0].strip() + old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:]) + + if not old_shebang.startswith(shebang): + if os.path.basename(filename) in OK_ABS_SCRIPTS: + logger.debug('Cannot make script %s relative' % filename) + elif lines[0].strip() == new_shebang: + logger.info('Script %s has already been made relative' % filename) + else: + logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)' + % (filename, shebang)) + continue + logger.notify('Making script %s relative' % filename) + script = relative_script([new_shebang] + lines[1:]) + with open(filename, 'wb') as f: + f.write('\n'.join(script).encode('utf-8')) + + +def relative_script(lines): + "Return a script that'll work in a relocatable environment." + activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); exec(compile(open(activate_this).read(), activate_this, 'exec'), dict(__file__=activate_this)); del os, activate_this" + # Find the last future statement in the script. If we insert the activation + # line before a future statement, Python will raise a SyntaxError. + activate_at = None + for idx, line in reversed(list(enumerate(lines))): + if line.split()[:3] == ['from', '__future__', 'import']: + activate_at = idx + 1 + break + if activate_at is None: + # Activate after the shebang. + activate_at = 1 + return lines[:activate_at] + ['', activate, ''] + lines[activate_at:] + +def fixup_pth_and_egg_link(home_dir, sys_path=None): + """Makes .pth and .egg-link files use relative paths""" + home_dir = os.path.normcase(os.path.abspath(home_dir)) + if sys_path is None: + sys_path = sys.path + for path in sys_path: + if not path: + path = '.' + if not os.path.isdir(path): + continue + path = os.path.normcase(os.path.abspath(path)) + if not path.startswith(home_dir): + logger.debug('Skipping system (non-environment) directory %s' % path) + continue + for filename in os.listdir(path): + filename = os.path.join(path, filename) + if filename.endswith('.pth'): + if not os.access(filename, os.W_OK): + logger.warn('Cannot write .pth file %s, skipping' % filename) + else: + fixup_pth_file(filename) + if filename.endswith('.egg-link'): + if not os.access(filename, os.W_OK): + logger.warn('Cannot write .egg-link file %s, skipping' % filename) + else: + fixup_egg_link(filename) + +def fixup_pth_file(filename): + lines = [] + prev_lines = [] + with open(filename) as f: + prev_lines = f.readlines() + for line in prev_lines: + line = line.strip() + if (not line or line.startswith('#') or line.startswith('import ') + or os.path.abspath(line) != line): + lines.append(line) + else: + new_value = make_relative_path(filename, line) + if line != new_value: + logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename)) + lines.append(new_value) + if lines == prev_lines: + logger.info('No changes to .pth file %s' % filename) + return + logger.notify('Making paths in .pth file %s relative' % filename) + with open(filename, 'w') as f: + f.write('\n'.join(lines) + '\n') + +def fixup_egg_link(filename): + with open(filename) as f: + link = f.readline().strip() + if os.path.abspath(link) != link: + logger.debug('Link in %s already relative' % filename) + return + new_link = make_relative_path(filename, link) + logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) + with open(filename, 'w') as f: + f.write(new_link) + +def make_relative_path(source, dest, dest_is_directory=True): + """ + Make a filename relative, where the filename is dest, and it is + being referred to from the filename source. + + >>> make_relative_path('/usr/share/something/a-file.pth', + ... '/usr/share/another-place/src/Directory') + '../another-place/src/Directory' + >>> make_relative_path('/usr/share/something/a-file.pth', + ... '/home/user/src/Directory') + '../../../home/user/src/Directory' + >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') + './' + """ + source = os.path.dirname(source) + if not dest_is_directory: + dest_filename = os.path.basename(dest) + dest = os.path.dirname(dest) + dest = os.path.normpath(os.path.abspath(dest)) + source = os.path.normpath(os.path.abspath(source)) + dest_parts = dest.strip(os.path.sep).split(os.path.sep) + source_parts = source.strip(os.path.sep).split(os.path.sep) + while dest_parts and source_parts and dest_parts[0] == source_parts[0]: + dest_parts.pop(0) + source_parts.pop(0) + full_parts = ['..']*len(source_parts) + dest_parts + if not dest_is_directory: + full_parts.append(dest_filename) + if not full_parts: + # Special case for the current directory (otherwise it'd be '') + return './' + return os.path.sep.join(full_parts) + + + +############################################################ +## Bootstrap script creation: + +def create_bootstrap_script(extra_text, python_version=''): + """ + Creates a bootstrap script, which is like this script but with + extend_parser, adjust_options, and after_install hooks. + + This returns a string that (written to disk of course) can be used + as a bootstrap script with your own customizations. The script + will be the standard virtualenv.py script, with your extra text + added (your extra text should be Python code). + + If you include these functions, they will be called: + + ``extend_parser(optparse_parser)``: + You can add or remove options from the parser here. + + ``adjust_options(options, args)``: + You can change options here, or change the args (if you accept + different kinds of arguments, be sure you modify ``args`` so it is + only ``[DEST_DIR]``). + + ``after_install(options, home_dir)``: + + After everything is installed, this function is called. This + is probably the function you are most likely to use. An + example would be:: + + def after_install(options, home_dir): + subprocess.call([join(home_dir, 'bin', 'easy_install'), + 'MyPackage']) + subprocess.call([join(home_dir, 'bin', 'my-package-script'), + 'setup', home_dir]) + + This example immediately installs a package, and runs a setup + script from that package. + + If you provide something like ``python_version='2.5'`` then the + script will start with ``#!/usr/bin/env python2.5`` instead of + ``#!/usr/bin/env python``. You can use this when the script must + be run with a particular Python version. + """ + filename = __file__ + if filename.endswith('.pyc'): + filename = filename[:-1] + with codecs.open(filename, 'r', encoding='utf-8') as f: + content = f.read() + py_exe = 'python%s' % python_version + content = (('#!/usr/bin/env %s\n' % py_exe) + + '## WARNING: This file is generated\n' + + content) + return content.replace('##EXT' 'END##', extra_text) + +##EXTEND## + +def convert(s): + b = base64.b64decode(s.encode('ascii')) + return zlib.decompress(b).decode('utf-8') + +##file site.py +SITE_PY = convert(""" +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 +AVijEPwfucjncQ== +""") + +##file activate.sh +ACTIVATE_SH = convert(""" +eJytVd9v2kAMfs9fYQLq2m4MscdNVKMqEkgtVIQxbeuUHolpTgsXdHehpT/+9/mSEBJS2MOaB0ji +z77P9menDpOAK5jzEGERKw0zhFihD/dcB2CrKJYewoyLFvM0XzGNNpzOZbSAGVPBqVWHdRSDx4SI +NMhYANfgc4meDteW5ePGC45P4MkCumKhUENzDsu1H3lw1vJx1RJxGMKns6O2lWDqINGgotAHFCsu +I7FAoWHFJGezEFWGqsEvaD5C42naHb93X+A3+elYCgVaxgh8DmQAys9HL2SS0mIaWBgm7mTN/O3G +kzu6vHCng/HkW/fSve5O+hTOpnhfQAcoEry5jKVjNypoO0fgwzKSOgHm79KUK06Jfc7/RebHpD8a +9kdXvT2UcnuFWG6p0stNB0mWUUQ1q3uiGRVEMfXHR03dTuQATPjwqIIPcB9wL4CArRAY/ZHJixYL +Y9YBtcAoLQtFevOoI9QaHcEdMSAB0d08kuZhyUiSmav6CPCdVBnFOjNrLu6yMCWgKRA0TInBC5i4 +QwX3JG/mm581GKnSsSSxJTFHf9MAKr8w5T/vOv1mUurn5/zlT6fvTntjZzAaNl9rQ5JkU5KIc0GX +inagwU57T2eddqWlTrvaS6d9sImZeUMkhWysveF0m37NcGub9Dpgi0j4qGiOzATjDr06OBjOYQOo +7RBoGtNm9Denv1i0LVI7lxJDXLHSSBeWRflsyyqw7diuW3h0XdvK6lBMyaoMG1UyHdTsoYBuue75 +YOgOu1c91/2cwYpznPPeDoQpGL2xSm09NKp7BsvQ2hnT3aMs07lUnskpxewvBk73/LLnXo9HV9eT +ijB3hWBO2ygoiWg/bKuZxqCCQq0DD3vkWIVvI2KosIw+vqW1gIItEG5KJb+xb09g65ktwYKgTc51 +uGJ/EFQs0ayEWLCQM5V9N4g+1+8UbXOJzF8bqhKtIqIwicWvzNFROZJlpfD8A7Vc044R0FxkcezG +VzsV75usvTdYef+57v5n1b225qhXfwEmxHEs +""") + +##file activate.fish +ACTIVATE_FISH = convert(""" +eJyFVVFv0zAQfs+vONJO3RDNxCsSQoMVrdK2Vl03CSHkesllMXLsYDvZivjx2GmTOG0YfWhV+7u7 +73z33Y1gnTENKeMIeakNPCKUGhP7xcQTbCJ4ZOKcxoZV1GCUMp1t4O0zMxkTQEGVQjicO4dTyIwp +Ppyfu386Q86jWOZwBhq1ZlK8jYIRXEoQ0jhDYAYSpjA2fBsFQVoKG0UKSLAJB9MEJrMXi6uYMiXl +KCrIZYJARQIKTakEGAkmQ+tU5ZSDRTAlRY7CRJMA7GdkgRoNSJ74t1BRxegjR12jWAoGbfpTAeGY +LK4vycN8tb6/uCbLi/VVWGPcx3maPr2AO4VjYB+HMAxAkQT/i/ptfbW4vVrczAZit3eHDNqL13n0 +Ya+w+Tq/uyLL1eJmuSaLh9lqNb/0+IzgznqnAjAvzBa4jG0BNmNXfdJUkxTU2I6xRaKcy+e6VApz +WVmoTGFTgwslrYdN03ONrbbMN1E/FQ7H7gOP0UxRjV67TPRBjF3naCMV1mSkYk9MUN7F8cODZzsE +iIHYviIe6n8WeGQxWKuhl+9Xa49uijq7fehXMRxT9VR9f/8jhDcfYSKkSOyxKp22cNIrIk+nzd2b +Yc7FNpHx8FUn15ZfzXEE98JxZEohx4r6kosCT+R9ZkHQtLmXGYSEeH8JCTvYkcRgXAutp9Rw7Jmf +E/J5fktuL25m1tMe3vLdjDt9bNxr2sMo2P3C9BccqGeYhqfQITz6XurXaqdf99LF1mT2YJrvzqCu +5w7dKvV3PzNyOb+7+Hw923dOuB+AX2SxrZs9Lm0xbCH6kmhjUyuWw+7cC7DX8367H3VzDz6oBtty +tMIeobE21JT6HaRS+TbaoqhbE7rgdGs3xtE4cOF3xo0TfxwsdyRlhUoxuzes18r+Jp88zDx1G+kd +/HTrr1BY2CeuyfnbQtAcu9j+pOw6cy9X0k3IuoyKCZPC5ESf6MkgHE5tLiSW3Oa+W2NnrQfkGv/h +7tR5PNFnMBlw4B9NJTxnzKA9fLTT0aXSb5vw7FUKzcTZPddqYHi2T9/axJmEEN3qHncVCuEPaFmq +uEtpcBj2Z1wjrqGReJBHrY6/go21NA== +""") + +##file activate.csh +ACTIVATE_CSH = convert(""" +eJx1U2FP2zAQ/e5f8TAV3Soo+0zXbYUiDQkKQgVp2ibjJNfFUuIg22nVf885SVFLO3+I7Lt3fr6X +d8eY58ZjYQpCWfuAhFB7yrAyIYf0Ve1SQmLsuU6DWepAw9TnEoOFq0rwdjAUx/hV1Ui1tVWAqy1M +QGYcpaFYx+yVI67LkKwx1UuTEaYGl4X2Bl+zJpAlP/6V2hTDtCq/DYXQhdEeGW040Q/Eb+t9V/e3 +U/V88zh/mtyqh8n8J47G+IKTE3gKZJdoYrK3h5MRU1tGYS83gqNc+3yEgyyP93cP820evHLvr2H8 +kaYB/peoyY7aVHzpJnE9e+6I5Z+ji4GMTNJWNuOQq6MA1N25p8pW9HWdVWlfsNpPDbdxjgpaahuw +1M7opCA/FFu1uwxC7L8KUqmto1KyQe3rx0I0Eovdf7BVe67U5c1MzSZ310pddGheZoFPWyytRkzU +aCA/I+RkBXhFXr5aWV0SxjhUI6jwdAj8kmhPzX7nTfJFkM3MImp2VdVFFq1vLHSU5szYQK4Ri+Jd +xlW2JBtOGcyYVW7SnB3v6RS91g3gKapZ0oWxbHVteYIIq3iv7QeuSrUj6KSqQ+yqsxDj1ivNQxKF +YON10Q+NH/ARS95i5Tuqq2Vxfvc23f/FO6zrtXXmJr+ZtMY9/A15ZXFWtmch2rEQ4g1ryVHH +""") + +##file activate.bat +ACTIVATE_BAT = convert(""" +eJx9Ul9LhEAQfxf8DoOclI/dYyFkaCmcq4gZQTBUrincuZFbff12T133TM+nnd35/Zvxlr7XDFhV +mUZHOVhFlOWP3g4DUriIWoVomYZpNBWUtGpaWgImO191pFkSpzlcmgaI70jVX7n2Qp8tuByg+46O +CMHbMq64T+nmlJt082D1T44muCDk2prgEHF4mdI9RaS/QwSt3zSyIAaftRccvqVTBziD1x/WlPD5 +xd729NDBb8Nr4DU9QNMKsJeH9pkhPedhQsIkDuCDCa6A+NF9IevVFAohkqizdHetg/tkWvPoftWJ +MCqnOxv7/x7Np6yv9P2Ker5dmX8yNyCkkWnbZy3N5LarczlqL8htx2EM9rQ/2H5BvIsIEi8OEG8U ++g8CsNTr +""") + +##file deactivate.bat +DEACTIVATE_BAT = convert(""" +eJyFkN0KgkAUhO8F32EQpHqFQEjQUPAPMaErqVxzId3IrV6/XST/UDx3c86c4WMO5FYysKJQFVVp +CEfqxsnJ9DI7SA25i20fFqs3HO+GYLsDZ7h8GM3xfLHrg1QNvpSX4CWpQGvokZk4uqrQAjXjyElB +a5IjCz0r+2dHcehHCe5MZNmB5R7TdqMqECMptHZh6DN/utb7Zs6Cej8OXYE5J04YOKFvD4GkHuJ0 +pilSd1jG6n87tDZ+BUwUOepI6CGSkFMYWf0ihvT33Qj1A+tCkSI= +""") + +##file activate.ps1 +ACTIVATE_PS = convert(""" +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 +rKQDxR6N/rffXv+lROXet/9Q+l9I4D1U +""") + +##file distutils-init.py +DISTUTILS_INIT = convert(""" +eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E +UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB +C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss +aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT +0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9 +oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE +NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c +f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8 +p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk +vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw +hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh +cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw +buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ +5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh +gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC +1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL +MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6 +84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK +0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO +kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG +qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h +kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9 +GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ= +""") + +##file distutils.cfg +DISTUTILS_CFG = convert(""" +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= +""") + +##file activate_this.py +ACTIVATE_THIS = convert(""" +eJyNU01v2zAMvetXEB4K21jnDOstQA4dMGCHbeihlyEIDMWmE62yJEiKE//7kXKdpEWLzYBt8evx +kRSzLPs6wiEoswM8YdMpjUXcq1Dz6RZa1cSiTkJdr86GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe +5a3p0cRKiEe2NtLAFikftnDco0ko/SFEVgEZ8aRCZDIPY9xbA8pE9M4jfW/B2CjiHq9zbJVZuOQq +siwTIvpxKYCembPAU4Muwi/Z4zfvrZ/MXipKeB8C+qisSZYiWfjJfs+0/MFMdWn1hJcO5U7G/SLa +xVx8zU6VG/PXLXvfsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCJN9dzKaoexyB/uH79TnjwvxcW0ntSb +yZ8jq1Z5Q1UXsyy3gf9nbjTEj7NzQMfCJa/YSmrQ+2D/BqfiOi6sclrGzvoeVivIj8rcfcmnIQRF +7XCyeZI7DFe5/lhlCs5PRf5QW66VXT/NrlQ46oD/D6InkOmi3IQcbhKxAX2g4a+Xd5s3UtCtG2py +m8eg6WYWqR6SL5OjKMGfSrYt/6kxxQtOpeAgj1LXBNmpE2ElmCSIy5H0zFd8gJ924HWijWhb2hRC +6wNEm1QdDZtuSZcEprIUBo/XRNcbQe1OUbQ/r3hPTaPJJDNtFLu8KHV5XoNr3Eo6h6YtOKw8e8yw +VF5PnJ+ts3a9/Mz38RpG/AUSzYUW +""") + +##file python-config +PYTHON_CONFIG = convert(""" +eJyNVV1P2zAUfc+v8ODBiSABxlulTipbO6p1LWqBgVhlhcZpPYUkctzSivHfd6+dpGloGH2Ja/ue +e+65Hz78xNhtf3x90xmw7vCWsRPGLvpDNuz87MKfdKMWSWxZ4ilNpCLZJiuWc66SVFUOZkkcirll +rfxIBAzOMtImDzSVPBRrekwoX/OZu/0r4lm0DHiG60g86u8sjPw5rCyy86NRkB8QuuBRSqfAKESn +3orLTCQxE3GYkC9tYp8fk89OSwNsmXgizrhUtnumeSgeo5GbLUMk49Rv+2nK48Cm/qMwfp333J2/ +dVcAGE0CIQHBsgIeEr4Wij0LtWDLzJ9ze5YEvH2WI6CHTAVcSu9ZCsXtgxu81CIvp6/k4eXsdfo7 +PvDCRD75yi41QitfzlcPp1OI7i/1/iQitqnr0iMgQ+A6wa+IKwwdxyk9IiXNAzgquTFU8NIxAVjM +osm1Zz526e+shQ4hKRVci69nPC3Kw4NQEmkQ65E7OodxorSvxjvpBjQHDmWFIQ1mlmzlS5vedseT +/mgIEsMJ7Lxz2bLAF9M5xeLEhdbHxpWOw0GdkJApMVBRF1y+a0z3c9WZPAXGFcFrJgCIB+024uad +0CrzmEoRa3Ub4swNIHPGf7QDV+2uj2OiFWsChgCwjKqN6rp5izpbH6Wc1O1TclQTP/XVwi6anTr1 +1sbubjZLI1+VptPSdCfwnFBrB1jvebrTA9uUhU2/9gad7xPqeFkaQcnnLbCViZK8d7R1kxzFrIJV +8EaLYmKYpvGVkig+3C5HCXbM1jGCGekiM2pRCVPyRyXYdPf6kcbWEQ36F5V4Gq9N7icNNw+JHwRE +LTgxRXACpvnQv/PuT0xCCAywY/K4hE6Now2qDwaSE5FB+1agsoUveYDepS83qFcF1NufvULD3fTl +g6Hgf7WBt6lzMeiyyWVn3P1WVbwaczHmTzE9A5SyItTVgFYyvs/L/fXlaNgbw8v3azT+0eikVlWD +/vBHbzQumP23uBCjsYdrL9OWARwxs/nuLOzeXbPJTa/Xv6sUmQir5pC1YRLz3eA+CD8Z0XpcW8v9 +MZWF36ryyXXf3yBIz6nzqz8Muyz0m5Qj7OexfYo/Ph3LqvkHUg7AuA== +""") + +MH_MAGIC = 0xfeedface +MH_CIGAM = 0xcefaedfe +MH_MAGIC_64 = 0xfeedfacf +MH_CIGAM_64 = 0xcffaedfe +FAT_MAGIC = 0xcafebabe +BIG_ENDIAN = '>' +LITTLE_ENDIAN = '<' +LC_LOAD_DYLIB = 0xc +maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint') + + +class fileview(object): + """ + A proxy for file-like objects that exposes a given view of a file. + Modified from macholib. + """ + + def __init__(self, fileobj, start=0, size=maxint): + if isinstance(fileobj, fileview): + self._fileobj = fileobj._fileobj + else: + self._fileobj = fileobj + self._start = start + self._end = start + size + self._pos = 0 + + def __repr__(self): + return '<fileview [%d, %d] %r>' % ( + self._start, self._end, self._fileobj) + + def tell(self): + return self._pos + + def _checkwindow(self, seekto, op): + if not (self._start <= seekto <= self._end): + raise IOError("%s to offset %d is outside window [%d, %d]" % ( + op, seekto, self._start, self._end)) + + def seek(self, offset, whence=0): + seekto = offset + if whence == os.SEEK_SET: + seekto += self._start + elif whence == os.SEEK_CUR: + seekto += self._start + self._pos + elif whence == os.SEEK_END: + seekto += self._end + else: + raise IOError("Invalid whence argument to seek: %r" % (whence,)) + self._checkwindow(seekto, 'seek') + self._fileobj.seek(seekto) + self._pos = seekto - self._start + + def write(self, bytes): + here = self._start + self._pos + self._checkwindow(here, 'write') + self._checkwindow(here + len(bytes), 'write') + self._fileobj.seek(here, os.SEEK_SET) + self._fileobj.write(bytes) + self._pos += len(bytes) + + def read(self, size=maxint): + assert size >= 0 + here = self._start + self._pos + self._checkwindow(here, 'read') + size = min(size, self._end - here) + self._fileobj.seek(here, os.SEEK_SET) + bytes = self._fileobj.read(size) + self._pos += len(bytes) + return bytes + + +def read_data(file, endian, num=1): + """ + Read a given number of 32-bits unsigned integers from the given file + with the given endianness. + """ + res = struct.unpack(endian + 'L' * num, file.read(num * 4)) + if len(res) == 1: + return res[0] + return res + + +def mach_o_change(path, what, value): + """ + Replace a given name (what) in any LC_LOAD_DYLIB command found in + the given binary with a new name (value), provided it's shorter. + """ + + def do_macho(file, bits, endian): + # Read Mach-O header (the magic number is assumed read by the caller) + cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6) + # 64-bits header has one more field. + if bits == 64: + read_data(file, endian) + # The header is followed by ncmds commands + for n in range(ncmds): + where = file.tell() + # Read command header + cmd, cmdsize = read_data(file, endian, 2) + if cmd == LC_LOAD_DYLIB: + # The first data field in LC_LOAD_DYLIB commands is the + # offset of the name, starting from the beginning of the + # command. + name_offset = read_data(file, endian) + file.seek(where + name_offset, os.SEEK_SET) + # Read the NUL terminated string + load = file.read(cmdsize - name_offset).decode() + load = load[:load.index('\0')] + # If the string is what is being replaced, overwrite it. + if load == what: + file.seek(where + name_offset, os.SEEK_SET) + file.write(value.encode() + '\0'.encode()) + # Seek to the next command + file.seek(where + cmdsize, os.SEEK_SET) + + def do_file(file, offset=0, size=maxint): + file = fileview(file, offset, size) + # Read magic number + magic = read_data(file, BIG_ENDIAN) + if magic == FAT_MAGIC: + # Fat binaries contain nfat_arch Mach-O binaries + nfat_arch = read_data(file, BIG_ENDIAN) + for n in range(nfat_arch): + # Read arch header + cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5) + do_file(file, offset, size) + elif magic == MH_MAGIC: + do_macho(file, 32, BIG_ENDIAN) + elif magic == MH_CIGAM: + do_macho(file, 32, LITTLE_ENDIAN) + elif magic == MH_MAGIC_64: + do_macho(file, 64, BIG_ENDIAN) + elif magic == MH_CIGAM_64: + do_macho(file, 64, LITTLE_ENDIAN) + + assert(len(what) >= len(value)) + + with open(path, 'r+b') as f: + do_file(f) + + +if __name__ == '__main__': + main() + +# TODO: +# Copy python.exe.manifest +# Monkeypatch distutils.sysconfig
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/activate.bat @@ -0,0 +1,30 @@ +@echo off +set "VIRTUAL_ENV=__VIRTUAL_ENV__" + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) else ( + if not defined PROMPT ( + set "PROMPT=$P$G" + ) + set "_OLD_VIRTUAL_PROMPT=%PROMPT%" +) +set "PROMPT=__VIRTUAL_WINPROMPT__ %PROMPT%" + +REM Don't use () to avoid problems with them in %PATH% +if defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME + set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%" +:ENDIFVHOME + +set PYTHONHOME= + +REM if defined _OLD_VIRTUAL_PATH ( +if not defined _OLD_VIRTUAL_PATH goto ENDIFVPATH1 + set "PATH=%_OLD_VIRTUAL_PATH%" +:ENDIFVPATH1 +REM ) else ( +if defined _OLD_VIRTUAL_PATH goto ENDIFVPATH2 + set "_OLD_VIRTUAL_PATH=%PATH%" +:ENDIFVPATH2 + +set "PATH=%VIRTUAL_ENV%\__BIN_NAME__;%PATH%"
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/activate.csh @@ -0,0 +1,36 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi <davidedb@gmail.com>. + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "__VIRTUAL_ENV__" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/__BIN_NAME__:$PATH" + + + +if ("__VIRTUAL_PROMPT__" != "") then + set env_name = "__VIRTUAL_PROMPT__" +else + set env_name = `basename "$VIRTUAL_ENV"` +endif + +# Could be in a non-interactive environment, +# in which case, $prompt is undefined and we wouldn't +# care about the prompt anyway. +if ( $?prompt ) then + set _OLD_VIRTUAL_PROMPT="$prompt" + set prompt = "[$env_name] $prompt" +endif + +unset env_name + +alias pydoc python -m pydoc + +rehash +
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/activate.fish @@ -0,0 +1,76 @@ +# This file must be used using `. bin/activate.fish` *within a running fish ( http://fishshell.com ) session*. +# Do not run it directly. + +function deactivate -d 'Exit virtualenv mode and return to the normal environment.' + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`. + set -l fish_function_path + + # Erase virtualenv's `fish_prompt` and restore the original. + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + end + + set -e VIRTUAL_ENV + + if test "$argv[1]" != 'nondestructive' + # Self-destruct! + functions -e pydoc + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "__VIRTUAL_ENV__" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/__BIN_NAME__" $PATH + +# Unset `$PYTHONHOME` if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +function pydoc + python -m pydoc $argv +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # Copy the current `fish_prompt` function as `_old_fish_prompt`. + functions -c fish_prompt _old_fish_prompt + + function fish_prompt + # Save the current $status, for fish_prompts that display it. + set -l old_status $status + + # Prompt override provided? + # If not, just prepend the environment name. + if test -n "__VIRTUAL_PROMPT__" + printf '%s%s' "__VIRTUAL_PROMPT__" (set_color normal) + else + printf '%s(%s%s%s) ' (set_color normal) (set_color -o white) (basename "$VIRTUAL_ENV") (set_color normal) + end + + # Restore the original $status + echo "exit $old_status" | source + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/activate.ps1 @@ -0,0 +1,150 @@ +# This file must be dot sourced from PoSh; you cannot run it +# directly. Do this: . ./activate.ps1 + +# FIXME: clean up unused vars. +$script:THIS_PATH = $myinvocation.mycommand.path +$script:BASE_DIR = split-path (resolve-path "$THIS_PATH/..") -Parent +$script:DIR_NAME = split-path $BASE_DIR -Leaf + +function global:deactivate ( [switch] $NonDestructive ){ + + if ( test-path variable:_OLD_VIRTUAL_PATH ) { + $env:PATH = $variable:_OLD_VIRTUAL_PATH + remove-variable "_OLD_VIRTUAL_PATH" -scope global + } + + if ( test-path function:_old_virtual_prompt ) { + $function:prompt = $function:_old_virtual_prompt + remove-item function:\_old_virtual_prompt + } + + if ($env:VIRTUAL_ENV) { + $old_env = split-path $env:VIRTUAL_ENV -leaf + remove-item env:VIRTUAL_ENV -erroraction silentlycontinue + } + + if ( !$NonDestructive ) { + # Self destruct! + remove-item function:deactivate + } +} + +# unset irrelevant variables +deactivate -nondestructive + +$VIRTUAL_ENV = $BASE_DIR +$env:VIRTUAL_ENV = $VIRTUAL_ENV + +$global:_OLD_VIRTUAL_PATH = $env:PATH +$env:PATH = "$env:VIRTUAL_ENV/Scripts;" + $env:PATH +if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { + function global:_old_virtual_prompt { "" } + $function:_old_virtual_prompt = $function:prompt + function global:prompt { + # Add a prefix to the current prompt, but don't discard it. + write-host "($(split-path $env:VIRTUAL_ENV -leaf)) " -nonewline + & $function:_old_virtual_prompt + } +} + +# SIG # Begin signature block +# MIISeAYJKoZIhvcNAQcCoIISaTCCEmUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB +# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR +# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUS5reBwSg3zOUwhXf2jPChZzf +# yPmggg6tMIIGcDCCBFigAwIBAgIBJDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQG +# EwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp +# Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2Vy +# dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjIwMTQ2WhcNMTcxMDI0MjIw +# MTQ2WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzAp +# BgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNV +# BAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUgT2JqZWN0 +# IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyiOLIjUemqAbPJ1J +# 0D8MlzgWKbr4fYlbRVjvhHDtfhFN6RQxq0PjTQxRgWzwFQNKJCdU5ftKoM5N4YSj +# Id6ZNavcSa6/McVnhDAQm+8H3HWoD030NVOxbjgD/Ih3HaV3/z9159nnvyxQEckR +# ZfpJB2Kfk6aHqW3JnSvRe+XVZSufDVCe/vtxGSEwKCaNrsLc9pboUoYIC3oyzWoU +# TZ65+c0H4paR8c8eK/mC914mBo6N0dQ512/bkSdaeY9YaQpGtW/h/W/FkbQRT3sC +# pttLVlIjnkuY4r9+zvqhToPjxcfDYEf+XD8VGkAqle8Aa8hQ+M1qGdQjAye8OzbV +# uUOw7wIDAQABo4IB6TCCAeUwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +# AQYwHQYDVR0OBBYEFNBOD0CZbLhLGW87KLjg44gHNKq3MB8GA1UdIwQYMBaAFE4L +# 7xqkQFulF2mHMMo0aEPQQa7yMD0GCCsGAQUFBwEBBDEwLzAtBggrBgEFBQcwAoYh +# aHR0cDovL3d3dy5zdGFydHNzbC5jb20vc2ZzY2EuY3J0MFsGA1UdHwRUMFIwJ6Al +# oCOGIWh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3Nmc2NhLmNybDAnoCWgI4YhaHR0 +# cDovL2NybC5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMIGABgNVHSAEeTB3MHUGCysG +# AQQBgbU3AQIBMGYwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +# L3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +# L2ludGVybWVkaWF0ZS5wZGYwEQYJYIZIAYb4QgEBBAQDAgABMFAGCWCGSAGG+EIB +# DQRDFkFTdGFydENvbSBDbGFzcyAyIFByaW1hcnkgSW50ZXJtZWRpYXRlIE9iamVj +# dCBTaWduaW5nIENlcnRpZmljYXRlczANBgkqhkiG9w0BAQUFAAOCAgEAcnMLA3Va +# N4OIE9l4QT5OEtZy5PByBit3oHiqQpgVEQo7DHRsjXD5H/IyTivpMikaaeRxIv95 +# baRd4hoUcMwDj4JIjC3WA9FoNFV31SMljEZa66G8RQECdMSSufgfDYu1XQ+cUKxh +# D3EtLGGcFGjjML7EQv2Iol741rEsycXwIXcryxeiMbU2TPi7X3elbwQMc4JFlJ4B +# y9FhBzuZB1DV2sN2irGVbC3G/1+S2doPDjL1CaElwRa/T0qkq2vvPxUgryAoCppU +# FKViw5yoGYC+z1GaesWWiP1eFKAL0wI7IgSvLzU3y1Vp7vsYaxOVBqZtebFTWRHt +# XjCsFrrQBngt0d33QbQRI5mwgzEp7XJ9xu5d6RVWM4TPRUsd+DDZpBHm9mszvi9g +# VFb2ZG7qRRXCSqys4+u/NLBPbXi/m/lU00cODQTlC/euwjk9HQtRrXQ/zqsBJS6U +# J+eLGw1qOfj+HVBl/ZQpfoLk7IoWlRQvRL1s7oirEaqPZUIWY/grXq9r6jDKAp3L +# ZdKQpPOnnogtqlU4f7/kLjEJhrrc98mrOWmVMK/BuFRAfQ5oDUMnVmCzAzLMjKfG +# cVW/iMew41yfhgKbwpfzm3LBr1Zv+pEBgcgW6onRLSAn3XHM0eNtz+AkxH6rRf6B +# 2mYhLEEGLapH8R1AMAo4BbVFOZR5kXcMCwowggg1MIIHHaADAgECAgIEuDANBgkq +# hkiG9w0BAQUFADCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0 +# ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcx +# ODA2BgNVBAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUg +# T2JqZWN0IENBMB4XDTExMTIwMzE1MzQxOVoXDTEzMTIwMzE0NTgwN1owgYwxIDAe +# BgNVBA0TFzU4MTc5Ni1HaDd4Zkp4a3hRU0lPNEUwMQswCQYDVQQGEwJERTEPMA0G +# A1UECBMGQmVybGluMQ8wDQYDVQQHEwZCZXJsaW4xFjAUBgNVBAMTDUphbm5pcyBM +# ZWlkZWwxITAfBgkqhkiG9w0BCQEWEmphbm5pc0BsZWlkZWwuaW5mbzCCAiIwDQYJ +# KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMcPeABYdN7nPq/AkZ/EkyUBGx/l2Yui +# Lfm8ZdLG0ulMb/kQL3fRY7sUjYPyn9S6PhqqlFnNoGHJvbbReCdUC9SIQYmOEjEA +# raHfb7MZU10NjO4U2DdGucj2zuO5tYxKizizOJF0e4yRQZVxpUGdvkW/+GLjCNK5 +# L7mIv3Z1dagxDKHYZT74HXiS4VFUwHF1k36CwfM2vsetdm46bdgSwV+BCMmZICYT +# IJAS9UQHD7kP4rik3bFWjUx08NtYYFAVOd/HwBnemUmJe4j3IhZHr0k1+eDG8hDH +# KVvPgLJIoEjC4iMFk5GWsg5z2ngk0LLu3JZMtckHsnnmBPHQK8a3opUNd8hdMNJx +# gOwKjQt2JZSGUdIEFCKVDqj0FmdnDMPfwy+FNRtpBMl1sz78dUFhSrnM0D8NXrqa +# 4rG+2FoOXlmm1rb6AFtpjAKksHRpYcPk2DPGWp/1sWB+dUQkS3gOmwFzyqeTuXpT +# 0juqd3iAxOGx1VRFQ1VHLLf3AzV4wljBau26I+tu7iXxesVucSdsdQu293jwc2kN +# xK2JyHCoZH+RyytrwS0qw8t7rMOukU9gwP8mn3X6mgWlVUODMcHTULjSiCEtvyZ/ +# aafcwjUbt4ReEcnmuZtWIha86MTCX7U7e+cnpWG4sIHPnvVTaz9rm8RyBkIxtFCB +# nQ3FnoQgyxeJAgMBAAGjggOdMIIDmTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIH +# gDAuBgNVHSUBAf8EJDAiBggrBgEFBQcDAwYKKwYBBAGCNwIBFQYKKwYBBAGCNwoD +# DTAdBgNVHQ4EFgQUWyCgrIWo8Ifvvm1/YTQIeMU9nc8wHwYDVR0jBBgwFoAU0E4P +# QJlsuEsZbzsouODjiAc0qrcwggIhBgNVHSAEggIYMIICFDCCAhAGCysGAQQBgbU3 +# AQICMIIB/zAuBggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9s +# aWN5LnBkZjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50 +# ZXJtZWRpYXRlLnBkZjCB9wYIKwYBBQUHAgIwgeowJxYgU3RhcnRDb20gQ2VydGlm +# aWNhdGlvbiBBdXRob3JpdHkwAwIBARqBvlRoaXMgY2VydGlmaWNhdGUgd2FzIGlz +# c3VlZCBhY2NvcmRpbmcgdG8gdGhlIENsYXNzIDIgVmFsaWRhdGlvbiByZXF1aXJl +# bWVudHMgb2YgdGhlIFN0YXJ0Q29tIENBIHBvbGljeSwgcmVsaWFuY2Ugb25seSBm +# b3IgdGhlIGludGVuZGVkIHB1cnBvc2UgaW4gY29tcGxpYW5jZSBvZiB0aGUgcmVs +# eWluZyBwYXJ0eSBvYmxpZ2F0aW9ucy4wgZwGCCsGAQUFBwICMIGPMCcWIFN0YXJ0 +# Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MAMCAQIaZExpYWJpbGl0eSBhbmQg +# d2FycmFudGllcyBhcmUgbGltaXRlZCEgU2VlIHNlY3Rpb24gIkxlZ2FsIGFuZCBM +# aW1pdGF0aW9ucyIgb2YgdGhlIFN0YXJ0Q29tIENBIHBvbGljeS4wNgYDVR0fBC8w +# LTAroCmgJ4YlaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0YzItY3JsLmNybDCB +# iQYIKwYBBQUHAQEEfTB7MDcGCCsGAQUFBzABhitodHRwOi8vb2NzcC5zdGFydHNz +# bC5jb20vc3ViL2NsYXNzMi9jb2RlL2NhMEAGCCsGAQUFBzAChjRodHRwOi8vYWlh +# LnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xhc3MyLmNvZGUuY2EuY3J0MCMGA1Ud +# EgQcMBqGGGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tLzANBgkqhkiG9w0BAQUFAAOC +# AQEAhrzEV6zwoEtKjnFRhCsjwiPykVpo5Eiye77Ve801rQDiRKgSCCiW6g3HqedL +# OtaSs65Sj2pm3Viea4KR0TECLcbCTgsdaHqw2x1yXwWBQWZEaV6EB05lIwfr94P1 +# SFpV43zkuc+bbmA3+CRK45LOcCNH5Tqq7VGTCAK5iM7tvHwFlbQRl+I6VEL2mjpF +# NsuRjDOVrv/9qw/a22YJ9R7Y1D0vUSs3IqZx2KMUaYDP7H2mSRxJO2nADQZBtriF +# gTyfD3lYV12MlIi5CQwe3QC6DrrfSMP33i5Wa/OFJiQ27WPxmScYVhiqozpImFT4 +# PU9goiBv9RKXdgTmZE1PN0NQ5jGCAzUwggMxAgEBMIGTMIGMMQswCQYDVQQGEwJJ +# TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0 +# YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg +# MiBQcmltYXJ5IEludGVybWVkaWF0ZSBPYmplY3QgQ0ECAgS4MAkGBSsOAwIaBQCg +# eDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEE +# AYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJ +# BDEWBBRVGw0FDSiaIi38dWteRUAg/9Pr6DANBgkqhkiG9w0BAQEFAASCAgCInvOZ +# FdaNFzbf6trmFDZKMojyx3UjKMCqNjHVBbuKY0qXwFC/ElYDV1ShJ2CBZbdurydO +# OQ6cIQ0KREOCwmX/xB49IlLHHUxNhEkVv7HGU3EKAFf9IBt9Yr7jikiR9cjIsfHK +# 4cjkoKJL7g28yEpLLkHt1eo37f1Ga9lDWEa5Zq3U5yX+IwXhrUBm1h8Xr033FhTR +# VEpuSz6LHtbrL/zgJnCzJ2ahjtJoYevdcWiNXffosJHFaSfYDDbiNsPRDH/1avmb +# 5j/7BhP8BcBaR6Fp8tFbNGIcWHHGcjqLMnTc4w13b7b4pDhypqElBa4+lCmwdvv9 +# GydYtRgPz8GHeoBoKj30YBlMzRIfFYaIFGIC4Ai3UEXkuH9TxYohVbGm/W0Kl4Lb +# RJ1FwiVcLcTOJdgNId2vQvKc+jtNrjcg5SP9h2v/C4aTx8tyc6tE3TOPh2f9b8DL +# S+SbVArJpuJqrPTxDDoO1QNjTgLcdVYeZDE+r/NjaGZ6cMSd8db3EaG3ijD/0bud +# SItbm/OlNVbQOFRR76D+ZNgPcU5iNZ3bmvQQIg6aSB9MHUpIE/SeCkNl9YeVk1/1 +# GFULgNMRmIYP4KLvu9ylh5Gu3hvD5VNhH6+FlXANwFy07uXks5uF8mfZVxVCnodG +# xkNCx+6PsrA5Z7WP4pXcmYnMn97npP/Q9EHJWw== +# SIG # End signature block
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/activate.sh @@ -0,0 +1,78 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + unset -f pydoc >/dev/null 2>&1 + + # reset old environment variables + # ! [ -z ${VAR+_} ] returns true if VAR is declared at all + if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then + PATH="$_OLD_VIRTUAL_PATH" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then + PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null + fi + + if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then + PS1="$_OLD_VIRTUAL_PS1" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="__VIRTUAL_ENV__" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/__BIN_NAME__:$PATH" +export PATH + +# unset PYTHONHOME if set +if ! [ -z "${PYTHONHOME+_}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then + _OLD_VIRTUAL_PS1="$PS1" + if [ "x__VIRTUAL_PROMPT__" != x ] ; then + PS1="__VIRTUAL_PROMPT__$PS1" + else + PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1" + fi + export PS1 +fi + +# Make sure to unalias pydoc if it's already there +alias pydoc 2>/dev/null >/dev/null && unalias pydoc + +pydoc () { + python -m pydoc "$@" +} + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null +fi
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/activate_this.py @@ -0,0 +1,34 @@ +"""By using execfile(this_file, dict(__file__=this_file)) you will +activate this virtualenv environment. + +This can be used when you must use an existing Python interpreter, not +the virtualenv bin/python +""" + +try: + __file__ +except NameError: + raise AssertionError( + "You must run this like execfile('path/to/activate_this.py', dict(__file__='path/to/activate_this.py'))") +import sys +import os + +old_os_path = os.environ.get('PATH', '') +os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path +base = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if sys.platform == 'win32': + site_packages = os.path.join(base, 'Lib', 'site-packages') +else: + site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages') +prev_sys_path = list(sys.path) +import site +site.addsitedir(site_packages) +sys.real_prefix = sys.prefix +sys.prefix = base +# Move the added items to the front of the path: +new_sys_path = [] +for item in list(sys.path): + if item not in prev_sys_path: + new_sys_path.append(item) + sys.path.remove(item) +sys.path[:0] = new_sys_path
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/deactivate.bat @@ -0,0 +1,19 @@ +@echo off + +set VIRTUAL_ENV= + +REM Don't use () to avoid problems with them in %PATH% +if not defined _OLD_VIRTUAL_PROMPT goto ENDIFVPROMPT + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" + set _OLD_VIRTUAL_PROMPT= +:ENDIFVPROMPT + +if not defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + set _OLD_VIRTUAL_PYTHONHOME= +:ENDIFVHOME + +if not defined _OLD_VIRTUAL_PATH goto ENDIFVPATH + set "PATH=%_OLD_VIRTUAL_PATH%" + set _OLD_VIRTUAL_PATH= +:ENDIFVPATH \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/distutils-init.py @@ -0,0 +1,101 @@ +import os +import sys +import warnings +import imp +import opcode # opcode is not a virtualenv module, so we can use it to find the stdlib + # Important! To work on pypy, this must be a module that resides in the + # lib-python/modified-x.y.z directory + +dirname = os.path.dirname + +distutils_path = os.path.join(os.path.dirname(opcode.__file__), 'distutils') +if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)): + warnings.warn( + "The virtualenv distutils package at %s appears to be in the same location as the system distutils?") +else: + __path__.insert(0, distutils_path) + real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ('', '', imp.PKG_DIRECTORY)) + # Copy the relevant attributes + try: + __revision__ = real_distutils.__revision__ + except AttributeError: + pass + __version__ = real_distutils.__version__ + +from distutils import dist, sysconfig + +try: + basestring +except NameError: + basestring = str + +## patch build_ext (distutils doesn't know how to get the libs directory +## path on windows - it hardcodes the paths around the patched sys.prefix) + +if sys.platform == 'win32': + from distutils.command.build_ext import build_ext as old_build_ext + class build_ext(old_build_ext): + def finalize_options (self): + if self.library_dirs is None: + self.library_dirs = [] + elif isinstance(self.library_dirs, basestring): + self.library_dirs = self.library_dirs.split(os.pathsep) + + self.library_dirs.insert(0, os.path.join(sys.real_prefix, "Libs")) + old_build_ext.finalize_options(self) + + from distutils.command import build_ext as build_ext_module + build_ext_module.build_ext = build_ext + +## distutils.dist patches: + +old_find_config_files = dist.Distribution.find_config_files +def find_config_files(self): + found = old_find_config_files(self) + system_distutils = os.path.join(distutils_path, 'distutils.cfg') + #if os.path.exists(system_distutils): + # found.insert(0, system_distutils) + # What to call the per-user config file + if os.name == 'posix': + user_filename = ".pydistutils.cfg" + else: + user_filename = "pydistutils.cfg" + user_filename = os.path.join(sys.prefix, user_filename) + if os.path.isfile(user_filename): + for item in list(found): + if item.endswith('pydistutils.cfg'): + found.remove(item) + found.append(user_filename) + return found +dist.Distribution.find_config_files = find_config_files + +## distutils.sysconfig patches: + +old_get_python_inc = sysconfig.get_python_inc +def sysconfig_get_python_inc(plat_specific=0, prefix=None): + if prefix is None: + prefix = sys.real_prefix + return old_get_python_inc(plat_specific, prefix) +sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__ +sysconfig.get_python_inc = sysconfig_get_python_inc + +old_get_python_lib = sysconfig.get_python_lib +def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None): + if standard_lib and prefix is None: + prefix = sys.real_prefix + return old_get_python_lib(plat_specific, standard_lib, prefix) +sysconfig_get_python_lib.__doc__ = old_get_python_lib.__doc__ +sysconfig.get_python_lib = sysconfig_get_python_lib + +old_get_config_vars = sysconfig.get_config_vars +def sysconfig_get_config_vars(*args): + real_vars = old_get_config_vars(*args) + if sys.platform == 'win32': + lib_dir = os.path.join(sys.real_prefix, "libs") + if isinstance(real_vars, dict) and 'LIBDIR' not in real_vars: + real_vars['LIBDIR'] = lib_dir # asked for all + elif isinstance(real_vars, list) and 'LIBDIR' in args: + real_vars = real_vars + [lib_dir] # asked for list + return real_vars +sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__ +sysconfig.get_config_vars = sysconfig_get_config_vars
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/distutils.cfg @@ -0,0 +1,6 @@ +# This is a config file local to this virtualenv installation +# You may include options that will be used by all distutils commands, +# and by easy_install. For instance: +# +# [easy_install] +# find_links = http://mylocalsite
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/python-config @@ -0,0 +1,78 @@ +#!__VIRTUAL_ENV__/__BIN_NAME__/python + +import sys +import getopt +import sysconfig + +valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags', + 'ldflags', 'help'] + +if sys.version_info >= (3, 2): + valid_opts.insert(-1, 'extension-suffix') + valid_opts.append('abiflags') +if sys.version_info >= (3, 3): + valid_opts.append('configdir') + + +def exit_with_usage(code=1): + sys.stderr.write("Usage: {0} [{1}]\n".format( + sys.argv[0], '|'.join('--'+opt for opt in valid_opts))) + sys.exit(code) + +try: + opts, args = getopt.getopt(sys.argv[1:], '', valid_opts) +except getopt.error: + exit_with_usage() + +if not opts: + exit_with_usage() + +pyver = sysconfig.get_config_var('VERSION') +getvar = sysconfig.get_config_var + +opt_flags = [flag for (flag, val) in opts] + +if '--help' in opt_flags: + exit_with_usage(code=0) + +for opt in opt_flags: + if opt == '--prefix': + print(sysconfig.get_config_var('prefix')) + + elif opt == '--exec-prefix': + print(sysconfig.get_config_var('exec_prefix')) + + elif opt in ('--includes', '--cflags'): + flags = ['-I' + sysconfig.get_path('include'), + '-I' + sysconfig.get_path('platinclude')] + if opt == '--cflags': + flags.extend(getvar('CFLAGS').split()) + print(' '.join(flags)) + + elif opt in ('--libs', '--ldflags'): + abiflags = getattr(sys, 'abiflags', '') + libs = ['-lpython' + pyver + abiflags] + libs += getvar('LIBS').split() + libs += getvar('SYSLIBS').split() + # add the prefix/lib/pythonX.Y/config dir, but only if there is no + # shared library in prefix/lib/. + if opt == '--ldflags': + if not getvar('Py_ENABLE_SHARED'): + libs.insert(0, '-L' + getvar('LIBPL')) + if not getvar('PYTHONFRAMEWORK'): + libs.extend(getvar('LINKFORSHARED').split()) + print(' '.join(libs)) + + elif opt == '--extension-suffix': + ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') + if ext_suffix is None: + ext_suffix = sysconfig.get_config_var('SO') + print(ext_suffix) + + elif opt == '--abiflags': + if not getattr(sys, 'abiflags', None): + exit_with_usage() + print(sys.abiflags) + + elif opt == '--configdir': + print(sysconfig.get_config_var('LIBPL'))
new file mode 100644 --- /dev/null +++ b/testing/mozharness/external_tools/virtualenv/virtualenv_embedded/site.py @@ -0,0 +1,758 @@ +"""Append module search paths for third-party packages to sys.path. + +**************************************************************** +* This module is automatically imported during initialization. * +**************************************************************** + +In earlier versions of Python (up to 1.5a3), scripts or modules that +needed to use site-specific modules would place ``import site'' +somewhere near the top of their code. Because of the automatic +import, this is no longer necessary (but code that does it still +works). + +This will append site-specific paths to the module search path. On +Unix, it starts with sys.prefix and sys.exec_prefix (if different) and +appends lib/python<version>/site-packages as well as lib/site-python. +It also supports the Debian convention of +lib/python<version>/dist-packages. On other platforms (mainly Mac and +Windows), it uses just sys.prefix (and sys.exec_prefix, if different, +but this is unlikely). The resulting directories, if they exist, are +appended to sys.path, and also inspected for path configuration files. + +FOR DEBIAN, this sys.path is augmented with directories in /usr/local. +Local addons go into /usr/local/lib/python<version>/site-packages +(resp. /usr/local/lib/site-python), Debian addons install into +/usr/{lib,share}/python<version>/dist-packages. + +A path configuration file is a file whose name has the form +<package>.pth; its contents are additional directories (one per line) +to be added to sys.path. Non-existing directories (or +non-directories) are never added to sys.path; no directory is added to +sys.path more than once. Blank lines and lines beginning with +'#' are skipped. Lines starting with 'import' are executed. + +For example, suppose sys.prefix and sys.exec_prefix are set to +/usr/local and there is a directory /usr/local/lib/python2.X/site-packages +with three subdirectories, foo, bar and spam, and two path +configuration files, foo.pth and bar.pth. Assume foo.pth contains the +following: + + # foo package configuration + foo + bar + bletch + +and bar.pth contains: + + # bar package configuration + bar + +Then the following directories are added to sys.path, in this order: + + /usr/local/lib/python2.X/site-packages/bar + /usr/local/lib/python2.X/site-packages/foo + +Note that bletch is omitted because it doesn't exist; bar precedes foo +because bar.pth comes alphabetically before foo.pth; and spam is +omitted because it is not mentioned in either path configuration file. + +After these path manipulations, an attempt is made to import a module +named sitecustomize, which can perform arbitrary additional +site-specific customizations. If this import fails with an +ImportError exception, it is silently ignored. + +""" + +import sys +import os +try: + import __builtin__ as builtins +except ImportError: + import builtins +try: + set +except NameError: + from sets import Set as set + +# Prefixes for site-packages; add additional prefixes like /usr/local here +PREFIXES = [sys.prefix, sys.exec_prefix] +# Enable per user site-packages directory +# set it to False to disable the feature or True to force the feature +ENABLE_USER_SITE = None +# for distutils.commands.install +USER_SITE = None +USER_BASE = None + +_is_64bit = (getattr(sys, 'maxsize', None) or getattr(sys, 'maxint')) > 2**32 +_is_pypy = hasattr(sys, 'pypy_version_info') +_is_jython = sys.platform[:4] == 'java' +if _is_jython: + ModuleType = type(os) + +def makepath(*paths): + dir = os.path.join(*paths) + if _is_jython and (dir == '__classpath__' or + dir.startswith('__pyclasspath__')): + return dir, dir + dir = os.path.abspath(dir) + return dir, os.path.normcase(dir) + +def abs__file__(): + """Set all module' __file__ attribute to an absolute path""" + for m in sys.modules.values(): + if ((_is_jython and not isinstance(m, ModuleType)) or + hasattr(m, '__loader__')): + # only modules need the abspath in Jython. and don't mess + # with a PEP 302-supplied __file__ + continue + f = getattr(m, '__file__', None) + if f is None: + continue + m.__file__ = os.path.abspath(f) + +def removeduppaths(): + """ Remove duplicate entries from sys.path along with making them + absolute""" + # This ensures that the initial path provided by the interpreter contains + # only absolute pathnames, even if we're running from the build directory. + L = [] + known_paths = set() + for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in known_paths: + L.append(dir) + known_paths.add(dircase) + sys.path[:] = L + return known_paths + +# XXX This should not be part of site.py, since it is needed even when +# using the -S option for Python. See http://www.python.org/sf/586680 +def addbuilddir(): + """Append ./build/lib.<platform> in case we're running in the build dir + (especially for Guido :-)""" + from distutils.util import get_platform + s = "build/lib.%s-%.3s" % (get_platform(), sys.version) + if hasattr(sys, 'gettotalrefcount'): + s += '-pydebug' + s = os.path.join(os.path.dirname(sys.path[-1]), s) + sys.path.append(s) + +def _init_pathinfo(): + """Return a set containing all existing directory entries from sys.path""" + d = set() + for dir in sys.path: + try: + if os.path.isdir(dir): + dir, dircase = makepath(dir) + d.add(dircase) + except TypeError: + continue + return d + +def addpackage(sitedir, name, known_paths): + """Add a new path to known_paths by combining sitedir and 'name' or execute + sitedir if it starts with 'import'""" + if known_paths is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + f = open(fullname, "rU") + except IOError: + return + try: + for line in f: + if line.startswith("#"): + continue + if line.startswith("import"): + exec(line) + continue + line = line.rstrip() + dir, dircase = makepath(sitedir, line) + if not dircase in known_paths and os.path.exists(dir): + sys.path.append(dir) + known_paths.add(dircase) + finally: + f.close() + if reset: + known_paths = None + return known_paths + +def addsitedir(sitedir, known_paths=None): + """Add 'sitedir' argument to sys.path if missing and handle .pth files in + 'sitedir'""" + if known_paths is None: + known_paths = _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in known_paths: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + names.sort() + for name in names: + if name.endswith(os.extsep + "pth"): + addpackage(sitedir, name, known_paths) + if reset: + known_paths = None + return known_paths + +def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix): + """Add site-packages (and possibly site-python) to sys.path""" + prefixes = [os.path.join(sys_prefix, "local"), sys_prefix] + if exec_prefix != sys_prefix: + prefixes.append(os.path.join(exec_prefix, "local")) + + for prefix in prefixes: + if prefix: + if sys.platform in ('os2emx', 'riscos') or _is_jython: + sitedirs = [os.path.join(prefix, "Lib", "site-packages")] + elif _is_pypy: + sitedirs = [os.path.join(prefix, 'site-packages')] + elif sys.platform == 'darwin' and prefix == sys_prefix: + + if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python + + sitedirs = [os.path.join("/Library/Python", sys.version[:3], "site-packages"), + os.path.join(prefix, "Extras", "lib", "python")] + + else: # any other Python distros on OSX work this way + sitedirs = [os.path.join(prefix, "lib", + "python" + sys.version[:3], "site-packages")] + + elif os.sep == '/': + sitedirs = [os.path.join(prefix, + "lib", + "python" + sys.version[:3], + "site-packages"), + os.path.join(prefix, "lib", "site-python"), + os.path.join(prefix, "python" + sys.version[:3], "lib-dynload")] + lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages") + if (os.path.exists(lib64_dir) and + os.path.realpath(lib64_dir) not in [os.path.realpath(p) for p in sitedirs]): + if _is_64bit: + sitedirs.insert(0, lib64_dir) + else: + sitedirs.append(lib64_dir) + try: + # sys.getobjects only available in --with-pydebug build + sys.getobjects + sitedirs.insert(0, os.path.join(sitedirs[0], 'debug')) + except AttributeError: + pass + # Debian-specific dist-packages directories: + sitedirs.append(os.path.join(prefix, "local/lib", + "python" + sys.version[:3], + "dist-packages")) + if sys.version[0] == '2': + sitedirs.append(os.path.join(prefix, "lib", + "python" + sys.version[:3], + "dist-packages")) + else: + sitedirs.append(os.path.join(prefix, "lib", + "python" + sys.version[0], + "dist-packages")) + sitedirs.append(os.path.join(prefix, "lib", "dist-python")) + else: + sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] + if sys.platform == 'darwin': + # for framework builds *only* we add the standard Apple + # locations. Currently only per-user, but /Library and + # /Network/Library could be added too + if 'Python.framework' in prefix: + home = os.environ.get('HOME') + if home: + sitedirs.append( + os.path.join(home, + 'Library', + 'Python', + sys.version[:3], + 'site-packages')) + for sitedir in sitedirs: + if os.path.isdir(sitedir): + addsitedir(sitedir, known_paths) + return None + +def check_enableusersite(): + """Check if user site directory is safe for inclusion + + The function tests for the command line flag (including environment var), + process uid/gid equal to effective uid/gid. + + None: Disabled for security reasons + False: Disabled by user (command line option) + True: Safe and enabled + """ + if hasattr(sys, 'flags') and getattr(sys.flags, 'no_user_site', False): + return False + + if hasattr(os, "getuid") and hasattr(os, "geteuid"): + # check process uid == effective uid + if os.geteuid() != os.getuid(): + return None + if hasattr(os, "getgid") and hasattr(os, "getegid"): + # check process gid == effective gid + if os.getegid() != os.getgid(): + return None + + return True + +def addusersitepackages(known_paths): + """Add a per user site-package to sys.path + + Each user has its own python directory with site-packages in the + home directory. + + USER_BASE is the root directory for all Python versions + + USER_SITE is the user specific site-packages directory + + USER_SITE/.. can be used for data. + """ + global USER_BASE, USER_SITE, ENABLE_USER_SITE + env_base = os.environ.get("PYTHONUSERBASE", None) + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + #if sys.platform in ('os2emx', 'riscos'): + # # Don't know what to put here + # USER_BASE = '' + # USER_SITE = '' + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + if env_base: + USER_BASE = env_base + else: + USER_BASE = joinuser(base, "Python") + USER_SITE = os.path.join(USER_BASE, + "Python" + sys.version[0] + sys.version[2], + "site-packages") + else: + if env_base: + USER_BASE = env_base + else: + USER_BASE = joinuser("~", ".local") + USER_SITE = os.path.join(USER_BASE, "lib", + "python" + sys.version[:3], + "site-packages") + + if ENABLE_USER_SITE and os.path.isdir(USER_SITE): + addsitedir(USER_SITE, known_paths) + if ENABLE_USER_SITE: + for dist_libdir in ("lib", "local/lib"): + user_site = os.path.join(USER_BASE, dist_libdir, + "python" + sys.version[:3], + "dist-packages") + if os.path.isdir(user_site): + addsitedir(user_site, known_paths) + return known_paths + + + +def setBEGINLIBPATH(): + """The OS/2 EMX port has optional extension modules that do double duty + as DLLs (and must use the .DLL file extension) for other extensions. + The library search path needs to be amended so these will be found + during module import. Use BEGINLIBPATH so that these are at the start + of the library search path. + + """ + dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") + libpath = os.environ['BEGINLIBPATH'].split(';') + if libpath[-1]: + libpath.append(dllpath) + else: + libpath[-1] = dllpath + os.environ['BEGINLIBPATH'] = ';'.join(libpath) + + +def setquit(): + """Define new built-ins 'quit' and 'exit'. + These are simply strings that display a hint on how to exit. + + """ + if os.sep == ':': + eof = 'Cmd-Q' + elif os.sep == '\\': + eof = 'Ctrl-Z plus Return' + else: + eof = 'Ctrl-D (i.e. EOF)' + + class Quitter(object): + def __init__(self, name): + self.name = name + def __repr__(self): + return 'Use %s() or %s to exit' % (self.name, eof) + def __call__(self, code=None): + # Shells like IDLE catch the SystemExit, but listen when their + # stdin wrapper is closed. + try: + sys.stdin.close() + except: + pass + raise SystemExit(code) + builtins.quit = Quitter('quit') + builtins.exit = Quitter('exit') + + +class _Printer(object): + """interactive prompt objects for printing the license text, a list of + contributors and the copyright notice.""" + + MAXLINES = 23 + + def __init__(self, name, data, files=(), dirs=()): + self.__name = name + self.__data = data + self.__files = files + self.__dirs = dirs + self.__lines = None + + def __setup(self): + if self.__lines: + return + data = None + for dir in self.__dirs: + for filename in self.__files: + filename = os.path.join(dir, filename) + try: + fp = open(filename, "rU") + data = fp.read() + fp.close() + break + except IOError: + pass + if data: + break + if not data: + data = self.__data + self.__lines = data.split('\n') + self.__linecnt = len(self.__lines) + + def __repr__(self): + self.__setup() + if len(self.__lines) <= self.MAXLINES: + return "\n".join(self.__lines) + else: + return "Type %s() to see the full %s text" % ((self.__name,)*2) + + def __call__(self): + self.__setup() + prompt = 'Hit Return for more, or q (and Return) to quit: ' + lineno = 0 + while 1: + try: + for i in range(lineno, lineno + self.MAXLINES): + print(self.__lines[i]) + except IndexError: + break + else: + lineno += self.MAXLINES + key = None + while key is None: + try: + key = raw_input(prompt) + except NameError: + key = input(prompt) + if key not in ('', 'q'): + key = None + if key == 'q': + break + +def setcopyright(): + """Set 'copyright' and 'credits' in __builtin__""" + builtins.copyright = _Printer("copyright", sys.copyright) + if _is_jython: + builtins.credits = _Printer( + "credits", + "Jython is maintained by the Jython developers (www.jython.org).") + elif _is_pypy: + builtins.credits = _Printer( + "credits", + "PyPy is maintained by the PyPy developers: http://pypy.org/") + else: + builtins.credits = _Printer("credits", """\ + Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands + for supporting Python development. See www.python.org for more information.""") + here = os.path.dirname(os.__file__) + builtins.license = _Printer( + "license", "See http://www.python.org/%.3s/license.html" % sys.version, + ["LICENSE.txt", "LICENSE"], + [os.path.join(here, os.pardir), here, os.curdir]) + + +class _Helper(object): + """Define the built-in 'help'. + This is a wrapper around pydoc.help (with a twist). + + """ + + def __repr__(self): + return "Type help() for interactive help, " \ + "or help(object) for help about object." + def __call__(self, *args, **kwds): + import pydoc + return pydoc.help(*args, **kwds) + +def sethelper(): + builtins.help = _Helper() + +def aliasmbcs(): + """On Windows, some default encodings are not provided by Python, + while they are always available as "mbcs" in each locale. Make + them usable by aliasing to "mbcs" in such a case.""" + if sys.platform == 'win32': + import locale, codecs + enc = locale.getdefaultlocale()[1] + if enc.startswith('cp'): # "cp***" ? + try: + codecs.lookup(enc) + except LookupError: + import encodings + encodings._cache[enc] = encodings._unknown + encodings.aliases.aliases[enc] = 'mbcs' + +def setencoding(): + """Set the string encoding used by the Unicode implementation. The + default is 'ascii', but if you're willing to experiment, you can + change this.""" + encoding = "ascii" # Default value set by _PyUnicode_Init() + if 0: + # Enable to support locale aware default string encodings. + import locale + loc = locale.getdefaultlocale() + if loc[1]: + encoding = loc[1] + if 0: + # Enable to switch off string to Unicode coercion and implicit + # Unicode to string conversion. + encoding = "undefined" + if encoding != "ascii": + # On Non-Unicode builds this will raise an AttributeError... + sys.setdefaultencoding(encoding) # Needs Python Unicode build ! + + +def execsitecustomize(): + """Run custom site specific code, if available.""" + try: + import sitecustomize + except ImportError: + pass + +def virtual_install_main_packages(): + f = open(os.path.join(os.path.dirname(__file__), 'orig-prefix.txt')) + sys.real_prefix = f.read().strip() + f.close() + pos = 2 + hardcoded_relative_dirs = [] + if sys.path[0] == '': + pos += 1 + if _is_jython: + paths = [os.path.join(sys.real_prefix, 'Lib')] + elif _is_pypy: + if sys.version_info > (3, 2): + cpyver = '%d' % sys.version_info[0] + elif sys.pypy_version_info >= (1, 5): + cpyver = '%d.%d' % sys.version_info[:2] + else: + cpyver = '%d.%d.%d' % sys.version_info[:3] + paths = [os.path.join(sys.real_prefix, 'lib_pypy'), + os.path.join(sys.real_prefix, 'lib-python', cpyver)] + if sys.pypy_version_info < (1, 9): + paths.insert(1, os.path.join(sys.real_prefix, + 'lib-python', 'modified-%s' % cpyver)) + hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below + # + # This is hardcoded in the Python executable, but relative to sys.prefix: + for path in paths[:]: + plat_path = os.path.join(path, 'plat-%s' % sys.platform) + if os.path.exists(plat_path): + paths.append(plat_path) + elif sys.platform == 'win32': + paths = [os.path.join(sys.real_prefix, 'Lib'), os.path.join(sys.real_prefix, 'DLLs')] + else: + paths = [os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3])] + hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below + lib64_path = os.path.join(sys.real_prefix, 'lib64', 'python'+sys.version[:3]) + if os.path.exists(lib64_path): + if _is_64bit: + paths.insert(0, lib64_path) + else: + paths.append(lib64_path) + # This is hardcoded in the Python executable, but relative to + # sys.prefix. Debian change: we need to add the multiarch triplet + # here, which is where the real stuff lives. As per PEP 421, in + # Python 3.3+, this lives in sys.implementation, while in Python 2.7 + # it lives in sys. + try: + arch = getattr(sys, 'implementation', sys)._multiarch + except AttributeError: + # This is a non-multiarch aware Python. Fallback to the old way. + arch = sys.platform + plat_path = os.path.join(sys.real_prefix, 'lib', + 'python'+sys.version[:3], + 'plat-%s' % arch) + if os.path.exists(plat_path): + paths.append(plat_path) + # This is hardcoded in the Python executable, but + # relative to sys.prefix, so we have to fix up: + for path in list(paths): + tk_dir = os.path.join(path, 'lib-tk') + if os.path.exists(tk_dir): + paths.append(tk_dir) + + # These are hardcoded in the Apple's Python executable, + # but relative to sys.prefix, so we have to fix them up: + if sys.platform == 'darwin': + hardcoded_paths = [os.path.join(relative_dir, module) + for relative_dir in hardcoded_relative_dirs + for module in ('plat-darwin', 'plat-mac', 'plat-mac/lib-scriptpackages')] + + for path in hardcoded_paths: + if os.path.exists(path): + paths.append(path) + + sys.path.extend(paths) + +def force_global_eggs_after_local_site_packages(): + """ + Force easy_installed eggs in the global environment to get placed + in sys.path after all packages inside the virtualenv. This + maintains the "least surprise" result that packages in the + virtualenv always mask global packages, never the other way + around. + + """ + egginsert = getattr(sys, '__egginsert', 0) + for i, path in enumerate(sys.path): + if i > egginsert and path.startswith(sys.prefix): + egginsert = i + sys.__egginsert = egginsert + 1 + +def virtual_addsitepackages(known_paths): + force_global_eggs_after_local_site_packages() + return addsitepackages(known_paths, sys_prefix=sys.real_prefix) + +def fixclasspath(): + """Adjust the special classpath sys.path entries for Jython. These + entries should follow the base virtualenv lib directories. + """ + paths = [] + classpaths = [] + for path in sys.path: + if path == '__classpath__' or path.startswith('__pyclasspath__'): + classpaths.append(path) + else: + paths.append(path) + sys.path = paths + sys.path.extend(classpaths) + +def execusercustomize(): + """Run custom user specific code, if available.""" + try: + import usercustomize + except ImportError: + pass + + +def main(): + global ENABLE_USER_SITE + virtual_install_main_packages() + abs__file__() + paths_in_sys = removeduppaths() + if (os.name == "posix" and sys.path and + os.path.basename(sys.path[-1]) == "Modules"): + addbuilddir() + if _is_jython: + fixclasspath() + GLOBAL_SITE_PACKAGES = not os.path.exists(os.path.join(os.path.dirname(__file__), 'no-global-site-packages.txt')) + if not GLOBAL_SITE_PACKAGES: + ENABLE_USER_SITE = False + if ENABLE_USER_SITE is None: + ENABLE_USER_SITE = check_enableusersite() + paths_in_sys = addsitepackages(paths_in_sys) + paths_in_sys = addusersitepackages(paths_in_sys) + if GLOBAL_SITE_PACKAGES: + paths_in_sys = virtual_addsitepackages(paths_in_sys) + if sys.platform == 'os2emx': + setBEGINLIBPATH() + setquit() + setcopyright() + sethelper() + aliasmbcs() + setencoding() + execsitecustomize() + if ENABLE_USER_SITE: + execusercustomize() + # Remove sys.setdefaultencoding() so that users cannot change the + # encoding after initialization. The test for presence is needed when + # this module is run as a script, because this code is executed twice. + if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding + +main() + +def _script(): + help = """\ + %s [--user-base] [--user-site] + + Without arguments print some useful information + With arguments print the value of USER_BASE and/or USER_SITE separated + by '%s'. + + Exit codes with --user-base or --user-site: + 0 - user site directory is enabled + 1 - user site directory is disabled by user + 2 - uses site directory is disabled by super user + or for security reasons + >2 - unknown error + """ + args = sys.argv[1:] + if not args: + print("sys.path = [") + for dir in sys.path: + print(" %r," % (dir,)) + print("]") + def exists(path): + if os.path.isdir(path): + return "exists" + else: + return "doesn't exist" + print("USER_BASE: %r (%s)" % (USER_BASE, exists(USER_BASE))) + print("USER_SITE: %r (%s)" % (USER_SITE, exists(USER_BASE))) + print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE) + sys.exit(0) + + buffer = [] + if '--user-base' in args: + buffer.append(USER_BASE) + if '--user-site' in args: + buffer.append(USER_SITE) + + if buffer: + print(os.pathsep.join(buffer)) + if ENABLE_USER_SITE: + sys.exit(0) + elif ENABLE_USER_SITE is False: + sys.exit(1) + elif ENABLE_USER_SITE is None: + sys.exit(2) + else: + sys.exit(3) + else: + import textwrap + print(textwrap.dedent(help % (sys.argv[0], os.pathsep))) + sys.exit(10) + +if __name__ == '__main__': + _script()
new file mode 100644 index 0000000000000000000000000000000000000000..dfef51d4483025c5a535e553266234d372480439 GIT binary patch literal 23000 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 WP*ni|@gF}U{eCHa0}6Ehar!UP6A?xL
new file mode 100644 index 0000000000000000000000000000000000000000..cc49227a0c7e13757f4863a9b7ace1eb56c3ce61 GIT binary patch literal 1198961 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�oKpVIp(B`g@qqdD(UIrp;p8pV0;?dm$q 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⪙D_<L%`vErbc3q_r1O042$~&ZhHdXi= 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