mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
virtualenv: Update to upstream v16.7.11.
Based on Miro Hrončok's and Patrick Laimbock's findings: https://bugzilla.redhat.com/show_bug.cgi?id=1987713 Using upstream commit fb6e546cc1dfd0d363dc4d769486805d2d8f04bc.
This commit is contained in:
parent
ba7c38da4a
commit
712db1d962
@ -7,6 +7,7 @@ Maintainers
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
Brian Rosner
|
Brian Rosner
|
||||||
|
Bernat Gabor
|
||||||
Carl Meyer
|
Carl Meyer
|
||||||
Jannis Leidel
|
Jannis Leidel
|
||||||
Paul Moore
|
Paul Moore
|
||||||
@ -89,3 +90,4 @@ Vinay Sajip
|
|||||||
Vitaly Babiy
|
Vitaly Babiy
|
||||||
Vladimir Rutsky
|
Vladimir Rutsky
|
||||||
Wang Xuerui
|
Wang Xuerui
|
||||||
|
Wouter De Borger
|
||||||
|
25
python/virtualenv/CONTRIBUTING.rst
Normal file
25
python/virtualenv/CONTRIBUTING.rst
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
virtualenv
|
||||||
|
==========
|
||||||
|
|
||||||
|
See docs/index.rst for user documentation.
|
||||||
|
|
||||||
|
Contributor notes
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* virtualenv is designed to work on python 2 and 3 with a single code base.
|
||||||
|
Use Python 3 print-function syntax, and always ``use sys.exc_info()[1]``
|
||||||
|
inside the ``except`` block to get at exception objects.
|
||||||
|
|
||||||
|
* Pull requests should be made against ``master`` branch, which is also our
|
||||||
|
latest stable version.
|
||||||
|
|
||||||
|
* All changes to files inside virtualenv_embedded must be integrated to
|
||||||
|
``virtualenv.py`` with ``tox -e embed``. The tox run will report failure
|
||||||
|
when changes are integrated, as a flag for CI.
|
||||||
|
|
||||||
|
* The codebase must be linted with ``tox -e fix_lint`` before being merged.
|
||||||
|
The tox run will report failure when the linters revise code, as a flag
|
||||||
|
for CI.
|
||||||
|
|
||||||
|
.. _git-flow: https://github.com/nvie/gitflow
|
||||||
|
.. _coordinate development: http://nvie.com/posts/a-successful-git-branching-model/
|
@ -1,12 +1,22 @@
|
|||||||
recursive-include docs *
|
include virtualenv.py
|
||||||
recursive-include tests *.py *.sh *.expected
|
|
||||||
recursive-include virtualenv_support *.whl
|
recursive-include virtualenv_support *.whl
|
||||||
recursive-include virtualenv_embedded *
|
recursive-include virtualenv_embedded *
|
||||||
recursive-exclude docs/_templates *
|
|
||||||
recursive-exclude docs/_build *
|
|
||||||
include virtualenv_support/__init__.py
|
include virtualenv_support/__init__.py
|
||||||
include bin/*
|
include pyproject.toml
|
||||||
include scripts/*
|
|
||||||
include *.py
|
|
||||||
include AUTHORS.txt
|
include AUTHORS.txt
|
||||||
include LICENSE.txt
|
include LICENSE.txt
|
||||||
|
|
||||||
|
recursive-include tests *
|
||||||
|
recursive-include docs *
|
||||||
|
include tasks/*
|
||||||
|
include tox.ini
|
||||||
|
|
||||||
|
exclude readthedocs.yml
|
||||||
|
exclude CONTRIBUTING.rst
|
||||||
|
exclude .pre-commit-config.yaml
|
||||||
|
exclude azure-run-tox-env.yml
|
||||||
|
exclude azure-pipelines.yml
|
||||||
|
exclude .gitignore
|
||||||
|
exclude .gitattributes
|
||||||
|
recursive-exclude .github *
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
Metadata-Version: 1.1
|
|
||||||
Name: virtualenv
|
|
||||||
Version: 15.2.0
|
|
||||||
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.2.0 (2018-03-21)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
* Upgrade setuptools to 39.0.1.
|
|
||||||
|
|
||||||
* Upgrade pip to 9.0.3.
|
|
||||||
|
|
||||||
* Upgrade wheel to 0.30.0.
|
|
||||||
|
|
||||||
|
|
||||||
15.1.0 (2016-11-15)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
* Support Python 3.6.
|
|
||||||
|
|
||||||
* Upgrade setuptools to 28.0.0.
|
|
||||||
|
|
||||||
* Upgrade pip to 9.0.1.
|
|
||||||
|
|
||||||
* Don't install pre-release versions of pip, setuptools, or wheel from PyPI.
|
|
||||||
|
|
||||||
|
|
||||||
`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.4
|
|
||||||
Classifier: Programming Language :: Python :: 3.5
|
|
||||||
Classifier: Programming Language :: Python :: 3.6
|
|
@ -4,21 +4,34 @@ virtualenv
|
|||||||
A tool for creating isolated 'virtual' python environments.
|
A tool for creating isolated 'virtual' python environments.
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/v/virtualenv.svg
|
.. image:: https://img.shields.io/pypi/v/virtualenv.svg
|
||||||
:target: https://pypi.python.org/pypi/virtualenv
|
:target: https://pypi.org/project/virtualenv
|
||||||
|
:alt: Latest version on PyPi
|
||||||
.. image:: https://img.shields.io/travis/pypa/virtualenv/develop.svg
|
.. image:: https://img.shields.io/pypi/pyversions/virtualenv.svg
|
||||||
:target: http://travis-ci.org/pypa/virtualenv
|
:target: https://pypi.org/project/virtualenv/
|
||||||
|
:alt: Supported Python versions
|
||||||
|
.. image:: https://dev.azure.com/pypa/virtualenv/_apis/build/status/pypa.virtualenv?branchName=master
|
||||||
|
:target: https://dev.azure.com/pypa/virtualenv/_build/latest?definitionId=11&branchName=master
|
||||||
|
:alt: Azure Pipelines build status
|
||||||
|
.. image:: https://readthedocs.org/projects/virtualenv/badge/?version=latest&style=flat-square
|
||||||
|
:target: https://virtualenv.readthedocs.io/en/latest/?badge=latest
|
||||||
|
:alt: Documentation status
|
||||||
|
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||||
|
:target: https://github.com/ambv/black
|
||||||
|
:alt: Code style: black
|
||||||
|
.. image:: https://pepy.tech/badge/virtualenv/month
|
||||||
|
:target: https://pepy.tech/project/virtualenv/month
|
||||||
|
:alt: Downloads
|
||||||
|
|
||||||
* `Installation <https://virtualenv.pypa.io/en/latest/installation.html>`_
|
* `Installation <https://virtualenv.pypa.io/en/latest/installation.html>`_
|
||||||
* `Documentation <https://virtualenv.pypa.io/>`_
|
* `Documentation <https://virtualenv.pypa.io/>`_
|
||||||
* `Changelog <https://virtualenv.pypa.io/en/latest/changes.html>`_
|
* `Changelog <https://virtualenv.pypa.io/en/latest/changes.html>`_
|
||||||
* `Issues <https://github.com/pypa/virtualenv/issues>`_
|
* `Issues <https://github.com/pypa/virtualenv/issues>`_
|
||||||
* `PyPI <https://pypi.python.org/pypi/virtualenv/>`_
|
* `PyPI <https://pypi.org/project/virtualenv/>`_
|
||||||
* `Github <https://github.com/pypa/virtualenv>`_
|
* `Github <https://github.com/pypa/virtualenv>`_
|
||||||
* `User mailing list <http://groups.google.com/group/python-virtualenv>`_
|
* `User mailing list <http://groups.google.com/group/python-virtualenv>`_
|
||||||
* `Dev mailing list <http://groups.google.com/group/pypa-dev>`_
|
* `Dev mailing list <http://groups.google.com/group/pypa-dev>`_
|
||||||
* User IRC: #pypa on Freenode.
|
* User IRC: `#pypa on Freenode <https://webchat.freenode.net/?channels=%23pypa>`_
|
||||||
* Dev IRC: #pypa-dev on Freenode.
|
* Dev IRC: `#pypa-dev on Freenode <https://webchat.freenode.net/?channels=%23pypa-dev>`_
|
||||||
|
|
||||||
|
|
||||||
Code of Conduct
|
Code of Conduct
|
||||||
|
72
python/virtualenv/azure-pipelines.yml
Normal file
72
python/virtualenv/azure-pipelines.yml
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr)
|
||||||
|
resources:
|
||||||
|
repositories:
|
||||||
|
- repository: tox
|
||||||
|
type: github
|
||||||
|
endpoint: github-gb
|
||||||
|
name: tox-dev/azure-pipelines-template
|
||||||
|
ref: master
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
batch: true
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- master
|
||||||
|
- rewrite
|
||||||
|
- refs/tags/*
|
||||||
|
|
||||||
|
pr:
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
schedules:
|
||||||
|
- cron: "12 0 * * *"
|
||||||
|
displayName: Daily build
|
||||||
|
branches:
|
||||||
|
include: [ master, rewrite ]
|
||||||
|
always: true
|
||||||
|
|
||||||
|
variables:
|
||||||
|
PYTEST_ADDOPTS: "-v -v -ra --showlocals"
|
||||||
|
PYTEST_XDIST_PROC_NR: 'auto'
|
||||||
|
CI_RUN: 'yes'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- template: run-tox-env.yml@tox
|
||||||
|
parameters:
|
||||||
|
jobs:
|
||||||
|
fix_lint: null
|
||||||
|
embed: null
|
||||||
|
cross_python2: null
|
||||||
|
cross_python3: null
|
||||||
|
docs: null
|
||||||
|
py38:
|
||||||
|
image: [linux, windows, macOs]
|
||||||
|
py37:
|
||||||
|
image: [linux, windows, macOs]
|
||||||
|
py36:
|
||||||
|
image: [linux, windows, macOs]
|
||||||
|
py35:
|
||||||
|
image: [linux, windows, macOs]
|
||||||
|
py27:
|
||||||
|
image: [linux, windows, macOs]
|
||||||
|
dev: null
|
||||||
|
package_readme: null
|
||||||
|
before:
|
||||||
|
- script: 'sudo apt-get update -y && sudo apt-get install fish csh'
|
||||||
|
condition: and(succeeded(), eq(variables['image_name'], 'linux'), in(variables['TOXENV'], 'py38', 'py37', 'py36', 'py35', 'py34', 'py27'))
|
||||||
|
displayName: install fish and csh via apt-get
|
||||||
|
- script: 'brew update -vvv && brew install fish tcsh'
|
||||||
|
condition: and(succeeded(), eq(variables['image_name'], 'macOs'), in(variables['TOXENV'], 'py38', 'py37', 'py36', 'py35', 'py34', 'py27'))
|
||||||
|
displayName: install fish and csh via brew
|
||||||
|
coverage:
|
||||||
|
with_toxenv: 'coverage' # generate .tox/.coverage, .tox/coverage.xml after test run
|
||||||
|
for_envs: [py38, py37, py36, py35, py27]
|
||||||
|
|
||||||
|
- ${{ if startsWith(variables['Build.SourceBranch'], 'refs/tags/') }}:
|
||||||
|
- template: publish-pypi.yml@tox
|
||||||
|
parameters:
|
||||||
|
external_feed: 'gb'
|
||||||
|
pypi_remote: 'pypi-gb'
|
||||||
|
dependsOn: [fix_lint, embed, cross_python3, cross_python3, docs, report_coverage, dev, package_readme]
|
@ -1,80 +0,0 @@
|
|||||||
#!/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 as _crc32
|
|
||||||
|
|
||||||
|
|
||||||
def crc32(data):
|
|
||||||
"""Python version idempotent"""
|
|
||||||
return _crc32(data) & 0xffffffff
|
|
||||||
|
|
||||||
|
|
||||||
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: %08x)' % new_crc)
|
|
||||||
parts += [match.group(0)]
|
|
||||||
continue
|
|
||||||
# Else: content has changed
|
|
||||||
crc = crc32(gzip.decode(b64.decode(data)[0])[0])
|
|
||||||
print(' Content changed (crc: %08x -> %08x)' %
|
|
||||||
(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)
|
|
@ -1,130 +0,0 @@
|
|||||||
# 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."
|
|
18
python/virtualenv/docs/changelog/examples.rst
Normal file
18
python/virtualenv/docs/changelog/examples.rst
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
.. examples for changelog entries adding to your Pull Requests
|
||||||
|
|
||||||
|
file ``544.doc.rst``::
|
||||||
|
|
||||||
|
explain everything much better - by ``passionate_technicalwriter``
|
||||||
|
|
||||||
|
file ``544.feature.rst``::
|
||||||
|
|
||||||
|
``tox --version`` now shows information about all registered plugins - by ``obestwalter``
|
||||||
|
|
||||||
|
|
||||||
|
file ``571.bugfix.rst``::
|
||||||
|
|
||||||
|
``skip_install`` overrides ``usedevelop`` (``usedevelop`` is an option to choose the
|
||||||
|
installation type if the package is installed and ``skip_install`` determines if it should be
|
||||||
|
installed at all) - by ``ferdonline``
|
||||||
|
|
||||||
|
.. see pyproject.toml for all available categories
|
31
python/virtualenv/docs/changelog/template.jinja2
Normal file
31
python/virtualenv/docs/changelog/template.jinja2
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{% for section, _ in sections.items() %}
|
||||||
|
{% set underline = underlines[0] %}
|
||||||
|
{% if section %}
|
||||||
|
{{section}}
|
||||||
|
{{ underline * section|length }}
|
||||||
|
{% set underline = underlines[1] %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if sections[section] %}
|
||||||
|
{% for category, val in definitions.items() if category in sections[section] %}
|
||||||
|
{{ definitions[category]['name'] }}
|
||||||
|
{{ underline * definitions[category]['name']|length }}
|
||||||
|
{% if definitions[category]['showcontent'] %}
|
||||||
|
|
||||||
|
{% for text, values in sections[section][category].items() %}
|
||||||
|
- {{ text }} ({{ values|join(', ') }})
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
- {{ sections[section][category]['']|join(', ') }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if sections[section][category]|length == 0 %}
|
||||||
|
No significant changes.
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
No significant changes.
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
File diff suppressed because it is too large
Load Diff
@ -1,153 +1,73 @@
|
|||||||
# -*- coding: utf-8 -*-
|
from __future__ import absolute_import, unicode_literals
|
||||||
#
|
|
||||||
# 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 os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
from virtualenv import __version__
|
||||||
|
|
||||||
# If your extensions are in another directory, add it here.
|
extensions = ["sphinx.ext.autodoc", "sphinx.ext.extlinks"]
|
||||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
source_suffix = ".rst"
|
||||||
|
master_doc = "index"
|
||||||
|
project = "virtualenv"
|
||||||
|
copyright = "2007-2018, Ian Bicking, The Open Planning Project, PyPA"
|
||||||
|
|
||||||
# General configuration
|
ROOT_SRC_TREE_DIR = Path(__file__).parents[1]
|
||||||
# ---------------------
|
|
||||||
|
|
||||||
# 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.
|
def generate_draft_news():
|
||||||
#templates_path = ['_templates']
|
home = "https://github.com"
|
||||||
|
issue = "{}/issue".format(home)
|
||||||
|
fragments_path = ROOT_SRC_TREE_DIR / "docs" / "changelog"
|
||||||
|
for pattern, replacement in (
|
||||||
|
(r"[^`]@([^,\s]+)", r"`@\1 <{}/\1>`_".format(home)),
|
||||||
|
(r"[^`]#([\d]+)", r"`#pr\1 <{}/\1>`_".format(issue)),
|
||||||
|
):
|
||||||
|
for path in fragments_path.glob("*.rst"):
|
||||||
|
path.write_text(re.sub(pattern, replacement, path.read_text()))
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["PATH"] += os.pathsep.join([os.path.dirname(sys.executable)] + env["PATH"].split(os.pathsep))
|
||||||
|
changelog = subprocess.check_output(
|
||||||
|
["towncrier", "--draft", "--version", "DRAFT"], cwd=str(ROOT_SRC_TREE_DIR), env=env
|
||||||
|
).decode("utf-8")
|
||||||
|
if "No significant changes" in changelog:
|
||||||
|
content = ""
|
||||||
|
else:
|
||||||
|
note = "*Changes in master, but not released yet are under the draft section*."
|
||||||
|
content = "{}\n\n{}".format(note, changelog)
|
||||||
|
(ROOT_SRC_TREE_DIR / "docs" / "_draft.rst").write_text(content)
|
||||||
|
|
||||||
# The suffix of source filenames.
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The master toctree document.
|
generate_draft_news()
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# General substitutions.
|
version = ".".join(__version__.split(".")[:2])
|
||||||
project = 'virtualenv'
|
release = __version__
|
||||||
copyright = '2007-2014, Ian Bicking, The Open Planning Project, PyPA'
|
|
||||||
|
|
||||||
# The default replacements for |version| and |release|, also used in various
|
today_fmt = "%B %d, %Y"
|
||||||
# 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 = []
|
unused_docs = []
|
||||||
|
pygments_style = "sphinx"
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
exclude_patterns = ["changelog/*"]
|
||||||
#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 = {
|
extlinks = {
|
||||||
'issue': ('https://github.com/pypa/virtualenv/issues/%s', '#'),
|
"issue": ("https://github.com/pypa/virtualenv/issues/%s", "#"),
|
||||||
'pull': ('https://github.com/pypa/virtualenv/pull/%s', 'PR #'),
|
"pull": ("https://github.com/pypa/virtualenv/pull/%s", "PR #"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html_theme = "sphinx_rtd_theme"
|
||||||
# Options for HTML output
|
html_theme_options = {
|
||||||
# -----------------------
|
"canonical_url": "https://virtualenv.pypa.io/en/latest/",
|
||||||
|
"logo_only": False,
|
||||||
# The style sheet to use for HTML and HTML Help pages. A file of that name
|
"display_version": True,
|
||||||
# must exist either in Sphinx' static/ path, or in one of the custom paths
|
"prev_next_buttons_location": "bottom",
|
||||||
# given in html_static_path.
|
"style_external_links": True,
|
||||||
#html_style = 'default.css'
|
# Toc options
|
||||||
|
"collapse_navigation": True,
|
||||||
html_theme = 'default'
|
"sticky_navigation": True,
|
||||||
if not on_rtd:
|
"navigation_depth": 4,
|
||||||
try:
|
"includehidden": True,
|
||||||
import sphinx_rtd_theme
|
"titles_only": False,
|
||||||
html_theme = 'sphinx_rtd_theme'
|
}
|
||||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
html_last_updated_fmt = "%b %d, %Y"
|
||||||
except ImportError:
|
htmlhelp_basename = "Pastedoc"
|
||||||
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
|
|
||||||
|
@ -5,19 +5,24 @@ Contributing
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
Refer to the `pip development`_ documentation - it applies equally to
|
Refer to the `pip development`_ documentation - it applies equally to
|
||||||
virtualenv, except that virtualenv issues should filed on the `virtualenv
|
virtualenv, except that virtualenv issues should be filed on the `virtualenv
|
||||||
repo`_ at GitHub.
|
repo`_ at GitHub.
|
||||||
|
|
||||||
Virtualenv's release schedule is tied to pip's -- each time there's a new pip
|
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
|
release, there will be a new virtualenv release that bundles the new version of
|
||||||
pip.
|
pip.
|
||||||
|
|
||||||
Files in the `virtualenv_embedded/` subdirectory are embedded into
|
Files in the ``virtualenv_embedded/`` subdirectory are embedded into
|
||||||
`virtualenv.py` itself as base64-encoded strings (in order to support
|
``virtualenv.py`` itself as base64-encoded strings (in order to support
|
||||||
single-file use of `virtualenv.py` without installing it). If your patch
|
single-file use of ``virtualenv.py`` without installing it). If your patch
|
||||||
changes any file in `virtualenv_embedded/`, run `bin/rebuild-script.py` to
|
changes any file in ``virtualenv_embedded/``, run ``tox -e embed`` to update
|
||||||
update the embedded version of that file in `virtualenv.py`; commit that and
|
the embedded version of that file in ``virtualenv.py``; commit that and submit
|
||||||
submit it as part of your patch / pull request.
|
it as part of your patch / pull request. The tox run will report failure
|
||||||
|
when changes are embedded, as a flag for CI.
|
||||||
|
|
||||||
|
The codebase should be linted before a pull request is merged by running
|
||||||
|
``tox -e fix_lint``. The tox run will report failure when any linting
|
||||||
|
revisions are required, as a flag for CI.
|
||||||
|
|
||||||
.. _pip development: https://pip.pypa.io/en/latest/development/
|
.. _pip development: https://pip.pypa.io/en/latest/development/
|
||||||
.. _virtualenv repo: https://github.com/pypa/virtualenv/
|
.. _virtualenv repo: https://github.com/pypa/virtualenv/
|
||||||
@ -25,26 +30,16 @@ submit it as part of your patch / pull request.
|
|||||||
Running the tests
|
Running the tests
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Virtualenv's test suite is small and not yet at all comprehensive, but we aim
|
The easy way to run tests (handles test dependencies automatically, works with the ``sdist`` too)::
|
||||||
to grow it.
|
|
||||||
|
|
||||||
The easy way to run tests (handles test dependencies automatically)::
|
$ tox
|
||||||
|
|
||||||
$ python setup.py test
|
Note you need to first install tox separately by using::
|
||||||
|
|
||||||
If you want to run only a selection of the tests, you'll need to run them
|
$ python -m pip --user install -U tox
|
||||||
directly with pytest instead. Create a virtualenv, and install required
|
|
||||||
packages::
|
|
||||||
|
|
||||||
$ pip install pytest mock
|
Run ``python -m tox -av`` for a list of all supported Python environments or just run the
|
||||||
|
tests in all of the available ones by running just ``tox``.
|
||||||
Run pytest::
|
|
||||||
|
|
||||||
$ pytest
|
|
||||||
|
|
||||||
Or select just a single test file to run::
|
|
||||||
|
|
||||||
$ pytest tests/test_virtualenv
|
|
||||||
|
|
||||||
Status and License
|
Status and License
|
||||||
------------------
|
------------------
|
||||||
|
@ -4,14 +4,23 @@ Virtualenv
|
|||||||
`Mailing list <http://groups.google.com/group/python-virtualenv>`_ |
|
`Mailing list <http://groups.google.com/group/python-virtualenv>`_ |
|
||||||
`Issues <https://github.com/pypa/virtualenv/issues>`_ |
|
`Issues <https://github.com/pypa/virtualenv/issues>`_ |
|
||||||
`Github <https://github.com/pypa/virtualenv>`_ |
|
`Github <https://github.com/pypa/virtualenv>`_ |
|
||||||
`PyPI <https://pypi.python.org/pypi/virtualenv/>`_ |
|
`PyPI <https://pypi.org/project/virtualenv/>`_ |
|
||||||
User IRC: #pypa
|
User IRC: #pypa
|
||||||
Dev IRC: #pypa-dev
|
Dev IRC: #pypa-dev
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
``virtualenv`` is a tool to create isolated Python environments.
|
|
||||||
|
``virtualenv`` is a tool to create isolated Python environments. Since
|
||||||
|
Python 3.3, a subset of it has been integrated into the standard
|
||||||
|
library under the `venv module <https://docs.python.org/3/library/venv.html>`_.
|
||||||
|
Note though, that the ``venv`` module does not offer all features of this
|
||||||
|
library (e.g. cannot create bootstrap scripts, cannot create virtual
|
||||||
|
environments for other python versions than the host python,
|
||||||
|
not relocatable, etc.). Tools in general as such still may prefer using
|
||||||
|
virtualenv for its ease of upgrading (via pip), unified handling of different
|
||||||
|
Python versions and some more advanced features.
|
||||||
|
|
||||||
The basic problem being addressed is one of dependencies and versions,
|
The basic problem being addressed is one of dependencies and versions,
|
||||||
and indirectly permissions. Imagine you have an application that
|
and indirectly permissions. Imagine you have an application that
|
||||||
@ -45,18 +54,6 @@ doesn't access the globally installed libraries either).
|
|||||||
development
|
development
|
||||||
changes
|
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
|
Other Documentation and Links
|
||||||
-----------------------------
|
-----------------------------
|
||||||
@ -76,14 +73,14 @@ Other Documentation and Links
|
|||||||
your workflow with many virtualenvs even easier. `His initial blog post on it`__.
|
your workflow with many virtualenvs even easier. `His initial blog post on it`__.
|
||||||
He also wrote `an example of using virtualenv to try IPython`__.
|
He also wrote `an example of using virtualenv to try IPython`__.
|
||||||
|
|
||||||
.. _virtualenvwrapper: https://pypi.python.org/pypi/virtualenvwrapper/
|
.. _virtualenvwrapper: https://pypi.org/project/virtualenvwrapper/
|
||||||
.. __: https://doughellmann.com/blog/2008/05/01/virtualenvwrapper/
|
.. __: https://doughellmann.com/blog/2008/05/01/virtualenvwrapper/
|
||||||
.. __: https://doughellmann.com/blog/2008/02/01/ipython-and-virtualenv/
|
.. __: https://doughellmann.com/blog/2008/02/01/ipython-and-virtualenv/
|
||||||
|
|
||||||
* `Pew`_ is another wrapper for virtualenv that makes use of a different
|
* `Pew`_ is another wrapper for virtualenv that makes use of a different
|
||||||
activation technique.
|
activation technique.
|
||||||
|
|
||||||
.. _Pew: https://pypi.python.org/pypi/pew/
|
.. _Pew: https://pypi.org/project/pew/
|
||||||
|
|
||||||
* `Using virtualenv with mod_wsgi
|
* `Using virtualenv with mod_wsgi
|
||||||
<http://code.google.com/p/modwsgi/wiki/VirtualEnvironments>`_.
|
<http://code.google.com/p/modwsgi/wiki/VirtualEnvironments>`_.
|
||||||
@ -103,6 +100,10 @@ Compare & Contrast with Alternatives
|
|||||||
|
|
||||||
There are several alternatives that create isolated environments:
|
There are several alternatives that create isolated environments:
|
||||||
|
|
||||||
|
* Python 3's `venv module <https://docs.python.org/3/library/venv.html>`_
|
||||||
|
is recommended for projects that no longer need to support Python 2 and want
|
||||||
|
to create just simple environments for the host python.
|
||||||
|
|
||||||
* ``workingenv`` (which I do not suggest you use anymore) is the
|
* ``workingenv`` (which I do not suggest you use anymore) is the
|
||||||
predecessor to this library. It used the main Python interpreter,
|
predecessor to this library. It used the main Python interpreter,
|
||||||
but relied on setting ``$PYTHONPATH`` to activate the environment.
|
but relied on setting ``$PYTHONPATH`` to activate the environment.
|
||||||
@ -125,7 +126,7 @@ There are several alternatives that create isolated environments:
|
|||||||
Setuptools automatically, saving a step and avoiding the need for
|
Setuptools automatically, saving a step and avoiding the need for
|
||||||
network access.
|
network access.
|
||||||
|
|
||||||
* `zc.buildout <http://pypi.python.org/pypi/zc.buildout>`_ doesn't
|
* `zc.buildout <http://pypi.org/project/zc.buildout>`_ doesn't
|
||||||
create an isolated Python environment in the same style, but
|
create an isolated Python environment in the same style, but
|
||||||
achieves similar results through a declarative config file that sets
|
achieves similar results through a declarative config file that sets
|
||||||
up scripts with very particular packages. As a declarative system,
|
up scripts with very particular packages. As a declarative system,
|
||||||
|
@ -17,36 +17,47 @@ Installation
|
|||||||
setuptools < 0.9.7, because easy_install didn't download from PyPI over SSL
|
setuptools < 0.9.7, because easy_install didn't download from PyPI over SSL
|
||||||
and was broken in some subtle ways.
|
and was broken in some subtle ways.
|
||||||
|
|
||||||
To install globally with `pip` (if you have pip 1.3 or greater installed globally):
|
In Windows, run the ``pip`` provided by your Python installation to install ``virtualenv``.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ [sudo] pip install virtualenv
|
> pip install virtualenv
|
||||||
|
|
||||||
|
In non-Windows systems it is discouraged to run ``pip`` as root including with ``sudo``.
|
||||||
|
Generally use your system package manager if it provides a package.
|
||||||
|
This avoids conflicts in versions and file locations between the system package manager and ``pip``.
|
||||||
|
See your distribution's package manager documentation for instructions on using it to install ``virtualenv``.
|
||||||
|
|
||||||
|
Using ``pip install --user`` is less hazardous but can still cause trouble within the particular user account.
|
||||||
|
If a system package expects the system provided ``virtualenv`` and an incompatible version is installed with ``--user`` that package may have problems within that user account.
|
||||||
|
To install within your user account with ``pip`` (if you have pip 1.3 or greater installed):
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
$ pip install --user virtualenv
|
||||||
|
|
||||||
|
Note: The specific ``bin`` path may vary per distribution but is often ``~/.local/bin`` and must be added to your ``$PATH`` if not already present.
|
||||||
|
|
||||||
Or to get the latest unreleased dev version:
|
Or to get the latest unreleased dev version:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ [sudo] pip install https://github.com/pypa/virtualenv/tarball/master
|
$ pip install --user https://github.com/pypa/virtualenv/tarball/master
|
||||||
|
|
||||||
|
|
||||||
To install version X.X globally from source:
|
To install version ``X.X.X`` globally from source:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-X.X.tar.gz
|
$ pip install --user https://github.com/pypa/virtualenv/tarball/X.X.X
|
||||||
$ tar xvfz virtualenv-X.X.tar.gz
|
|
||||||
$ cd virtualenv-X.X
|
|
||||||
$ [sudo] python setup.py install
|
|
||||||
|
|
||||||
|
|
||||||
To *use* locally from source:
|
To *use* locally from source:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-X.X.tar.gz
|
$ curl --location --output virtualenv-X.X.X.tar.gz https://github.com/pypa/virtualenv/tarball/X.X.X
|
||||||
$ tar xvfz virtualenv-X.X.tar.gz
|
$ tar xvfz virtualenv-X.X.X.tar.gz
|
||||||
$ cd virtualenv-X.X
|
$ cd pypa-virtualenv-YYYYYY
|
||||||
$ python virtualenv.py myVE
|
$ python virtualenv.py myVE
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -1,170 +0,0 @@
|
|||||||
@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
|
|
@ -40,7 +40,7 @@ Options
|
|||||||
.. option:: -p PYTHON_EXE, --python=PYTHON_EXE
|
.. option:: -p PYTHON_EXE, --python=PYTHON_EXE
|
||||||
|
|
||||||
The Python interpreter to use, e.g.,
|
The Python interpreter to use, e.g.,
|
||||||
--python=python2.5 will use the python2.5 interpreter
|
``--python=python2.5`` will use the python2.5 interpreter
|
||||||
to create the new environment. The default is the
|
to create the new environment. The default is the
|
||||||
interpreter that virtualenv was installed with
|
interpreter that virtualenv was installed with
|
||||||
(like ``/usr/bin/python``)
|
(like ``/usr/bin/python``)
|
||||||
@ -111,8 +111,8 @@ Options
|
|||||||
virtualenv. Distribute has now been merged into Setuptools, and the
|
virtualenv. Distribute has now been merged into Setuptools, and the
|
||||||
latter is always installed.
|
latter is always installed.
|
||||||
|
|
||||||
.. _Distribute: https://pypi.python.org/pypi/distribute
|
.. _Distribute: https://pypi.org/project/distribute
|
||||||
.. _Setuptools: https://pypi.python.org/pypi/setuptools
|
.. _Setuptools: https://pypi.org/project/setuptools
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
@ -148,8 +148,10 @@ is the same as calling::
|
|||||||
|
|
||||||
.. envvar:: VIRTUAL_ENV_DISABLE_PROMPT
|
.. envvar:: VIRTUAL_ENV_DISABLE_PROMPT
|
||||||
|
|
||||||
Any virtualenv created when this is set to a non-empty value will not have
|
Any virtualenv *activated* when this is set to a non-empty value will leave
|
||||||
it's :ref:`activate` modify the shell prompt.
|
the shell prompt unchanged during processing of the
|
||||||
|
:ref:`activate script <activate>`, rather than modifying it to indicate
|
||||||
|
the newly activated environment.
|
||||||
|
|
||||||
|
|
||||||
Configuration File
|
Configuration File
|
||||||
@ -189,6 +191,15 @@ environment. Developers may find it useful to distribute a script
|
|||||||
that sets up a particular environment, for example a script that
|
that sets up a particular environment, for example a script that
|
||||||
installs a particular web application.
|
installs a particular web application.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
A bootstrap script requires a ``virtualenv_support`` directory containing
|
||||||
|
``pip`` and ``setuptools`` wheels alongside it, just like the actual virtualenv
|
||||||
|
script. Running a bootstrap script without a ``virtualenv_support`` directory
|
||||||
|
is unsupported (but if you use ``--no-setuptools`` and manually install ``pip``
|
||||||
|
and ``setuptools`` in your virtualenv, it will work).
|
||||||
|
|
||||||
|
|
||||||
To create a script like this, call
|
To create a script like this, call
|
||||||
:py:func:`virtualenv.create_bootstrap_script`, and write the
|
:py:func:`virtualenv.create_bootstrap_script`, and write the
|
||||||
result to your new bootstrapping script.
|
result to your new bootstrapping script.
|
||||||
@ -259,3 +270,62 @@ Here's a more concrete example of how you could use this::
|
|||||||
Another example is available `here`__.
|
Another example is available `here`__.
|
||||||
|
|
||||||
.. __: https://github.com/socialplanning/fassembler/blob/master/fassembler/create-venv-script.py
|
.. __: https://github.com/socialplanning/fassembler/blob/master/fassembler/create-venv-script.py
|
||||||
|
|
||||||
|
|
||||||
|
Compatibility with the stdlib venv module
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
Starting with Python 3.3, the Python standard library includes a ``venv``
|
||||||
|
module that provides similar functionality to ``virtualenv`` - however, the
|
||||||
|
mechanisms used by the two modules are very different.
|
||||||
|
|
||||||
|
Problems arise when environments get "nested" (a virtual environment is
|
||||||
|
created from within another one - for example, running the virtualenv tests
|
||||||
|
using tox, where tox creates a virtual environment to run the tests, and the
|
||||||
|
tests themselves create further virtual environments).
|
||||||
|
|
||||||
|
``virtualenv`` supports creating virtual environments from within another one
|
||||||
|
(the ``sys.real_prefix`` variable allows ``virtualenv`` to locate the "base"
|
||||||
|
environment) but stdlib-style ``venv`` environments don't use that mechanism,
|
||||||
|
so explicit support is needed for those environments.
|
||||||
|
|
||||||
|
A standard library virtual environment is most easily identified by checking
|
||||||
|
``sys.prefix`` and ``sys.base_prefix``. If these differ, the interpreter is
|
||||||
|
running in a virtual environment and the base interpreter is located in the
|
||||||
|
directory specified by ``sys.base_prefix``. Therefore, when
|
||||||
|
``sys.base_prefix`` is set, virtualenv gets the interpreter files from there
|
||||||
|
rather than from ``sys.prefix`` (in the same way as ``sys.real_prefix`` is
|
||||||
|
used for virtualenv-style environments). In practice, this is sufficient for
|
||||||
|
all platforms other than Windows.
|
||||||
|
|
||||||
|
On Windows from Python 3.7.2 onwards, a stdlib-style virtual environment does
|
||||||
|
not contain an actual Python interpreter executable, but rather a "redirector"
|
||||||
|
which launches the actual interpreter from the base environment (this
|
||||||
|
redirector is based on the same code as the standard ``py.exe`` launcher). As
|
||||||
|
a result, the virtualenv approach of copying the interpreter from the starting
|
||||||
|
environment fails. In order to correctly set up the virtualenv, therefore, we
|
||||||
|
need to be running from a "full" environment. To ensure that, we re-invoke the
|
||||||
|
``virtualenv.py`` script using the "base" interpreter, in the same way as we
|
||||||
|
do with the ``--python`` command line option.
|
||||||
|
|
||||||
|
The process of identifying the base interpreter is complicated by the fact
|
||||||
|
that the implementation changed between different Python versions. The
|
||||||
|
logic used is as follows:
|
||||||
|
|
||||||
|
1. If the (private) attribute ``sys._base_executable`` is present, this is
|
||||||
|
the base interpreter. This is the long-term solution and should be stable
|
||||||
|
in the future (the attribute may become public, and have the leading
|
||||||
|
underscore removed, in a Python 3.8, but that is not confirmed yet).
|
||||||
|
2. In the absence of ``sys._base_executable`` (only the case for Python 3.7.2)
|
||||||
|
we check for the existence of the environment variable
|
||||||
|
``__PYVENV_LAUNCHER__``. This is used by the redirector, and if it is
|
||||||
|
present, we know that we are in a stdlib-style virtual environment and need
|
||||||
|
to locate the base Python. In most cases, the base environment is located
|
||||||
|
at ``sys.base_prefix`` - however, in the case where the user creates a
|
||||||
|
virtualenv, and then creates a venv from that virtualenv,
|
||||||
|
``sys.base_prefix`` is not correct - in that case, though, we have
|
||||||
|
``sys.real_prefix`` (set by virtualenv) which *is* correct.
|
||||||
|
|
||||||
|
There is one further complication - as noted above, the environment variable
|
||||||
|
``__PYVENV_LAUNCHER__`` affects how the interpreter works, so before we
|
||||||
|
re-invoke the virtualenv script, we remove this from the environment.
|
||||||
|
@ -9,7 +9,7 @@ Virtualenv has one basic command::
|
|||||||
|
|
||||||
$ virtualenv ENV
|
$ virtualenv ENV
|
||||||
|
|
||||||
Where ``ENV`` is a directory to place the new virtual environment. It has
|
Where ``ENV`` is a directory in which to place the new virtual environment. It has
|
||||||
a number of usual effects (modifiable by many :ref:`options`):
|
a number of usual effects (modifiable by many :ref:`options`):
|
||||||
|
|
||||||
- :file:`ENV/lib/` and :file:`ENV/include/` are created, containing supporting
|
- :file:`ENV/lib/` and :file:`ENV/include/` are created, containing supporting
|
||||||
@ -27,8 +27,8 @@ a number of usual effects (modifiable by many :ref:`options`):
|
|||||||
The python in your new virtualenv is effectively isolated from the python that
|
The python in your new virtualenv is effectively isolated from the python that
|
||||||
was used to create it.
|
was used to create it.
|
||||||
|
|
||||||
.. _pip: https://pypi.python.org/pypi/pip
|
.. _pip: https://pypi.org/project/pip
|
||||||
.. _setuptools: https://pypi.python.org/pypi/setuptools
|
.. _setuptools: https://pypi.org/project/setuptools
|
||||||
|
|
||||||
|
|
||||||
.. _activate:
|
.. _activate:
|
||||||
@ -40,9 +40,9 @@ In a newly created virtualenv there will also be a :command:`activate` shell
|
|||||||
script. For Windows systems, activation scripts are provided for
|
script. For Windows systems, activation scripts are provided for
|
||||||
the Command Prompt and Powershell.
|
the Command Prompt and Powershell.
|
||||||
|
|
||||||
On Posix systems, this resides in :file:`/ENV/bin/`, so you can run::
|
On Posix systems, this resides in :file:`ENV/bin/`, so you can run::
|
||||||
|
|
||||||
$ source bin/activate
|
$ source /path/to/ENV/bin/activate
|
||||||
|
|
||||||
For some shells (e.g. the original Bourne Shell) you may need to use the
|
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
|
:command:`.` command, when :command:`source` does not exist. There are also
|
||||||
@ -52,10 +52,20 @@ separate activate files for some other shells, like csh and fish.
|
|||||||
This will change your ``$PATH`` so its first entry is the virtualenv's
|
This will change your ``$PATH`` so its first entry is the virtualenv's
|
||||||
``bin/`` directory. (You have to use ``source`` because it changes your
|
``bin/`` directory. (You have to use ``source`` because it changes your
|
||||||
shell environment in-place.) This is all it does; it's purely a
|
shell environment in-place.) This is all it does; it's purely a
|
||||||
convenience. If you directly run a script or the python interpreter
|
convenience.
|
||||||
|
|
||||||
|
If you directly run a script or the python interpreter
|
||||||
from the virtualenv's ``bin/`` directory (e.g. ``path/to/ENV/bin/pip``
|
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
|
or ``/path/to/ENV/bin/python-script.py``) then ``sys.path`` will
|
||||||
activation.
|
automatically be set to use the Python libraries associated with the
|
||||||
|
virtualenv. But, unlike the activation scripts, the environment variables
|
||||||
|
``PATH`` and ``VIRTUAL_ENV`` will *not* be modified. This means that if
|
||||||
|
your Python script uses e.g. ``subprocess`` to run another Python script
|
||||||
|
(e.g. via a ``#!/usr/bin/env python`` shebang line) the second script
|
||||||
|
*may not be executed with the same Python binary as the first* nor have
|
||||||
|
the same libraries available to it. To avoid this happening your first
|
||||||
|
script will need to modify the environment variables in the same manner
|
||||||
|
as the activation scripts, before the second script is executed.
|
||||||
|
|
||||||
The ``activate`` script will also modify your shell prompt to indicate
|
The ``activate`` script will also modify your shell prompt to indicate
|
||||||
which environment is currently active. To disable this behaviour, see
|
which environment is currently active. To disable this behaviour, see
|
||||||
@ -65,7 +75,7 @@ To undo these changes to your path (and prompt), just run::
|
|||||||
|
|
||||||
$ deactivate
|
$ deactivate
|
||||||
|
|
||||||
On Windows, the equivalent `activate` script is in the ``Scripts`` folder::
|
On Windows, the equivalent ``activate`` script is in the ``Scripts`` folder::
|
||||||
|
|
||||||
> \path\to\env\Scripts\activate
|
> \path\to\env\Scripts\activate
|
||||||
|
|
||||||
@ -80,7 +90,7 @@ below.
|
|||||||
|
|
||||||
If using Powershell, the ``activate`` script is subject to the
|
If using Powershell, the ``activate`` script is subject to the
|
||||||
`execution policies`_ on the system. By default on Windows 7, the system's
|
`execution policies`_ on the system. By default on Windows 7, the system's
|
||||||
excution policy is set to ``Restricted``, meaning no scripts like the
|
execution policy is set to ``Restricted``, meaning no scripts like the
|
||||||
``activate`` script are allowed to be executed. But that can't stop us
|
``activate`` script are allowed to be executed. But that can't stop us
|
||||||
from changing that slightly to allow it to be executed.
|
from changing that slightly to allow it to be executed.
|
||||||
|
|
||||||
@ -125,6 +135,15 @@ below.
|
|||||||
Since the ``activate.ps1`` script is generated locally for each virtualenv,
|
Since the ``activate.ps1`` script is generated locally for each virtualenv,
|
||||||
it is not considered a remote script and can then be executed.
|
it is not considered a remote script and can then be executed.
|
||||||
|
|
||||||
|
On xonsh, the equivalent ``activate`` script is called ``activate.xsh``, and
|
||||||
|
lives in either the ``bin/`` directory (on posix systems) or the ``Scripts\``
|
||||||
|
directory (on Windows). For example::
|
||||||
|
|
||||||
|
$ source /path/to/ENV/bin/activate.xsh
|
||||||
|
|
||||||
|
With xonsh, you may still run the ``deactivate`` command to undo the changes.
|
||||||
|
|
||||||
|
|
||||||
.. _`execution policies`: http://technet.microsoft.com/en-us/library/dd347641.aspx
|
.. _`execution policies`: http://technet.microsoft.com/en-us/library/dd347641.aspx
|
||||||
|
|
||||||
Removing an Environment
|
Removing an Environment
|
||||||
@ -147,6 +166,10 @@ 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
|
and you want to depend on the packages there. If you want isolation from the
|
||||||
global system, do not use this flag.
|
global system, do not use this flag.
|
||||||
|
|
||||||
|
If you need to change this option after creating a virtual environment, you can
|
||||||
|
add (to turn off) or remove (to turn on) the file ``no-global-site-packages.txt``
|
||||||
|
from ``lib/python3.7/`` or equivalent in the environments directory.
|
||||||
|
|
||||||
Windows Notes
|
Windows Notes
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -155,7 +178,7 @@ executables on Windows go in ``ENV\Scripts\`` instead of ``ENV/bin/`` and
|
|||||||
libraries go in ``ENV\Lib\`` rather than ``ENV/lib/``.
|
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
|
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.
|
the `win32api <https://github.com/mhammond/pywin32/>`_ library installed.
|
||||||
|
|
||||||
|
|
||||||
Using Virtualenv without ``bin/python``
|
Using Virtualenv without ``bin/python``
|
||||||
@ -172,7 +195,7 @@ the path is correct. A script is available to correct the path. You
|
|||||||
can setup the environment like::
|
can setup the environment like::
|
||||||
|
|
||||||
activate_this = '/path/to/env/bin/activate_this.py'
|
activate_this = '/path/to/env/bin/activate_this.py'
|
||||||
execfile(activate_this, dict(__file__=activate_this))
|
exec(open(activate_this).read(), {'__file__': activate_this})
|
||||||
|
|
||||||
This will change ``sys.path`` and even change ``sys.prefix``, but also allow
|
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
|
you to use an existing interpreter. Items in your environment will show up
|
||||||
@ -255,4 +278,3 @@ As well as the extra directories, the search order includes:
|
|||||||
#. The ``virtualenv_support`` directory relative to virtualenv.py
|
#. The ``virtualenv_support`` directory relative to virtualenv.py
|
||||||
#. The directory where virtualenv.py is located.
|
#. The directory where virtualenv.py is located.
|
||||||
#. The current directory.
|
#. The current directory.
|
||||||
|
|
||||||
|
51
python/virtualenv/pyproject.toml
Normal file
51
python/virtualenv/pyproject.toml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = [
|
||||||
|
"setuptools >= 40.6.3",
|
||||||
|
"wheel >= 0.29.0",
|
||||||
|
]
|
||||||
|
build-backend = 'setuptools.build_meta'
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.towncrier]
|
||||||
|
package = "virtualenv"
|
||||||
|
filename = "docs/changes.rst"
|
||||||
|
directory = "docs/changelog"
|
||||||
|
template = "docs/changelog/template.jinja2"
|
||||||
|
title_format = "v{version} ({project_date})"
|
||||||
|
issue_format = "`#{issue} <https://github.com/pypa/virtualenv/issues/{issue}>`_"
|
||||||
|
underlines = ["-", "^"]
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
path = ""
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "bugfix"
|
||||||
|
name = "Bugfixes"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "feature"
|
||||||
|
name = "Features"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "deprecation"
|
||||||
|
name = "Deprecations (removal in next major release)"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "breaking"
|
||||||
|
name = "Backward incompatible changes"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "doc"
|
||||||
|
name = "Documentation"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "misc"
|
||||||
|
name = "Miscellaneous"
|
||||||
|
showcontent = true
|
8
python/virtualenv/readthedocs.yml
Normal file
8
python/virtualenv/readthedocs.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
build:
|
||||||
|
image: latest
|
||||||
|
python:
|
||||||
|
version: 3.6
|
||||||
|
pip_install: true
|
||||||
|
extra_requirements:
|
||||||
|
- docs
|
||||||
|
formats: []
|
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import virtualenv
|
|
||||||
virtualenv.main()
|
|
@ -1,7 +1,81 @@
|
|||||||
|
[metadata]
|
||||||
|
name = virtualenv
|
||||||
|
description = Virtual Python Environment builder
|
||||||
|
long_description = file: README.rst
|
||||||
|
keywords = virtual, environments, isolated
|
||||||
|
maintainer = Bernat Gabor
|
||||||
|
author = Ian Bicking
|
||||||
|
maintainer-email = gaborjbernat@gmail.com
|
||||||
|
author-email = ianb@colorstudy.com
|
||||||
|
url = https://virtualenv.pypa.io/
|
||||||
|
project_urls =
|
||||||
|
Source=https://github.com/pypa/virtualenv
|
||||||
|
Tracker=https://github.com/pypa/virtualenv/issues
|
||||||
|
classifiers = Development Status :: 5 - Production/Stable
|
||||||
|
Intended Audience :: Developers
|
||||||
|
License :: OSI Approved :: MIT License
|
||||||
|
Operating System :: POSIX
|
||||||
|
Operating System :: Microsoft :: Windows
|
||||||
|
Operating System :: MacOS :: MacOS X
|
||||||
|
Topic :: Software Development :: Testing
|
||||||
|
Topic :: Software Development :: Libraries
|
||||||
|
Topic :: Utilities
|
||||||
|
Programming Language :: Python :: 2
|
||||||
|
Programming Language :: Python :: 2.7
|
||||||
|
Programming Language :: Python :: 3
|
||||||
|
Programming Language :: Python :: 3.4
|
||||||
|
Programming Language :: Python :: 3.5
|
||||||
|
Programming Language :: Python :: 3.6
|
||||||
|
Programming Language :: Python :: 3.7
|
||||||
|
platforms = any
|
||||||
|
license = MIT
|
||||||
|
license_file = LICENSE.txt
|
||||||
|
|
||||||
|
[options]
|
||||||
|
packages = find:
|
||||||
|
include_package_data = True
|
||||||
|
zip_safe = True
|
||||||
|
python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
||||||
|
|
||||||
|
[options.extras_require]
|
||||||
|
testing = mock;python_version<"3.3"
|
||||||
|
pytest >= 4.0.0, <5
|
||||||
|
coverage >= 4.5.0, <5
|
||||||
|
pytest-timeout >= 1.3.0, <2
|
||||||
|
xonsh; python_version>="3.5"
|
||||||
|
six >= 1.10.0, < 2
|
||||||
|
pytest-xdist
|
||||||
|
pytest-localserver
|
||||||
|
pypiserver
|
||||||
|
docs = sphinx >= 1.8.0, < 2
|
||||||
|
towncrier >= 18.5.0
|
||||||
|
sphinx_rtd_theme >= 0.4.2, < 1
|
||||||
|
|
||||||
|
[options.packages.find]
|
||||||
|
where = .
|
||||||
|
|
||||||
|
[options.package_data]
|
||||||
|
virtualenv_support = *.whl
|
||||||
|
|
||||||
|
[options.entry_points]
|
||||||
|
console_scripts = virtualenv=virtualenv:main
|
||||||
|
|
||||||
|
[sdist]
|
||||||
|
formats = gztar
|
||||||
|
|
||||||
[bdist_wheel]
|
[bdist_wheel]
|
||||||
universal = 1
|
universal = true
|
||||||
|
|
||||||
[egg_info]
|
[coverage:run]
|
||||||
tag_build =
|
branch = false
|
||||||
tag_date = 0
|
parallel = true
|
||||||
|
|
||||||
|
[coverage:report]
|
||||||
|
skip_covered = True
|
||||||
|
show_missing = True
|
||||||
|
|
||||||
|
[coverage:paths]
|
||||||
|
source = .
|
||||||
|
.tox/*/*/site-packages
|
||||||
|
.tox/*/*/*/site-packages
|
||||||
|
*/s
|
||||||
|
@ -1,123 +1,16 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
|
||||||
import sys
|
|
||||||
|
|
||||||
if sys.version_info[:2] < (2, 6):
|
from setuptools import setup
|
||||||
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():
|
def get_version():
|
||||||
version_file = read_file('virtualenv.py')
|
with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "virtualenv.py")) as file_handler:
|
||||||
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
|
version_file = file_handler.read()
|
||||||
version_file, re.M)
|
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
|
||||||
if version_match:
|
if version_match:
|
||||||
return version_match.group(1)
|
return version_match.group(1)
|
||||||
raise RuntimeError("Unable to find version string.")
|
raise RuntimeError("Unable to find version string.")
|
||||||
|
|
||||||
|
|
||||||
# Hack to prevent stupid TypeError: 'NoneType' object is not callable error on
|
setup(version=get_version(), py_modules=["virtualenv"], setup_requires=["setuptools >= 40.6.3"])
|
||||||
# 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.4',
|
|
||||||
'Programming Language :: Python :: 3.5',
|
|
||||||
'Programming Language :: Python :: 3.6',
|
|
||||||
],
|
|
||||||
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)
|
|
||||||
|
37
python/virtualenv/tasks/make_zipapp.py
Normal file
37
python/virtualenv/tasks/make_zipapp.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
"""https://docs.python.org/3/library/zipapp.html"""
|
||||||
|
import argparse
|
||||||
|
import io
|
||||||
|
import os.path
|
||||||
|
import zipapp
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--root", default=".")
|
||||||
|
parser.add_argument("--dest")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.dest is not None:
|
||||||
|
dest = args.dest
|
||||||
|
else:
|
||||||
|
dest = os.path.join(args.root, "virtualenv.pyz")
|
||||||
|
|
||||||
|
bio = io.BytesIO()
|
||||||
|
with zipfile.ZipFile(bio, "w") as zipf:
|
||||||
|
filenames = ["LICENSE.txt", "virtualenv.py"]
|
||||||
|
for whl in os.listdir(os.path.join(args.root, "virtualenv_support")):
|
||||||
|
filenames.append(os.path.join("virtualenv_support", whl))
|
||||||
|
|
||||||
|
for filename in filenames:
|
||||||
|
zipf.write(os.path.join(args.root, filename), filename)
|
||||||
|
|
||||||
|
zipf.writestr("__main__.py", "import virtualenv; virtualenv.main()")
|
||||||
|
|
||||||
|
bio.seek(0)
|
||||||
|
zipapp.create_archive(bio, dest)
|
||||||
|
print("zipapp created at {}".format(dest))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
exit(main())
|
76
python/virtualenv/tasks/release.py
Normal file
76
python/virtualenv/tasks/release.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Handles creating a release PR"""
|
||||||
|
from pathlib import Path
|
||||||
|
from subprocess import check_call
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
from git import Commit, Head, Remote, Repo, TagReference
|
||||||
|
from packaging.version import Version
|
||||||
|
|
||||||
|
ROOT_SRC_DIR = Path(__file__).resolve().parents[1]
|
||||||
|
|
||||||
|
|
||||||
|
def main(version_str: str) -> None:
|
||||||
|
version = Version(version_str)
|
||||||
|
repo = Repo(str(ROOT_SRC_DIR))
|
||||||
|
|
||||||
|
if repo.is_dirty():
|
||||||
|
raise RuntimeError("Current repository is dirty. Please commit any changes and try again.")
|
||||||
|
upstream, release_branch = create_release_branch(repo, version)
|
||||||
|
release_commit = release_changelog(repo, version)
|
||||||
|
tag = tag_release_commit(release_commit, repo, version)
|
||||||
|
print("push release commit")
|
||||||
|
repo.git.push(upstream.name, release_branch)
|
||||||
|
print("push release tag")
|
||||||
|
repo.git.push(upstream.name, tag)
|
||||||
|
print("All done! ✨ 🍰 ✨")
|
||||||
|
|
||||||
|
|
||||||
|
def create_release_branch(repo: Repo, version: Version) -> Tuple[Remote, Head]:
|
||||||
|
print("create release branch from upstream legacy")
|
||||||
|
upstream = get_upstream(repo)
|
||||||
|
upstream.fetch()
|
||||||
|
branch_name = f"release-{version}"
|
||||||
|
release_branch = repo.create_head(branch_name, upstream.refs.legacy, force=True)
|
||||||
|
upstream.push(refspec=f"{branch_name}:{branch_name}", force=True)
|
||||||
|
release_branch.set_tracking_branch(repo.refs[f"{upstream.name}/{branch_name}"])
|
||||||
|
release_branch.checkout()
|
||||||
|
return upstream, release_branch
|
||||||
|
|
||||||
|
|
||||||
|
def get_upstream(repo: Repo) -> Remote:
|
||||||
|
upstream_remote = "pypa/virtualenv.git"
|
||||||
|
urls = set()
|
||||||
|
for remote in repo.remotes:
|
||||||
|
for url in remote.urls:
|
||||||
|
if url.endswith(upstream_remote):
|
||||||
|
return remote
|
||||||
|
urls.add(url)
|
||||||
|
raise RuntimeError(f"could not find {upstream_remote} remote, has {urls}")
|
||||||
|
|
||||||
|
|
||||||
|
def release_changelog(repo: Repo, version: Version) -> Commit:
|
||||||
|
print("generate release commit")
|
||||||
|
check_call(["towncrier", "--yes", "--version", version.public], cwd=str(ROOT_SRC_DIR))
|
||||||
|
release_commit = repo.index.commit(f"release {version}")
|
||||||
|
return release_commit
|
||||||
|
|
||||||
|
|
||||||
|
def tag_release_commit(release_commit, repo, version) -> TagReference:
|
||||||
|
print("tag release commit")
|
||||||
|
existing_tags = [x.name for x in repo.tags]
|
||||||
|
if version in existing_tags:
|
||||||
|
print("delete existing tag {}".format(version))
|
||||||
|
repo.delete_tag(version)
|
||||||
|
print("create tag {}".format(version))
|
||||||
|
tag = repo.create_tag(version, ref=release_commit, force=True)
|
||||||
|
return tag
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(prog="release")
|
||||||
|
parser.add_argument("--version", required=True)
|
||||||
|
options = parser.parse_args()
|
||||||
|
main(options.version)
|
89
python/virtualenv/tasks/update_embedded.py
Executable file
89
python/virtualenv/tasks/update_embedded.py
Executable file
@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
Helper script to rebuild virtualenv.py from virtualenv_support
|
||||||
|
"""
|
||||||
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
|
import codecs
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from zlib import crc32 as _crc32
|
||||||
|
|
||||||
|
if sys.version_info < (3,):
|
||||||
|
print("requires Python 3 (use tox from Python 3 if invoked via tox)")
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def crc32(data):
|
||||||
|
"""Python version idempotent"""
|
||||||
|
return _crc32(data.encode()) & 0xFFFFFFFF
|
||||||
|
|
||||||
|
|
||||||
|
here = os.path.realpath(os.path.dirname(__file__))
|
||||||
|
script = os.path.realpath(os.path.join(here, "..", "virtualenv.py"))
|
||||||
|
|
||||||
|
gzip = codecs.lookup("zlib")
|
||||||
|
b64 = codecs.lookup("base64")
|
||||||
|
|
||||||
|
file_regex = re.compile(r'# file (.*?)\n([a-zA-Z][a-zA-Z0-9_]+) = convert\(\n """\n(.*?)"""\n\)', re.S)
|
||||||
|
file_template = '# file {filename}\n{variable} = convert(\n """\n{data}"""\n)'
|
||||||
|
|
||||||
|
|
||||||
|
def rebuild(script_path):
|
||||||
|
with open(script_path, "rt") as current_fh:
|
||||||
|
script_content = current_fh.read()
|
||||||
|
script_parts = []
|
||||||
|
match_end = 0
|
||||||
|
next_match = None
|
||||||
|
_count, did_update = 0, False
|
||||||
|
for _count, next_match in enumerate(file_regex.finditer(script_content)):
|
||||||
|
script_parts += [script_content[match_end : next_match.start()]]
|
||||||
|
match_end = next_match.end()
|
||||||
|
filename, variable_name, previous_encoded = next_match.group(1), next_match.group(2), next_match.group(3)
|
||||||
|
differ, content = handle_file(next_match.group(0), filename, variable_name, previous_encoded)
|
||||||
|
script_parts.append(content)
|
||||||
|
if differ:
|
||||||
|
did_update = True
|
||||||
|
|
||||||
|
script_parts += [script_content[match_end:]]
|
||||||
|
new_content = "".join(script_parts)
|
||||||
|
|
||||||
|
report(1 if not _count or did_update else 0, new_content, next_match, script_content, script_path)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_file(previous_content, filename, variable_name, previous_encoded):
|
||||||
|
print("Found file {}".format(filename))
|
||||||
|
current_path = os.path.realpath(os.path.join(here, "..", "virtualenv_embedded", filename))
|
||||||
|
_, file_type = os.path.splitext(current_path)
|
||||||
|
keep_line_ending = file_type in (".bat",)
|
||||||
|
with open(current_path, "rt", encoding="utf-8", newline="" if keep_line_ending else None) as current_fh:
|
||||||
|
current_text = current_fh.read()
|
||||||
|
current_crc = crc32(current_text)
|
||||||
|
current_encoded = b64.encode(gzip.encode(current_text.encode())[0])[0].decode()
|
||||||
|
if current_encoded == previous_encoded:
|
||||||
|
print(" File up to date (crc: {:08x})".format(current_crc))
|
||||||
|
return False, previous_content
|
||||||
|
# Else: content has changed
|
||||||
|
previous_text = gzip.decode(b64.decode(previous_encoded.encode())[0])[0].decode()
|
||||||
|
previous_crc = crc32(previous_text)
|
||||||
|
print(" Content changed (crc: {:08x} -> {:08x})".format(previous_crc, current_crc))
|
||||||
|
new_part = file_template.format(filename=filename, variable=variable_name, data=current_encoded)
|
||||||
|
return True, new_part
|
||||||
|
|
||||||
|
|
||||||
|
def report(exit_code, new, next_match, current, script_path):
|
||||||
|
if new != current:
|
||||||
|
print("Content updated; overwriting... ", end="")
|
||||||
|
with open(script_path, "wt") as current_fh:
|
||||||
|
current_fh.write(new)
|
||||||
|
print("done.")
|
||||||
|
else:
|
||||||
|
print("No changes in content")
|
||||||
|
if next_match is None:
|
||||||
|
print("No variables were matched/found")
|
||||||
|
raise SystemExit(exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
rebuild(script)
|
48
python/virtualenv/tasks/upgrade_wheels.py
Normal file
48
python/virtualenv/tasks/upgrade_wheels.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
"""
|
||||||
|
Helper script to rebuild virtualenv_support. Downloads the wheel files using pip
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def virtualenv_support_path():
|
||||||
|
return os.path.join(os.path.dirname(__file__), "..", "virtualenv_support")
|
||||||
|
|
||||||
|
|
||||||
|
def collect_wheels():
|
||||||
|
for filename in glob.glob(os.path.join(virtualenv_support_path(), "*.whl")):
|
||||||
|
name, version = os.path.basename(filename).split("-")[:2]
|
||||||
|
yield filename, name, version
|
||||||
|
|
||||||
|
|
||||||
|
def remove_wheel_files():
|
||||||
|
old_versions = {}
|
||||||
|
for filename, name, version in collect_wheels():
|
||||||
|
old_versions[name] = version
|
||||||
|
os.remove(filename)
|
||||||
|
return old_versions
|
||||||
|
|
||||||
|
|
||||||
|
def download(package):
|
||||||
|
subprocess.call(["pip", "download", "-d", virtualenv_support_path(), package])
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
old = remove_wheel_files()
|
||||||
|
for package in ("pip", "wheel", "setuptools"):
|
||||||
|
download(package)
|
||||||
|
new = {name: version for _, name, version in collect_wheels()}
|
||||||
|
|
||||||
|
changes = []
|
||||||
|
for package, version in old.items():
|
||||||
|
if new[package] != version:
|
||||||
|
changes.append((package, version, new[package]))
|
||||||
|
|
||||||
|
print("\n".join(" * upgrade {} from {} to {}".format(p, o, n) for p, o, n in changes))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run()
|
104
python/virtualenv/tests/activation/test_activate_this.py
Normal file
104
python/virtualenv/tests/activation/test_activate_this.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
"""Activate this does not mangles with the shell itself to provision the python, but instead mangles
|
||||||
|
with the caller interpreter, effectively making so that the virtualenv activation constraints are met once
|
||||||
|
it's loaded.
|
||||||
|
|
||||||
|
While initially may feel like a import is all we need, import is executed only once not at every activation. To
|
||||||
|
work around this we'll use Python 2 execfile, and Python 3 exec(read()).
|
||||||
|
|
||||||
|
Virtual env activation constraints that we guarantee:
|
||||||
|
- the virtualenv site-package will be visible from the activator Python
|
||||||
|
- virtualenv packages take priority over python 2
|
||||||
|
- virtualenv bin PATH pre-pended
|
||||||
|
- VIRTUAL_ENV env var will be set.
|
||||||
|
- if the user tries to import we'll raise
|
||||||
|
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
|
||||||
|
def test_activate_this(clean_python, tmp_path, monkeypatch):
|
||||||
|
# to test this, we'll try to use the activation env from this Python
|
||||||
|
monkeypatch.delenv(str("VIRTUAL_ENV"), raising=False)
|
||||||
|
monkeypatch.delenv(str("PYTHONPATH"), raising=False)
|
||||||
|
paths = [str(tmp_path), str(tmp_path / "other")]
|
||||||
|
start_path = os.pathsep.join(paths)
|
||||||
|
monkeypatch.setenv(str("PATH"), start_path)
|
||||||
|
activator = tmp_path.__class__(clean_python[1]) / "activate_this.py"
|
||||||
|
assert activator.exists()
|
||||||
|
|
||||||
|
activator_at = str(activator)
|
||||||
|
script = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
print(os.environ.get("VIRTUAL_ENV"))
|
||||||
|
print(os.environ.get("PATH"))
|
||||||
|
try:
|
||||||
|
import pydoc_test
|
||||||
|
raise RuntimeError("this should not happen")
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
print(os.pathsep.join(sys.path))
|
||||||
|
file_at = {!r}
|
||||||
|
exec(open(file_at).read(), {{'__file__': file_at}})
|
||||||
|
print(os.environ.get("VIRTUAL_ENV"))
|
||||||
|
print(os.environ.get("PATH"))
|
||||||
|
print(os.pathsep.join(sys.path))
|
||||||
|
import pydoc_test
|
||||||
|
print(pydoc_test.__file__)
|
||||||
|
""".format(
|
||||||
|
str(activator_at)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
script_path = tmp_path / "test.py"
|
||||||
|
script_path.write_text(script)
|
||||||
|
try:
|
||||||
|
raw = subprocess.check_output(
|
||||||
|
[sys.executable, str(script_path)], stderr=subprocess.STDOUT, universal_newlines=True
|
||||||
|
)
|
||||||
|
|
||||||
|
out = re.sub(r"pydev debugger: process \d+ is connecting\n\n", "", raw, re.M).strip().split("\n")
|
||||||
|
|
||||||
|
assert out[0] == "None"
|
||||||
|
assert out[1] == start_path
|
||||||
|
prev_sys_path = out[2].split(os.path.pathsep)
|
||||||
|
|
||||||
|
assert out[3] == clean_python[0] # virtualenv set as the activated env
|
||||||
|
|
||||||
|
# PATH updated with activated
|
||||||
|
assert out[4].endswith(start_path)
|
||||||
|
assert out[4][: -len(start_path)].split(os.pathsep) == [clean_python[1], ""]
|
||||||
|
|
||||||
|
# sys path contains the site package at its start
|
||||||
|
new_sys_path = out[5].split(os.path.pathsep)
|
||||||
|
assert new_sys_path[-len(prev_sys_path) :] == prev_sys_path
|
||||||
|
extra_start = new_sys_path[0 : -len(prev_sys_path)]
|
||||||
|
assert len(extra_start) == 1
|
||||||
|
assert extra_start[0].startswith(clean_python[0])
|
||||||
|
assert tmp_path.__class__(extra_start[0]).exists()
|
||||||
|
|
||||||
|
# manage to import from activate site package
|
||||||
|
assert os.path.realpath(out[6]) == os.path.realpath(str(clean_python[2]))
|
||||||
|
except subprocess.CalledProcessError as exception:
|
||||||
|
assert not exception.returncode, exception.output
|
||||||
|
|
||||||
|
|
||||||
|
def test_activate_this_no_file(clean_python, tmp_path, monkeypatch):
|
||||||
|
activator = tmp_path.__class__(clean_python[1]) / "activate_this.py"
|
||||||
|
assert activator.exists()
|
||||||
|
try:
|
||||||
|
subprocess.check_output(
|
||||||
|
[sys.executable, "-c", "exec(open({!r}).read())".format(str(activator))],
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
universal_newlines=True,
|
||||||
|
)
|
||||||
|
raise RuntimeError("this should not happen")
|
||||||
|
except subprocess.CalledProcessError as exception:
|
||||||
|
out = re.sub(r"pydev debugger: process \d+ is connecting\n\n", "", exception.output, re.M).strip()
|
||||||
|
assert "You must use exec(open(this_file).read(), {'__file__': this_file}))" in out, out
|
236
python/virtualenv/tests/activation/test_activation.py
Normal file
236
python/virtualenv/tests/activation/test_activation.py
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pipes
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from os.path import dirname, join, normcase, realpath
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import six
|
||||||
|
|
||||||
|
import virtualenv
|
||||||
|
|
||||||
|
IS_INSIDE_CI = "CI_RUN" in os.environ
|
||||||
|
|
||||||
|
|
||||||
|
def need_executable(name, check_cmd):
|
||||||
|
"""skip running this locally if executable not found, unless we're inside the CI"""
|
||||||
|
|
||||||
|
def wrapper(fn):
|
||||||
|
fn = getattr(pytest.mark, name)(fn)
|
||||||
|
if not IS_INSIDE_CI:
|
||||||
|
# locally we disable, so that contributors don't need to have everything setup
|
||||||
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
fn.version = subprocess.check_output(check_cmd, env=get_env())
|
||||||
|
except Exception as exception:
|
||||||
|
return pytest.mark.skip(reason="{} is not available due {}".format(name, exception))(fn)
|
||||||
|
return fn
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def requires(on):
|
||||||
|
def wrapper(fn):
|
||||||
|
return need_executable(on.cmd.replace(".exe", ""), on.check)(fn)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def norm_path(path):
|
||||||
|
# python may return Windows short paths, normalize
|
||||||
|
path = realpath(path)
|
||||||
|
if virtualenv.IS_WIN:
|
||||||
|
from ctypes import create_unicode_buffer, windll
|
||||||
|
|
||||||
|
buffer_cont = create_unicode_buffer(256)
|
||||||
|
get_long_path_name = windll.kernel32.GetLongPathNameW
|
||||||
|
get_long_path_name(six.text_type(path), buffer_cont, 256) # noqa: F821
|
||||||
|
result = buffer_cont.value
|
||||||
|
else:
|
||||||
|
result = path
|
||||||
|
return normcase(result)
|
||||||
|
|
||||||
|
|
||||||
|
class Activation(object):
|
||||||
|
cmd = ""
|
||||||
|
extension = "test"
|
||||||
|
invoke_script = []
|
||||||
|
command_separator = os.linesep
|
||||||
|
activate_cmd = "source"
|
||||||
|
activate_script = ""
|
||||||
|
check_has_exe = []
|
||||||
|
check = []
|
||||||
|
env = {}
|
||||||
|
also_test_error_if_not_sourced = False
|
||||||
|
|
||||||
|
def __init__(self, activation_env, tmp_path):
|
||||||
|
self.home_dir = activation_env[0]
|
||||||
|
self.bin_dir = activation_env[1]
|
||||||
|
self.path = tmp_path
|
||||||
|
|
||||||
|
def quote(self, s):
|
||||||
|
return pipes.quote(s)
|
||||||
|
|
||||||
|
def python_cmd(self, cmd):
|
||||||
|
return "{} -c {}".format(self.quote(virtualenv.EXPECTED_EXE), self.quote(cmd))
|
||||||
|
|
||||||
|
def python_script(self, script):
|
||||||
|
return "{} {}".format(self.quote(virtualenv.EXPECTED_EXE), self.quote(script))
|
||||||
|
|
||||||
|
def print_python_exe(self):
|
||||||
|
return self.python_cmd("import sys; print(sys.executable)")
|
||||||
|
|
||||||
|
def print_os_env_var(self, var):
|
||||||
|
val = '"{}"'.format(var)
|
||||||
|
return self.python_cmd("import os; print(os.environ.get({}, None))".format(val))
|
||||||
|
|
||||||
|
def __call__(self, monkeypatch):
|
||||||
|
absolute_activate_script = norm_path(join(self.bin_dir, self.activate_script))
|
||||||
|
|
||||||
|
commands = [
|
||||||
|
self.print_python_exe(),
|
||||||
|
self.print_os_env_var("VIRTUAL_ENV"),
|
||||||
|
self.activate_call(absolute_activate_script),
|
||||||
|
self.print_python_exe(),
|
||||||
|
self.print_os_env_var("VIRTUAL_ENV"),
|
||||||
|
# pydoc loads documentation from the virtualenv site packages
|
||||||
|
"pydoc -w pydoc_test",
|
||||||
|
"deactivate",
|
||||||
|
self.print_python_exe(),
|
||||||
|
self.print_os_env_var("VIRTUAL_ENV"),
|
||||||
|
"", # just finish with an empty new line
|
||||||
|
]
|
||||||
|
script = self.command_separator.join(commands)
|
||||||
|
test_script = self.path / "script.{}".format(self.extension)
|
||||||
|
test_script.write_text(script)
|
||||||
|
assert test_script.exists()
|
||||||
|
|
||||||
|
monkeypatch.chdir(str(self.path))
|
||||||
|
invoke_shell = self.invoke_script + [str(test_script)]
|
||||||
|
|
||||||
|
monkeypatch.delenv(str("VIRTUAL_ENV"), raising=False)
|
||||||
|
|
||||||
|
# in case the tool is provided by the dev environment (e.g. xonosh)
|
||||||
|
env = get_env()
|
||||||
|
env.update(self.env)
|
||||||
|
|
||||||
|
try:
|
||||||
|
raw = subprocess.check_output(invoke_shell, universal_newlines=True, stderr=subprocess.STDOUT, env=env)
|
||||||
|
except subprocess.CalledProcessError as exception:
|
||||||
|
assert not exception.returncode, exception.output
|
||||||
|
out = re.sub(r"pydev debugger: process \d+ is connecting\n\n", "", raw, re.M).strip().split("\n")
|
||||||
|
|
||||||
|
# pre-activation
|
||||||
|
assert out[0], raw
|
||||||
|
assert out[1] == "None", raw
|
||||||
|
|
||||||
|
# post-activation
|
||||||
|
exe = "{}.exe".format(virtualenv.EXPECTED_EXE) if virtualenv.IS_WIN else virtualenv.EXPECTED_EXE
|
||||||
|
assert norm_path(out[2]) == norm_path(join(self.bin_dir, exe)), raw
|
||||||
|
assert norm_path(out[3]) == norm_path(str(self.home_dir)).replace("\\\\", "\\"), raw
|
||||||
|
|
||||||
|
assert out[4] == "wrote pydoc_test.html"
|
||||||
|
content = self.path / "pydoc_test.html"
|
||||||
|
assert content.exists(), raw
|
||||||
|
|
||||||
|
# post deactivation, same as before
|
||||||
|
assert out[-2] == out[0], raw
|
||||||
|
assert out[-1] == "None", raw
|
||||||
|
|
||||||
|
if self.also_test_error_if_not_sourced:
|
||||||
|
invoke_shell = self.invoke_script + [absolute_activate_script]
|
||||||
|
|
||||||
|
with pytest.raises(subprocess.CalledProcessError) as c:
|
||||||
|
subprocess.check_output(invoke_shell, stderr=subprocess.STDOUT, env=env)
|
||||||
|
assert c.value.returncode, c
|
||||||
|
|
||||||
|
def activate_call(self, script):
|
||||||
|
return "{} {}".format(pipes.quote(self.activate_cmd), pipes.quote(script)).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def get_env():
|
||||||
|
env = os.environ.copy()
|
||||||
|
env[str("PATH")] = os.pathsep.join([dirname(sys.executable)] + env.get(str("PATH"), str("")).split(os.pathsep))
|
||||||
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
class BashActivation(Activation):
|
||||||
|
cmd = "bash.exe" if virtualenv.IS_WIN else "bash"
|
||||||
|
invoke_script = [cmd]
|
||||||
|
extension = "sh"
|
||||||
|
activate_script = "activate"
|
||||||
|
check = [cmd, "--version"]
|
||||||
|
also_test_error_if_not_sourced = True
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform == "win32", reason="no sane way to provision bash on Windows yet")
|
||||||
|
@requires(BashActivation)
|
||||||
|
def test_bash(clean_python, monkeypatch, tmp_path):
|
||||||
|
BashActivation(clean_python, tmp_path)(monkeypatch)
|
||||||
|
|
||||||
|
|
||||||
|
class CshActivation(Activation):
|
||||||
|
cmd = "csh.exe" if virtualenv.IS_WIN else "csh"
|
||||||
|
invoke_script = [cmd]
|
||||||
|
extension = "csh"
|
||||||
|
activate_script = "activate.csh"
|
||||||
|
check = [cmd, "--version"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform == "win32", reason="no sane way to provision csh on Windows yet")
|
||||||
|
@requires(CshActivation)
|
||||||
|
def test_csh(clean_python, monkeypatch, tmp_path):
|
||||||
|
CshActivation(clean_python, tmp_path)(monkeypatch)
|
||||||
|
|
||||||
|
|
||||||
|
class FishActivation(Activation):
|
||||||
|
cmd = "fish.exe" if virtualenv.IS_WIN else "fish"
|
||||||
|
invoke_script = [cmd]
|
||||||
|
extension = "fish"
|
||||||
|
activate_script = "activate.fish"
|
||||||
|
check = [cmd, "--version"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform == "win32", reason="no sane way to provision fish on Windows yet")
|
||||||
|
@requires(FishActivation)
|
||||||
|
def test_fish(clean_python, monkeypatch, tmp_path):
|
||||||
|
FishActivation(clean_python, tmp_path)(monkeypatch)
|
||||||
|
|
||||||
|
|
||||||
|
class PowershellActivation(Activation):
|
||||||
|
cmd = "powershell.exe" if virtualenv.IS_WIN else "pwsh"
|
||||||
|
extension = "ps1"
|
||||||
|
invoke_script = [cmd, "-File"]
|
||||||
|
activate_script = "activate.ps1"
|
||||||
|
activate_cmd = "."
|
||||||
|
check = [cmd, "-c", "$PSVersionTable"]
|
||||||
|
|
||||||
|
def quote(self, s):
|
||||||
|
"""powershell double double quote needed for quotes within single quotes"""
|
||||||
|
return pipes.quote(s).replace('"', '""')
|
||||||
|
|
||||||
|
|
||||||
|
@requires(PowershellActivation)
|
||||||
|
def test_powershell(clean_python, monkeypatch, tmp_path):
|
||||||
|
PowershellActivation(clean_python, tmp_path)(monkeypatch)
|
||||||
|
|
||||||
|
|
||||||
|
class XonoshActivation(Activation):
|
||||||
|
cmd = "xonsh"
|
||||||
|
extension = "xsh"
|
||||||
|
invoke_script = [sys.executable, "-m", "xonsh"]
|
||||||
|
activate_script = "activate.xsh"
|
||||||
|
check = [sys.executable, "-m", "xonsh", "--version"]
|
||||||
|
env = {"XONSH_DEBUG": "1", "XONSH_SHOW_TRACEBACK": "True"}
|
||||||
|
|
||||||
|
def activate_call(self, script):
|
||||||
|
return "{} {}".format(self.activate_cmd, repr(script)).strip()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.version_info < (3, 5), reason="xonosh requires Python 3.5 at least")
|
||||||
|
@requires(XonoshActivation)
|
||||||
|
def test_xonosh(clean_python, monkeypatch, tmp_path):
|
||||||
|
XonoshActivation(clean_python, tmp_path)(monkeypatch)
|
440
python/virtualenv/tests/activation/test_prompts.py
Normal file
440
python/virtualenv/tests/activation/test_prompts.py
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
"""test that prompt behavior is correct in supported shells"""
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import virtualenv
|
||||||
|
from virtualenv import IS_DARWIN, IS_WIN
|
||||||
|
|
||||||
|
try:
|
||||||
|
from pathlib import Path
|
||||||
|
except ImportError:
|
||||||
|
from pathlib2 import Path
|
||||||
|
|
||||||
|
VIRTUAL_ENV_DISABLE_PROMPT = "VIRTUAL_ENV_DISABLE_PROMPT"
|
||||||
|
|
||||||
|
# This must match the DEST_DIR provided in the ../conftest.py:clean_python fixture
|
||||||
|
ENV_DEFAULT = "env"
|
||||||
|
|
||||||
|
# This can be anything
|
||||||
|
ENV_CUSTOM = "envy"
|
||||||
|
|
||||||
|
# Standard prefix, surround the env name in parentheses and separate by a space
|
||||||
|
PREFIX_DEFAULT = "({}) ".format(ENV_DEFAULT)
|
||||||
|
|
||||||
|
# Arbitrary prefix for the environment that's provided a 'prompt' arg
|
||||||
|
PREFIX_CUSTOM = "---ENV---"
|
||||||
|
|
||||||
|
# Temp script filename template: {shell}.script.(normal|suppress).(default|custom)[extension]
|
||||||
|
SCRIPT_TEMPLATE = "{}.script.{}.{}{}"
|
||||||
|
|
||||||
|
# Temp output filename template: {shell}.out.(normal|suppress).(default|custom)
|
||||||
|
OUTPUT_TEMPLATE = "{}.out.{}.{}"
|
||||||
|
|
||||||
|
# For skipping shells not installed by default if absent on a contributor's system
|
||||||
|
IS_INSIDE_CI = "CI_RUN" in os.environ
|
||||||
|
|
||||||
|
|
||||||
|
# Py2 doesn't like unicode in the environment
|
||||||
|
def env_compat(string):
|
||||||
|
return string.encode("utf-8") if sys.version_info.major < 3 else string
|
||||||
|
|
||||||
|
|
||||||
|
class ShellInfo(object):
|
||||||
|
"""Parent class for shell information for prompt testing."""
|
||||||
|
|
||||||
|
# Typo insurance
|
||||||
|
__slots__ = []
|
||||||
|
|
||||||
|
# Equality check based on .name, but only if both are not None
|
||||||
|
def __eq__(self, other):
|
||||||
|
if type(self) != type(other):
|
||||||
|
return False
|
||||||
|
if self.name is None or other.name is None:
|
||||||
|
return False
|
||||||
|
return self.name == other.name
|
||||||
|
|
||||||
|
# Helper formatting string
|
||||||
|
@property
|
||||||
|
def platform_incompat_msg(self):
|
||||||
|
return "No sane provision for {} on {{}} yet".format(self.name)
|
||||||
|
|
||||||
|
# Each shell must specify
|
||||||
|
name = None
|
||||||
|
avail_cmd = None
|
||||||
|
execute_cmd = None
|
||||||
|
prompt_cmd = None
|
||||||
|
activate_script = None
|
||||||
|
|
||||||
|
# Default values defined here
|
||||||
|
# 'preamble_cmd' *MUST NOT* emit anything to stdout!
|
||||||
|
testscript_extension = ""
|
||||||
|
preamble_cmd = ""
|
||||||
|
activate_cmd = "source "
|
||||||
|
deactivate_cmd = "deactivate"
|
||||||
|
clean_env_update = {}
|
||||||
|
|
||||||
|
# Skip check function; must be specified per-shell
|
||||||
|
platform_check_skip = None
|
||||||
|
|
||||||
|
# Test assert method for comparing activated prompt to deactivated.
|
||||||
|
# Default defined, but can be overridden per-shell. Takes the captured
|
||||||
|
# lines of output as the lone argument.
|
||||||
|
def overall_prompt_test(self, lines, prefix):
|
||||||
|
"""Perform all tests on (de)activated prompts.
|
||||||
|
|
||||||
|
From a Python 3 perspective, 'lines' is expected to be *bytes*,
|
||||||
|
and 'prefix' is expected to be *str*.
|
||||||
|
|
||||||
|
Happily, this all seems to translate smoothly enough to 2.7.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Prompts before activation and after deactivation should be identical.
|
||||||
|
assert lines[1] == lines[3], lines
|
||||||
|
|
||||||
|
# The .partition here operates on the environment marker text expected to occur
|
||||||
|
# in the prompt. A non-empty 'env_marker' thus tests that the correct marker text
|
||||||
|
# has been applied into the prompt string.
|
||||||
|
before, env_marker, after = lines[2].partition(prefix.encode("utf-8"))
|
||||||
|
assert env_marker != b"", lines
|
||||||
|
|
||||||
|
# Some shells need custom activated-prompt tests, so this is split into
|
||||||
|
# its own submethod.
|
||||||
|
self.activated_prompt_test(lines, after)
|
||||||
|
|
||||||
|
def activated_prompt_test(self, lines, after):
|
||||||
|
"""Perform just the check for the deactivated prompt contents in the activated prompt text.
|
||||||
|
|
||||||
|
The default is a strict requirement that the portion of the activated prompt following the environment
|
||||||
|
marker must exactly match the non-activated prompt.
|
||||||
|
|
||||||
|
Some shells require weaker tests, due to idiosyncrasies.
|
||||||
|
|
||||||
|
"""
|
||||||
|
assert after == lines[1], lines
|
||||||
|
|
||||||
|
|
||||||
|
class BashInfo(ShellInfo):
|
||||||
|
name = "bash"
|
||||||
|
avail_cmd = "bash -c 'echo foo'"
|
||||||
|
execute_cmd = "bash"
|
||||||
|
prompt_cmd = 'echo "$PS1"'
|
||||||
|
activate_script = "activate"
|
||||||
|
|
||||||
|
def platform_check_skip(self):
|
||||||
|
if IS_WIN:
|
||||||
|
return self.platform_incompat_msg.format(sys.platform)
|
||||||
|
|
||||||
|
|
||||||
|
class FishInfo(ShellInfo):
|
||||||
|
name = "fish"
|
||||||
|
avail_cmd = "fish -c 'echo foo'"
|
||||||
|
execute_cmd = "fish"
|
||||||
|
prompt_cmd = "fish_prompt; echo ' '"
|
||||||
|
activate_script = "activate.fish"
|
||||||
|
|
||||||
|
# Azure Devops doesn't set a terminal type, which breaks fish's colorization
|
||||||
|
# machinery in a way that spuriously fouls the activation script.
|
||||||
|
clean_env_update = {"TERM": "linux"}
|
||||||
|
|
||||||
|
def platform_check_skip(self):
|
||||||
|
if IS_WIN:
|
||||||
|
return self.platform_incompat_msg.format(sys.platform)
|
||||||
|
|
||||||
|
def activated_prompt_test(self, lines, after):
|
||||||
|
"""Require a looser match here, due to interposed ANSI color codes.
|
||||||
|
|
||||||
|
This construction allows coping with the messiness of fish's ANSI codes for colorizing.
|
||||||
|
It's not as rigorous as I would like---it doesn't ensure no space is inserted between
|
||||||
|
a custom env prompt (argument to --prompt) and the base prompt---but it does provide assurance as
|
||||||
|
to the key pieces of content that should be present.
|
||||||
|
|
||||||
|
"""
|
||||||
|
assert lines[1] in after, lines
|
||||||
|
|
||||||
|
|
||||||
|
class CshInfo(ShellInfo):
|
||||||
|
name = "csh"
|
||||||
|
avail_cmd = "csh -c 'echo foo'"
|
||||||
|
execute_cmd = "csh"
|
||||||
|
prompt_cmd = r"set | grep -E 'prompt\s' | sed -E 's/^prompt\s+(.*)$/\1/'"
|
||||||
|
activate_script = "activate.csh"
|
||||||
|
|
||||||
|
# csh defaults to an unset 'prompt' in non-interactive shells
|
||||||
|
preamble_cmd = "set prompt=%"
|
||||||
|
|
||||||
|
def platform_check_skip(self):
|
||||||
|
if IS_WIN:
|
||||||
|
return self.platform_incompat_msg.format(sys.platform)
|
||||||
|
|
||||||
|
def activated_prompt_test(self, lines, after):
|
||||||
|
"""Test with special handling on MacOS, which does funny things to stdout under (t)csh."""
|
||||||
|
if IS_DARWIN:
|
||||||
|
# Looser assert for (t)csh on MacOS, which prepends extra text to
|
||||||
|
# what gets sent to stdout
|
||||||
|
assert lines[1].endswith(after), lines
|
||||||
|
else:
|
||||||
|
# Otherwise, use the rigorous default
|
||||||
|
# Full 2-arg form for super() used for 2.7 compat
|
||||||
|
super(CshInfo, self).activated_prompt_test(lines, after)
|
||||||
|
|
||||||
|
|
||||||
|
class XonshInfo(ShellInfo):
|
||||||
|
name = "xonsh"
|
||||||
|
avail_cmd = "xonsh -c 'echo foo'"
|
||||||
|
execute_cmd = "xonsh"
|
||||||
|
prompt_cmd = "print(__xonsh__.shell.prompt)"
|
||||||
|
activate_script = "activate.xsh"
|
||||||
|
|
||||||
|
# Sets consistent initial state
|
||||||
|
preamble_cmd = (
|
||||||
|
"$VIRTUAL_ENV = ''; $PROMPT = '{env_name}$ '; "
|
||||||
|
"$PROMPT_FIELDS['env_prefix'] = '('; $PROMPT_FIELDS['env_postfix'] = ') '"
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def platform_check_skip():
|
||||||
|
if IS_WIN:
|
||||||
|
return "Provisioning xonsh on windows is unreliable"
|
||||||
|
|
||||||
|
if sys.version_info < (3, 5):
|
||||||
|
return "xonsh requires Python 3.5 at least"
|
||||||
|
|
||||||
|
|
||||||
|
class CmdInfo(ShellInfo):
|
||||||
|
name = "cmd"
|
||||||
|
avail_cmd = "echo foo"
|
||||||
|
execute_cmd = ""
|
||||||
|
prompt_cmd = "echo %PROMPT%"
|
||||||
|
activate_script = "activate.bat"
|
||||||
|
|
||||||
|
testscript_extension = ".bat"
|
||||||
|
preamble_cmd = "@echo off & set PROMPT=$P$G" # For consistent initial state
|
||||||
|
activate_cmd = "call "
|
||||||
|
deactivate_cmd = "call deactivate"
|
||||||
|
|
||||||
|
def platform_check_skip(self):
|
||||||
|
if not IS_WIN:
|
||||||
|
return self.platform_incompat_msg.format(sys.platform)
|
||||||
|
|
||||||
|
|
||||||
|
class PoshInfo(ShellInfo):
|
||||||
|
name = "powershell"
|
||||||
|
avail_cmd = "powershell 'echo foo'"
|
||||||
|
execute_cmd = "powershell -File "
|
||||||
|
prompt_cmd = "prompt"
|
||||||
|
activate_script = "activate.ps1"
|
||||||
|
|
||||||
|
testscript_extension = ".ps1"
|
||||||
|
activate_cmd = ". "
|
||||||
|
|
||||||
|
def platform_check_skip(self):
|
||||||
|
if not IS_WIN:
|
||||||
|
return self.platform_incompat_msg.format(sys.platform)
|
||||||
|
|
||||||
|
|
||||||
|
SHELL_INFO_LIST = [BashInfo(), FishInfo(), CshInfo(), XonshInfo(), CmdInfo(), PoshInfo()]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def posh_execute_enabled(tmp_path_factory):
|
||||||
|
"""Return check value for whether Powershell script execution is enabled.
|
||||||
|
|
||||||
|
Posh may be available interactively, but the security settings may not allow
|
||||||
|
execution of script files.
|
||||||
|
|
||||||
|
# Enable with: PS> Set-ExecutionPolicy -scope currentuser -ExecutionPolicy Bypass -Force;
|
||||||
|
# Disable with: PS> Set-ExecutionPolicy -scope currentuser -ExecutionPolicy Restricted -Force;
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not IS_WIN:
|
||||||
|
return False
|
||||||
|
|
||||||
|
test_ps1 = tmp_path_factory.mktemp("posh_test") / "test.ps1"
|
||||||
|
with open(str(test_ps1), "w") as f:
|
||||||
|
f.write("echo 'foo bar baz'\n")
|
||||||
|
|
||||||
|
out = subprocess.check_output(["powershell", "-File", "{}".format(str(test_ps1))], shell=True)
|
||||||
|
return b"foo bar baz" in out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def shell_avail(posh_execute_enabled):
|
||||||
|
"""Generate mapping of ShellInfo.name strings to bools of shell availability."""
|
||||||
|
retvals = {si.name: subprocess.call(si.avail_cmd, shell=True) for si in SHELL_INFO_LIST}
|
||||||
|
avails = {si.name: retvals[si.name] == 0 for si in SHELL_INFO_LIST}
|
||||||
|
|
||||||
|
# Extra check for whether powershell scripts are enabled
|
||||||
|
avails[PoshInfo().name] = avails[PoshInfo().name] and posh_execute_enabled
|
||||||
|
|
||||||
|
return avails
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def custom_prompt_root(tmp_path_factory):
|
||||||
|
"""Provide Path to root with default and custom venvs created."""
|
||||||
|
root = tmp_path_factory.mktemp("custom_prompt")
|
||||||
|
virtualenv.create_environment(
|
||||||
|
str(root / ENV_CUSTOM), prompt=PREFIX_CUSTOM, no_setuptools=True, no_pip=True, no_wheel=True
|
||||||
|
)
|
||||||
|
|
||||||
|
_, _, _, bin_dir = virtualenv.path_locations(str(root / ENV_DEFAULT))
|
||||||
|
|
||||||
|
bin_dir_name = os.path.split(bin_dir)[-1]
|
||||||
|
|
||||||
|
return root, bin_dir_name
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def clean_python_root(clean_python):
|
||||||
|
root = Path(clean_python[0]).resolve().parent
|
||||||
|
bin_dir_name = os.path.split(clean_python[1])[-1]
|
||||||
|
|
||||||
|
return root, bin_dir_name
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def get_work_root(clean_python_root, custom_prompt_root):
|
||||||
|
def pick_root(env):
|
||||||
|
if env == ENV_DEFAULT:
|
||||||
|
return clean_python_root
|
||||||
|
elif env == ENV_CUSTOM:
|
||||||
|
return custom_prompt_root
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid test virtualenv")
|
||||||
|
|
||||||
|
return pick_root
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def clean_env():
|
||||||
|
"""Provide a fresh copy of the shell environment.
|
||||||
|
|
||||||
|
VIRTUAL_ENV_DISABLE_PROMPT is always removed, if present, because
|
||||||
|
the prompt tests assume it to be unset.
|
||||||
|
|
||||||
|
"""
|
||||||
|
clean_env = os.environ.copy()
|
||||||
|
clean_env.pop(env_compat(VIRTUAL_ENV_DISABLE_PROMPT), None)
|
||||||
|
return clean_env
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("shell_info", SHELL_INFO_LIST, ids=[i.name for i in SHELL_INFO_LIST])
|
||||||
|
@pytest.mark.parametrize("env", [ENV_DEFAULT, ENV_CUSTOM], ids=["default", "custom"])
|
||||||
|
@pytest.mark.parametrize(("value", "disable"), [("", False), ("0", True), ("1", True)])
|
||||||
|
def test_suppressed_prompt(shell_info, shell_avail, env, value, disable, get_work_root, clean_env):
|
||||||
|
"""Confirm non-empty VIRTUAL_ENV_DISABLE_PROMPT suppresses prompt changes on activate."""
|
||||||
|
skip_test = shell_info.platform_check_skip()
|
||||||
|
if skip_test:
|
||||||
|
pytest.skip(skip_test)
|
||||||
|
|
||||||
|
if not IS_INSIDE_CI and not shell_avail[shell_info.name]:
|
||||||
|
pytest.skip(
|
||||||
|
"Shell '{}' not provisioned{}".format(
|
||||||
|
shell_info.name, " - is Powershell script execution disabled?" if shell_info == PoshInfo() else ""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
script_name = SCRIPT_TEMPLATE.format(shell_info.name, "suppress", env, shell_info.testscript_extension)
|
||||||
|
output_name = OUTPUT_TEMPLATE.format(shell_info.name, "suppress", env)
|
||||||
|
|
||||||
|
clean_env.update({env_compat(VIRTUAL_ENV_DISABLE_PROMPT): env_compat(value)})
|
||||||
|
|
||||||
|
work_root = get_work_root(env)
|
||||||
|
|
||||||
|
# The extra "{prompt}" here copes with some oddity of xonsh in certain emulated terminal
|
||||||
|
# contexts: xonsh can dump stuff into the first line of the recorded script output,
|
||||||
|
# so we have to include a dummy line of output that can get munged w/o consequence.
|
||||||
|
with open(str(work_root[0] / script_name), "w") as f:
|
||||||
|
f.write(
|
||||||
|
dedent(
|
||||||
|
"""\
|
||||||
|
{preamble}
|
||||||
|
{prompt}
|
||||||
|
{prompt}
|
||||||
|
{act_cmd}{env}/{bindir}/{act_script}
|
||||||
|
{prompt}
|
||||||
|
""".format(
|
||||||
|
env=env,
|
||||||
|
act_cmd=shell_info.activate_cmd,
|
||||||
|
preamble=shell_info.preamble_cmd,
|
||||||
|
prompt=shell_info.prompt_cmd,
|
||||||
|
act_script=shell_info.activate_script,
|
||||||
|
bindir=work_root[1],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
command = "{} {} > {}".format(shell_info.execute_cmd, script_name, output_name)
|
||||||
|
|
||||||
|
assert 0 == subprocess.call(command, cwd=str(work_root[0]), shell=True, env=clean_env)
|
||||||
|
|
||||||
|
with open(str(work_root[0] / output_name), "rb") as f:
|
||||||
|
text = f.read()
|
||||||
|
lines = text.split(b"\n")
|
||||||
|
|
||||||
|
# Is the prompt suppressed based on the env var value?
|
||||||
|
assert (lines[1] == lines[2]) == disable, text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("shell_info", SHELL_INFO_LIST, ids=[i.name for i in SHELL_INFO_LIST])
|
||||||
|
@pytest.mark.parametrize(["env", "prefix"], [(ENV_DEFAULT, PREFIX_DEFAULT), (ENV_CUSTOM, PREFIX_CUSTOM)])
|
||||||
|
def test_activated_prompt(shell_info, shell_avail, env, prefix, get_work_root, clean_env):
|
||||||
|
"""Confirm prompt modification behavior with and without --prompt specified."""
|
||||||
|
skip_test = shell_info.platform_check_skip()
|
||||||
|
if skip_test:
|
||||||
|
pytest.skip(skip_test)
|
||||||
|
|
||||||
|
if not IS_INSIDE_CI and not shell_avail[shell_info.name]:
|
||||||
|
pytest.skip(
|
||||||
|
"Shell '{}' not provisioned".format(shell_info.name)
|
||||||
|
+ (" - is Powershell script execution disabled?" if shell_info == PoshInfo() else "")
|
||||||
|
)
|
||||||
|
|
||||||
|
for k, v in shell_info.clean_env_update.items():
|
||||||
|
clean_env.update({env_compat(k): env_compat(v)})
|
||||||
|
|
||||||
|
script_name = SCRIPT_TEMPLATE.format(shell_info.name, "normal", env, shell_info.testscript_extension)
|
||||||
|
output_name = OUTPUT_TEMPLATE.format(shell_info.name, "normal", env)
|
||||||
|
|
||||||
|
work_root = get_work_root(env)
|
||||||
|
|
||||||
|
# The extra "{prompt}" here copes with some oddity of xonsh in certain emulated terminal
|
||||||
|
# contexts: xonsh can dump stuff into the first line of the recorded script output,
|
||||||
|
# so we have to include a dummy line of output that can get munged w/o consequence.
|
||||||
|
with open(str(work_root[0] / script_name), "w") as f:
|
||||||
|
f.write(
|
||||||
|
dedent(
|
||||||
|
"""\
|
||||||
|
{preamble}
|
||||||
|
{prompt}
|
||||||
|
{prompt}
|
||||||
|
{act_cmd}{env}/{bindir}/{act_script}
|
||||||
|
{prompt}
|
||||||
|
{deactivate}
|
||||||
|
{prompt}
|
||||||
|
""".format(
|
||||||
|
env=env,
|
||||||
|
act_cmd=shell_info.activate_cmd,
|
||||||
|
deactivate=shell_info.deactivate_cmd,
|
||||||
|
preamble=shell_info.preamble_cmd,
|
||||||
|
prompt=shell_info.prompt_cmd,
|
||||||
|
act_script=shell_info.activate_script,
|
||||||
|
bindir=work_root[1],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
command = "{} {} > {}".format(shell_info.execute_cmd, script_name, output_name)
|
||||||
|
|
||||||
|
assert 0 == subprocess.call(command, cwd=str(work_root[0]), shell=True, env=clean_env)
|
||||||
|
|
||||||
|
with open(str(work_root[0] / output_name), "rb") as f:
|
||||||
|
lines = f.read().split(b"\n")
|
||||||
|
|
||||||
|
shell_info.overall_prompt_test(lines, prefix)
|
139
python/virtualenv/tests/conftest.py
Normal file
139
python/virtualenv/tests/conftest.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pipes
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import virtualenv
|
||||||
|
|
||||||
|
try:
|
||||||
|
from pathlib import Path
|
||||||
|
except ImportError:
|
||||||
|
from pathlib2 import Path
|
||||||
|
|
||||||
|
ROOT_DIR = Path(__file__).parents[1]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def clean_python(tmp_path_factory):
|
||||||
|
path = tmp_path_factory.mktemp("activation-test-env")
|
||||||
|
prev_cwd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(str(path))
|
||||||
|
home_dir, _, __, bin_dir = virtualenv.path_locations(str(path / "env"))
|
||||||
|
virtualenv.create_environment(home_dir, no_pip=True, no_setuptools=True, no_wheel=True)
|
||||||
|
|
||||||
|
site_packages = subprocess.check_output(
|
||||||
|
[
|
||||||
|
os.path.join(bin_dir, virtualenv.EXPECTED_EXE),
|
||||||
|
"-c",
|
||||||
|
"from distutils.sysconfig import get_python_lib; print(get_python_lib())",
|
||||||
|
],
|
||||||
|
universal_newlines=True,
|
||||||
|
).strip()
|
||||||
|
|
||||||
|
pydoc_test = path.__class__(site_packages) / "pydoc_test.py"
|
||||||
|
pydoc_test.write_text('"""This is pydoc_test.py"""')
|
||||||
|
finally:
|
||||||
|
os.chdir(str(prev_cwd))
|
||||||
|
|
||||||
|
yield home_dir, bin_dir, pydoc_test
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def sdist(tmp_path):
|
||||||
|
"""make assertions on what we package"""
|
||||||
|
import tarfile
|
||||||
|
|
||||||
|
path = os.environ.get("TOX_PACKAGE")
|
||||||
|
if path is not None:
|
||||||
|
dest_path = tmp_path / "sdist"
|
||||||
|
dest_path.mkdir()
|
||||||
|
prev = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(str(dest_path))
|
||||||
|
tar = tarfile.open(path, "r:gz")
|
||||||
|
tar.extractall()
|
||||||
|
return next(dest_path.iterdir())
|
||||||
|
finally:
|
||||||
|
os.chdir(prev)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def wheel(tmp_path_factory):
|
||||||
|
"""test that we can create a virtual environment by feeding to a clean python the wheels content"""
|
||||||
|
dest_path = tmp_path_factory.mktemp("wheel")
|
||||||
|
env = os.environ.copy()
|
||||||
|
try:
|
||||||
|
subprocess.check_output(
|
||||||
|
[sys.executable, "-m", "pip", "wheel", "-w", str(dest_path), "--no-deps", str(ROOT_DIR)],
|
||||||
|
universal_newlines=True,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
env=env,
|
||||||
|
)
|
||||||
|
except subprocess.CalledProcessError as exception:
|
||||||
|
assert not exception.returncode, exception.output
|
||||||
|
|
||||||
|
wheels = list(dest_path.glob("*.whl"))
|
||||||
|
assert len(wheels) == 1
|
||||||
|
wheel = wheels[0]
|
||||||
|
return wheel
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def extracted_wheel(tmp_path, wheel):
|
||||||
|
dest_path = tmp_path / "wheel-extracted"
|
||||||
|
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
with zipfile.ZipFile(str(wheel), "r") as zip_ref:
|
||||||
|
zip_ref.extractall(str(dest_path))
|
||||||
|
return dest_path
|
||||||
|
|
||||||
|
|
||||||
|
def _call(cmd, env=None, stdin=None, allow_fail=False, shell=False, **kwargs):
|
||||||
|
env = os.environ if env is None else env
|
||||||
|
process = subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
universal_newlines=True,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
env=env,
|
||||||
|
shell=shell,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
out, err = process.communicate(input=stdin)
|
||||||
|
if allow_fail is False:
|
||||||
|
msg = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
cmd:
|
||||||
|
{}
|
||||||
|
out:
|
||||||
|
{}
|
||||||
|
err:
|
||||||
|
{}
|
||||||
|
env:
|
||||||
|
{}
|
||||||
|
"""
|
||||||
|
).format(
|
||||||
|
cmd if shell else " ".join(pipes.quote(str(i)) for i in cmd),
|
||||||
|
out,
|
||||||
|
err,
|
||||||
|
os.linesep.join("{}={!r}".format(k, v) for k, v in env.items()),
|
||||||
|
)
|
||||||
|
msg = msg.lstrip()
|
||||||
|
assert process.returncode == 0, msg
|
||||||
|
return out, err
|
||||||
|
else:
|
||||||
|
return process.returncode, out, err
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def call_subprocess():
|
||||||
|
return _call
|
Binary file not shown.
Binary file not shown.
27
python/virtualenv/tests/ssl/rootCA.key
Normal file
27
python/virtualenv/tests/ssl/rootCA.key
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpQIBAAKCAQEA0D+NxiOUkvWp45C75ZmCdzl3Cqu09MV9GvVjv5vU2So92pJI
|
||||||
|
sMmZDavteLEdA1g/T3Wzh6vop0NGXskrGIQ0QXPcnbtJtWH2n+R8/N4xlFliEwX+
|
||||||
|
JZOrzWFeZGzVJd7VKr2ncO/B5VGIYPB+HTD3VYzm2ACZnyB7NvTJXM/IH0x19TI8
|
||||||
|
Bad3rNNX3XnL0c6N8Zd9Hqyj25ciNSiY8a/TnvOEtLw1yo1HNUX6V5xgI5fslDXl
|
||||||
|
t3tKg3zmuGZXSLhYMjEN4q7NOdI8qW7mQrabCvyiIDCxJeLHdL+ks6FWmoHL9j5r
|
||||||
|
vHq8lyaMM28d/928KSlZtNpwxh5nhHEChLlf8QIDAQABAoIBAQCxII13LYZO5ZNm
|
||||||
|
ExIuvT5iKEeflOLqmxvJFVWNgX8uY6aOxYP8ksyS+1yWHped466d6HAWgtr1gdxV
|
||||||
|
/OeiB7jmvyS0KLwOAlAiOdcxwdAL7Wbk5WEBFzS3EQ2Xf5ZgisNngj7saZHTemD0
|
||||||
|
iznJnH+TjbA/o2sHFTqYSOcJAVanfviqCxH/3xKPAS9vnFPYcpPr8xrQaR2sX6Zy
|
||||||
|
aZUNVE4udSl3+GqMhMeq1dxssua4PQVsplwIJbY3KUIQIkXNLR8Zal8ygi5HI29U
|
||||||
|
q+PPiM89O9lgzUz246x1ruNKIl+zgOQsn1yg0Wx+ho1b5kVE4yqi58tVPCN/Bc8H
|
||||||
|
lWai906RAoGBAPjFWDnrBo5PBVuXOYmPvo10J9n2iIOKOBr3V4OlUb46LcRk19E9
|
||||||
|
nV+zidoNKxTaB+g7dlKqYpvOnZ0MUKLPPE1G1U3RlKO+qVhnQ/Pf1N1e88ojCWDu
|
||||||
|
pFWezwOAO/BJGKQk7sYqMz47hfnLRydeipMv3ASEhKr1rP/b3M1ICrd1AoGBANZM
|
||||||
|
wOHm0fd87w3WS8eBivI3+W1mL6mHzNJ20G3OM1kUPcbUBzqocwYp3AUXZmO6X8GC
|
||||||
|
RSmkQ7U81yA5GcdhPIlGa8emSuYPyKBAjgX3fOGgZGNMrcmc+o+uRdyzfxKR1Oph
|
||||||
|
nnLKj2f7xIXGgGs6gqv00omLEScZ4oqBL+I4ovMNAoGBAM9fem81as6gMqAqDI2O
|
||||||
|
ZNL3u+ym5R95zdE01B/qZJzFVLd9NKa4zQIk4MoC5iHIqoS9ZKH+ZJrq/loXFPTS
|
||||||
|
+bqVTGRFS7m/ytzloDCgKoqqh2C+GihSZmz1KC4L7GseE8to+h34uaSr67/R4yt/
|
||||||
|
VNbjM24UpZ75ks/qEEKTRlOtAoGAad6nV7MJvgO5shNRgrGL7Fgc4KAgIdfWJ4/N
|
||||||
|
LsI0+egXEPhEzgTUNpJNgTJrQg+cKORruMPPM2VoPiIXizmNh6ADtTGBRSE9E3Zw
|
||||||
|
85+t0WXE0o3aOYVU/9Cv8PW4bHshPd2WQs2xhUSLdS942ACi98LOlGbgxXlzQsvJ
|
||||||
|
1S/3yK0CgYEAwu+gAfwpuJSSk7yyiUjIh6PA00lZnuxgj2AeqS2RSRk+YkV8ZJOP
|
||||||
|
MhoZpJv+OCrAQFY9ybptJfbGyJQNkpkRHt82aNbevFxly2tTVT+zbeUbeMnX5qn4
|
||||||
|
nOCaAc9u4QDTrSE3DS/JSWelv4gjq782THmWSSZfrwS/qV6KrhqZfXk=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
21
python/virtualenv/tests/ssl/rootCA.pem
Normal file
21
python/virtualenv/tests/ssl/rootCA.pem
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDXzCCAkegAwIBAgIJAJyQNZE5SUeEMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||||
|
BAYTAlJVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||||
|
aWRnaXRzIFB0eSBMdGQwIBcNMTkwMTExMTkwNjM4WhgPMjI5MjEwMjYxOTA2Mzha
|
||||||
|
MEUxCzAJBgNVBAYTAlJVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJ
|
||||||
|
bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||||
|
ggEKAoIBAQDQP43GI5SS9anjkLvlmYJ3OXcKq7T0xX0a9WO/m9TZKj3akkiwyZkN
|
||||||
|
q+14sR0DWD9PdbOHq+inQ0ZeySsYhDRBc9ydu0m1Yfaf5Hz83jGUWWITBf4lk6vN
|
||||||
|
YV5kbNUl3tUqvadw78HlUYhg8H4dMPdVjObYAJmfIHs29Mlcz8gfTHX1MjwFp3es
|
||||||
|
01fdecvRzo3xl30erKPblyI1KJjxr9Oe84S0vDXKjUc1RfpXnGAjl+yUNeW3e0qD
|
||||||
|
fOa4ZldIuFgyMQ3irs050jypbuZCtpsK/KIgMLEl4sd0v6SzoVaagcv2Pmu8eryX
|
||||||
|
Jowzbx3/3bwpKVm02nDGHmeEcQKEuV/xAgMBAAGjUDBOMB0GA1UdDgQWBBTYiCMT
|
||||||
|
/U1XaXKam/gNiQK28/f1jzAfBgNVHSMEGDAWgBTYiCMT/U1XaXKam/gNiQK28/f1
|
||||||
|
jzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBll3abJLJxh8LNAz/B
|
||||||
|
xpPly54SttwEqDeFC6y35ilgq53aNAu5Smx+ka9OotnPcfuUEIuOf7kWre02OuAU
|
||||||
|
FCEcViXLM9+NWMVKTD+ZQ8H0VL0GMJOidt/FReTSixawJY1YB6HhFwI1yVd+x8+l
|
||||||
|
vwyqoHNz/Uk6unsHIAJk5Esj3IuiYwOw6KmsiZv9IsIX7IXv3g6eKYC7162ArLyw
|
||||||
|
8nPFWcKJTAHFzmGhvrS6vV08mv+6Helgp/B3OFm/OqDm2LwASIUDlzQjdeowNo9Z
|
||||||
|
z6O/JNjoBLCMAVm/an/zONUb/XZXsw3CAYAta3fuRT7FptMBIJCtMuVgrmzzG79X
|
||||||
|
PcF/
|
||||||
|
-----END CERTIFICATE-----
|
19
python/virtualenv/tests/ssl/server.crt
Normal file
19
python/virtualenv/tests/ssl/server.crt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDHDCCAgQCCQD8eKhHCWYb1TANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJS
|
||||||
|
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||||
|
cyBQdHkgTHRkMCAXDTE5MDExMTE5MDc0N1oYDzIyOTIxMDI2MTkwNzQ3WjBZMQsw
|
||||||
|
CQYDVQQGEwJSVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJu
|
||||||
|
ZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqG
|
||||||
|
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDr/u2BS0mKqz+rLwyd79LrcvBZOpXoRVib
|
||||||
|
lE2zhz9ZBlQZ/nmSg40QPZqOsgrGZKYFMfLY1AYNpKCJYe4lBQ2YqU1Jac0WYXdh
|
||||||
|
WEfEKW1hYCsuY9wpz1kVfCAfUD2+1/hOBd2ghgpx3YJgkjIPUeywpalOxD+1j+8r
|
||||||
|
RjfouVl4kB9UOsRoJzZHP2L6yzCABeoZgVgupkJNHx1KMSYyETLvwxni/FE1lmFA
|
||||||
|
kxdRV7B8YcWlG+0ewl23KTdMtxtfzUJ+OrShs5fl1UoG8BqRxLVxf889cfkYy6aF
|
||||||
|
q3tKbRtAgIpmET0UoYzrBbWIVoKgqYnASTFR/hXfGhozN8chStW1AgMBAAEwDQYJ
|
||||||
|
KoZIhvcNAQELBQADggEBAC/2/sdFcsPSv48dk5GPqutOhQnFDH4qoW9B4cCQXISD
|
||||||
|
GZ4hDme/RDB/cIgpHBWrtrSq0893d7cXl57aMWjDJmWH1iXTFJ5h9mYhvaWZekR0
|
||||||
|
t4D0ZJYVhTiSOdavMc50payWYuTwaUqeXHPkOKKNgGrlcVV4n+tkQq/dvFBZXA8b
|
||||||
|
ql4x6PmU/Oqf0dY/f5PzgNb1rEHhsdqpJEZdjLsFFKdJX0ikaGak13iEDPR3uEZt
|
||||||
|
/Eu8VOVGuMwK8+Q4/AUctsfh03wqP82RBlCWTk5eTe34y0dNui3hc+oWIjLf6+pc
|
||||||
|
xjEnh5EWq/Hf4AEUT6PwP3m3ZmxeUlWMMx6GA27ovrc=
|
||||||
|
-----END CERTIFICATE-----
|
28
python/virtualenv/tests/ssl/server.key
Normal file
28
python/virtualenv/tests/ssl/server.key
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDr/u2BS0mKqz+r
|
||||||
|
Lwyd79LrcvBZOpXoRViblE2zhz9ZBlQZ/nmSg40QPZqOsgrGZKYFMfLY1AYNpKCJ
|
||||||
|
Ye4lBQ2YqU1Jac0WYXdhWEfEKW1hYCsuY9wpz1kVfCAfUD2+1/hOBd2ghgpx3YJg
|
||||||
|
kjIPUeywpalOxD+1j+8rRjfouVl4kB9UOsRoJzZHP2L6yzCABeoZgVgupkJNHx1K
|
||||||
|
MSYyETLvwxni/FE1lmFAkxdRV7B8YcWlG+0ewl23KTdMtxtfzUJ+OrShs5fl1UoG
|
||||||
|
8BqRxLVxf889cfkYy6aFq3tKbRtAgIpmET0UoYzrBbWIVoKgqYnASTFR/hXfGhoz
|
||||||
|
N8chStW1AgMBAAECggEAVpw0piLvVokK0NRvmPcPPYHtW5H4uknY/yAqdBzKzu1X
|
||||||
|
qEKQc4j8GF3Df2MwOSdvFrECIzmNDyzADit2rvdvyfs4dhzyO6iBm6Q+kmtxzS7y
|
||||||
|
KhBUGLQUSaJIV7WnM4cnhdr5P5Rx+OAGnVKKNL0oVJw3ysSTbRrp98PJeQutHmVx
|
||||||
|
7wIBePrmrIeRS3uESty3rqSyypKO6DYhIwsV3yzsr0kad+o6MT1gb/EB7qEj5uNX
|
||||||
|
E81lnhoHlYtPJujJUCucQmfqKX7LRSq7bEfxFcJXOwKB2/2ILT3tXBTlYlKuvC43
|
||||||
|
TaajaaUTSBFhL9zuYv1XWCyX/MXXxA27SvaBIjFE8QKBgQD3I4vGQ94juCCNaUT8
|
||||||
|
dPSBn+dnkfqKdxH8WF6q2KdsdYFbFEfW7/rY5jSRQMu6VF/AXiJFh5amQiDUnfWb
|
||||||
|
QDmtyqGk2kb1g5gUm6plRPL3P3pQ4x1FVtJgVvxV26rQxTV6Bv6zM8SoJUMZJaEz
|
||||||
|
/z8QX5/dF7vlFGmy8LH4efYsXwKBgQD0dRnvQGFtwnD7xI/0ihltdogrzFb6sOpU
|
||||||
|
vsXporJS19vjfunCJKjXL9JvFAw2Gk6XUQ9wCUYjLMu1ovahiLm5FMsfhDtTMhvS
|
||||||
|
9HQvV8RdMk0NSorP/2LfpEsUqqkTXB5dxelbmNJeLr3fK+9azsK0wLXCT3vUo/kV
|
||||||
|
uPISrh32awKBgEn9jWplhUtCZBSSUMIYrd9lJV2/ubfc4DihqG4UAUQahgjjsIJs
|
||||||
|
RLjNay2Vrajye9xXEoGoj3TlVXjydcbuWpZqlSyK4TW+GTkKReCd3PQjQBaZeHj6
|
||||||
|
/m8ze8akxqZMdK89CuJR/G2vAkC0IGg14gaf6nfCFFIIY4DcSRwwP4CXAoGAantz
|
||||||
|
r46oocnXsyNc3VUmXFMMX5+jp5FWkVGEHg/7gzB5nK/UnPehABLZo/7kjtCIuUra
|
||||||
|
4Z94iKvjlBwHODe5RpBzJihQOx4RlqNa1KBzbXEStR5qNs30wJvtBHSOL1up8ojZ
|
||||||
|
7Ec2I0ZS+JpHqZN0po1m3twGgYpnXnnwIAjuDj8CgYBJHcoMJCRnuYqvDBJzqZDj
|
||||||
|
6DAGT60qa6E+p/xkKAmys69Un1KDsnLTYNvV7wivqfve0/2Ja9gg3Neocq39tsTF
|
||||||
|
rTjeKHO3D8FN3C79diWj65ohrS6vOyhkBroAmOxDQgD7nKQrkyd865qlTNsyGFmC
|
||||||
|
KEFgzjGWDx2Wk9vUYUxBOg==
|
||||||
|
-----END PRIVATE KEY-----
|
@ -1,96 +0,0 @@
|
|||||||
#!/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}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
New python executable in /tmp/test_virtualenv_activate.venv/bin/python
|
|
||||||
Installing setuptools, pip, wheel...done.
|
|
87
python/virtualenv/tests/test_bootstrap.py
Normal file
87
python/virtualenv/tests/test_bootstrap.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
import virtualenv
|
||||||
|
|
||||||
|
|
||||||
|
def bootstrap():
|
||||||
|
print("startup")
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
|
def extend_parser(opt_parse_parser):
|
||||||
|
print("extend parser with count")
|
||||||
|
opt_parse_parser.add_option("-c", action="count", dest="count", default=0, help="Count number of times passed")
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
|
def adjust_options(options, args):
|
||||||
|
print("adjust options")
|
||||||
|
options.count += 1
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
|
def after_install(options, home_dir):
|
||||||
|
print("after install {} with options {}".format(home_dir, options.count))
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
_, _, _, bin_dir = path_locations(home_dir) # noqa: F821
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
print(
|
||||||
|
"exe at {}".format(
|
||||||
|
subprocess.check_output(
|
||||||
|
[os.path.join(bin_dir, EXPECTED_EXE), "-c", "import sys; print(sys.executable)"], # noqa: F821
|
||||||
|
universal_newlines=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_bootstrap(tmp_path, monkeypatch):
|
||||||
|
monkeypatch.chdir(tmp_path)
|
||||||
|
|
||||||
|
extra_code = inspect.getsource(bootstrap)
|
||||||
|
extra_code = textwrap.dedent(extra_code[extra_code.index("\n") + 1 :])
|
||||||
|
|
||||||
|
output = virtualenv.create_bootstrap_script(extra_code)
|
||||||
|
assert extra_code in output
|
||||||
|
if six.PY2:
|
||||||
|
output = output.decode()
|
||||||
|
write_at = tmp_path / "blog-bootstrap.py"
|
||||||
|
write_at.write_text(output)
|
||||||
|
|
||||||
|
try:
|
||||||
|
monkeypatch.chdir(tmp_path)
|
||||||
|
cmd = [
|
||||||
|
sys.executable,
|
||||||
|
str(write_at),
|
||||||
|
"--no-download",
|
||||||
|
"--no-pip",
|
||||||
|
"--no-wheel",
|
||||||
|
"--no-setuptools",
|
||||||
|
"-ccc",
|
||||||
|
"-qqq",
|
||||||
|
"env",
|
||||||
|
]
|
||||||
|
raw = subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
|
||||||
|
out = re.sub(r"pydev debugger: process \d+ is connecting\n\n", "", raw, re.M).strip().split("\n")
|
||||||
|
|
||||||
|
_, _, _, bin_dir = virtualenv.path_locations(str(tmp_path / "env"))
|
||||||
|
exe = os.path.realpath(
|
||||||
|
os.path.join(bin_dir, "{}{}".format(virtualenv.EXPECTED_EXE, ".exe" if virtualenv.IS_WIN else ""))
|
||||||
|
)
|
||||||
|
assert out == [
|
||||||
|
"startup",
|
||||||
|
"extend parser with count",
|
||||||
|
"adjust options",
|
||||||
|
"after install env with options 4",
|
||||||
|
"exe at {}".format(exe),
|
||||||
|
]
|
||||||
|
except subprocess.CalledProcessError as exception:
|
||||||
|
assert not exception.returncode, exception.output
|
@ -1,44 +1,69 @@
|
|||||||
import sys
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import virtualenv
|
import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
VIRTUALENV_SCRIPT = virtualenv.__file__
|
import virtualenv
|
||||||
|
|
||||||
|
|
||||||
def test_commandline_basic(tmpdir):
|
def test_commandline_basic(tmpdir):
|
||||||
"""Simple command line usage should work"""
|
"""Simple command line usage should work and files should be generated"""
|
||||||
subprocess.check_call([
|
home_dir, lib_dir, inc_dir, bin_dir = virtualenv.path_locations(str(tmpdir.join("venv")))
|
||||||
sys.executable,
|
subprocess.check_call([sys.executable, "-m", "virtualenv", "-vvv", home_dir, "--no-download"])
|
||||||
VIRTUALENV_SCRIPT,
|
|
||||||
str(tmpdir.join('venv'))
|
assert os.path.exists(home_dir)
|
||||||
])
|
assert os.path.exists(bin_dir)
|
||||||
|
|
||||||
|
assert os.path.exists(os.path.join(bin_dir, "activate"))
|
||||||
|
assert os.path.exists(os.path.join(bin_dir, "activate_this.py"))
|
||||||
|
assert os.path.exists(os.path.join(bin_dir, "activate.ps1"))
|
||||||
|
|
||||||
|
exe = os.path.join(bin_dir, os.path.basename(sys.executable))
|
||||||
|
assert os.path.exists(exe)
|
||||||
|
|
||||||
|
def _check_no_warnings(module):
|
||||||
|
subprocess.check_call((exe, "-Werror", "-c", "import {}".format(module)))
|
||||||
|
|
||||||
|
_check_no_warnings("distutils")
|
||||||
|
|
||||||
|
|
||||||
|
def test_commandline_os_path_sep(tmp_path):
|
||||||
|
path = tmp_path / "bad{}0".format(os.pathsep)
|
||||||
|
assert not path.exists()
|
||||||
|
process = subprocess.Popen(
|
||||||
|
[sys.executable, "-m", "virtualenv", str(path)],
|
||||||
|
cwd=str(tmp_path),
|
||||||
|
universal_newlines=True,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
out, err = process.communicate()
|
||||||
|
assert process.returncode == 3
|
||||||
|
msg = (
|
||||||
|
"ERROR: target path contains the operating system path separator '{}'\n"
|
||||||
|
"This is not allowed as would make the activation scripts unusable.\n".format(os.pathsep)
|
||||||
|
)
|
||||||
|
assert not err
|
||||||
|
assert out == msg
|
||||||
|
assert not path.exists()
|
||||||
|
|
||||||
|
|
||||||
def test_commandline_explicit_interp(tmpdir):
|
def test_commandline_explicit_interp(tmpdir):
|
||||||
"""Specifying the Python interpreter should work"""
|
"""Specifying the Python interpreter should work"""
|
||||||
subprocess.check_call([
|
subprocess.check_call([sys.executable, "-m", "virtualenv", "-p", sys.executable, str(tmpdir.join("venv"))])
|
||||||
sys.executable,
|
|
||||||
VIRTUALENV_SCRIPT,
|
|
||||||
'-p', sys.executable,
|
|
||||||
str(tmpdir.join('venv'))
|
|
||||||
])
|
|
||||||
|
|
||||||
# The registry lookups to support the abbreviated "-p 3.5" form of specifying
|
# 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
|
# 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
|
# registry layout is not well documented, and it's not clear that the feature
|
||||||
# is sufficiently widely used to be worth fixing.
|
# is sufficiently widely used to be worth fixing.
|
||||||
# See https://github.com/pypa/virtualenv/issues/864
|
# See https://github.com/pypa/virtualenv/issues/864
|
||||||
@pytest.mark.skipif("sys.platform == 'win32' and sys.version_info[:2] >= (3,5)")
|
@pytest.mark.skipif("sys.platform == 'win32' and sys.version_info[:1] >= (3,)")
|
||||||
def test_commandline_abbrev_interp(tmpdir):
|
def test_commandline_abbrev_interp(tmpdir):
|
||||||
"""Specifying abbreviated forms of the Python interpreter should work"""
|
"""Specifying abbreviated forms of the Python interpreter should work"""
|
||||||
if sys.platform == 'win32':
|
abbrev = "{}{}.{}".format("" if sys.platform == "win32" else "python", *sys.version_info[0:2])
|
||||||
fmt = '%s.%s'
|
subprocess.check_call([sys.executable, "-m", "virtualenv", "-p", abbrev, str(tmpdir.join("venv"))])
|
||||||
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'))
|
|
||||||
])
|
|
||||||
|
|
||||||
|
49
python/virtualenv/tests/test_from_source.py
Normal file
49
python/virtualenv/tests/test_from_source.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"""test using the project from source/package rather than install"""
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import virtualenv
|
||||||
|
|
||||||
|
try:
|
||||||
|
from pathlib import Path
|
||||||
|
except ImportError:
|
||||||
|
from pathlib2 import Path
|
||||||
|
|
||||||
|
ROOT_DIR = Path(__file__).parents[1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_use_from_source_tree(tmp_path, clean_python, monkeypatch, call_subprocess):
|
||||||
|
"""test that we can create a virtual environment by feeding to a clean python the wheels content"""
|
||||||
|
monkeypatch.chdir(tmp_path)
|
||||||
|
call_subprocess(
|
||||||
|
[
|
||||||
|
str(Path(clean_python[1]) / virtualenv.EXPECTED_EXE),
|
||||||
|
str(Path(ROOT_DIR) / "virtualenv.py"),
|
||||||
|
"--no-download",
|
||||||
|
"env",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(os.environ.get("TOX_PACKAGE") is None, reason="needs tox provisioned sdist")
|
||||||
|
def test_use_from_source_sdist(sdist, tmp_path, clean_python, monkeypatch, call_subprocess):
|
||||||
|
"""test that we can create a virtual environment by feeding to a clean python the sdist content"""
|
||||||
|
virtualenv_file = sdist / "virtualenv.py"
|
||||||
|
assert virtualenv_file.exists()
|
||||||
|
|
||||||
|
monkeypatch.chdir(tmp_path)
|
||||||
|
call_subprocess(
|
||||||
|
[str(Path(clean_python[1]) / virtualenv.EXPECTED_EXE), str(virtualenv_file), "--no-download", "env"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_use_from_wheel(tmp_path, extracted_wheel, clean_python, monkeypatch, call_subprocess):
|
||||||
|
"""test that we can create a virtual environment by feeding to a clean python the wheels content"""
|
||||||
|
virtualenv_file = extracted_wheel / "virtualenv.py"
|
||||||
|
monkeypatch.chdir(tmp_path)
|
||||||
|
call_subprocess(
|
||||||
|
[str(Path(clean_python[1]) / virtualenv.EXPECTED_EXE), str(virtualenv_file), "--no-download", "env"]
|
||||||
|
)
|
62
python/virtualenv/tests/test_source_content.py
Normal file
62
python/virtualenv/tests/test_source_content.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import virtualenv
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(os.environ.get("TOX_PACKAGE") is None, reason="needs tox provisioned sdist")
|
||||||
|
def test_sdist_contains(sdist):
|
||||||
|
"""make assertions on what we package"""
|
||||||
|
content = set(sdist.iterdir())
|
||||||
|
|
||||||
|
names = {i.name for i in content}
|
||||||
|
|
||||||
|
must_have = {
|
||||||
|
# sources
|
||||||
|
"virtualenv.py",
|
||||||
|
"virtualenv_embedded",
|
||||||
|
"virtualenv_support",
|
||||||
|
"setup.py",
|
||||||
|
"setup.cfg",
|
||||||
|
"MANIFEST.in",
|
||||||
|
"pyproject.toml",
|
||||||
|
# test files
|
||||||
|
"tests",
|
||||||
|
# documentation
|
||||||
|
"docs",
|
||||||
|
"README.rst",
|
||||||
|
# helpers
|
||||||
|
"tasks",
|
||||||
|
"tox.ini",
|
||||||
|
# meta-data
|
||||||
|
"AUTHORS.txt",
|
||||||
|
"LICENSE.txt",
|
||||||
|
}
|
||||||
|
|
||||||
|
missing = must_have - names
|
||||||
|
assert not missing
|
||||||
|
|
||||||
|
extra = names - must_have - {"PKG-INFO", "virtualenv.egg-info"}
|
||||||
|
assert not extra, " | ".join(extra)
|
||||||
|
|
||||||
|
|
||||||
|
def test_wheel_contains(extracted_wheel):
|
||||||
|
content = set(extracted_wheel.iterdir())
|
||||||
|
|
||||||
|
names = {i.name for i in content}
|
||||||
|
must_have = {
|
||||||
|
# sources
|
||||||
|
"virtualenv.py",
|
||||||
|
"virtualenv_support",
|
||||||
|
"virtualenv-{}.dist-info".format(virtualenv.__version__),
|
||||||
|
}
|
||||||
|
assert must_have == names
|
||||||
|
|
||||||
|
support = {i.name for i in (extracted_wheel / "virtualenv_support").iterdir()}
|
||||||
|
assert "__init__.py" in support
|
||||||
|
for package in ("pip", "wheel", "setuptools"):
|
||||||
|
assert any(package in i for i in support)
|
||||||
|
|
||||||
|
meta = {i.name for i in (extracted_wheel / "virtualenv-{}.dist-info".format(virtualenv.__version__)).iterdir()}
|
||||||
|
assert {"entry_points.txt", "WHEEL", "RECORD", "METADATA", "top_level.txt", "zip-safe", "LICENSE.txt"} == meta
|
@ -1,13 +1,34 @@
|
|||||||
import virtualenv
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import inspect
|
||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import pytest
|
import textwrap
|
||||||
import platform # noqa
|
import zipfile
|
||||||
|
|
||||||
from mock import patch, Mock
|
import pypiserver
|
||||||
|
import pytest
|
||||||
|
import pytest_localserver.http
|
||||||
|
import six
|
||||||
|
|
||||||
|
import virtualenv
|
||||||
|
|
||||||
|
try:
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest.mock import NonCallableMock, call, patch
|
||||||
|
except ImportError:
|
||||||
|
from mock import NonCallableMock, call, patch
|
||||||
|
from pathlib2 import Path
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
import venv as std_venv
|
||||||
|
except ImportError:
|
||||||
|
std_venv = None
|
||||||
|
|
||||||
|
|
||||||
def test_version():
|
def test_version():
|
||||||
@ -15,11 +36,222 @@ def test_version():
|
|||||||
assert virtualenv.virtualenv_version, "Should have version"
|
assert virtualenv.virtualenv_version, "Should have version"
|
||||||
|
|
||||||
|
|
||||||
@patch('os.path.exists')
|
class TestGetInstalledPythons:
|
||||||
def test_resolve_interpreter_with_absolute_path(mock_exists):
|
key_local_machine = "key-local-machine"
|
||||||
|
key_current_user = "key-current-user"
|
||||||
|
key_local_machine_64 = "key-local-machine-64"
|
||||||
|
key_current_user_64 = "key-current-user-64"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mock_virtualenv_winreg(cls, monkeypatch, data):
|
||||||
|
def enum_key(key, index):
|
||||||
|
try:
|
||||||
|
return data.get(key, [])[index]
|
||||||
|
except IndexError:
|
||||||
|
raise WindowsError
|
||||||
|
|
||||||
|
def query_value(key, path):
|
||||||
|
installed_version_tags = data.get(key, [])
|
||||||
|
suffix = "\\InstallPath"
|
||||||
|
if path.endswith(suffix):
|
||||||
|
version_tag = path[: -len(suffix)]
|
||||||
|
if version_tag in installed_version_tags:
|
||||||
|
return "{}-{}-path".format(key, version_tag)
|
||||||
|
raise WindowsError
|
||||||
|
|
||||||
|
mock_winreg = NonCallableMock(
|
||||||
|
spec_set=[
|
||||||
|
"HKEY_LOCAL_MACHINE",
|
||||||
|
"HKEY_CURRENT_USER",
|
||||||
|
"KEY_READ",
|
||||||
|
"KEY_WOW64_32KEY",
|
||||||
|
"KEY_WOW64_64KEY",
|
||||||
|
"OpenKey",
|
||||||
|
"EnumKey",
|
||||||
|
"QueryValue",
|
||||||
|
"CloseKey",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
mock_winreg.HKEY_LOCAL_MACHINE = "HKEY_LOCAL_MACHINE"
|
||||||
|
mock_winreg.HKEY_CURRENT_USER = "HKEY_CURRENT_USER"
|
||||||
|
mock_winreg.KEY_READ = 0x10
|
||||||
|
mock_winreg.KEY_WOW64_32KEY = 0x1
|
||||||
|
mock_winreg.KEY_WOW64_64KEY = 0x2
|
||||||
|
mock_winreg.OpenKey.side_effect = [
|
||||||
|
cls.key_local_machine,
|
||||||
|
cls.key_current_user,
|
||||||
|
cls.key_local_machine_64,
|
||||||
|
cls.key_current_user_64,
|
||||||
|
]
|
||||||
|
mock_winreg.EnumKey.side_effect = enum_key
|
||||||
|
mock_winreg.QueryValue.side_effect = query_value
|
||||||
|
mock_winreg.CloseKey.return_value = None
|
||||||
|
monkeypatch.setattr(virtualenv, "winreg", mock_winreg)
|
||||||
|
return mock_winreg
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform == "win32", reason="non-windows specific test")
|
||||||
|
def test_on_non_windows(self, monkeypatch):
|
||||||
|
assert not virtualenv.IS_WIN
|
||||||
|
assert not hasattr(virtualenv, "winreg")
|
||||||
|
assert virtualenv.get_installed_pythons() == {}
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform != "win32", reason="windows specific test")
|
||||||
|
def test_on_windows(self, monkeypatch):
|
||||||
|
assert virtualenv.IS_WIN
|
||||||
|
mock_winreg = self.mock_virtualenv_winreg(
|
||||||
|
monkeypatch,
|
||||||
|
{
|
||||||
|
self.key_local_machine: (
|
||||||
|
"2.4",
|
||||||
|
"2.7",
|
||||||
|
"3.2",
|
||||||
|
"3.4",
|
||||||
|
"3.6-32", # 32-bit only
|
||||||
|
"3.7-32", # both 32 & 64-bit with a 64-bit user install
|
||||||
|
),
|
||||||
|
self.key_current_user: ("2.5", "2.7", "3.8-32"),
|
||||||
|
self.key_local_machine_64: (
|
||||||
|
"2.6",
|
||||||
|
"3.5", # 64-bit only
|
||||||
|
"3.7",
|
||||||
|
"3.8", # 64-bit with a 32-bit user install
|
||||||
|
),
|
||||||
|
self.key_current_user_64: ("3.7",),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(virtualenv, "join", "{}\\{}".format)
|
||||||
|
|
||||||
|
installed_pythons = virtualenv.get_installed_pythons()
|
||||||
|
|
||||||
|
assert installed_pythons == {
|
||||||
|
"2": self.key_current_user + "-2.7-path\\python.exe",
|
||||||
|
"2-32": self.key_current_user + "-2.7-path\\python.exe",
|
||||||
|
"2-64": self.key_local_machine_64 + "-2.6-path\\python.exe",
|
||||||
|
"2.4": self.key_local_machine + "-2.4-path\\python.exe",
|
||||||
|
"2.4-32": self.key_local_machine + "-2.4-path\\python.exe",
|
||||||
|
"2.5": self.key_current_user + "-2.5-path\\python.exe",
|
||||||
|
"2.5-32": self.key_current_user + "-2.5-path\\python.exe",
|
||||||
|
"2.6": self.key_local_machine_64 + "-2.6-path\\python.exe",
|
||||||
|
"2.6-64": self.key_local_machine_64 + "-2.6-path\\python.exe",
|
||||||
|
"2.7": self.key_current_user + "-2.7-path\\python.exe",
|
||||||
|
"2.7-32": self.key_current_user + "-2.7-path\\python.exe",
|
||||||
|
"3": self.key_local_machine_64 + "-3.8-path\\python.exe",
|
||||||
|
"3-32": self.key_current_user + "-3.8-32-path\\python.exe",
|
||||||
|
"3-64": self.key_local_machine_64 + "-3.8-path\\python.exe",
|
||||||
|
"3.2": self.key_local_machine + "-3.2-path\\python.exe",
|
||||||
|
"3.2-32": self.key_local_machine + "-3.2-path\\python.exe",
|
||||||
|
"3.4": self.key_local_machine + "-3.4-path\\python.exe",
|
||||||
|
"3.4-32": self.key_local_machine + "-3.4-path\\python.exe",
|
||||||
|
"3.5": self.key_local_machine_64 + "-3.5-path\\python.exe",
|
||||||
|
"3.5-64": self.key_local_machine_64 + "-3.5-path\\python.exe",
|
||||||
|
"3.6": self.key_local_machine + "-3.6-32-path\\python.exe",
|
||||||
|
"3.6-32": self.key_local_machine + "-3.6-32-path\\python.exe",
|
||||||
|
"3.7": self.key_current_user_64 + "-3.7-path\\python.exe",
|
||||||
|
"3.7-32": self.key_local_machine + "-3.7-32-path\\python.exe",
|
||||||
|
"3.7-64": self.key_current_user_64 + "-3.7-path\\python.exe",
|
||||||
|
"3.8": self.key_local_machine_64 + "-3.8-path\\python.exe",
|
||||||
|
"3.8-32": self.key_current_user + "-3.8-32-path\\python.exe",
|
||||||
|
"3.8-64": self.key_local_machine_64 + "-3.8-path\\python.exe",
|
||||||
|
}
|
||||||
|
assert mock_winreg.mock_calls == [
|
||||||
|
call.OpenKey(mock_winreg.HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore", 0, 0x11),
|
||||||
|
call.EnumKey(self.key_local_machine, 0),
|
||||||
|
call.QueryValue(self.key_local_machine, "2.4\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine, 1),
|
||||||
|
call.QueryValue(self.key_local_machine, "2.7\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine, 2),
|
||||||
|
call.QueryValue(self.key_local_machine, "3.2\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine, 3),
|
||||||
|
call.QueryValue(self.key_local_machine, "3.4\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine, 4),
|
||||||
|
call.QueryValue(self.key_local_machine, "3.6-32\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine, 5),
|
||||||
|
call.QueryValue(self.key_local_machine, "3.7-32\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine, 6),
|
||||||
|
call.CloseKey(self.key_local_machine),
|
||||||
|
call.OpenKey(mock_winreg.HKEY_CURRENT_USER, "Software\\Python\\PythonCore", 0, 0x11),
|
||||||
|
call.EnumKey(self.key_current_user, 0),
|
||||||
|
call.QueryValue(self.key_current_user, "2.5\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_current_user, 1),
|
||||||
|
call.QueryValue(self.key_current_user, "2.7\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_current_user, 2),
|
||||||
|
call.QueryValue(self.key_current_user, "3.8-32\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_current_user, 3),
|
||||||
|
call.CloseKey(self.key_current_user),
|
||||||
|
call.OpenKey(mock_winreg.HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore", 0, 0x12),
|
||||||
|
call.EnumKey(self.key_local_machine_64, 0),
|
||||||
|
call.QueryValue(self.key_local_machine_64, "2.6\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine_64, 1),
|
||||||
|
call.QueryValue(self.key_local_machine_64, "3.5\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine_64, 2),
|
||||||
|
call.QueryValue(self.key_local_machine_64, "3.7\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine_64, 3),
|
||||||
|
call.QueryValue(self.key_local_machine_64, "3.8\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_local_machine_64, 4),
|
||||||
|
call.CloseKey(self.key_local_machine_64),
|
||||||
|
call.OpenKey(mock_winreg.HKEY_CURRENT_USER, "Software\\Python\\PythonCore", 0, 0x12),
|
||||||
|
call.EnumKey(self.key_current_user_64, 0),
|
||||||
|
call.QueryValue(self.key_current_user_64, "3.7\\InstallPath"),
|
||||||
|
call.EnumKey(self.key_current_user_64, 1),
|
||||||
|
call.CloseKey(self.key_current_user_64),
|
||||||
|
]
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform != "win32", reason="windows specific test")
|
||||||
|
def test_on_windows_with_no_installations(self, monkeypatch):
|
||||||
|
assert virtualenv.IS_WIN
|
||||||
|
mock_winreg = self.mock_virtualenv_winreg(monkeypatch, {})
|
||||||
|
|
||||||
|
installed_pythons = virtualenv.get_installed_pythons()
|
||||||
|
|
||||||
|
assert installed_pythons == {}
|
||||||
|
assert mock_winreg.mock_calls == [
|
||||||
|
call.OpenKey(mock_winreg.HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore", 0, 0x11),
|
||||||
|
call.EnumKey(self.key_local_machine, 0),
|
||||||
|
call.CloseKey(self.key_local_machine),
|
||||||
|
call.OpenKey(mock_winreg.HKEY_CURRENT_USER, "Software\\Python\\PythonCore", 0, 0x11),
|
||||||
|
call.EnumKey(self.key_current_user, 0),
|
||||||
|
call.CloseKey(self.key_current_user),
|
||||||
|
call.OpenKey(mock_winreg.HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore", 0, 0x12),
|
||||||
|
call.EnumKey(self.key_local_machine_64, 0),
|
||||||
|
call.CloseKey(self.key_local_machine_64),
|
||||||
|
call.OpenKey(mock_winreg.HKEY_CURRENT_USER, "Software\\Python\\PythonCore", 0, 0x12),
|
||||||
|
call.EnumKey(self.key_current_user_64, 0),
|
||||||
|
call.CloseKey(self.key_current_user_64),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@patch("distutils.spawn.find_executable")
|
||||||
|
@patch("virtualenv.is_executable", return_value=True)
|
||||||
|
@patch("virtualenv.get_installed_pythons")
|
||||||
|
@patch("os.path.exists", return_value=True)
|
||||||
|
@patch("os.path.abspath")
|
||||||
|
def test_resolve_interpreter_with_installed_python(
|
||||||
|
mock_abspath, mock_exists, mock_get_installed_pythons, mock_is_executable, mock_find_executable
|
||||||
|
):
|
||||||
|
test_tag = "foo"
|
||||||
|
test_path = "/path/to/foo/python.exe"
|
||||||
|
test_abs_path = "some-abs-path"
|
||||||
|
test_found_path = "some-found-path"
|
||||||
|
mock_get_installed_pythons.return_value = {test_tag: test_path, test_tag + "2": test_path + "2"}
|
||||||
|
mock_abspath.return_value = test_abs_path
|
||||||
|
mock_find_executable.return_value = test_found_path
|
||||||
|
|
||||||
|
exe = virtualenv.resolve_interpreter("foo")
|
||||||
|
|
||||||
|
assert exe == test_found_path, "installed python should be accessible by key"
|
||||||
|
|
||||||
|
mock_get_installed_pythons.assert_called_once_with()
|
||||||
|
mock_abspath.assert_called_once_with(test_path)
|
||||||
|
mock_find_executable.assert_called_once_with(test_path)
|
||||||
|
mock_exists.assert_called_once_with(test_found_path)
|
||||||
|
mock_is_executable.assert_called_once_with(test_found_path)
|
||||||
|
|
||||||
|
|
||||||
|
@patch("virtualenv.is_executable", return_value=True)
|
||||||
|
@patch("virtualenv.get_installed_pythons", return_value={"foo": "bar"})
|
||||||
|
@patch("os.path.exists", return_value=True)
|
||||||
|
def test_resolve_interpreter_with_absolute_path(mock_exists, mock_get_installed_pythons, mock_is_executable):
|
||||||
"""Should return absolute path if given and 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")
|
test_abs_path = os.path.abspath("/usr/bin/python53")
|
||||||
|
|
||||||
exe = virtualenv.resolve_interpreter(test_abs_path)
|
exe = virtualenv.resolve_interpreter(test_abs_path)
|
||||||
@ -27,99 +259,99 @@ def test_resolve_interpreter_with_absolute_path(mock_exists):
|
|||||||
assert exe == test_abs_path, "Absolute path should return as is"
|
assert exe == test_abs_path, "Absolute path should return as is"
|
||||||
|
|
||||||
mock_exists.assert_called_with(test_abs_path)
|
mock_exists.assert_called_with(test_abs_path)
|
||||||
virtualenv.is_executable.assert_called_with(test_abs_path)
|
mock_is_executable.assert_called_with(test_abs_path)
|
||||||
|
|
||||||
|
|
||||||
@patch('os.path.exists')
|
@patch("virtualenv.get_installed_pythons", return_value={"foo": "bar"})
|
||||||
def test_resolve_interpreter_with_nonexistent_interpreter(mock_exists):
|
@patch("os.path.exists", return_value=False)
|
||||||
|
def test_resolve_interpreter_with_nonexistent_interpreter(mock_exists, mock_get_installed_pythons):
|
||||||
"""Should SystemExit with an nonexistent python interpreter path"""
|
"""Should SystemExit with an nonexistent python interpreter path"""
|
||||||
mock_exists.return_value = False
|
|
||||||
|
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
virtualenv.resolve_interpreter("/usr/bin/python53")
|
virtualenv.resolve_interpreter("/usr/bin/python53")
|
||||||
|
|
||||||
mock_exists.assert_called_with("/usr/bin/python53")
|
mock_exists.assert_called_with("/usr/bin/python53")
|
||||||
|
|
||||||
|
|
||||||
@patch('os.path.exists')
|
@patch("virtualenv.is_executable", return_value=False)
|
||||||
def test_resolve_interpreter_with_invalid_interpreter(mock_exists):
|
@patch("os.path.exists", return_value=True)
|
||||||
|
def test_resolve_interpreter_with_invalid_interpreter(mock_exists, mock_is_executable):
|
||||||
"""Should exit when with absolute path if not 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")
|
invalid = os.path.abspath("/usr/bin/pyt_hon53")
|
||||||
|
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
virtualenv.resolve_interpreter(invalid)
|
virtualenv.resolve_interpreter(invalid)
|
||||||
|
|
||||||
mock_exists.assert_called_with(invalid)
|
mock_exists.assert_called_with(invalid)
|
||||||
virtualenv.is_executable.assert_called_with(invalid)
|
mock_is_executable.assert_called_with(invalid)
|
||||||
|
|
||||||
|
|
||||||
def test_activate_after_future_statements():
|
def test_activate_after_future_statements():
|
||||||
"""Should insert activation line after last future statement"""
|
"""Should insert activation line after last future statement"""
|
||||||
script = [
|
script = [
|
||||||
'#!/usr/bin/env python',
|
"#!/usr/bin/env python",
|
||||||
'from __future__ import with_statement',
|
"from __future__ import with_statement",
|
||||||
'from __future__ import print_function',
|
"from __future__ import print_function",
|
||||||
'print("Hello, world!")'
|
'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!")'
|
|
||||||
]
|
]
|
||||||
|
out = virtualenv.relative_script(script)
|
||||||
|
assert out == [
|
||||||
|
"#!/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'), { '__file__': activate_this}); "
|
||||||
|
"del os, activate_this",
|
||||||
|
"",
|
||||||
|
'print("Hello, world!")',
|
||||||
|
], out
|
||||||
|
|
||||||
|
|
||||||
def test_cop_update_defaults_with_store_false():
|
def test_cop_update_defaults_with_store_false():
|
||||||
"""store_false options need reverted logic"""
|
"""store_false options need reverted logic"""
|
||||||
|
|
||||||
class MyConfigOptionParser(virtualenv.ConfigOptionParser):
|
class MyConfigOptionParser(virtualenv.ConfigOptionParser):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.config = virtualenv.ConfigParser.RawConfigParser()
|
self.config = virtualenv.ConfigParser.RawConfigParser()
|
||||||
self.files = []
|
self.files = []
|
||||||
optparse.OptionParser.__init__(self, *args, **kwargs)
|
optparse.OptionParser.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def get_environ_vars(self, prefix='VIRTUALENV_'):
|
def get_environ_vars(self, prefix="VIRTUALENV_"):
|
||||||
yield ("no_site_packages", "1")
|
yield ("no_site_packages", "1")
|
||||||
|
|
||||||
cop = MyConfigOptionParser()
|
cop = MyConfigOptionParser()
|
||||||
cop.add_option(
|
cop.add_option(
|
||||||
'--no-site-packages',
|
"--no-site-packages",
|
||||||
dest='system_site_packages',
|
dest="system_site_packages",
|
||||||
action='store_false',
|
action="store_false",
|
||||||
help="Don't give access to the global site-packages dir to the "
|
help="Don't give access to the global site-packages dir to the " "virtual environment (default)",
|
||||||
"virtual environment (default)")
|
)
|
||||||
|
|
||||||
defaults = {}
|
defaults = {}
|
||||||
cop.update_defaults(defaults)
|
cop.update_defaults(defaults)
|
||||||
assert defaults == {'system_site_packages': 0}
|
assert defaults == {"system_site_packages": 0}
|
||||||
|
|
||||||
|
|
||||||
def test_install_python_bin():
|
def test_install_python_bin():
|
||||||
"""Should create the right python executables and links"""
|
"""Should create the right python executables and links"""
|
||||||
tmp_virtualenv = tempfile.mkdtemp()
|
tmp_virtualenv = tempfile.mkdtemp()
|
||||||
try:
|
try:
|
||||||
home_dir, lib_dir, inc_dir, bin_dir = \
|
home_dir, lib_dir, inc_dir, bin_dir = virtualenv.path_locations(tmp_virtualenv)
|
||||||
virtualenv.path_locations(tmp_virtualenv)
|
virtualenv.install_python(home_dir, lib_dir, inc_dir, bin_dir, False, False)
|
||||||
virtualenv.install_python(home_dir, lib_dir, inc_dir, bin_dir, False,
|
|
||||||
False)
|
|
||||||
|
|
||||||
if virtualenv.is_win:
|
if virtualenv.IS_WIN:
|
||||||
required_executables = ['python.exe', 'pythonw.exe']
|
required_executables = ["python.exe", "pythonw.exe"]
|
||||||
else:
|
else:
|
||||||
py_exe_no_version = 'python'
|
py_exe_no_version = "python"
|
||||||
py_exe_version_major = 'python%s' % sys.version_info[0]
|
py_exe_version_major = "python%s" % sys.version_info[0]
|
||||||
py_exe_version_major_minor = 'python%s.%s' % (
|
py_exe_version_major_minor = "python{}.{}".format(sys.version_info[0], sys.version_info[1])
|
||||||
sys.version_info[0], sys.version_info[1])
|
required_executables = [py_exe_no_version, py_exe_version_major, py_exe_version_major_minor]
|
||||||
required_executables = [py_exe_no_version, py_exe_version_major,
|
|
||||||
py_exe_version_major_minor]
|
|
||||||
|
|
||||||
for pth in required_executables:
|
for pth in required_executables:
|
||||||
assert os.path.exists(os.path.join(bin_dir, pth)), \
|
assert os.path.exists(os.path.join(bin_dir, pth)), "%s should exist in bin_dir" % pth
|
||||||
("%s should exist in bin_dir" % pth)
|
root_inc_dir = os.path.join(home_dir, "include")
|
||||||
|
assert not os.path.islink(root_inc_dir)
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(tmp_virtualenv)
|
shutil.rmtree(tmp_virtualenv)
|
||||||
|
|
||||||
@ -128,14 +360,309 @@ def test_install_python_bin():
|
|||||||
def test_always_copy_option():
|
def test_always_copy_option():
|
||||||
"""Should be no symlinks in directory tree"""
|
"""Should be no symlinks in directory tree"""
|
||||||
tmp_virtualenv = tempfile.mkdtemp()
|
tmp_virtualenv = tempfile.mkdtemp()
|
||||||
ve_path = os.path.join(tmp_virtualenv, 'venv')
|
ve_path = os.path.join(tmp_virtualenv, "venv")
|
||||||
try:
|
try:
|
||||||
virtualenv.create_environment(ve_path, symlink=False)
|
virtualenv.create_environment(ve_path, symlink=False)
|
||||||
|
|
||||||
for root, dirs, files in os.walk(tmp_virtualenv):
|
for root, dirs, files in os.walk(tmp_virtualenv):
|
||||||
for f in files + dirs:
|
for f in files + dirs:
|
||||||
full_name = os.path.join(root, f)
|
full_name = os.path.join(root, f)
|
||||||
assert not os.path.islink(full_name), "%s should not be a" \
|
assert not os.path.islink(full_name), "%s should not be a" " symlink (to %s)" % (
|
||||||
" symlink (to %s)" % (full_name, os.readlink(full_name))
|
full_name,
|
||||||
|
os.readlink(full_name),
|
||||||
|
)
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(tmp_virtualenv)
|
shutil.rmtree(tmp_virtualenv)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not hasattr(os, "symlink"), reason="requires working symlink implementation")
|
||||||
|
def test_relative_symlink(tmpdir):
|
||||||
|
""" Test if a virtualenv works correctly if it was created via a symlink and this symlink is removed """
|
||||||
|
|
||||||
|
tmpdir = str(tmpdir)
|
||||||
|
ve_path = os.path.join(tmpdir, "venv")
|
||||||
|
os.mkdir(ve_path)
|
||||||
|
|
||||||
|
workdir = os.path.join(tmpdir, "work")
|
||||||
|
os.mkdir(workdir)
|
||||||
|
|
||||||
|
ve_path_linked = os.path.join(workdir, "venv")
|
||||||
|
os.symlink(ve_path, ve_path_linked)
|
||||||
|
|
||||||
|
lib64 = os.path.join(ve_path, "lib64")
|
||||||
|
|
||||||
|
virtualenv.create_environment(ve_path_linked, symlink=True)
|
||||||
|
if not os.path.lexists(lib64):
|
||||||
|
# no lib 64 on this platform
|
||||||
|
return
|
||||||
|
|
||||||
|
assert os.path.exists(lib64)
|
||||||
|
|
||||||
|
shutil.rmtree(workdir)
|
||||||
|
|
||||||
|
assert os.path.exists(lib64)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not hasattr(os, "symlink"), reason="requires working symlink implementation")
|
||||||
|
def test_copyfile_from_symlink(tmp_path):
|
||||||
|
"""Test that copyfile works correctly when the source is a symlink with a
|
||||||
|
relative target, and a symlink to a symlink. (This can occur when creating
|
||||||
|
an environment if Python was installed using stow or homebrew.)"""
|
||||||
|
|
||||||
|
# Set up src/link2 -> ../src/link1 -> file.
|
||||||
|
# We will copy to a different directory, so misinterpreting either symlink
|
||||||
|
# will be detected.
|
||||||
|
src_dir = tmp_path / "src"
|
||||||
|
src_dir.mkdir()
|
||||||
|
with open(str(src_dir / "file"), "w") as f:
|
||||||
|
f.write("contents")
|
||||||
|
os.symlink("file", str(src_dir / "link1"))
|
||||||
|
os.symlink(str(Path("..") / "src" / "link1"), str(src_dir / "link2"))
|
||||||
|
|
||||||
|
# Check that copyfile works on link2.
|
||||||
|
# This may produce a symlink or a regular file depending on the platform --
|
||||||
|
# which doesn't matter as long as it has the right contents.
|
||||||
|
copy_path = tmp_path / "copy"
|
||||||
|
virtualenv.copyfile(str(src_dir / "link2"), str(copy_path))
|
||||||
|
with open(str(copy_path), "r") as f:
|
||||||
|
assert f.read() == "contents"
|
||||||
|
|
||||||
|
shutil.rmtree(str(src_dir))
|
||||||
|
os.remove(str(copy_path))
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_certifi_pem(tmp_path):
|
||||||
|
"""Make sure that we can still create virtual environment if pip is
|
||||||
|
patched to not use certifi's cacert.pem and the file is removed.
|
||||||
|
This can happen if pip is packaged by Linux distributions."""
|
||||||
|
proj_dir = Path(__file__).parent.parent
|
||||||
|
support_original = proj_dir / "virtualenv_support"
|
||||||
|
pip_wheel = sorted(support_original.glob("pip*whl"))[0]
|
||||||
|
whl_name = pip_wheel.name
|
||||||
|
|
||||||
|
wheeldir = tmp_path / "wheels"
|
||||||
|
wheeldir.mkdir()
|
||||||
|
tmpcert = tmp_path / "tmpcert.pem"
|
||||||
|
cacert = "pip/_vendor/certifi/cacert.pem"
|
||||||
|
certifi = "pip/_vendor/certifi/core.py"
|
||||||
|
oldpath = b"os.path.join(f, 'cacert.pem')"
|
||||||
|
newpath = "r'{}'".format(tmpcert).encode()
|
||||||
|
removed = False
|
||||||
|
replaced = False
|
||||||
|
|
||||||
|
with zipfile.ZipFile(str(pip_wheel), "r") as whlin:
|
||||||
|
with zipfile.ZipFile(str(wheeldir / whl_name), "w") as whlout:
|
||||||
|
for item in whlin.infolist():
|
||||||
|
buff = whlin.read(item.filename)
|
||||||
|
if item.filename == cacert:
|
||||||
|
tmpcert.write_bytes(buff)
|
||||||
|
removed = True
|
||||||
|
continue
|
||||||
|
if item.filename == certifi:
|
||||||
|
nbuff = buff.replace(oldpath, newpath)
|
||||||
|
assert nbuff != buff
|
||||||
|
buff = nbuff
|
||||||
|
replaced = True
|
||||||
|
whlout.writestr(item, buff)
|
||||||
|
|
||||||
|
assert removed and replaced
|
||||||
|
|
||||||
|
venvdir = tmp_path / "venv"
|
||||||
|
search_dirs = [str(wheeldir), str(support_original)]
|
||||||
|
virtualenv.create_environment(str(venvdir), search_dirs=search_dirs)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_environment_from_dir_with_spaces(tmpdir):
|
||||||
|
"""Should work with wheel sources read from a dir with spaces."""
|
||||||
|
ve_path = str(tmpdir / "venv")
|
||||||
|
spaced_support_dir = str(tmpdir / "support with spaces")
|
||||||
|
from virtualenv_support import __file__ as support_dir
|
||||||
|
|
||||||
|
support_dir = os.path.dirname(os.path.abspath(support_dir))
|
||||||
|
shutil.copytree(support_dir, spaced_support_dir)
|
||||||
|
virtualenv.create_environment(ve_path, search_dirs=[spaced_support_dir])
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_environment_in_dir_with_spaces(tmpdir):
|
||||||
|
"""Should work with environment path containing spaces."""
|
||||||
|
ve_path = str(tmpdir / "venv with spaces")
|
||||||
|
virtualenv.create_environment(ve_path)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_environment_with_local_https_pypi(tmpdir):
|
||||||
|
"""Create virtual environment using local PyPI listening https with
|
||||||
|
certificate signed with custom certificate authority
|
||||||
|
"""
|
||||||
|
test_dir = Path(__file__).parent
|
||||||
|
ssl_dir = test_dir / "ssl"
|
||||||
|
proj_dir = test_dir.parent
|
||||||
|
support_dir = proj_dir / "virtualenv_support"
|
||||||
|
local_pypi_app = pypiserver.app(root=str(support_dir))
|
||||||
|
local_pypi = pytest_localserver.http.WSGIServer(
|
||||||
|
host="localhost",
|
||||||
|
port=0,
|
||||||
|
application=local_pypi_app,
|
||||||
|
ssl_context=(str(ssl_dir / "server.crt"), str(ssl_dir / "server.key")),
|
||||||
|
)
|
||||||
|
local_pypi.start()
|
||||||
|
local_pypi_url = "https://localhost:{}/".format(local_pypi.server_address[1])
|
||||||
|
venvdir = tmpdir / "venv"
|
||||||
|
pip_log = tmpdir / "pip.log"
|
||||||
|
env_addition = {
|
||||||
|
"PIP_CERT": str(ssl_dir / "rootCA.pem"),
|
||||||
|
"PIP_INDEX_URL": local_pypi_url,
|
||||||
|
"PIP_LOG": str(pip_log),
|
||||||
|
"PIP_RETRIES": "0",
|
||||||
|
}
|
||||||
|
if six.PY2:
|
||||||
|
env_addition = {key.encode("utf-8"): value.encode("utf-8") for key, value in env_addition.items()}
|
||||||
|
env_backup = {}
|
||||||
|
for key, value in env_addition.items():
|
||||||
|
if key in os.environ:
|
||||||
|
env_backup[key] = os.environ[key]
|
||||||
|
os.environ[key] = value
|
||||||
|
try:
|
||||||
|
virtualenv.create_environment(str(venvdir), download=True)
|
||||||
|
with pip_log.open("rb") as f:
|
||||||
|
assert b"SSLError" not in f.read()
|
||||||
|
finally:
|
||||||
|
local_pypi.stop()
|
||||||
|
for key in env_addition.keys():
|
||||||
|
os.environ.pop(key)
|
||||||
|
if key in env_backup:
|
||||||
|
os.environ[key] = env_backup[key]
|
||||||
|
|
||||||
|
|
||||||
|
def check_pypy_pre_import():
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# These modules(module_name, optional) are taken from PyPy's site.py:
|
||||||
|
# https://bitbucket.org/pypy/pypy/src/d0187cf2f1b70ec4b60f10673ff081bdd91e9a17/lib-python/2.7/site.py#lines-532:539
|
||||||
|
modules = [
|
||||||
|
("encodings", False),
|
||||||
|
("exceptions", True), # "exceptions" module does not exist in Python3
|
||||||
|
("zipimport", True),
|
||||||
|
]
|
||||||
|
|
||||||
|
for module, optional in modules:
|
||||||
|
if not optional or module in sys.builtin_module_names:
|
||||||
|
assert module in sys.modules, "missing {!r} in sys.modules".format(module)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("platform.python_implementation() != 'PyPy'")
|
||||||
|
def test_pypy_pre_import(tmp_path):
|
||||||
|
"""For PyPy, some built-in modules should be pre-imported because
|
||||||
|
some programs expect them to be in sys.modules on startup.
|
||||||
|
"""
|
||||||
|
check_code = inspect.getsource(check_pypy_pre_import)
|
||||||
|
check_code = textwrap.dedent(check_code[check_code.index("\n") + 1 :])
|
||||||
|
if six.PY2:
|
||||||
|
check_code = check_code.decode()
|
||||||
|
|
||||||
|
check_prog = tmp_path / "check-pre-import.py"
|
||||||
|
check_prog.write_text(check_code)
|
||||||
|
|
||||||
|
ve_path = str(tmp_path / "venv")
|
||||||
|
virtualenv.create_environment(ve_path)
|
||||||
|
|
||||||
|
bin_dir = virtualenv.path_locations(ve_path)[-1]
|
||||||
|
|
||||||
|
try:
|
||||||
|
cmd = [
|
||||||
|
os.path.join(bin_dir, "{}{}".format(virtualenv.EXPECTED_EXE, ".exe" if virtualenv.IS_WIN else "")),
|
||||||
|
str(check_prog),
|
||||||
|
]
|
||||||
|
subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
|
||||||
|
except subprocess.CalledProcessError as exception:
|
||||||
|
assert not exception.returncode, exception.output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not hasattr(os, "symlink"), reason="requires working symlink implementation")
|
||||||
|
def test_create_environment_with_exec_prefix_pointing_to_prefix(tmpdir):
|
||||||
|
"""Create virtual environment for Python with ``sys.exec_prefix`` pointing
|
||||||
|
to ``sys.prefix`` or ``sys.base_prefix`` or ``sys.real_prefix`` under a
|
||||||
|
different name
|
||||||
|
"""
|
||||||
|
venvdir = str(tmpdir / "venv")
|
||||||
|
python_dir = tmpdir / "python"
|
||||||
|
python_dir.mkdir()
|
||||||
|
path_key = str("PATH")
|
||||||
|
old_path = os.environ[path_key]
|
||||||
|
if hasattr(sys, "real_prefix"):
|
||||||
|
os.environ[path_key] = os.pathsep.join(
|
||||||
|
p for p in os.environ[path_key].split(os.pathsep) if not p.startswith(sys.prefix)
|
||||||
|
)
|
||||||
|
python = virtualenv.resolve_interpreter(os.path.basename(sys.executable))
|
||||||
|
try:
|
||||||
|
subprocess.check_call([sys.executable, "-m", "virtualenv", "-p", python, venvdir])
|
||||||
|
home_dir, lib_dir, inc_dir, bin_dir = virtualenv.path_locations(venvdir)
|
||||||
|
assert not os.path.islink(os.path.join(lib_dir, "distutils"))
|
||||||
|
finally:
|
||||||
|
os.environ[path_key] = old_path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not hasattr(sys, "real_prefix"), reason="requires running from inside virtualenv")
|
||||||
|
def test_create_environment_from_virtual_environment(tmpdir):
|
||||||
|
"""Create virtual environment using Python from another virtual environment
|
||||||
|
"""
|
||||||
|
venvdir = str(tmpdir / "venv")
|
||||||
|
home_dir, lib_dir, inc_dir, bin_dir = virtualenv.path_locations(venvdir)
|
||||||
|
virtualenv.create_environment(venvdir)
|
||||||
|
assert not os.path.islink(os.path.join(lib_dir, "distutils"))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(std_venv is None, reason="needs standard venv module")
|
||||||
|
def test_create_environment_from_venv(tmpdir):
|
||||||
|
std_venv_dir = str(tmpdir / "stdvenv")
|
||||||
|
ve_venv_dir = str(tmpdir / "vevenv")
|
||||||
|
home_dir, lib_dir, inc_dir, bin_dir = virtualenv.path_locations(ve_venv_dir)
|
||||||
|
builder = std_venv.EnvBuilder()
|
||||||
|
ctx = builder.ensure_directories(std_venv_dir)
|
||||||
|
builder.create_configuration(ctx)
|
||||||
|
builder.setup_python(ctx)
|
||||||
|
builder.setup_scripts(ctx)
|
||||||
|
subprocess.check_call([ctx.env_exe, virtualenv.__file__, "--no-setuptools", "--no-pip", "--no-wheel", ve_venv_dir])
|
||||||
|
ve_exe = os.path.join(bin_dir, "python")
|
||||||
|
out = subprocess.check_output([ve_exe, "-c", "import sys; print(sys.real_prefix)"], universal_newlines=True)
|
||||||
|
# Test against real_prefix if present - we might be running the test from a virtualenv (e.g. tox).
|
||||||
|
assert out.strip() == getattr(sys, "real_prefix", sys.prefix)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(std_venv is None, reason="needs standard venv module")
|
||||||
|
def test_create_environment_from_venv_no_pip(tmpdir):
|
||||||
|
std_venv_dir = str(tmpdir / "stdvenv")
|
||||||
|
ve_venv_dir = str(tmpdir / "vevenv")
|
||||||
|
home_dir, lib_dir, inc_dir, bin_dir = virtualenv.path_locations(ve_venv_dir)
|
||||||
|
builder = std_venv.EnvBuilder()
|
||||||
|
ctx = builder.ensure_directories(std_venv_dir)
|
||||||
|
builder.create_configuration(ctx)
|
||||||
|
builder.setup_python(ctx)
|
||||||
|
builder.setup_scripts(ctx)
|
||||||
|
subprocess.check_call([ctx.env_exe, virtualenv.__file__, "--no-pip", ve_venv_dir])
|
||||||
|
ve_exe = os.path.join(bin_dir, "python")
|
||||||
|
out = subprocess.check_output([ve_exe, "-c", "import sys; print(sys.real_prefix)"], universal_newlines=True)
|
||||||
|
# Test against real_prefix if present - we might be running the test from a virtualenv (e.g. tox).
|
||||||
|
assert out.strip() == getattr(sys, "real_prefix", sys.prefix)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_environment_with_old_pip(tmpdir):
|
||||||
|
old = Path(__file__).parent / "old-wheels"
|
||||||
|
old_pip = old / "pip-9.0.1-py2.py3-none-any.whl"
|
||||||
|
old_setuptools = old / "setuptools-30.4.0-py2.py3-none-any.whl"
|
||||||
|
support_dir = str(tmpdir / "virtualenv_support")
|
||||||
|
os.makedirs(support_dir)
|
||||||
|
for old_dep in [old_pip, old_setuptools]:
|
||||||
|
shutil.copy(str(old_dep), support_dir)
|
||||||
|
venvdir = str(tmpdir / "venv")
|
||||||
|
virtualenv.create_environment(venvdir, search_dirs=[support_dir], no_wheel=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_license_builtin(clean_python):
|
||||||
|
_, bin_dir, _ = clean_python
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
(os.path.join(bin_dir, "python"), "-c", "license()"), stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
out_b, _ = proc.communicate(b"q\n")
|
||||||
|
out = out_b.decode()
|
||||||
|
assert not proc.returncode
|
||||||
|
assert "Ian Bicking and Contributors" not in out
|
||||||
|
100
python/virtualenv/tests/test_zipapp.py
Normal file
100
python/virtualenv/tests/test_zipapp.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os.path
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import six
|
||||||
|
|
||||||
|
import virtualenv
|
||||||
|
|
||||||
|
HERE = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def _python(v):
|
||||||
|
return virtualenv.get_installed_pythons().get(v, "python{}".format(v))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def call_zipapp(tmp_path_factory, call_subprocess):
|
||||||
|
if sys.version_info < (3, 5):
|
||||||
|
pytest.skip("zipapp was introduced in python3.5")
|
||||||
|
pyz = str(tmp_path_factory.mktemp(basename="zipapp") / "virtualenv.pyz")
|
||||||
|
call_subprocess(
|
||||||
|
(sys.executable, os.path.join(HERE, "tasks/make_zipapp.py"), "--root", virtualenv.HERE, "--dest", pyz)
|
||||||
|
)
|
||||||
|
|
||||||
|
def zipapp_make_env(path, python=None):
|
||||||
|
cmd = (sys.executable, pyz, "--no-download", path)
|
||||||
|
if python:
|
||||||
|
cmd += ("-p", python)
|
||||||
|
call_subprocess(cmd)
|
||||||
|
|
||||||
|
return zipapp_make_env
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def call_wheel(tmp_path_factory, call_subprocess):
|
||||||
|
wheels = tmp_path_factory.mktemp(basename="wheel")
|
||||||
|
call_subprocess((sys.executable, "-m", "pip", "wheel", "--no-deps", "-w", str(wheels), HERE))
|
||||||
|
(wheel,) = wheels.iterdir()
|
||||||
|
|
||||||
|
def wheel_make_env(path, python=None):
|
||||||
|
cmd = (sys.executable, "-m", "virtualenv", "--no-download", path)
|
||||||
|
if python:
|
||||||
|
cmd += ("-p", python)
|
||||||
|
env = dict(os.environ, PYTHONPATH=str(wheel))
|
||||||
|
call_subprocess(cmd, env=env)
|
||||||
|
|
||||||
|
return wheel_make_env
|
||||||
|
|
||||||
|
|
||||||
|
def test_zipapp_basic_invocation(call_zipapp, tmp_path):
|
||||||
|
_test_basic_invocation(call_zipapp, tmp_path)
|
||||||
|
|
||||||
|
|
||||||
|
def test_wheel_basic_invocation(call_wheel, tmp_path):
|
||||||
|
_test_basic_invocation(call_wheel, tmp_path)
|
||||||
|
|
||||||
|
|
||||||
|
def _test_basic_invocation(make_env, tmp_path):
|
||||||
|
venv = tmp_path / "venv"
|
||||||
|
make_env(str(venv))
|
||||||
|
assert_venv_looks_good(
|
||||||
|
venv, list(sys.version_info), "{}{}".format(virtualenv.EXPECTED_EXE, ".exe" if virtualenv.IS_WIN else "")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def version_exe(venv, exe_name):
|
||||||
|
_, _, _, bin_dir = virtualenv.path_locations(str(venv))
|
||||||
|
exe = os.path.join(bin_dir, exe_name)
|
||||||
|
script = "import sys; import json; print(json.dumps(dict(v=list(sys.version_info), e=sys.executable)))"
|
||||||
|
cmd = [exe, "-c", script]
|
||||||
|
out = json.loads(subprocess.check_output(cmd, universal_newlines=True))
|
||||||
|
return out["v"], out["e"]
|
||||||
|
|
||||||
|
|
||||||
|
def assert_venv_looks_good(venv, version_info, exe_name):
|
||||||
|
assert venv.exists()
|
||||||
|
version, exe = version_exe(venv, exe_name=exe_name)
|
||||||
|
assert version[: len(version_info)] == version_info
|
||||||
|
assert exe != sys.executable
|
||||||
|
|
||||||
|
|
||||||
|
def _test_invocation_dash_p(make_env, tmp_path):
|
||||||
|
venv = tmp_path / "venv"
|
||||||
|
python = {2: _python("3"), 3: _python("2.7")}[sys.version_info[0]]
|
||||||
|
make_env(str(venv), python)
|
||||||
|
expected = {3: 2, 2: 3}[sys.version_info[0]]
|
||||||
|
assert_venv_looks_good(venv, [expected], "python{}".format(".exe" if virtualenv.IS_WIN else ""))
|
||||||
|
|
||||||
|
|
||||||
|
def test_zipapp_invocation_dash_p(call_zipapp, tmp_path):
|
||||||
|
_test_invocation_dash_p(call_zipapp, tmp_path)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform == "win32" and six.PY2, reason="no python 3 for windows on CI")
|
||||||
|
def test_wheel_invocation_dash_p(call_wheel, tmp_path):
|
||||||
|
_test_invocation_dash_p(call_wheel, tmp_path)
|
127
python/virtualenv/tox.ini
Normal file
127
python/virtualenv/tox.ini
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
[tox]
|
||||||
|
minversion = 3.6.1
|
||||||
|
envlist = fix_lint, embed, py{27,34,35,36,37}, pypy{,3}, cross_python{2,3}, docs, package_readme
|
||||||
|
isolated_build = true
|
||||||
|
skip_missing_interpreters = true
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
description = run tests with {basepython}
|
||||||
|
deps = pip >= 19.1.1
|
||||||
|
setenv = COVERAGE_FILE = {env:COVERAGE_FILE:{toxworkdir}/.coverage.{envname}}
|
||||||
|
passenv = https_proxy http_proxy no_proxy HOME PYTEST_* PIP_* CI_RUN TERM
|
||||||
|
extras = testing
|
||||||
|
install_command = python -m pip install {opts} {packages} --disable-pip-version-check
|
||||||
|
commands = coverage run --source=virtualenv \
|
||||||
|
-m pytest tests \
|
||||||
|
{posargs:\
|
||||||
|
--junitxml={env:JUNIT_XML_FILE:{toxworkdir}/junit.{envname}.xml} \
|
||||||
|
}
|
||||||
|
coverage combine
|
||||||
|
coverage report --show-missing
|
||||||
|
|
||||||
|
[testenv:coverage]
|
||||||
|
description = [run locally after tests]: combine coverage data and create report;
|
||||||
|
generates a diff coverage against origin/master (can be changed by setting DIFF_AGAINST env var)
|
||||||
|
deps = {[testenv]deps}
|
||||||
|
coverage >= 4.4.1, < 5
|
||||||
|
diff_cover
|
||||||
|
extras =
|
||||||
|
skip_install = True
|
||||||
|
passenv = DIFF_AGAINST
|
||||||
|
setenv = COVERAGE_FILE={toxworkdir}/.coverage
|
||||||
|
commands = coverage combine
|
||||||
|
coverage report --show-missing
|
||||||
|
coverage xml -o {toxworkdir}/coverage.xml
|
||||||
|
coverage html -d {toxworkdir}/htmlcov
|
||||||
|
diff-cover --compare-branch {env:DIFF_AGAINST:origin/master} {toxworkdir}/coverage.xml
|
||||||
|
|
||||||
|
[testenv:cross_python2]
|
||||||
|
description = test creating a python3 venv with a python2-based virtualenv
|
||||||
|
basepython = python2
|
||||||
|
extras =
|
||||||
|
commands = virtualenv -p python3 {envtmpdir}/{envname}
|
||||||
|
{envtmpdir}/{envname}/bin/python -V 2>&1 | grep "Python 3"
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:cross_python3]
|
||||||
|
description = test creating a python2 venv with a python3-based virtualenv
|
||||||
|
basepython = python3
|
||||||
|
extras =
|
||||||
|
commands = virtualenv -p python2 {envtmpdir}/{envname}
|
||||||
|
{envtmpdir}/{envname}/bin/python -V 2>&1 | grep "Python 2"
|
||||||
|
|
||||||
|
[testenv:docs]
|
||||||
|
basepython = python3
|
||||||
|
description = build documentation
|
||||||
|
extras = docs
|
||||||
|
commands = sphinx-build -d "{envtmpdir}/doctree" -W docs "{toxworkdir}/docs_out" --color -bhtml {posargs}
|
||||||
|
python -c 'import pathlib; print("documentation available under file://\{0\}".format(pathlib.Path(r"{toxworkdir}") / "docs_out" / "index.html"))'
|
||||||
|
|
||||||
|
[testenv:package_readme]
|
||||||
|
description = check that the long description is valid (need for PyPi)
|
||||||
|
deps = {[testenv]deps}
|
||||||
|
twine >= 1.12.1
|
||||||
|
skip_install = true
|
||||||
|
extras =
|
||||||
|
commands = pip wheel -w {envtmpdir}/build --no-deps .
|
||||||
|
twine check {envtmpdir}/build/*
|
||||||
|
|
||||||
|
[testenv:embed]
|
||||||
|
description = embed dependencies into virtualenv.py
|
||||||
|
skip_install = true
|
||||||
|
changedir = {toxinidir}/tasks
|
||||||
|
extras =
|
||||||
|
commands = python update_embedded.py
|
||||||
|
|
||||||
|
[testenv:upgrade]
|
||||||
|
description = upgrade pip/wheels/setuptools to latest
|
||||||
|
skip_install = true
|
||||||
|
changedir = {toxinidir}/tasks
|
||||||
|
commands = python upgrade_wheels.py
|
||||||
|
|
||||||
|
[testenv:fix_lint]
|
||||||
|
description = format the code base to adhere to our styles, and complain about what we cannot do automatically
|
||||||
|
basepython = python3.8
|
||||||
|
passenv = *
|
||||||
|
deps = {[testenv]deps}
|
||||||
|
pre-commit >= 1.12.0, <2
|
||||||
|
skip_install = True
|
||||||
|
commands = pre-commit run --all-files --show-diff-on-failure
|
||||||
|
python -c 'import pathlib; print("hint: run \{\} install to add checks as pre-commit hook".format(pathlib.Path(r"{envdir}") / "bin" / "pre-commit"))'
|
||||||
|
|
||||||
|
[isort]
|
||||||
|
multi_line_output = 3
|
||||||
|
include_trailing_comma = True
|
||||||
|
force_grid_wrap = 0
|
||||||
|
line_length = 120
|
||||||
|
known_standard_library = ConfigParser
|
||||||
|
known_first_party = virtualenv
|
||||||
|
known_third_party = git,packaging,pypiserver,pytest,pytest_localserver,setuptools,six
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
max-complexity = 22
|
||||||
|
max-line-length = 120
|
||||||
|
ignore = E203, W503, C901, E402
|
||||||
|
exclude = virtualenv_embedded/site.py
|
||||||
|
|
||||||
|
[pep8]
|
||||||
|
max-line-length = 120
|
||||||
|
|
||||||
|
[testenv:dev]
|
||||||
|
description = generate a DEV environment
|
||||||
|
extras = testing, docs
|
||||||
|
usedevelop = True
|
||||||
|
commands = python -m pip list --format=columns
|
||||||
|
python -c 'import sys; print(sys.executable)'
|
||||||
|
|
||||||
|
[testenv:release]
|
||||||
|
description = do a release, required posarg of the version number
|
||||||
|
basepython = python3.8
|
||||||
|
skip_install = true
|
||||||
|
passenv = *
|
||||||
|
deps = {[testenv]deps}
|
||||||
|
gitpython >= 2.1.10, < 3
|
||||||
|
towncrier >= 18.5.0
|
||||||
|
packaging >= 17.1
|
||||||
|
changedir = {toxinidir}/tasks
|
||||||
|
commands = python release.py --version {posargs}
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
set "VIRTUAL_ENV=__VIRTUAL_ENV__"
|
set "VIRTUAL_ENV=__VIRTUAL_ENV__"
|
||||||
|
|
||||||
if defined _OLD_VIRTUAL_PROMPT (
|
if defined _OLD_VIRTUAL_PROMPT (
|
||||||
@ -7,9 +8,13 @@ if defined _OLD_VIRTUAL_PROMPT (
|
|||||||
if not defined PROMPT (
|
if not defined PROMPT (
|
||||||
set "PROMPT=$P$G"
|
set "PROMPT=$P$G"
|
||||||
)
|
)
|
||||||
|
if not defined VIRTUAL_ENV_DISABLE_PROMPT (
|
||||||
set "_OLD_VIRTUAL_PROMPT=%PROMPT%"
|
set "_OLD_VIRTUAL_PROMPT=%PROMPT%"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not defined VIRTUAL_ENV_DISABLE_PROMPT (
|
||||||
|
set "PROMPT=__VIRTUAL_WINPROMPT__%PROMPT%"
|
||||||
)
|
)
|
||||||
set "PROMPT=__VIRTUAL_WINPROMPT__ %PROMPT%"
|
|
||||||
|
|
||||||
REM Don't use () to avoid problems with them in %PATH%
|
REM Don't use () to avoid problems with them in %PATH%
|
||||||
if defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME
|
if defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME
|
||||||
|
@ -2,35 +2,54 @@
|
|||||||
# You cannot run it directly.
|
# You cannot run it directly.
|
||||||
# Created by Davide Di Blasi <davidedb@gmail.com>.
|
# 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'
|
set newline='\
|
||||||
|
'
|
||||||
|
|
||||||
|
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc'
|
||||||
|
|
||||||
# Unset irrelevant variables.
|
# Unset irrelevant variables.
|
||||||
deactivate nondestructive
|
deactivate nondestructive
|
||||||
|
|
||||||
setenv VIRTUAL_ENV "__VIRTUAL_ENV__"
|
setenv VIRTUAL_ENV "__VIRTUAL_ENV__"
|
||||||
|
|
||||||
set _OLD_VIRTUAL_PATH="$PATH"
|
set _OLD_VIRTUAL_PATH="$PATH:q"
|
||||||
setenv PATH "$VIRTUAL_ENV/__BIN_NAME__:$PATH"
|
setenv PATH "$VIRTUAL_ENV:q/__BIN_NAME__:$PATH:q"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ("__VIRTUAL_PROMPT__" != "") then
|
if ("__VIRTUAL_PROMPT__" != "") then
|
||||||
set env_name = "__VIRTUAL_PROMPT__"
|
set env_name = "__VIRTUAL_PROMPT__"
|
||||||
else
|
else
|
||||||
set env_name = `basename "$VIRTUAL_ENV"`
|
set env_name = '('"$VIRTUAL_ENV:t:q"') '
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Could be in a non-interactive environment,
|
if ( $?VIRTUAL_ENV_DISABLE_PROMPT ) then
|
||||||
# in which case, $prompt is undefined and we wouldn't
|
if ( $VIRTUAL_ENV_DISABLE_PROMPT == "" ) then
|
||||||
# care about the prompt anyway.
|
set do_prompt = "1"
|
||||||
if ( $?prompt ) then
|
else
|
||||||
set _OLD_VIRTUAL_PROMPT="$prompt"
|
set do_prompt = "0"
|
||||||
set prompt = "[$env_name] $prompt"
|
endif
|
||||||
|
else
|
||||||
|
set do_prompt = "1"
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ( $do_prompt == "1" ) then
|
||||||
|
# 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:q"
|
||||||
|
if ( "$prompt:q" =~ *"$newline:q"* ) then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
set prompt = "$env_name:q$prompt:q"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
unset env_name
|
unset env_name
|
||||||
|
unset do_prompt
|
||||||
|
|
||||||
alias pydoc python -m pydoc
|
alias pydoc python -m pydoc
|
||||||
|
|
||||||
rehash
|
rehash
|
||||||
|
|
||||||
|
@ -1,10 +1,28 @@
|
|||||||
# This file must be used using `. bin/activate.fish` *within a running fish ( http://fishshell.com ) session*.
|
# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*.
|
||||||
# Do not run it directly.
|
# Do not run it directly.
|
||||||
|
|
||||||
|
function _bashify_path -d "Converts a fish path to something bash can recognize"
|
||||||
|
set fishy_path $argv
|
||||||
|
set bashy_path $fishy_path[1]
|
||||||
|
for path_part in $fishy_path[2..-1]
|
||||||
|
set bashy_path "$bashy_path:$path_part"
|
||||||
|
end
|
||||||
|
echo $bashy_path
|
||||||
|
end
|
||||||
|
|
||||||
|
function _fishify_path -d "Converts a bash path to something fish can recognize"
|
||||||
|
echo $argv | tr ':' '\n'
|
||||||
|
end
|
||||||
|
|
||||||
function deactivate -d 'Exit virtualenv mode and return to the normal environment.'
|
function deactivate -d 'Exit virtualenv mode and return to the normal environment.'
|
||||||
# reset old environment variables
|
# reset old environment variables
|
||||||
if test -n "$_OLD_VIRTUAL_PATH"
|
if test -n "$_OLD_VIRTUAL_PATH"
|
||||||
|
# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling
|
||||||
|
if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3
|
||||||
|
set -gx PATH (_fishify_path $_OLD_VIRTUAL_PATH)
|
||||||
|
else
|
||||||
set -gx PATH $_OLD_VIRTUAL_PATH
|
set -gx PATH $_OLD_VIRTUAL_PATH
|
||||||
|
end
|
||||||
set -e _OLD_VIRTUAL_PATH
|
set -e _OLD_VIRTUAL_PATH
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -14,6 +32,7 @@ function deactivate -d 'Exit virtualenv mode and return to the normal environmen
|
|||||||
end
|
end
|
||||||
|
|
||||||
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
|
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
|
||||||
|
and functions -q _old_fish_prompt
|
||||||
# Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`.
|
# Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`.
|
||||||
set -l fish_function_path
|
set -l fish_function_path
|
||||||
|
|
||||||
@ -30,6 +49,8 @@ function deactivate -d 'Exit virtualenv mode and return to the normal environmen
|
|||||||
# Self-destruct!
|
# Self-destruct!
|
||||||
functions -e pydoc
|
functions -e pydoc
|
||||||
functions -e deactivate
|
functions -e deactivate
|
||||||
|
functions -e _bashify_path
|
||||||
|
functions -e _fishify_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -38,7 +59,12 @@ deactivate nondestructive
|
|||||||
|
|
||||||
set -gx VIRTUAL_ENV "__VIRTUAL_ENV__"
|
set -gx VIRTUAL_ENV "__VIRTUAL_ENV__"
|
||||||
|
|
||||||
set -gx _OLD_VIRTUAL_PATH $PATH
|
# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling
|
||||||
|
if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3
|
||||||
|
set -gx _OLD_VIRTUAL_PATH (_bashify_path $PATH)
|
||||||
|
else
|
||||||
|
set -gx _OLD_VIRTUAL_PATH $PATH
|
||||||
|
end
|
||||||
set -gx PATH "$VIRTUAL_ENV/__BIN_NAME__" $PATH
|
set -gx PATH "$VIRTUAL_ENV/__BIN_NAME__" $PATH
|
||||||
|
|
||||||
# Unset `$PYTHONHOME` if set.
|
# Unset `$PYTHONHOME` if set.
|
||||||
|
@ -1,150 +1,60 @@
|
|||||||
# 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:THIS_PATH = $myinvocation.mycommand.path
|
||||||
$script:BASE_DIR = split-path (resolve-path "$THIS_PATH/..") -Parent
|
$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent
|
||||||
$script:DIR_NAME = split-path $BASE_DIR -Leaf
|
|
||||||
|
|
||||||
function global:deactivate ( [switch] $NonDestructive ){
|
function global:deactivate([switch] $NonDestructive) {
|
||||||
|
if (Test-Path variable:_OLD_VIRTUAL_PATH) {
|
||||||
if ( test-path variable:_OLD_VIRTUAL_PATH ) {
|
|
||||||
$env:PATH = $variable:_OLD_VIRTUAL_PATH
|
$env:PATH = $variable:_OLD_VIRTUAL_PATH
|
||||||
remove-variable "_OLD_VIRTUAL_PATH" -scope global
|
Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( test-path function:_old_virtual_prompt ) {
|
if (Test-Path function:_old_virtual_prompt) {
|
||||||
$function:prompt = $function:_old_virtual_prompt
|
$function:prompt = $function:_old_virtual_prompt
|
||||||
remove-item function:\_old_virtual_prompt
|
Remove-Item function:\_old_virtual_prompt
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($env:VIRTUAL_ENV) {
|
if ($env:VIRTUAL_ENV) {
|
||||||
$old_env = split-path $env:VIRTUAL_ENV -leaf
|
Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue
|
||||||
remove-item env:VIRTUAL_ENV -erroraction silentlycontinue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !$NonDestructive ) {
|
if (!$NonDestructive) {
|
||||||
# Self destruct!
|
# Self destruct!
|
||||||
remove-item function:deactivate
|
Remove-Item function:deactivate
|
||||||
|
Remove-Item function:pydoc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function global:pydoc {
|
||||||
|
python -m pydoc $args
|
||||||
|
}
|
||||||
|
|
||||||
# unset irrelevant variables
|
# unset irrelevant variables
|
||||||
deactivate -nondestructive
|
deactivate -nondestructive
|
||||||
|
|
||||||
$VIRTUAL_ENV = $BASE_DIR
|
$VIRTUAL_ENV = $BASE_DIR
|
||||||
$env:VIRTUAL_ENV = $VIRTUAL_ENV
|
$env:VIRTUAL_ENV = $VIRTUAL_ENV
|
||||||
|
|
||||||
$global:_OLD_VIRTUAL_PATH = $env:PATH
|
New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH
|
||||||
$env:PATH = "$env:VIRTUAL_ENV/Scripts;" + $env:PATH
|
|
||||||
if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
$env:PATH = "$env:VIRTUAL_ENV/__BIN_NAME____PATH_SEP__" + $env:PATH
|
||||||
function global:_old_virtual_prompt { "" }
|
if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
||||||
|
function global:_old_virtual_prompt {
|
||||||
|
""
|
||||||
|
}
|
||||||
$function:_old_virtual_prompt = $function:prompt
|
$function:_old_virtual_prompt = $function:prompt
|
||||||
|
|
||||||
|
if ("__VIRTUAL_PROMPT__" -ne "") {
|
||||||
|
function global:prompt {
|
||||||
|
# Add the custom prefix to the existing prompt
|
||||||
|
$previous_prompt_value = & $function:_old_virtual_prompt
|
||||||
|
("__VIRTUAL_PROMPT__" + $previous_prompt_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
function global:prompt {
|
function global:prompt {
|
||||||
# Add a prefix to the current prompt, but don't discard it.
|
# Add a prefix to the current prompt, but don't discard it.
|
||||||
write-host "($(split-path $env:VIRTUAL_ENV -leaf)) " -nonewline
|
$previous_prompt_value = & $function:_old_virtual_prompt
|
||||||
& $function:_old_virtual_prompt
|
$new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) "
|
||||||
|
($new_prompt_value + $previous_prompt_value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 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
|
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
# This file must be used with "source bin/activate" *from bash*
|
# This file must be used with "source bin/activate" *from bash*
|
||||||
# you cannot run it directly
|
# you cannot run it directly
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${BASH_SOURCE-}" = "$0" ]; then
|
||||||
|
echo "You must source this script: \$ source $0" >&2
|
||||||
|
exit 33
|
||||||
|
fi
|
||||||
|
|
||||||
deactivate () {
|
deactivate () {
|
||||||
unset -f pydoc >/dev/null 2>&1
|
unset -f pydoc >/dev/null 2>&1
|
||||||
|
|
||||||
# reset old environment variables
|
# reset old environment variables
|
||||||
# ! [ -z ${VAR+_} ] returns true if VAR is declared at all
|
# ! [ -z ${VAR+_} ] returns true if VAR is declared at all
|
||||||
if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then
|
if ! [ -z "${_OLD_VIRTUAL_PATH:+_}" ] ; then
|
||||||
PATH="$_OLD_VIRTUAL_PATH"
|
PATH="$_OLD_VIRTUAL_PATH"
|
||||||
export PATH
|
export PATH
|
||||||
unset _OLD_VIRTUAL_PATH
|
unset _OLD_VIRTUAL_PATH
|
||||||
@ -54,17 +60,17 @@ if ! [ -z "${PYTHONHOME+_}" ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
|
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
|
||||||
_OLD_VIRTUAL_PS1="$PS1"
|
_OLD_VIRTUAL_PS1="${PS1-}"
|
||||||
if [ "x__VIRTUAL_PROMPT__" != x ] ; then
|
if [ "x__VIRTUAL_PROMPT__" != x ] ; then
|
||||||
PS1="__VIRTUAL_PROMPT__$PS1"
|
PS1="__VIRTUAL_PROMPT__${PS1-}"
|
||||||
else
|
else
|
||||||
PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1"
|
PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}"
|
||||||
fi
|
fi
|
||||||
export PS1
|
export PS1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Make sure to unalias pydoc if it's already there
|
# Make sure to unalias pydoc if it's already there
|
||||||
alias pydoc 2>/dev/null >/dev/null && unalias pydoc
|
alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true
|
||||||
|
|
||||||
pydoc () {
|
pydoc () {
|
||||||
python -m pydoc "$@"
|
python -m pydoc "$@"
|
||||||
|
46
python/virtualenv/virtualenv_embedded/activate.xsh
Normal file
46
python/virtualenv/virtualenv_embedded/activate.xsh
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
"""Xonsh activate script for virtualenv"""
|
||||||
|
from xonsh.tools import get_sep as _get_sep
|
||||||
|
|
||||||
|
def _deactivate(args):
|
||||||
|
if "pydoc" in aliases:
|
||||||
|
del aliases["pydoc"]
|
||||||
|
|
||||||
|
if ${...}.get("_OLD_VIRTUAL_PATH", ""):
|
||||||
|
$PATH = $_OLD_VIRTUAL_PATH
|
||||||
|
del $_OLD_VIRTUAL_PATH
|
||||||
|
|
||||||
|
if ${...}.get("_OLD_VIRTUAL_PYTHONHOME", ""):
|
||||||
|
$PYTHONHOME = $_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
del $_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
|
||||||
|
if "VIRTUAL_ENV" in ${...}:
|
||||||
|
del $VIRTUAL_ENV
|
||||||
|
|
||||||
|
if "VIRTUAL_ENV_PROMPT" in ${...}:
|
||||||
|
del $VIRTUAL_ENV_PROMPT
|
||||||
|
|
||||||
|
if "nondestructive" not in args:
|
||||||
|
# Self destruct!
|
||||||
|
del aliases["deactivate"]
|
||||||
|
|
||||||
|
|
||||||
|
# unset irrelevant variables
|
||||||
|
_deactivate(["nondestructive"])
|
||||||
|
aliases["deactivate"] = _deactivate
|
||||||
|
|
||||||
|
$VIRTUAL_ENV = r"__VIRTUAL_ENV__"
|
||||||
|
|
||||||
|
$_OLD_VIRTUAL_PATH = $PATH
|
||||||
|
$PATH = $PATH[:]
|
||||||
|
$PATH.add($VIRTUAL_ENV + _get_sep() + "__BIN_NAME__", front=True, replace=True)
|
||||||
|
|
||||||
|
if ${...}.get("PYTHONHOME", ""):
|
||||||
|
# unset PYTHONHOME if set
|
||||||
|
$_OLD_VIRTUAL_PYTHONHOME = $PYTHONHOME
|
||||||
|
del $PYTHONHOME
|
||||||
|
|
||||||
|
$VIRTUAL_ENV_PROMPT = "__VIRTUAL_PROMPT__"
|
||||||
|
if not $VIRTUAL_ENV_PROMPT:
|
||||||
|
del $VIRTUAL_ENV_PROMPT
|
||||||
|
|
||||||
|
aliases["pydoc"] = ["python", "-m", "pydoc"]
|
@ -1,34 +1,46 @@
|
|||||||
"""By using execfile(this_file, dict(__file__=this_file)) you will
|
"""Activate virtualenv for current interpreter:
|
||||||
activate this virtualenv environment.
|
|
||||||
|
|
||||||
This can be used when you must use an existing Python interpreter, not
|
Use exec(open(this_file).read(), {'__file__': this_file}).
|
||||||
the virtualenv bin/python
|
|
||||||
|
This can be used when you must use an existing Python interpreter, not the virtualenv bin/python.
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
|
import site
|
||||||
|
import sys
|
||||||
|
|
||||||
try:
|
try:
|
||||||
__file__
|
__file__
|
||||||
except NameError:
|
except NameError:
|
||||||
raise AssertionError(
|
raise AssertionError("You must use exec(open(this_file).read(), {'__file__': this_file}))")
|
||||||
"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', '')
|
# prepend bin to PATH (this file is inside the bin directory)
|
||||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path
|
bin_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
os.environ["PATH"] = os.pathsep.join([bin_dir] + os.environ.get("PATH", "").split(os.pathsep))
|
||||||
if sys.platform == 'win32':
|
|
||||||
site_packages = os.path.join(base, 'Lib', 'site-packages')
|
base = os.path.dirname(bin_dir)
|
||||||
|
|
||||||
|
# virtual env is right above bin directory
|
||||||
|
os.environ["VIRTUAL_ENV"] = base
|
||||||
|
|
||||||
|
# add the virtual environments site-package to the host python import mechanism
|
||||||
|
IS_PYPY = hasattr(sys, "pypy_version_info")
|
||||||
|
IS_JYTHON = sys.platform.startswith("java")
|
||||||
|
if IS_JYTHON:
|
||||||
|
site_packages = os.path.join(base, "Lib", "site-packages")
|
||||||
|
elif IS_PYPY:
|
||||||
|
site_packages = os.path.join(base, "site-packages")
|
||||||
else:
|
else:
|
||||||
site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages')
|
IS_WIN = sys.platform == "win32"
|
||||||
prev_sys_path = list(sys.path)
|
if IS_WIN:
|
||||||
import site
|
site_packages = os.path.join(base, "Lib", "site-packages")
|
||||||
|
else:
|
||||||
|
site_packages = os.path.join(base, "lib", "python{}.{}".format(*sys.version_info), "site-packages")
|
||||||
|
|
||||||
|
prev = set(sys.path)
|
||||||
site.addsitedir(site_packages)
|
site.addsitedir(site_packages)
|
||||||
sys.real_prefix = sys.prefix
|
sys.real_prefix = sys.prefix
|
||||||
sys.prefix = base
|
sys.prefix = base
|
||||||
# Move the added items to the front of the path:
|
|
||||||
new_sys_path = []
|
# Move the added items to the front of the path, in place
|
||||||
for item in list(sys.path):
|
new = list(sys.path)
|
||||||
if item not in prev_sys_path:
|
sys.path[:] = [i for i in new if i not in prev] + [i for i in new if i in prev]
|
||||||
new_sys_path.append(item)
|
|
||||||
sys.path.remove(item)
|
|
||||||
sys.path[:0] = new_sys_path
|
|
||||||
|
@ -1,20 +1,39 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
import imp
|
|
||||||
import opcode # opcode is not a virtualenv module, so we can use it to find the stdlib
|
# 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
|
# Important! To work on pypy, this must be a module that resides in the
|
||||||
# lib-python/modified-x.y.z directory
|
# lib-python/modified-x.y.z directory
|
||||||
|
import opcode
|
||||||
|
|
||||||
dirname = os.path.dirname
|
dirname = os.path.dirname
|
||||||
|
|
||||||
distutils_path = os.path.join(os.path.dirname(opcode.__file__), 'distutils')
|
distutils_path = os.path.join(os.path.dirname(opcode.__file__), "distutils")
|
||||||
if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)):
|
if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)):
|
||||||
warnings.warn(
|
warnings.warn("The virtualenv distutils package at %s appears to be in the same location as the system distutils?")
|
||||||
"The virtualenv distutils package at %s appears to be in the same location as the system distutils?")
|
|
||||||
else:
|
else:
|
||||||
__path__.insert(0, distutils_path)
|
__path__.insert(0, distutils_path) # noqa: F821
|
||||||
real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ('', '', imp.PKG_DIRECTORY))
|
if sys.version_info < (3, 4):
|
||||||
|
import imp
|
||||||
|
|
||||||
|
real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ("", "", imp.PKG_DIRECTORY))
|
||||||
|
else:
|
||||||
|
import importlib.machinery
|
||||||
|
|
||||||
|
distutils_path = os.path.join(distutils_path, "__init__.py")
|
||||||
|
loader = importlib.machinery.SourceFileLoader("_virtualenv_distutils", distutils_path)
|
||||||
|
if sys.version_info < (3, 5):
|
||||||
|
import types
|
||||||
|
|
||||||
|
real_distutils = types.ModuleType(loader.name)
|
||||||
|
else:
|
||||||
|
import importlib.util
|
||||||
|
|
||||||
|
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||||
|
real_distutils = importlib.util.module_from_spec(spec)
|
||||||
|
loader.exec_module(real_distutils)
|
||||||
|
|
||||||
# Copy the relevant attributes
|
# Copy the relevant attributes
|
||||||
try:
|
try:
|
||||||
__revision__ = real_distutils.__revision__
|
__revision__ = real_distutils.__revision__
|
||||||
@ -22,20 +41,21 @@ else:
|
|||||||
pass
|
pass
|
||||||
__version__ = real_distutils.__version__
|
__version__ = real_distutils.__version__
|
||||||
|
|
||||||
from distutils import dist, sysconfig
|
from distutils import dist, sysconfig # isort:skip
|
||||||
|
|
||||||
try:
|
try:
|
||||||
basestring
|
basestring
|
||||||
except NameError:
|
except NameError:
|
||||||
basestring = str
|
basestring = str
|
||||||
|
|
||||||
## patch build_ext (distutils doesn't know how to get the libs directory
|
# 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)
|
# path on windows - it hardcodes the paths around the patched sys.prefix)
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == "win32":
|
||||||
from distutils.command.build_ext import build_ext as old_build_ext
|
from distutils.command.build_ext import build_ext as old_build_ext
|
||||||
|
|
||||||
class build_ext(old_build_ext):
|
class build_ext(old_build_ext):
|
||||||
def finalize_options (self):
|
def finalize_options(self):
|
||||||
if self.library_dirs is None:
|
if self.library_dirs is None:
|
||||||
self.library_dirs = []
|
self.library_dirs = []
|
||||||
elif isinstance(self.library_dirs, basestring):
|
elif isinstance(self.library_dirs, basestring):
|
||||||
@ -45,57 +65,70 @@ if sys.platform == 'win32':
|
|||||||
old_build_ext.finalize_options(self)
|
old_build_ext.finalize_options(self)
|
||||||
|
|
||||||
from distutils.command import build_ext as build_ext_module
|
from distutils.command import build_ext as build_ext_module
|
||||||
|
|
||||||
build_ext_module.build_ext = build_ext
|
build_ext_module.build_ext = build_ext
|
||||||
|
|
||||||
## distutils.dist patches:
|
# distutils.dist patches:
|
||||||
|
|
||||||
old_find_config_files = dist.Distribution.find_config_files
|
old_find_config_files = dist.Distribution.find_config_files
|
||||||
|
|
||||||
|
|
||||||
def find_config_files(self):
|
def find_config_files(self):
|
||||||
found = old_find_config_files(self)
|
found = old_find_config_files(self)
|
||||||
system_distutils = os.path.join(distutils_path, 'distutils.cfg')
|
if os.name == "posix":
|
||||||
#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"
|
user_filename = ".pydistutils.cfg"
|
||||||
else:
|
else:
|
||||||
user_filename = "pydistutils.cfg"
|
user_filename = "pydistutils.cfg"
|
||||||
user_filename = os.path.join(sys.prefix, user_filename)
|
user_filename = os.path.join(sys.prefix, user_filename)
|
||||||
if os.path.isfile(user_filename):
|
if os.path.isfile(user_filename):
|
||||||
for item in list(found):
|
for item in list(found):
|
||||||
if item.endswith('pydistutils.cfg'):
|
if item.endswith("pydistutils.cfg"):
|
||||||
found.remove(item)
|
found.remove(item)
|
||||||
found.append(user_filename)
|
found.append(user_filename)
|
||||||
return found
|
return found
|
||||||
|
|
||||||
|
|
||||||
dist.Distribution.find_config_files = find_config_files
|
dist.Distribution.find_config_files = find_config_files
|
||||||
|
|
||||||
## distutils.sysconfig patches:
|
# distutils.sysconfig patches:
|
||||||
|
|
||||||
old_get_python_inc = sysconfig.get_python_inc
|
old_get_python_inc = sysconfig.get_python_inc
|
||||||
|
|
||||||
|
|
||||||
def sysconfig_get_python_inc(plat_specific=0, prefix=None):
|
def sysconfig_get_python_inc(plat_specific=0, prefix=None):
|
||||||
if prefix is None:
|
if prefix is None:
|
||||||
prefix = sys.real_prefix
|
prefix = sys.real_prefix
|
||||||
return old_get_python_inc(plat_specific, prefix)
|
return old_get_python_inc(plat_specific, prefix)
|
||||||
|
|
||||||
|
|
||||||
sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__
|
sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__
|
||||||
sysconfig.get_python_inc = sysconfig_get_python_inc
|
sysconfig.get_python_inc = sysconfig_get_python_inc
|
||||||
|
|
||||||
old_get_python_lib = sysconfig.get_python_lib
|
old_get_python_lib = sysconfig.get_python_lib
|
||||||
|
|
||||||
|
|
||||||
def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
|
def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
|
||||||
if standard_lib and prefix is None:
|
if standard_lib and prefix is None:
|
||||||
prefix = sys.real_prefix
|
prefix = sys.real_prefix
|
||||||
return old_get_python_lib(plat_specific, standard_lib, 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.__doc__ = old_get_python_lib.__doc__
|
||||||
sysconfig.get_python_lib = sysconfig_get_python_lib
|
sysconfig.get_python_lib = sysconfig_get_python_lib
|
||||||
|
|
||||||
old_get_config_vars = sysconfig.get_config_vars
|
old_get_config_vars = sysconfig.get_config_vars
|
||||||
|
|
||||||
|
|
||||||
def sysconfig_get_config_vars(*args):
|
def sysconfig_get_config_vars(*args):
|
||||||
real_vars = old_get_config_vars(*args)
|
real_vars = old_get_config_vars(*args)
|
||||||
if sys.platform == 'win32':
|
if sys.platform == "win32":
|
||||||
lib_dir = os.path.join(sys.real_prefix, "libs")
|
lib_dir = os.path.join(sys.real_prefix, "libs")
|
||||||
if isinstance(real_vars, dict) and 'LIBDIR' not in real_vars:
|
if isinstance(real_vars, dict) and "LIBDIR" not in real_vars:
|
||||||
real_vars['LIBDIR'] = lib_dir # asked for all
|
real_vars["LIBDIR"] = lib_dir # asked for all
|
||||||
elif isinstance(real_vars, list) and 'LIBDIR' in args:
|
elif isinstance(real_vars, list) and "LIBDIR" in args:
|
||||||
real_vars = real_vars + [lib_dir] # asked for list
|
real_vars = real_vars + [lib_dir] # asked for list
|
||||||
return real_vars
|
return real_vars
|
||||||
|
|
||||||
|
|
||||||
sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__
|
sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__
|
||||||
sysconfig.get_config_vars = sysconfig_get_config_vars
|
sysconfig.get_config_vars = sysconfig_get_config_vars
|
||||||
|
@ -63,8 +63,9 @@ ImportError exception, it is silently ignored.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import __builtin__ as builtins
|
import __builtin__ as builtins
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -83,33 +84,25 @@ ENABLE_USER_SITE = None
|
|||||||
USER_SITE = None
|
USER_SITE = None
|
||||||
USER_BASE = None
|
USER_BASE = None
|
||||||
|
|
||||||
_is_64bit = (getattr(sys, 'maxsize', None) or getattr(sys, 'maxint')) > 2**32
|
_is_64bit = (getattr(sys, "maxsize", None) or getattr(sys, "maxint")) > 2 ** 32
|
||||||
_is_pypy = hasattr(sys, 'pypy_version_info')
|
_is_pypy = hasattr(sys, "pypy_version_info")
|
||||||
_is_jython = sys.platform[:4] == 'java'
|
|
||||||
if _is_jython:
|
|
||||||
ModuleType = type(os)
|
|
||||||
|
|
||||||
def makepath(*paths):
|
def makepath(*paths):
|
||||||
dir = os.path.join(*paths)
|
dir = os.path.join(*paths)
|
||||||
if _is_jython and (dir == '__classpath__' or
|
|
||||||
dir.startswith('__pyclasspath__')):
|
|
||||||
return dir, dir
|
|
||||||
dir = os.path.abspath(dir)
|
dir = os.path.abspath(dir)
|
||||||
return dir, os.path.normcase(dir)
|
return dir, os.path.normcase(dir)
|
||||||
|
|
||||||
|
|
||||||
def abs__file__():
|
def abs__file__():
|
||||||
"""Set all module' __file__ attribute to an absolute path"""
|
"""Set all module' __file__ attribute to an absolute path"""
|
||||||
for m in sys.modules.values():
|
for m in sys.modules.values():
|
||||||
if ((_is_jython and not isinstance(m, ModuleType)) or
|
f = getattr(m, "__file__", None)
|
||||||
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:
|
if f is None:
|
||||||
continue
|
continue
|
||||||
m.__file__ = os.path.abspath(f)
|
m.__file__ = os.path.abspath(f)
|
||||||
|
|
||||||
|
|
||||||
def removeduppaths():
|
def removeduppaths():
|
||||||
""" Remove duplicate entries from sys.path along with making them
|
""" Remove duplicate entries from sys.path along with making them
|
||||||
absolute"""
|
absolute"""
|
||||||
@ -128,18 +121,21 @@ def removeduppaths():
|
|||||||
sys.path[:] = L
|
sys.path[:] = L
|
||||||
return known_paths
|
return known_paths
|
||||||
|
|
||||||
|
|
||||||
# XXX This should not be part of site.py, since it is needed even when
|
# 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
|
# using the -S option for Python. See http://www.python.org/sf/586680
|
||||||
def addbuilddir():
|
def addbuilddir():
|
||||||
"""Append ./build/lib.<platform> in case we're running in the build dir
|
"""Append ./build/lib.<platform> in case we're running in the build dir
|
||||||
(especially for Guido :-)"""
|
(especially for Guido :-)"""
|
||||||
from distutils.util import get_platform
|
from distutils.util import get_platform
|
||||||
s = "build/lib.%s-%.3s" % (get_platform(), sys.version)
|
|
||||||
if hasattr(sys, 'gettotalrefcount'):
|
s = "build/lib.{}-{}.{}".format(get_platform(), *sys.version_info)
|
||||||
s += '-pydebug'
|
if hasattr(sys, "gettotalrefcount"):
|
||||||
|
s += "-pydebug"
|
||||||
s = os.path.join(os.path.dirname(sys.path[-1]), s)
|
s = os.path.join(os.path.dirname(sys.path[-1]), s)
|
||||||
sys.path.append(s)
|
sys.path.append(s)
|
||||||
|
|
||||||
|
|
||||||
def _init_pathinfo():
|
def _init_pathinfo():
|
||||||
"""Return a set containing all existing directory entries from sys.path"""
|
"""Return a set containing all existing directory entries from sys.path"""
|
||||||
d = set()
|
d = set()
|
||||||
@ -152,6 +148,7 @@ def _init_pathinfo():
|
|||||||
continue
|
continue
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
def addpackage(sitedir, name, known_paths):
|
def addpackage(sitedir, name, known_paths):
|
||||||
"""Add a new path to known_paths by combining sitedir and 'name' or execute
|
"""Add a new path to known_paths by combining sitedir and 'name' or execute
|
||||||
sitedir if it starts with 'import'"""
|
sitedir if it starts with 'import'"""
|
||||||
@ -162,7 +159,7 @@ def addpackage(sitedir, name, known_paths):
|
|||||||
reset = 0
|
reset = 0
|
||||||
fullname = os.path.join(sitedir, name)
|
fullname = os.path.join(sitedir, name)
|
||||||
try:
|
try:
|
||||||
f = open(fullname, "rU")
|
f = open(fullname, "r")
|
||||||
except IOError:
|
except IOError:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -183,6 +180,7 @@ def addpackage(sitedir, name, known_paths):
|
|||||||
known_paths = None
|
known_paths = None
|
||||||
return known_paths
|
return known_paths
|
||||||
|
|
||||||
|
|
||||||
def addsitedir(sitedir, known_paths=None):
|
def addsitedir(sitedir, known_paths=None):
|
||||||
"""Add 'sitedir' argument to sys.path if missing and handle .pth files in
|
"""Add 'sitedir' argument to sys.path if missing and handle .pth files in
|
||||||
'sitedir'"""
|
'sitedir'"""
|
||||||
@ -206,6 +204,7 @@ def addsitedir(sitedir, known_paths=None):
|
|||||||
known_paths = None
|
known_paths = None
|
||||||
return known_paths
|
return known_paths
|
||||||
|
|
||||||
|
|
||||||
def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix):
|
def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix):
|
||||||
"""Add site-packages (and possibly site-python) to sys.path"""
|
"""Add site-packages (and possibly site-python) to sys.path"""
|
||||||
prefixes = [os.path.join(sys_prefix, "local"), sys_prefix]
|
prefixes = [os.path.join(sys_prefix, "local"), sys_prefix]
|
||||||
@ -214,31 +213,32 @@ def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_pre
|
|||||||
|
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
if prefix:
|
if prefix:
|
||||||
if sys.platform in ('os2emx', 'riscos') or _is_jython:
|
if sys.platform in ("os2emx", "riscos"):
|
||||||
sitedirs = [os.path.join(prefix, "Lib", "site-packages")]
|
sitedirs = [os.path.join(prefix, "Lib", "site-packages")]
|
||||||
elif _is_pypy:
|
elif _is_pypy:
|
||||||
sitedirs = [os.path.join(prefix, 'site-packages')]
|
sitedirs = [os.path.join(prefix, "site-packages")]
|
||||||
elif sys.platform == 'darwin' and prefix == sys_prefix:
|
elif sys.platform == "darwin" and prefix == sys_prefix:
|
||||||
|
|
||||||
if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python
|
if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python
|
||||||
|
|
||||||
sitedirs = [os.path.join("/Library/Python", sys.version[:3], "site-packages"),
|
sitedirs = [
|
||||||
os.path.join(prefix, "Extras", "lib", "python")]
|
os.path.join("/Library/Python", "{}.{}".format(*sys.version_info), "site-packages"),
|
||||||
|
os.path.join(prefix, "Extras", "lib", "python"),
|
||||||
|
]
|
||||||
|
|
||||||
else: # any other Python distros on OSX work this way
|
else: # any other Python distros on OSX work this way
|
||||||
sitedirs = [os.path.join(prefix, "lib",
|
sitedirs = [os.path.join(prefix, "lib", "python{}.{}".format(*sys.version_info), "site-packages")]
|
||||||
"python" + sys.version[:3], "site-packages")]
|
|
||||||
|
|
||||||
elif os.sep == '/':
|
elif os.sep == "/":
|
||||||
sitedirs = [os.path.join(prefix,
|
sitedirs = [
|
||||||
"lib",
|
os.path.join(prefix, "lib", "python{}.{}".format(*sys.version_info), "site-packages"),
|
||||||
"python" + sys.version[:3],
|
|
||||||
"site-packages"),
|
|
||||||
os.path.join(prefix, "lib", "site-python"),
|
os.path.join(prefix, "lib", "site-python"),
|
||||||
os.path.join(prefix, "python" + sys.version[:3], "lib-dynload")]
|
os.path.join(prefix, "python{}.{}".format(*sys.version_info), "lib-dynload"),
|
||||||
lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages")
|
]
|
||||||
if (os.path.exists(lib64_dir) and
|
lib64_dir = os.path.join(prefix, "lib64", "python{}.{}".format(*sys.version_info), "site-packages")
|
||||||
os.path.realpath(lib64_dir) not in [os.path.realpath(p) for p in sitedirs]):
|
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:
|
if _is_64bit:
|
||||||
sitedirs.insert(0, lib64_dir)
|
sitedirs.insert(0, lib64_dir)
|
||||||
else:
|
else:
|
||||||
@ -246,42 +246,40 @@ def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_pre
|
|||||||
try:
|
try:
|
||||||
# sys.getobjects only available in --with-pydebug build
|
# sys.getobjects only available in --with-pydebug build
|
||||||
sys.getobjects
|
sys.getobjects
|
||||||
sitedirs.insert(0, os.path.join(sitedirs[0], 'debug'))
|
sitedirs.insert(0, os.path.join(sitedirs[0], "debug"))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
# Debian-specific dist-packages directories:
|
# Debian-specific dist-packages directories:
|
||||||
sitedirs.append(os.path.join(prefix, "local/lib",
|
sitedirs.append(
|
||||||
"python" + sys.version[:3],
|
os.path.join(prefix, "local/lib", "python{}.{}".format(*sys.version_info), "dist-packages")
|
||||||
"dist-packages"))
|
)
|
||||||
if sys.version[0] == '2':
|
if sys.version_info[0] == 2:
|
||||||
sitedirs.append(os.path.join(prefix, "lib",
|
sitedirs.append(
|
||||||
"python" + sys.version[:3],
|
os.path.join(prefix, "lib", "python{}.{}".format(*sys.version_info), "dist-packages")
|
||||||
"dist-packages"))
|
)
|
||||||
else:
|
else:
|
||||||
sitedirs.append(os.path.join(prefix, "lib",
|
sitedirs.append(
|
||||||
"python" + sys.version[0],
|
os.path.join(prefix, "lib", "python{}".format(sys.version_info[0]), "dist-packages")
|
||||||
"dist-packages"))
|
)
|
||||||
sitedirs.append(os.path.join(prefix, "lib", "dist-python"))
|
sitedirs.append(os.path.join(prefix, "lib", "dist-python"))
|
||||||
else:
|
else:
|
||||||
sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")]
|
sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")]
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == "darwin":
|
||||||
# for framework builds *only* we add the standard Apple
|
# for framework builds *only* we add the standard Apple
|
||||||
# locations. Currently only per-user, but /Library and
|
# locations. Currently only per-user, but /Library and
|
||||||
# /Network/Library could be added too
|
# /Network/Library could be added too
|
||||||
if 'Python.framework' in prefix:
|
if "Python.framework" in prefix or "Python3.framework" in prefix:
|
||||||
home = os.environ.get('HOME')
|
home = os.environ.get("HOME")
|
||||||
if home:
|
if home:
|
||||||
sitedirs.append(
|
sitedirs.append(
|
||||||
os.path.join(home,
|
os.path.join(home, "Library", "Python", "{}.{}".format(*sys.version_info), "site-packages")
|
||||||
'Library',
|
)
|
||||||
'Python',
|
|
||||||
sys.version[:3],
|
|
||||||
'site-packages'))
|
|
||||||
for sitedir in sitedirs:
|
for sitedir in sitedirs:
|
||||||
if os.path.isdir(sitedir):
|
if os.path.isdir(sitedir):
|
||||||
addsitedir(sitedir, known_paths)
|
addsitedir(sitedir, known_paths)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def check_enableusersite():
|
def check_enableusersite():
|
||||||
"""Check if user site directory is safe for inclusion
|
"""Check if user site directory is safe for inclusion
|
||||||
|
|
||||||
@ -292,7 +290,7 @@ def check_enableusersite():
|
|||||||
False: Disabled by user (command line option)
|
False: Disabled by user (command line option)
|
||||||
True: Safe and enabled
|
True: Safe and enabled
|
||||||
"""
|
"""
|
||||||
if hasattr(sys, 'flags') and getattr(sys.flags, 'no_user_site', False):
|
if hasattr(sys, "flags") and getattr(sys.flags, "no_user_site", False):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if hasattr(os, "getuid") and hasattr(os, "geteuid"):
|
if hasattr(os, "getuid") and hasattr(os, "geteuid"):
|
||||||
@ -306,6 +304,7 @@ def check_enableusersite():
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def addusersitepackages(known_paths):
|
def addusersitepackages(known_paths):
|
||||||
"""Add a per user site-package to sys.path
|
"""Add a per user site-package to sys.path
|
||||||
|
|
||||||
@ -324,7 +323,7 @@ def addusersitepackages(known_paths):
|
|||||||
def joinuser(*args):
|
def joinuser(*args):
|
||||||
return os.path.expanduser(os.path.join(*args))
|
return os.path.expanduser(os.path.join(*args))
|
||||||
|
|
||||||
#if sys.platform in ('os2emx', 'riscos'):
|
# if sys.platform in ('os2emx', 'riscos'):
|
||||||
# # Don't know what to put here
|
# # Don't know what to put here
|
||||||
# USER_BASE = ''
|
# USER_BASE = ''
|
||||||
# USER_SITE = ''
|
# USER_SITE = ''
|
||||||
@ -334,31 +333,24 @@ def addusersitepackages(known_paths):
|
|||||||
USER_BASE = env_base
|
USER_BASE = env_base
|
||||||
else:
|
else:
|
||||||
USER_BASE = joinuser(base, "Python")
|
USER_BASE = joinuser(base, "Python")
|
||||||
USER_SITE = os.path.join(USER_BASE,
|
USER_SITE = os.path.join(USER_BASE, "Python{}{}".format(*sys.version_info), "site-packages")
|
||||||
"Python" + sys.version[0] + sys.version[2],
|
|
||||||
"site-packages")
|
|
||||||
else:
|
else:
|
||||||
if env_base:
|
if env_base:
|
||||||
USER_BASE = env_base
|
USER_BASE = env_base
|
||||||
else:
|
else:
|
||||||
USER_BASE = joinuser("~", ".local")
|
USER_BASE = joinuser("~", ".local")
|
||||||
USER_SITE = os.path.join(USER_BASE, "lib",
|
USER_SITE = os.path.join(USER_BASE, "lib", "python{}.{}".format(*sys.version_info), "site-packages")
|
||||||
"python" + sys.version[:3],
|
|
||||||
"site-packages")
|
|
||||||
|
|
||||||
if ENABLE_USER_SITE and os.path.isdir(USER_SITE):
|
if ENABLE_USER_SITE and os.path.isdir(USER_SITE):
|
||||||
addsitedir(USER_SITE, known_paths)
|
addsitedir(USER_SITE, known_paths)
|
||||||
if ENABLE_USER_SITE:
|
if ENABLE_USER_SITE:
|
||||||
for dist_libdir in ("lib", "local/lib"):
|
for dist_libdir in ("lib", "local/lib"):
|
||||||
user_site = os.path.join(USER_BASE, dist_libdir,
|
user_site = os.path.join(USER_BASE, dist_libdir, "python{}.{}".format(*sys.version_info), "dist-packages")
|
||||||
"python" + sys.version[:3],
|
|
||||||
"dist-packages")
|
|
||||||
if os.path.isdir(user_site):
|
if os.path.isdir(user_site):
|
||||||
addsitedir(user_site, known_paths)
|
addsitedir(user_site, known_paths)
|
||||||
return known_paths
|
return known_paths
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def setBEGINLIBPATH():
|
def setBEGINLIBPATH():
|
||||||
"""The OS/2 EMX port has optional extension modules that do double duty
|
"""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.
|
as DLLs (and must use the .DLL file extension) for other extensions.
|
||||||
@ -368,12 +360,12 @@ def setBEGINLIBPATH():
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
|
dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
|
||||||
libpath = os.environ['BEGINLIBPATH'].split(';')
|
libpath = os.environ["BEGINLIBPATH"].split(";")
|
||||||
if libpath[-1]:
|
if libpath[-1]:
|
||||||
libpath.append(dllpath)
|
libpath.append(dllpath)
|
||||||
else:
|
else:
|
||||||
libpath[-1] = dllpath
|
libpath[-1] = dllpath
|
||||||
os.environ['BEGINLIBPATH'] = ';'.join(libpath)
|
os.environ["BEGINLIBPATH"] = ";".join(libpath)
|
||||||
|
|
||||||
|
|
||||||
def setquit():
|
def setquit():
|
||||||
@ -381,18 +373,20 @@ def setquit():
|
|||||||
These are simply strings that display a hint on how to exit.
|
These are simply strings that display a hint on how to exit.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if os.sep == ':':
|
if os.sep == ":":
|
||||||
eof = 'Cmd-Q'
|
eof = "Cmd-Q"
|
||||||
elif os.sep == '\\':
|
elif os.sep == "\\":
|
||||||
eof = 'Ctrl-Z plus Return'
|
eof = "Ctrl-Z plus Return"
|
||||||
else:
|
else:
|
||||||
eof = 'Ctrl-D (i.e. EOF)'
|
eof = "Ctrl-D (i.e. EOF)"
|
||||||
|
|
||||||
class Quitter(object):
|
class Quitter(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'Use %s() or %s to exit' % (self.name, eof)
|
return "Use {}() or {} to exit".format(self.name, eof)
|
||||||
|
|
||||||
def __call__(self, code=None):
|
def __call__(self, code=None):
|
||||||
# Shells like IDLE catch the SystemExit, but listen when their
|
# Shells like IDLE catch the SystemExit, but listen when their
|
||||||
# stdin wrapper is closed.
|
# stdin wrapper is closed.
|
||||||
@ -401,8 +395,9 @@ def setquit():
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
raise SystemExit(code)
|
raise SystemExit(code)
|
||||||
builtins.quit = Quitter('quit')
|
|
||||||
builtins.exit = Quitter('exit')
|
builtins.quit = Quitter("quit")
|
||||||
|
builtins.exit = Quitter("exit")
|
||||||
|
|
||||||
|
|
||||||
class _Printer(object):
|
class _Printer(object):
|
||||||
@ -426,7 +421,7 @@ class _Printer(object):
|
|||||||
for filename in self.__files:
|
for filename in self.__files:
|
||||||
filename = os.path.join(dir, filename)
|
filename = os.path.join(dir, filename)
|
||||||
try:
|
try:
|
||||||
fp = open(filename, "rU")
|
fp = open(filename, "r")
|
||||||
data = fp.read()
|
data = fp.read()
|
||||||
fp.close()
|
fp.close()
|
||||||
break
|
break
|
||||||
@ -436,7 +431,7 @@ class _Printer(object):
|
|||||||
break
|
break
|
||||||
if not data:
|
if not data:
|
||||||
data = self.__data
|
data = self.__data
|
||||||
self.__lines = data.split('\n')
|
self.__lines = data.split("\n")
|
||||||
self.__linecnt = len(self.__lines)
|
self.__linecnt = len(self.__lines)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@ -444,11 +439,11 @@ class _Printer(object):
|
|||||||
if len(self.__lines) <= self.MAXLINES:
|
if len(self.__lines) <= self.MAXLINES:
|
||||||
return "\n".join(self.__lines)
|
return "\n".join(self.__lines)
|
||||||
else:
|
else:
|
||||||
return "Type %s() to see the full %s text" % ((self.__name,)*2)
|
return "Type %s() to see the full %s text" % ((self.__name,) * 2)
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
self.__setup()
|
self.__setup()
|
||||||
prompt = 'Hit Return for more, or q (and Return) to quit: '
|
prompt = "Hit Return for more, or q (and Return) to quit: "
|
||||||
lineno = 0
|
lineno = 0
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
try:
|
||||||
@ -464,31 +459,31 @@ class _Printer(object):
|
|||||||
key = raw_input(prompt)
|
key = raw_input(prompt)
|
||||||
except NameError:
|
except NameError:
|
||||||
key = input(prompt)
|
key = input(prompt)
|
||||||
if key not in ('', 'q'):
|
if key not in ("", "q"):
|
||||||
key = None
|
key = None
|
||||||
if key == 'q':
|
if key == "q":
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
def setcopyright():
|
def setcopyright():
|
||||||
"""Set 'copyright' and 'credits' in __builtin__"""
|
"""Set 'copyright' and 'credits' in __builtin__"""
|
||||||
builtins.copyright = _Printer("copyright", sys.copyright)
|
builtins.copyright = _Printer("copyright", sys.copyright)
|
||||||
if _is_jython:
|
if _is_pypy:
|
||||||
builtins.credits = _Printer(
|
builtins.credits = _Printer("credits", "PyPy is maintained by the PyPy developers: http://pypy.org/")
|
||||||
"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:
|
else:
|
||||||
builtins.credits = _Printer("credits", """\
|
builtins.credits = _Printer(
|
||||||
|
"credits",
|
||||||
|
"""\
|
||||||
Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
|
Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
|
||||||
for supporting Python development. See www.python.org for more information.""")
|
for supporting Python development. See www.python.org for more information.""",
|
||||||
|
)
|
||||||
here = os.path.dirname(os.__file__)
|
here = os.path.dirname(os.__file__)
|
||||||
builtins.license = _Printer(
|
builtins.license = _Printer(
|
||||||
"license", "See http://www.python.org/%.3s/license.html" % sys.version,
|
"license",
|
||||||
|
"See https://www.python.org/psf/license/",
|
||||||
["LICENSE.txt", "LICENSE"],
|
["LICENSE.txt", "LICENSE"],
|
||||||
[os.path.join(here, os.pardir), here, os.curdir])
|
[sys.prefix, os.path.join(here, os.pardir), here, os.curdir],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class _Helper(object):
|
class _Helper(object):
|
||||||
@ -498,29 +493,35 @@ class _Helper(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "Type help() for interactive help, " \
|
return "Type help() for interactive help, " "or help(object) for help about object."
|
||||||
"or help(object) for help about object."
|
|
||||||
def __call__(self, *args, **kwds):
|
def __call__(self, *args, **kwds):
|
||||||
import pydoc
|
import pydoc
|
||||||
|
|
||||||
return pydoc.help(*args, **kwds)
|
return pydoc.help(*args, **kwds)
|
||||||
|
|
||||||
|
|
||||||
def sethelper():
|
def sethelper():
|
||||||
builtins.help = _Helper()
|
builtins.help = _Helper()
|
||||||
|
|
||||||
|
|
||||||
def aliasmbcs():
|
def aliasmbcs():
|
||||||
"""On Windows, some default encodings are not provided by Python,
|
"""On Windows, some default encodings are not provided by Python,
|
||||||
while they are always available as "mbcs" in each locale. Make
|
while they are always available as "mbcs" in each locale. Make
|
||||||
them usable by aliasing to "mbcs" in such a case."""
|
them usable by aliasing to "mbcs" in such a case."""
|
||||||
if sys.platform == 'win32':
|
if sys.platform == "win32":
|
||||||
import locale, codecs
|
import locale, codecs
|
||||||
|
|
||||||
enc = locale.getdefaultlocale()[1]
|
enc = locale.getdefaultlocale()[1]
|
||||||
if enc.startswith('cp'): # "cp***" ?
|
if enc.startswith("cp"): # "cp***" ?
|
||||||
try:
|
try:
|
||||||
codecs.lookup(enc)
|
codecs.lookup(enc)
|
||||||
except LookupError:
|
except LookupError:
|
||||||
import encodings
|
import encodings
|
||||||
|
|
||||||
encodings._cache[enc] = encodings._unknown
|
encodings._cache[enc] = encodings._unknown
|
||||||
encodings.aliases.aliases[enc] = 'mbcs'
|
encodings.aliases.aliases[enc] = "mbcs"
|
||||||
|
|
||||||
|
|
||||||
def setencoding():
|
def setencoding():
|
||||||
"""Set the string encoding used by the Unicode implementation. The
|
"""Set the string encoding used by the Unicode implementation. The
|
||||||
@ -530,6 +531,7 @@ def setencoding():
|
|||||||
if 0:
|
if 0:
|
||||||
# Enable to support locale aware default string encodings.
|
# Enable to support locale aware default string encodings.
|
||||||
import locale
|
import locale
|
||||||
|
|
||||||
loc = locale.getdefaultlocale()
|
loc = locale.getdefaultlocale()
|
||||||
if loc[1]:
|
if loc[1]:
|
||||||
encoding = loc[1]
|
encoding = loc[1]
|
||||||
@ -549,41 +551,38 @@ def execsitecustomize():
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def virtual_install_main_packages():
|
def virtual_install_main_packages():
|
||||||
f = open(os.path.join(os.path.dirname(__file__), 'orig-prefix.txt'))
|
f = open(os.path.join(os.path.dirname(__file__), "orig-prefix.txt"))
|
||||||
sys.real_prefix = f.read().strip()
|
sys.real_prefix = f.read().strip()
|
||||||
f.close()
|
f.close()
|
||||||
pos = 2
|
pos = 2
|
||||||
hardcoded_relative_dirs = []
|
hardcoded_relative_dirs = []
|
||||||
if sys.path[0] == '':
|
if sys.path[0] == "":
|
||||||
pos += 1
|
pos += 1
|
||||||
if _is_jython:
|
if _is_pypy:
|
||||||
paths = [os.path.join(sys.real_prefix, 'Lib')]
|
|
||||||
elif _is_pypy:
|
|
||||||
if sys.version_info > (3, 2):
|
if sys.version_info > (3, 2):
|
||||||
cpyver = '%d' % sys.version_info[0]
|
cpyver = "%d" % sys.version_info[0]
|
||||||
elif sys.pypy_version_info >= (1, 5):
|
elif sys.pypy_version_info >= (1, 5):
|
||||||
cpyver = '%d.%d' % sys.version_info[:2]
|
cpyver = "%d.%d" % sys.version_info[:2]
|
||||||
else:
|
else:
|
||||||
cpyver = '%d.%d.%d' % sys.version_info[:3]
|
cpyver = "%d.%d.%d" % sys.version_info[:3]
|
||||||
paths = [os.path.join(sys.real_prefix, 'lib_pypy'),
|
paths = [os.path.join(sys.real_prefix, "lib_pypy"), os.path.join(sys.real_prefix, "lib-python", cpyver)]
|
||||||
os.path.join(sys.real_prefix, 'lib-python', cpyver)]
|
|
||||||
if sys.pypy_version_info < (1, 9):
|
if sys.pypy_version_info < (1, 9):
|
||||||
paths.insert(1, os.path.join(sys.real_prefix,
|
paths.insert(1, os.path.join(sys.real_prefix, "lib-python", "modified-%s" % cpyver))
|
||||||
'lib-python', 'modified-%s' % cpyver))
|
|
||||||
hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below
|
hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below
|
||||||
#
|
#
|
||||||
# This is hardcoded in the Python executable, but relative to sys.prefix:
|
# This is hardcoded in the Python executable, but relative to sys.prefix:
|
||||||
for path in paths[:]:
|
for path in paths[:]:
|
||||||
plat_path = os.path.join(path, 'plat-%s' % sys.platform)
|
plat_path = os.path.join(path, "plat-%s" % sys.platform)
|
||||||
if os.path.exists(plat_path):
|
if os.path.exists(plat_path):
|
||||||
paths.append(plat_path)
|
paths.append(plat_path)
|
||||||
elif sys.platform == 'win32':
|
elif sys.platform == "win32":
|
||||||
paths = [os.path.join(sys.real_prefix, 'Lib'), os.path.join(sys.real_prefix, 'DLLs')]
|
paths = [os.path.join(sys.real_prefix, "Lib"), os.path.join(sys.real_prefix, "DLLs")]
|
||||||
else:
|
else:
|
||||||
paths = [os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3])]
|
paths = [os.path.join(sys.real_prefix, "lib", "python{}.{}".format(*sys.version_info))]
|
||||||
hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below
|
hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below
|
||||||
lib64_path = os.path.join(sys.real_prefix, 'lib64', 'python'+sys.version[:3])
|
lib64_path = os.path.join(sys.real_prefix, "lib64", "python{}.{}".format(*sys.version_info))
|
||||||
if os.path.exists(lib64_path):
|
if os.path.exists(lib64_path):
|
||||||
if _is_64bit:
|
if _is_64bit:
|
||||||
paths.insert(0, lib64_path)
|
paths.insert(0, lib64_path)
|
||||||
@ -595,28 +594,28 @@ def virtual_install_main_packages():
|
|||||||
# Python 3.3+, this lives in sys.implementation, while in Python 2.7
|
# Python 3.3+, this lives in sys.implementation, while in Python 2.7
|
||||||
# it lives in sys.
|
# it lives in sys.
|
||||||
try:
|
try:
|
||||||
arch = getattr(sys, 'implementation', sys)._multiarch
|
arch = getattr(sys, "implementation", sys)._multiarch
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# This is a non-multiarch aware Python. Fallback to the old way.
|
# This is a non-multiarch aware Python. Fallback to the old way.
|
||||||
arch = sys.platform
|
arch = sys.platform
|
||||||
plat_path = os.path.join(sys.real_prefix, 'lib',
|
plat_path = os.path.join(sys.real_prefix, "lib", "python{}.{}".format(*sys.version_info), "plat-%s" % arch)
|
||||||
'python'+sys.version[:3],
|
|
||||||
'plat-%s' % arch)
|
|
||||||
if os.path.exists(plat_path):
|
if os.path.exists(plat_path):
|
||||||
paths.append(plat_path)
|
paths.append(plat_path)
|
||||||
# This is hardcoded in the Python executable, but
|
# This is hardcoded in the Python executable, but
|
||||||
# relative to sys.prefix, so we have to fix up:
|
# relative to sys.prefix, so we have to fix up:
|
||||||
for path in list(paths):
|
for path in list(paths):
|
||||||
tk_dir = os.path.join(path, 'lib-tk')
|
tk_dir = os.path.join(path, "lib-tk")
|
||||||
if os.path.exists(tk_dir):
|
if os.path.exists(tk_dir):
|
||||||
paths.append(tk_dir)
|
paths.append(tk_dir)
|
||||||
|
|
||||||
# These are hardcoded in the Apple's Python executable,
|
# These are hardcoded in the Apple's Python executable,
|
||||||
# but relative to sys.prefix, so we have to fix them up:
|
# but relative to sys.prefix, so we have to fix them up:
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == "darwin":
|
||||||
hardcoded_paths = [os.path.join(relative_dir, module)
|
hardcoded_paths = [
|
||||||
|
os.path.join(relative_dir, module)
|
||||||
for relative_dir in hardcoded_relative_dirs
|
for relative_dir in hardcoded_relative_dirs
|
||||||
for module in ('plat-darwin', 'plat-mac', 'plat-mac/lib-scriptpackages')]
|
for module in ("plat-darwin", "plat-mac", "plat-mac/lib-scriptpackages")
|
||||||
|
]
|
||||||
|
|
||||||
for path in hardcoded_paths:
|
for path in hardcoded_paths:
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
@ -624,6 +623,7 @@ def virtual_install_main_packages():
|
|||||||
|
|
||||||
sys.path.extend(paths)
|
sys.path.extend(paths)
|
||||||
|
|
||||||
|
|
||||||
def force_global_eggs_after_local_site_packages():
|
def force_global_eggs_after_local_site_packages():
|
||||||
"""
|
"""
|
||||||
Force easy_installed eggs in the global environment to get placed
|
Force easy_installed eggs in the global environment to get placed
|
||||||
@ -633,29 +633,17 @@ def force_global_eggs_after_local_site_packages():
|
|||||||
around.
|
around.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
egginsert = getattr(sys, '__egginsert', 0)
|
egginsert = getattr(sys, "__egginsert", 0)
|
||||||
for i, path in enumerate(sys.path):
|
for i, path in enumerate(sys.path):
|
||||||
if i > egginsert and path.startswith(sys.prefix):
|
if i > egginsert and path.startswith(sys.prefix):
|
||||||
egginsert = i
|
egginsert = i
|
||||||
sys.__egginsert = egginsert + 1
|
sys.__egginsert = egginsert + 1
|
||||||
|
|
||||||
|
|
||||||
def virtual_addsitepackages(known_paths):
|
def virtual_addsitepackages(known_paths):
|
||||||
force_global_eggs_after_local_site_packages()
|
force_global_eggs_after_local_site_packages()
|
||||||
return addsitepackages(known_paths, sys_prefix=sys.real_prefix)
|
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():
|
def execusercustomize():
|
||||||
"""Run custom user specific code, if available."""
|
"""Run custom user specific code, if available."""
|
||||||
@ -665,17 +653,92 @@ def execusercustomize():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def enablerlcompleter():
|
||||||
|
"""Enable default readline configuration on interactive prompts, by
|
||||||
|
registering a sys.__interactivehook__.
|
||||||
|
If the readline module can be imported, the hook will set the Tab key
|
||||||
|
as completion key and register ~/.python_history as history file.
|
||||||
|
This can be overridden in the sitecustomize or usercustomize module,
|
||||||
|
or in a PYTHONSTARTUP file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def register_readline():
|
||||||
|
import atexit
|
||||||
|
|
||||||
|
try:
|
||||||
|
import readline
|
||||||
|
import rlcompleter
|
||||||
|
except ImportError:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Reading the initialization (config) file may not be enough to set a
|
||||||
|
# completion key, so we set one first and then read the file.
|
||||||
|
readline_doc = getattr(readline, "__doc__", "")
|
||||||
|
if readline_doc is not None and "libedit" in readline_doc:
|
||||||
|
readline.parse_and_bind("bind ^I rl_complete")
|
||||||
|
else:
|
||||||
|
readline.parse_and_bind("tab: complete")
|
||||||
|
|
||||||
|
try:
|
||||||
|
readline.read_init_file()
|
||||||
|
except OSError:
|
||||||
|
# An OSError here could have many causes, but the most likely one
|
||||||
|
# is that there's no .inputrc file (or .editrc file in the case of
|
||||||
|
# Mac OS X + libedit) in the expected location. In that case, we
|
||||||
|
# want to ignore the exception.
|
||||||
|
pass
|
||||||
|
|
||||||
|
if readline.get_current_history_length() == 0:
|
||||||
|
# If no history was loaded, default to .python_history.
|
||||||
|
# The guard is necessary to avoid doubling history size at
|
||||||
|
# each interpreter exit when readline was already configured
|
||||||
|
# through a PYTHONSTARTUP hook, see:
|
||||||
|
# http://bugs.python.org/issue5845#msg198636
|
||||||
|
history = os.path.join(os.path.expanduser("~"), ".python_history")
|
||||||
|
try:
|
||||||
|
readline.read_history_file(history)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def write_history():
|
||||||
|
try:
|
||||||
|
readline.write_history_file(history)
|
||||||
|
except (FileNotFoundError, PermissionError):
|
||||||
|
# home directory does not exist or is not writable
|
||||||
|
# https://bugs.python.org/issue19891
|
||||||
|
pass
|
||||||
|
|
||||||
|
atexit.register(write_history)
|
||||||
|
|
||||||
|
sys.__interactivehook__ = register_readline
|
||||||
|
|
||||||
|
|
||||||
|
if _is_pypy:
|
||||||
|
|
||||||
|
def import_builtin_stuff():
|
||||||
|
"""PyPy specific: some built-in modules should be pre-imported because
|
||||||
|
some programs expect them to be in sys.modules on startup. This is ported
|
||||||
|
from PyPy's site.py.
|
||||||
|
"""
|
||||||
|
import encodings
|
||||||
|
|
||||||
|
if "exceptions" in sys.builtin_module_names:
|
||||||
|
import exceptions
|
||||||
|
|
||||||
|
if "zipimport" in sys.builtin_module_names:
|
||||||
|
import zipimport
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global ENABLE_USER_SITE
|
global ENABLE_USER_SITE
|
||||||
virtual_install_main_packages()
|
virtual_install_main_packages()
|
||||||
|
if _is_pypy:
|
||||||
|
import_builtin_stuff()
|
||||||
abs__file__()
|
abs__file__()
|
||||||
paths_in_sys = removeduppaths()
|
paths_in_sys = removeduppaths()
|
||||||
if (os.name == "posix" and sys.path and
|
if os.name == "posix" and sys.path and os.path.basename(sys.path[-1]) == "Modules":
|
||||||
os.path.basename(sys.path[-1]) == "Modules"):
|
|
||||||
addbuilddir()
|
addbuilddir()
|
||||||
if _is_jython:
|
GLOBAL_SITE_PACKAGES = not os.path.exists(os.path.join(os.path.dirname(__file__), "no-global-site-packages.txt"))
|
||||||
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:
|
if not GLOBAL_SITE_PACKAGES:
|
||||||
ENABLE_USER_SITE = False
|
ENABLE_USER_SITE = False
|
||||||
if ENABLE_USER_SITE is None:
|
if ENABLE_USER_SITE is None:
|
||||||
@ -684,11 +747,13 @@ def main():
|
|||||||
paths_in_sys = addusersitepackages(paths_in_sys)
|
paths_in_sys = addusersitepackages(paths_in_sys)
|
||||||
if GLOBAL_SITE_PACKAGES:
|
if GLOBAL_SITE_PACKAGES:
|
||||||
paths_in_sys = virtual_addsitepackages(paths_in_sys)
|
paths_in_sys = virtual_addsitepackages(paths_in_sys)
|
||||||
if sys.platform == 'os2emx':
|
if sys.platform == "os2emx":
|
||||||
setBEGINLIBPATH()
|
setBEGINLIBPATH()
|
||||||
setquit()
|
setquit()
|
||||||
setcopyright()
|
setcopyright()
|
||||||
sethelper()
|
sethelper()
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
enablerlcompleter()
|
||||||
aliasmbcs()
|
aliasmbcs()
|
||||||
setencoding()
|
setencoding()
|
||||||
execsitecustomize()
|
execsitecustomize()
|
||||||
@ -700,8 +765,10 @@ def main():
|
|||||||
if hasattr(sys, "setdefaultencoding"):
|
if hasattr(sys, "setdefaultencoding"):
|
||||||
del sys.setdefaultencoding
|
del sys.setdefaultencoding
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
||||||
def _script():
|
def _script():
|
||||||
help = """\
|
help = """\
|
||||||
%s [--user-base] [--user-site]
|
%s [--user-base] [--user-site]
|
||||||
@ -721,22 +788,24 @@ def _script():
|
|||||||
if not args:
|
if not args:
|
||||||
print("sys.path = [")
|
print("sys.path = [")
|
||||||
for dir in sys.path:
|
for dir in sys.path:
|
||||||
print(" %r," % (dir,))
|
print(" {!r},".format(dir))
|
||||||
print("]")
|
print("]")
|
||||||
|
|
||||||
def exists(path):
|
def exists(path):
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
return "exists"
|
return "exists"
|
||||||
else:
|
else:
|
||||||
return "doesn't exist"
|
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("USER_BASE: {!r} ({})".format(USER_BASE, exists(USER_BASE)))
|
||||||
|
print("USER_SITE: {!r} ({})".format(USER_SITE, exists(USER_SITE)))
|
||||||
print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE)
|
print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
buffer = []
|
buffer = []
|
||||||
if '--user-base' in args:
|
if "--user-base" in args:
|
||||||
buffer.append(USER_BASE)
|
buffer.append(USER_BASE)
|
||||||
if '--user-site' in args:
|
if "--user-site" in args:
|
||||||
buffer.append(USER_SITE)
|
buffer.append(USER_SITE)
|
||||||
|
|
||||||
if buffer:
|
if buffer:
|
||||||
@ -751,8 +820,10 @@ def _script():
|
|||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
else:
|
else:
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
print(textwrap.dedent(help % (sys.argv[0], os.pathsep)))
|
print(textwrap.dedent(help % (sys.argv[0], os.pathsep)))
|
||||||
sys.exit(10)
|
sys.exit(10)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
_script()
|
_script()
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
python/virtualenv/virtualenv_support/pip-21.1.3-py3-none-any.whl
Normal file
BIN
python/virtualenv/virtualenv_support/pip-21.1.3-py3-none-any.whl
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user