summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonny Pfannschmidt <opensource@ronnypfannschmidt.de>2016-09-17 20:30:13 +0200
committerRonny Pfannschmidt <opensource@ronnypfannschmidt.de>2016-09-17 20:30:13 +0200
commit07fdce28e407b0ec10b5fee682f134550eae335b (patch)
tree74baed3d9a1daa2ecd8d4bb3f00ff1e47c9f88d4
parent2237fc53240f8892577b3a54016dfcfe8be7fd56 (diff)
downloadtox-07fdce28e407b0ec10b5fee682f134550eae335b.tar.gz
clean out source files and link to new repoHEADmaster
-rw-r--r--CHANGELOG695
-rw-r--r--CONTRIBUTORS34
-rw-r--r--ISSUES.txt162
-rw-r--r--LICENSE20
-rw-r--r--MANIFEST.in9
-rw-r--r--README.rst27
-rw-r--r--doc/Makefile140
-rwxr-xr-xdoc/_getdoctarget.py16
-rw-r--r--doc/_static/sphinxdoc.css339
-rw-r--r--doc/_templates/indexsidebar.html21
-rw-r--r--doc/_templates/layout.html15
-rw-r--r--doc/_templates/localtoc.html36
-rw-r--r--doc/announce/release-0.5.txt26
-rw-r--r--doc/announce/release-1.0.txt55
-rw-r--r--doc/announce/release-1.1.txt50
-rw-r--r--doc/announce/release-1.2.txt42
-rw-r--r--doc/announce/release-1.3.txt41
-rw-r--r--doc/announce/release-1.4.3.txt97
-rw-r--r--doc/announce/release-1.4.txt62
-rw-r--r--doc/announce/release-1.8.txt54
-rw-r--r--doc/announce/release-1.9.txt66
-rw-r--r--doc/announce/release-2.0.txt111
-rw-r--r--doc/changelog.txt7
-rw-r--r--doc/check_sphinx.py17
-rw-r--r--doc/conf.py272
-rw-r--r--doc/config-v2.txt292
-rw-r--r--doc/config.txt633
-rw-r--r--doc/drafts/extend-envs-and-packagebuilds.md155
-rw-r--r--doc/drafts/tox_conda_notes_niccodemus.md84
-rw-r--r--doc/example/basic.txt313
-rw-r--r--doc/example/devenv.txt78
-rw-r--r--doc/example/general.txt182
-rw-r--r--doc/example/jenkins.txt174
-rw-r--r--doc/example/nose.txt41
-rwxr-xr-xdoc/example/pytest.txt111
-rw-r--r--doc/example/result.txt44
-rw-r--r--doc/example/unittest.txt89
-rw-r--r--doc/examples.txt15
-rw-r--r--doc/index.txt123
-rw-r--r--doc/install.txt44
-rw-r--r--doc/links.txt20
-rw-r--r--doc/plugins.txt88
-rw-r--r--doc/support.txt36
-rw-r--r--setup.cfg13
-rw-r--r--setup.py79
-rw-r--r--tests/conftest.py2
-rw-r--r--tests/test_config.py2060
-rw-r--r--tests/test_interpreters.py112
-rw-r--r--tests/test_quickstart.py491
-rw-r--r--tests/test_result.py68
-rw-r--r--tests/test_venv.py699
-rw-r--r--tests/test_z_cmdline.py760
-rw-r--r--tox.ini63
-rw-r--r--tox/__init__.py33
-rw-r--r--tox/__main__.py4
-rw-r--r--tox/_pytestplugin.py333
-rw-r--r--tox/_quickstart.py275
-rw-r--r--tox/_verlib.py335
-rw-r--r--tox/config.py1247
-rw-r--r--tox/hookspecs.py59
-rw-r--r--tox/interpreters.py184
-rw-r--r--tox/result.py81
-rw-r--r--tox/session.py682
-rw-r--r--tox/venv.py416
64 files changed, 3 insertions, 12929 deletions
diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644
index 7f8e8bc..0000000
--- a/CHANGELOG
+++ /dev/null
@@ -1,695 +0,0 @@
-2.4.0
------
-
-- fix issue302: allow cross-testenv substitution where we substitute
- with ``{x,y}`` generative syntax. Thanks Andrew Pashkin.
-
-- fix issue212: allow escaping curly brace chars "\{" and "\}" if you need the
- chars "{" and "}" to appear in your commands or other ini values.
- Thanks John Vandenberg.
-
-- addresses issue66: add --workdir option to override where tox stores its ".tox" directory
- and all of the virtualenv environment. Thanks Danring.
-
-- introduce per-venv list_dependencies_command which defaults
- to "pip freeze" to obtain the list of installed packages.
- Thanks Ted Shaw, Holger Krekel.
-
-- close issue66: add documentation to jenkins page on how to avoid
- "too long shebang" lines when calling pip from tox. Note that we
- can not use "python -m pip install X" by default because the latter
- adds the CWD and pip will think X is installed if it is there.
- "pip install X" does not do that.
-
-- new list_dependencies_command to influence how tox determines
- which dependencies are installed in a testenv.
-
-- (experimental) New feature: When a search for a config file fails, tox tries loading
- setup.cfg with a section prefix of "tox".
-
-- fix issue275: Introduce hooks ``tox_runtest_pre``` and
- ``tox_runtest_post`` which run before and after the tests of a venv,
- respectively. Thanks to Matthew Schinckel and itxaka serrano.
-
-- fix issue317: evaluate minversion before tox config is parsed completely.
- Thanks Sachi King for the PR.
-
-2.3.2
------
-
-- fix issue314: fix command invocation with .py scripts on windows.
-
-- fix issue279: allow cross-section substitution when the value contains
- posargs. Thanks Sachi King for the PR.
-
-2.3.1
------
-
-- fix issue294: re-allow cross-section substitution for setenv.
-
-2.3.0
------
-
-- DEPRECATE use of "indexservers" in tox.ini. It complicates
- the internal code and it is recommended to rather use the
- devpi system for managing indexes for pip.
-
-- fix issue285: make setenv processing fully lazy to fix regressions
- of tox-2.2.X and so that we can now have testenv attributes like
- "basepython" depend on environment variables that are set in
- a setenv section. Thanks Nelfin for some tests and initial
- work on a PR.
-
-- allow "#" in commands. This is slightly incompatible with commands
- sections that used a comment after a "\" line continuation.
- Thanks David Stanek for the PR.
-
-- fix issue289: fix build_sphinx target, thanks Barry Warsaw.
-
-- fix issue252: allow environment names with special characters.
- Thanks Julien Castets for initial PR and patience.
-
-- introduce experimental tox_testenv_create(venv, action) and
- tox_testenv_install_deps(venv, action) hooks to allow
- plugins to do additional work on creation or installing
- deps. These hooks are experimental mainly because of
- the involved "venv" and session objects whose current public
- API is not fully guranteed.
-
-- internal: push some optional object creation into tests because
- tox core doesn't need it.
-
-2.2.1
------
-
-- fix bug where {envdir} substitution could not be used in setenv
- if that env value is then used in {basepython}. Thanks Florian Bruhin.
-
-2.2.0
------
-
-- fix issue265 and add LD_LIBRARY_PATH to passenv on linux by default
- because otherwise the python interpreter might not start up in
- certain configurations (redhat software collections). Thanks David Riddle.
-
-- fix issue246: fix regression in config parsing by reordering
- such that {envbindir} can be used again in tox.ini. Thanks Olli Walsh.
-
-- fix issue99: the {env:...} substitution now properly uses environment
- settings from the ``setenv`` section. Thanks Itxaka Serrano.
-
-- fix issue281: make --force-dep work when urls are present in
- dependency configs. Thanks Glyph Lefkowitz for reporting.
-
-- fix issue174: add new ``ignore_outcome`` testenv attribute which
- can be set to True in which case it will produce a warning instead
- of an error on a failed testenv command outcome.
- Thanks Rebecka Gulliksson for the PR.
-
-- fix issue280: properly skip missing interpreter if
- {envsitepackagesdir} is present in commands. Thanks BB:ceridwenv
-
-
-2.1.1
-----------
-
-- fix platform skipping for detox
-
-- report skipped platforms as skips in the summary
-
-2.1.0
-----------
-
-- fix issue258, fix issue248, fix issue253: for non-test commands
- (installation, venv creation) we pass in the full invocation environment.
-
-- remove experimental --set-home option which was hardly used and
- hackily implemented (if people want home-directory isolation we should
- figure out a better way to do it, possibly through a plugin)
-
-- fix issue259: passenv is now a line-list which allows to intersperse
- comments. Thanks stefano-m.
-
-- allow envlist to be a multi-line list, to intersperse comments
- and have long envlist settings split more naturally. Thanks Andre Caron.
-
-- introduce a TOX_TESTENV_PASSENV setting which is honored
- when constructing the set of environment variables for test environments.
- Thanks Marc Abramowitz for pushing in this direction.
-
-
-2.0.2
-----------
-
-- fix issue247: tox now passes the LANG variable from the tox invocation
- environment to the test environment by default.
-
-- add SYSTEMDRIVE into default passenv on windows to allow pip6 to work.
- Thanks Michael Krause.
-
-
-2.0.1
------------
-
-- fix wheel packaging to properly require argparse on py26.
-
-2.0.0
------------
-
-- (new) introduce environment variable isolation:
- tox now only passes the PATH and PIP_INDEX_URL variable from the tox
- invocation environment to the test environment and on Windows
- also ``SYSTEMROOT``, ``PATHEXT``, ``TEMP`` and ``TMP`` whereas
- on unix additionally ``TMPDIR`` is passed. If you need to pass
- through further environment variables you can use the new ``passenv`` setting,
- a space-separated list of environment variable names. Each name
- can make use of fnmatch-style glob patterns. All environment
- variables which exist in the tox-invocation environment will be copied
- to the test environment.
-
-- a new ``--help-ini`` option shows all possible testenv settings and
- their defaults.
-
-- (new) introduce a way to specify on which platform a testenvironment is to
- execute: the new per-venv "platform" setting allows to specify
- a regular expression which is matched against sys.platform.
- If platform is set and doesn't match the platform spec in the test
- environment the test environment is ignored, no setup or tests are attempted.
-
-- (new) add per-venv "ignore_errors" setting, which defaults to False.
- If ``True``, a non-zero exit code from one command will be ignored and
- further commands will be executed (which was the default behavior in tox <
- 2.0). If ``False`` (the default), then a non-zero exit code from one command
- will abort execution of commands for that environment.
-
-- show and store in json the version dependency information for each venv
-
-- remove the long-deprecated "distribute" option as it has no effect these days.
-
-- fix issue233: avoid hanging with tox-setuptools integration example. Thanks simonb.
-
-- fix issue120: allow substitution for the commands section. Thanks
- Volodymyr Vitvitski.
-
-- fix issue235: fix AttributeError with --installpkg. Thanks
- Volodymyr Vitvitski.
-
-- tox has now somewhat pep8 clean code, thanks to Volodymyr Vitvitski.
-
-- fix issue240: allow to specify empty argument list without it being
- rewritten to ".". Thanks Daniel Hahler.
-
-- introduce experimental (not much documented yet) plugin system
- based on pytest's externalized "pluggy" system.
- See tox/hookspecs.py for the current hooks.
-
-- introduce parser.add_testenv_attribute() to register an ini-variable
- for testenv sections. Can be used from plugins through the
- tox_add_option hook.
-
-- rename internal files -- tox offers no external API except for the
- experimental plugin hooks, use tox internals at your own risk.
-
-- DEPRECATE distshare in documentation
-
-
-
-1.9.2
------------
-
-- backout ability that --force-dep substitutes name/versions in
- requirement files due to various issues.
- This fixes issue228, fixes issue230, fixes issue231
- which popped up with 1.9.1.
-
-1.9.1
------------
-
-- use a file instead of a pipe for command output in "--result-json".
- Fixes some termination issues with python2.6.
-
-- allow --force-dep to override dependencies in "-r" requirements
- files. Thanks Sontek for the PR.
-
-- fix issue227: use "-m virtualenv" instead of "-mvirtualenv" to make
- it work with pyrun. Thanks Marc-Andre Lemburg.
-
-
-1.9.0
------------
-
-- fix issue193: Remove ``--pre`` from the default ``install_command``; by
- default tox will now only install final releases from PyPI for unpinned
- dependencies. Use ``pip_pre = true`` in a testenv or the ``--pre``
- command-line option to restore the previous behavior.
-
-- fix issue199: fill resultlog structure ahead of virtualenv creation
-
-- refine determination if we run from Jenkins, thanks Borge Lanes.
-
-- echo output to stdout when ``--report-json`` is used
-
-- fix issue11: add a ``skip_install`` per-testenv setting which
- prevents the installation of a package. Thanks Julian Krause.
-
-- fix issue124: ignore command exit codes; when a command has a "-" prefix,
- tox will ignore the exit code of that command
-
-- fix issue198: fix broken envlist settings, e.g. {py26,py27}{-lint,}
-
-- fix issue191: lessen factor-use checks
-
-
-1.8.1
------------
-
-- fix issue190: allow setenv to be empty.
-
-- allow escaping curly braces with "\". Thanks Marc Abramowitz for the PR.
-
-- allow "." names in environment names such that "py27-django1.7" is a
- valid environment name. Thanks Alex Gaynor and Alex Schepanovski.
-
-- report subprocess exit code when execution fails. Thanks Marius
- Gedminas.
-
-1.8.0
------------
-
-- new multi-dimensional configuration support. Many thanks to
- Alexander Schepanovski for the complete PR with docs.
- And to Mike Bayer and others for testing and feedback.
-
-- fix issue148: remove "__PYVENV_LAUNCHER__" from os.environ when starting
- subprocesses. Thanks Steven Myint.
-
-- fix issue152: set VIRTUAL_ENV when running test commands,
- thanks Florian Ludwig.
-
-- better report if we can't get version_info from an interpreter
- executable. Thanks Floris Bruynooghe.
-
-
-1.7.2
------------
-
-- fix issue150: parse {posargs} more like we used to do it pre 1.7.0.
- The 1.7.0 behaviour broke a lot of OpenStack projects.
- See PR85 and the issue discussions for (far) more details, hopefully
- resulting in a more refined behaviour in the 1.8 series.
- And thanks to Clark Boylan for the PR.
-
-- fix issue59: add a config variable ``skip-missing-interpreters`` as well as
- command line option ``--skip-missing-interpreters`` which won't fail the
- build if Python interpreters listed in tox.ini are missing. Thanks
- Alexandre Conrad for PR104.
-
-- fix issue164: better traceback info in case of failing test commands.
- Thanks Marc Abramowitz for PR92.
-
-- support optional env variable substitution, thanks Morgan Fainberg
- for PR86.
-
-- limit python hashseed to 1024 on Windows to prevent possible
- memory errors. Thanks March Schlaich for the PR90.
-
-1.7.1
----------
-
-- fix issue162: don't list python 2.5 as compatibiliy/supported
-
-- fix issue158 and fix issue155: windows/virtualenv properly works now:
- call virtualenv through "python -m virtualenv" with the same
- interpreter which invoked tox. Thanks Chris Withers, Ionel Maries Cristian.
-
-1.7.0
----------
-
-- don't lookup "pip-script" anymore but rather just "pip" on windows
- as this is a pip implementation detail and changed with pip-1.5.
- It might mean that tox-1.7 is not able to install a different pip
- version into a virtualenv anymore.
-
-- drop Python2.5 compatibility because it became too hard due
- to the setuptools-2.0 dropping support. tox now has no
- support for creating python2.5 based environments anymore
- and all internal special-handling has been removed.
-
-- merged PR81: new option --force-dep which allows to
- override tox.ini specified dependencies in setuptools-style.
- For example "--force-dep 'django<1.6'" will make sure
- that any environment using "django" as a dependency will
- get the latest 1.5 release. Thanks Bruno Oliveria for
- the complete PR.
-
-- merged PR125: tox now sets "PYTHONHASHSEED" to a random value
- and offers a "--hashseed" option to repeat a test run with a specific seed.
- You can also use --hashsheed=noset to instruct tox to leave the value
- alone. Thanks Chris Jerdonek for all the work behind this.
-
-- fix issue132: removing zip_safe setting (so it defaults to false)
- to allow installation of tox
- via easy_install/eggs. Thanks Jenisys.
-
-- fix issue126: depend on virtualenv>=1.11.2 so that we can rely
- (hopefully) on a pip version which supports --pre. (tox by default
- uses to --pre). also merged in PR84 so that we now call "virtualenv"
- directly instead of looking up interpreters. Thanks Ionel Maries Cristian.
- This also fixes issue140.
-
-- fix issue130: you can now set install_command=easy_install {opts} {packages}
- and expect it to work for repeated tox runs (previously it only worked
- when always recreating). Thanks jenisys for precise reporting.
-
-- fix issue129: tox now uses Popen(..., universal_newlines=True) to force
- creation of unicode stdout/stderr streams. fixes a problem on specific
- platform configs when creating virtualenvs with Python3.3. Thanks
- Jorgen Schäfer or investigation and solution sketch.
-
-- fix issue128: enable full substitution in install_command,
- thanks for the PR to Ronald Evers
-
-- rework and simplify "commands" parsing and in particular posargs
- substitutions to avoid various win32/posix related quoting issues.
-
-- make sure that the --installpkg option trumps any usedevelop settings
- in tox.ini or
-
-- introduce --no-network to tox's own test suite to skip tests
- requiring networks
-
-- introduce --sitepackages to force sitepackages=True in all
- environments.
-
-- fix issue105 -- don't depend on an existing HOME directory from tox tests.
-
-1.6.1
------
-
-- fix issue119: {envsitepackagesdir} is now correctly computed and has
- a better test to prevent regression.
-
-- fix issue116: make 1.6 introduced behaviour of changing to a
- per-env HOME directory during install activities dependent
- on "--set-home" for now. Should re-establish the old behaviour
- when no option is given.
-
-- fix issue118: correctly have two tests use realpath(). Thanks Barry
- Warsaw.
-
-- fix test runs on environments without a home directory
- (in this case we use toxinidir as the homedir)
-
-- fix issue117: python2.5 fix: don't use ``--insecure`` option because
- its very existence depends on presence of "ssl". If you
- want to support python2.5/pip1.3.1 based test environments you need
- to install ssl and/or use PIP_INSECURE=1 through ``setenv``. section.
-
-- fix issue102: change to {toxinidir} when installing dependencies.
- this allows to use relative path like in "-rrequirements.txt".
-
-1.6.0
------------------
-
-- fix issue35: add new EXPERIMENTAL "install_command" testenv-option to
- configure the installation command with options for dep/pkg install.
- Thanks Carl Meyer for the PR and docs.
-
-- fix issue91: python2.5 support by vendoring the virtualenv-1.9.1
- script and forcing pip<1.4. Also the default [py25] environment
- modifies the default installer_command (new config option)
- to use pip without the "--pre" option which was introduced
- with pip-1.4 and is now required if you want to install non-stable
- releases. (tox defaults to install with "--pre" everywhere).
-
-- during installation of dependencies HOME is now set to a pseudo
- location ({envtmpdir}/pseudo-home). If an index url was specified
- a .pydistutils.cfg file will be written with an index_url setting
- so that packages defining ``setup_requires`` dependencies will not
- silently use your HOME-directory settings or https://pypi.python.org.
-
-- fix issue1: empty setup files are properly detected, thanks Anthon van
- der Neuth
-
-- remove toxbootstrap.py for now because it is broken.
-
-- fix issue109 and fix issue111: multiple "-e" options are now combined
- (previously the last one would win). Thanks Anthon van der Neut.
-
-- add --result-json option to write out detailed per-venv information
- into a json report file to be used by upstream tools.
-
-- add new config options ``usedevelop`` and ``skipsdist`` as well as a
- command line option ``--develop`` to install the package-under-test in develop mode.
- thanks Monty Tailor for the PR.
-
-- always unset PYTHONDONTWRITEBYTE because newer setuptools doesn't like it
-
-- if a HOMEDIR cannot be determined, use the toxinidir.
-
-- refactor interpreter information detection to live in new
- tox/interpreters.py file, tests in tests/test_interpreters.py.
-
-1.5.0
------------------
-
-- fix issue104: use setuptools by default, instead of distribute,
- now that setuptools has distribute merged.
-
-- make sure test commands are searched first in the virtualenv
-
-- re-fix issue2 - add whitelist_externals to be used in ``[testenv*]``
- sections, allowing to avoid warnings for commands such as ``make``,
- used from the commands value.
-
-- fix issue97 - allow substitutions to reference from other sections
- (thanks Krisztian Fekete)
-
-- fix issue92 - fix {envsitepackagesdir} to actually work again
-
-- show (test) command that is being executed, thanks
- Lukasz Balcerzak
-
-- re-license tox to MIT license
-
-- depend on virtualenv-1.9.1
-
-- rename README.txt to README.rst to make bitbucket happier
-
-
-1.4.3
------------------
-
-- use pip-script.py instead of pip.exe on win32 to avoid the lock exe
- file on execution issue (thanks Philip Thiem)
-
-- introduce -l|--listenv option to list configured environments
- (thanks Lukasz Balcerzak)
-
-- fix downloadcache determination to work according to docs: Only
- make pip use a download cache if PIP_DOWNLOAD_CACHE or a
- downloadcache=PATH testenv setting is present. (The ENV setting
- takes precedence)
-
-- fix issue84 - pypy on windows creates a bin not a scripts venv directory
- (thanks Lukasz Balcerzak)
-
-- experimentally introduce --installpkg=PATH option to install a package
- rather than create/install an sdist package. This will still require
- and use tox.ini and tests from the current working dir (and not from the
- remote package).
-
-- substitute {envsitepackagesdir} with the package installation
- directory (closes #72) (thanks g2p)
-
-- issue #70 remove PYTHONDONTWRITEBYTECODE workaround now that
- virtualenv behaves properly (thanks g2p)
-
-- merged tox-quickstart command, contributed by Marc Abramowitz, which
- generates a default tox.ini after asking a few questions
-
-- fix #48 - win32 detection of pypy and other interpreters that are on PATH
- (thanks Gustavo Picon)
-
-- fix grouping of index servers, it is now done by name instead of
- indexserver url, allowing to use it to separate dependencies
- into groups even if using the same default indexserver.
-
-- look for "tox.ini" files in parent dirs of current dir (closes #34)
-
-- the "py" environment now by default uses the current interpreter
- (sys.executable) make tox' own setup.py test execute tests with it
- (closes #46)
-
-- change tests to not rely on os.path.expanduser (closes #60),
- also make mock session return args[1:] for more precise checking (closes #61)
- thanks to Barry Warsaw for both.
-
-1.4.2
------------------
-
-- fix some tests which fail if /tmp is a symlink to some other place
-- "python setup.py test" now runs tox tests via tox :)
- also added an example on how to do it for your project.
-
-1.4.1
------------------
-
-- fix issue41 better quoting on windows - you can now use "<" and ">" in
- deps specifications, thanks Chris Withers for reporting
-
-1.4
------------------
-
-- fix issue26 - no warnings on absolute or relative specified paths for commands
-- fix issue33 - commentchars are ignored in key-value settings allowing
- for specifying commands like: python -c "import sys ; print sys"
- which would formerly raise irritating errors because the ";"
- was considered a comment
-- tweak and improve reporting
-- refactor reporting and virtualenv manipulation
- to be more accessible from 3rd party tools
-- support value substitution from other sections
- with the {[section]key} syntax
-- fix issue29 - correctly point to pytest explanation
- for importing modules fully qualified
-- fix issue32 - use --system-site-packages and don't pass --no-site-packages
-- add python3.3 to the default env list, so early adopters can test
-- drop python2.4 support (you can still have your tests run on
-- fix the links/checkout howtos in the docs
- python-2.4, just tox itself requires 2.5 or higher.
-
-1.3
------------------
-
-- fix: allow to specify wildcard filesystem paths when
- specifying dependencies such that tox searches for
- the highest version
-
-- fix issue issue21: clear PIP_REQUIRES_VIRTUALENV which avoids
- pip installing to the wrong environment, thanks to bb's streeter
-
-- make the install step honour a testenv's setenv setting
- (thanks Ralf Schmitt)
-
-
-1.2
------------------
-
-- remove the virtualenv.py that was distributed with tox and depend
- on >=virtualenv-1.6.4 (possible now since the latter fixes a few bugs
- that the inlining tried to work around)
-- fix issue10: work around UnicodeDecodeError when invoking pip (thanks
- Marc Abramowitz)
-- fix a problem with parsing {posargs} in tox commands (spotted by goodwill)
-- fix the warning check for commands to be installed in testenvironment
- (thanks Michael Foord for reporting)
-
-1.1
------------------
-
-- fix issue5 - don't require argparse for python versions that have it
-- fix issue6 - recreate virtualenv if installing dependencies failed
-- fix issue3 - fix example on frontpage
-- fix issue2 - warn if a test command does not come from the test
- environment
-- fixed/enhanced: except for initial install always call "-U
- --no-deps" for installing the sdist package to ensure that a package
- gets upgraded even if its version number did not change. (reported on
- TIP mailing list and IRC)
-- inline virtualenv.py (1.6.1) script to avoid a number of issues,
- particularly failing to install python3 environments from a python2
- virtualenv installation.
-- rework and enhance docs for display on readthedocs.org
-
-1.0
------------------
-
-- move repository and toxbootstrap links to http://bitbucket.org/hpk42/tox
-- fix issue7: introduce a "minversion" directive such that tox
- bails out if it does not have the correct version.
-- fix issue24: introduce a way to set environment variables for
- for test commands (thanks Chris Rose)
-- fix issue22: require virtualenv-1.6.1, obsoleting virtualenv5 (thanks Jannis Leidel)
- and making things work with pypy-1.5 and python3 more seamlessly
-- toxbootstrap.py (used by jenkins build slaves) now follows the latest release of virtualenv
-- fix issue20: document format of URLs for specifying dependencies
-- fix issue19: substitute Hudson for Jenkins everywhere following the renaming
- of the project. NOTE: if you used the special [tox:hudson]
- section it will now need to be named [tox:jenkins].
-- fix issue 23 / apply some ReST fixes
-- change the positional argument specifier to use {posargs:} syntax and
- fix issues #15 and #10 by refining the argument parsing method (Chris Rose)
-- remove use of inipkg lazy importing logic -
- the namespace/imports are anyway very small with tox.
-- fix a fspath related assertion to work with debian installs which uses
- symlinks
-- show path of the underlying virtualenv invocation and bootstrap
- virtualenv.py into a working subdir
-- added a CONTRIBUTORS file
-
-0.9
------------------
-
-- fix pip-installation mixups by always unsetting PIP_RESPECT_VIRTUALENV
- (thanks Armin Ronacher)
-- issue1: Add a toxbootstrap.py script for tox, thanks to Sridhar
- Ratnakumar
-- added support for working with different and multiple PyPI indexservers.
-- new option: -r|--recreate to force recreation of virtualenv
-- depend on py>=1.4.0 which does not contain or install the py.test
- anymore which is now a separate distribution "pytest".
-- show logfile content if there is an error (makes CI output
- more readable)
-
-0.8
------------------
-
-- work around a virtualenv limitation which crashes if
- PYTHONDONTWRITEBYTECODE is set.
-- run pip/easy installs from the environment log directory, avoids
- naming clashes between env names and dependencies (thanks ronny)
-- require a more recent version of py lib
-- refactor and refine config detection to work from a single file
- and to detect the case where a python installation overwrote
- an old one and resulted in a new executable. This invalidates
- the existing virtualenvironment now.
-- change all internal source to strip trailing whitespaces
-
-0.7
------------------
-
-- use virtualenv5 (my own fork of virtualenv3) for now to create python3
- environments, fixes a couple of issues and makes tox more likely to
- work with Python3 (on non-windows environments)
-
-- add ``sitepackages`` option for testenv sections so that environments
- can be created with access to globals (default is not to have access,
- i.e. create environments with ``--no-site-packages``.
-
-- addressing issue4: always prepend venv-path to PATH variable when calling subprocesses
-
-- fix issue2: exit with proper non-zero return code if there were
- errors or test failures.
-
-- added unittest2 examples contributed by Michael Foord
-
-- only allow 'True' or 'False' for boolean config values
- (lowercase / uppercase is irrelevant)
-
-- recreate virtualenv on changed configurations
-
-0.6
------------------
-
-- fix OSX related bugs that could cause the caller's environment to get
- screwed (sorry). tox was using the same file as virtualenv for tracking
- the Python executable dependency and there also was confusion wrt links.
- this should be fixed now.
-
-- fix long description, thanks Michael Foord
-
-0.5
------------------
-
-- initial release
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
deleted file mode 100644
index 75a2dd8..0000000
--- a/CONTRIBUTORS
+++ /dev/null
@@ -1,34 +0,0 @@
-
-contributions:
-
-Krisztian Fekete
-Marc Abramowitz
-Aleaxner Schepanovski
-Sridhar Ratnakumar
-Barry Warsaw
-Chris Rose
-Jannis Leidl
-Ronny Pfannschmidt
-Lukasz Balcerzak
-Philip Thiem
-Monty Taylor
-Bruno Oliveira
-Ionel Maries Cristian
-Anatoly techntonik
-Matt Jeffery
-Chris Jerdonek
-Ronald Evers
-Carl Meyer
-Anthon van der Neuth
-Matt Good
-Mattieu Agopian
-Asmund Grammeltwedt
-Ionel Maries Cristian
-Julian Krause
-Alexandre Conrad
-Morgan Fainberg
-Marc Schlaich
-Clark Boylan
-Eugene Yunak
-Mark Hirota
-Itxaka Serrano
diff --git a/ISSUES.txt b/ISSUES.txt
deleted file mode 100644
index 4b05dff..0000000
--- a/ISSUES.txt
+++ /dev/null
@@ -1,162 +0,0 @@
-introduce package and setup.py less sdist creation
------------------------------------------------------------
-
-Example sections for tox itself::
-
- [pkgdef]
- basename = pytest
- description = virtualenv-based automation of test activities
- authors = holger krekel <holger@merlinux.eu>
- url = http://tox.testrun.org
- entry_points = console_scripts: tox=tox:cmdline
- requires = py
- packages =
- preuploadenvs = sphinx
-
- classifiers=
- Development Status :: 6 - Mature
- Intended Audience :: Developers
- License :: OSI Approved :: MIT License
- Topic :: Software Development :: Testing
- Topic :: Software Development :: Libraries
- Topic :: Utilities
-
-This would generate three different packages:
-
-- the main one containing the app with the specified description, etc.
- It has a test-requires pointing to the test package,
- which classifiers
-- the test package only containing the tests and setup.py
- depending on the main package and all requirements collected from the
- testenv
-- the doc package containing generated html and txt files
- (to be installable via a setup.py as well?)
-
-Here is what happens when tox is invoked now:
-
-- version gets auto-incremented (in setup.py and $PACKAGE/__init__.py files)
-- main setup.py generated, files copied, sdist generated
-- test setup.py generated, files copied, sdist generated
-- doc setup.py generated, doc environment run, files copied, sdist generated
-
-- if --upload is specified, all packages are uploaded under
- their respective names:
- tox-VER
- tests-tox-VER
- docs-tox-VER
-
-- tox --sync creates a test result file for the tests-tox-VER run
- and uploads it to testrun.org -- .tox/projectkeys contains a file that
- was created by visiting testrun.org and registering/logging in.
-
-- download toxslave and execute it:
-
- toxslave --userkey=... [--project tox]
-
- which will query testrun.org for outstanding testruns
- [for the tox project], download packages, execute them
- and report back to the server
-
-merge tox and detox?
-----------------------------------------------------------------
-
-maybe it's time to merge it?
-
-http://lists.idyll.org/pipermail/testing-in-python/2012-October/005205.html
-pyc files / test distributions
------------------------------------------------------------
-
-investigate pyc cleaning, see
-
-http://lists.idyll.org/pipermail/testing-in-python/2012-October/005205.html
-
-
-allow config overlays
------------------------------------------------------------
-
-tags: 1.5 feature
-
-You can specify wildcards in section titles.
-
- [testenv]
- testsrc=testing/**.py
- commands=py.test {posargs}
-
- [testenv:py3*]
- use2to3 = True
-
- [testenv:py32]
- deps =
- ...
-
-Configuration values are now looked up in a stricter-matches-first
-manner: If environment "py32" is considered then first the
-section under py32, then py3*, then testenv.
-
-
-support 2to3 configurations / test file postprocessing
------------------------------------------------------------
-
-tags: 1.5 feature
-
-Tests should be copied and transformed before being executed.
-Setup a test definition::
-
- [testenv]
- testsrc=testing/**.py
- commands=py.test {posargs}
-
- [testenv:py3*]
- use2to3 = True
-
-would transform all specified test files for all py3 environments
-such that a subsequent test run::
-
- $ tox -e py25,py32 testing/test_hello.py
-
-causes a transformation of the test files to prepare test runs on
-Python3 interpreters. The ``posargs`` specified files will be rewritten
-to point to the transformed test files.
-
-export support for travis
-----------------------------------------
-tag: 1.6 feature
-
-look into ways to support integration of tox with travis.
-
-- run tox from travis
-- let tox read commands from travis config
-- generate .travis.yml from tox.ini
-- generate tox.ini from .travis.yml
-
-For the last two, take a look at http://pypi.python.org/pypi/panci/
-
-allow user-specific python interpreters
-------------------------------------------------
-
-users should be able to define their set of python executables
-to be used for creating virtualenvs.
-.toxrc/interpreters:
-pypy-c=~/p/pypy/branch/sys-prefix/pypy-c
-...
-
-non-cached test dependencies
----------------------------------------------------------------
-
-if there is a dependency on a URL whose content changes
-the download-cache mechanism will prevent it from being reloaded.
-Introduce a 'nocache:' prefix which will inhibit using the cache.
-Also make and document a guarantee on the deps order so that
-one can influence the exact configuration (e.g. use a dev-version
-of some package which a later dependency or the original
-package depends upon - i.e. deps should be installed first).
-
-
-test and make "in-pkg" tests work
----------------------------------------
-
-it is common to put tests into pkg subdirs, possibly
-even with an __init__. See if/how this can be made
-to work. Maybe also re-consider how py.test does its
-importing, maybe add a pytest_addsyspath(testmodule)
-and look how nose does it in detail.
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 97aff5c..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 29c6fb2..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-include CHANGELOG
-include README.rst
-include CONTRIBUTORS
-include ISSUES.txt
-include LICENSE
-include setup.py
-include tox.ini
-graft doc
-graft tests
diff --git a/README.rst b/README.rst
index 1435598..8906e65 100644
--- a/README.rst
+++ b/README.rst
@@ -1,25 +1,4 @@
+We moved to github
+-------------------
-What is Tox?
---------------------
-
-Tox is a generic virtualenv management and test command line tool you can use for:
-
-* checking your package installs correctly with different Python versions and
- interpreters
-
-* running your tests in each of the environments, configuring your test tool of choice
-
-* acting as a frontend to Continuous Integration servers, greatly
- reducing boilerplate and merging CI and shell-based testing.
-
-For more information and the repository please checkout:
-
-- homepage: http://tox.testrun.org
-
-- repository: https://bitbucket.org/hpk42/tox
-
-
-have fun,
-
-holger krekel, 2015
-
+https://github.com/tox-dev/tox
diff --git a/doc/Makefile b/doc/Makefile
deleted file mode 100644
index aae1962..0000000
--- a/doc/Makefile
+++ /dev/null
@@ -1,140 +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) .
-
-SITETARGET=$(shell ./_getdoctarget.py)
-
-.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)/*
-
-
-install: clean html
- @rsync -avz $(BUILDDIR)/html/ testrun.org:/www/testrun.org/tox/latest
- @rsync -avz $(BUILDDIR)/html/ testrun.org:/www/testrun.org/tox/$(SITETARGET)
- #dev
- #latexpdf
- #@scp $(BUILDDIR)/latex/*.pdf testrun.org:www-tox/latest
-
-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/tox.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/tox.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/tox"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/tox"
- @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."
diff --git a/doc/_getdoctarget.py b/doc/_getdoctarget.py
deleted file mode 100755
index f92e87b..0000000
--- a/doc/_getdoctarget.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python
-
-import py
-
-def get_version_string():
- fn = py.path.local(__file__).join("..", "..",
- "tox", "__init__.py")
- for line in fn.readlines():
- if "version" in line and not line.strip().startswith('#'):
- return eval(line.split("=")[-1])
-
-def get_minor_version_string():
- return ".".join(get_version_string().split(".")[:2])
-
-if __name__ == "__main__":
- print(get_minor_version_string())
diff --git a/doc/_static/sphinxdoc.css b/doc/_static/sphinxdoc.css
deleted file mode 100644
index ab8ab5d..0000000
--- a/doc/_static/sphinxdoc.css
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * sphinxdoc.css_t
- * ~~~~~~~~~~~~~~~
- *
- * Sphinx stylesheet -- sphinxdoc theme. Originally created by
- * Armin Ronacher for Werkzeug.
- *
- * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
- * :license: BSD, see LICENSE for details.
- *
- */
-
-@import url("basic.css");
-
-/* -- page layout ----------------------------------------------------------- */
-
-body {
- font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
- 'Verdana', sans-serif;
- font-size: 1.1em;
- letter-spacing: -0.01em;
- line-height: 150%;
- text-align: center;
- background-color: #BFD1D4;
- color: black;
- padding: 0;
- border: 1px solid #aaa;
-
- margin: 0px 80px 0px 80px;
- min-width: 740px;
-}
-
-div.document {
- background-color: white;
- text-align: left;
- background-image: url(contents.png);
- background-repeat: repeat-x;
-}
-
-div.bodywrapper {
- margin: 0 240px 0 0;
- border-right: 1px solid #ccc;
-}
-
-div.body {
- margin: 0;
- padding: 0.5em 20px 20px 20px;
-}
-
-div.related {
- font-size: 0.8em;
-}
-
-div.related ul {
- background-image: url(navigation.png);
- height: 2em;
- border-top: 1px solid #ddd;
- border-bottom: 1px solid #ddd;
-}
-
-div.related ul li {
- margin: 0;
- padding: 0;
- height: 2em;
- float: left;
-}
-
-div.related ul li.right {
- float: right;
- margin-right: 5px;
-}
-
-div.related ul li a {
- margin: 0;
- padding: 0 5px 0 5px;
- line-height: 1.75em;
- color: #EE9816;
-}
-
-div.related ul li a:hover {
- color: #3CA8E7;
-}
-
-div.sphinxsidebarwrapper {
- padding: 0;
-}
-
-div.sphinxsidebar {
- margin: 0;
- padding: 0.5em 15px 15px 0;
- width: 210px;
- float: right;
- font-size: 1em;
- text-align: left;
-}
-
-div.sphinxsidebar h3, div.sphinxsidebar h4 {
- margin: 1em 0 0.5em 0;
- font-size: 1em;
- padding: 0.1em 0 0.1em 0.5em;
- color: white;
- border: 1px solid #86989B;
- background-color: #AFC1C4;
-}
-
-div.sphinxsidebar h3 a {
- color: white;
-}
-
-div.sphinxsidebar ul {
- padding-left: 1.5em;
- margin-top: 7px;
- padding: 0;
- line-height: 130%;
-}
-
-div.sphinxsidebar ul ul {
- margin-left: 20px;
-}
-
-div.footer {
- background-color: #E3EFF1;
- color: #86989B;
- padding: 3px 8px 3px 0;
- clear: both;
- font-size: 0.8em;
- text-align: right;
-}
-
-div.footer a {
- color: #86989B;
- text-decoration: underline;
-}
-
-/* -- body styles ----------------------------------------------------------- */
-
-p {
- margin: 0.8em 0 0.5em 0;
-}
-
-a {
- color: #CA7900;
- text-decoration: none;
-}
-
-a:hover {
- color: #2491CF;
-}
-
-div.body a {
- text-decoration: underline;
-}
-
-h1 {
- margin: 0;
- padding: 0.7em 0 0.3em 0;
- font-size: 1.5em;
- color: #11557C;
-}
-
-h2 {
- margin: 1.3em 0 0.2em 0;
- font-size: 1.35em;
- padding: 0;
-}
-
-h3 {
- margin: 1em 0 -0.3em 0;
- font-size: 1.2em;
-}
-
-div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
- color: black!important;
-}
-
-h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
- display: none;
- margin: 0 0 0 0.3em;
- padding: 0 0.2em 0 0.2em;
- color: #aaa!important;
-}
-
-h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
-h5:hover a.anchor, h6:hover a.anchor {
- display: inline;
-}
-
-h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
-h5 a.anchor:hover, h6 a.anchor:hover {
- color: #777;
- background-color: #eee;
-}
-
-a.headerlink {
- color: #c60f0f!important;
- font-size: 1em;
- margin-left: 6px;
- padding: 0 4px 0 4px;
- text-decoration: none!important;
-}
-
-a.headerlink:hover {
- background-color: #ccc;
- color: white!important;
-}
-
-cite, code, tt {
- font-family: 'Consolas', 'Deja Vu Sans Mono',
- 'Bitstream Vera Sans Mono', monospace;
- font-size: 0.95em;
- letter-spacing: 0.01em;
-}
-
-tt {
- background-color: #f2f2f2;
- border-bottom: 1px solid #ddd;
- color: #333;
-}
-
-tt.descname, tt.descclassname, tt.xref {
- border: 0;
-}
-
-hr {
- border: 1px solid #abc;
- margin: 2em;
-}
-
-a tt {
- border: 0;
- color: #CA7900;
-}
-
-a tt:hover {
- color: #2491CF;
-}
-
-pre {
- font-family: 'Consolas', 'Deja Vu Sans Mono',
- 'Bitstream Vera Sans Mono', monospace;
- font-size: 0.95em;
- letter-spacing: 0.015em;
- line-height: 120%;
- padding: 0.5em;
- border: 1px solid #ccc;
- background-color: #f8f8f8;
-}
-
-pre a {
- color: inherit;
- text-decoration: underline;
-}
-
-td.linenos pre {
- padding: 0.5em 0;
-}
-
-div.quotebar {
- background-color: #f8f8f8;
- max-width: 250px;
- float: right;
- padding: 2px 7px;
- border: 1px solid #ccc;
-}
-
-div.topic {
- background-color: #f8f8f8;
-}
-
-table {
- border-collapse: collapse;
- margin: 0 -0.5em 0 -0.5em;
-}
-
-table td, table th {
- padding: 0.2em 0.5em 0.2em 0.5em;
-}
-
-div.admonition, div.warning {
- font-size: 0.9em;
- margin: 1em 0 1em 0;
- border: 1px solid #86989B;
- background-color: #f7f7f7;
- padding: 0;
-}
-
-div.admonition p, div.warning p {
- margin: 0.5em 1em 0.5em 1em;
- padding: 0;
-}
-
-div.admonition pre, div.warning pre {
- margin: 0.4em 1em 0.4em 1em;
-}
-
-div.admonition p.admonition-title,
-div.warning p.admonition-title {
- margin: 0;
- padding: 0.1em 0 0.1em 0.5em;
- color: white;
- border-bottom: 1px solid #86989B;
- font-weight: bold;
- background-color: #AFC1C4;
-}
-
-div.warning {
- border: 1px solid #940000;
-}
-
-div.warning p.admonition-title {
- background-color: #CF0000;
- border-bottom-color: #940000;
-}
-
-div.admonition ul, div.admonition ol,
-div.warning ul, div.warning ol {
- margin: 0.1em 0.5em 0.5em 3em;
- padding: 0;
-}
-
-div.versioninfo {
- margin: 1em 0 0 0;
- border: 1px solid #ccc;
- background-color: #DDEAF0;
- padding: 8px;
- line-height: 1.3em;
- font-size: 0.9em;
-}
-
-.viewcode-back {
- font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
- 'Verdana', sans-serif;
-}
-
-div.viewcode-block:target {
- background-color: #f4debf;
- border-top: 1px solid #ac9;
- border-bottom: 1px solid #ac9;
-}
diff --git a/doc/_templates/indexsidebar.html b/doc/_templates/indexsidebar.html
deleted file mode 100644
index 12bf335..0000000
--- a/doc/_templates/indexsidebar.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<h3>Download</h3>
-{% if version.endswith('(hg)') %}
-<p>This documentation is for version <b>{{ version }}</b>, which is
- not released yet.</p>
-<p>You can use it from the
- <a href="http://code.google.com/p/pytox/source/checkout">Mercurial repo</a> or look for
- released versions in the <a href="http://pypi.python.org/pypi/tox">Python
- Package Index</a>.</p>
-{% else %}
-<p>Current: <b>{{ version }}</b>
-[<a href="{{ pathto('changelog') }}">Changes</a>]</p>
-<p>
-<a href="http://pypi.python.org/pypi/tox">tox on PyPI</a>
-</p>
-<pre>pip install tox</pre>
-{% endif %}
-
-<h3>Questions? Suggestions?</h3>
-
-<p>Checkout <a href="{{ pathto('support') }}">support channels</a>
-</p>
diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html
deleted file mode 100644
index 1892483..0000000
--- a/doc/_templates/layout.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% extends "!layout.html" %}
-
-
-{% block footer %}
-{{ super() }}
-<script type="text/javascript">
-var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
-try {
-var pageTracker = _gat._getTracker("UA-17241637-3");
-pageTracker._trackPageview();
-} catch(err) {}</script>
-{% endblock %}
diff --git a/doc/_templates/localtoc.html b/doc/_templates/localtoc.html
deleted file mode 100644
index 5976c4b..0000000
--- a/doc/_templates/localtoc.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-{%- if pagename != "search" %}
-<div id="searchbox" style="display: none">
- <form class="search" action="{{ pathto('search') }}" method="get">
- <input type="text" name="q" size="18" />
- <input type="submit" value="{{ _('Search') }}" />
- <input type="hidden" name="check_keywords" value="yes" />
- <input type="hidden" name="area" value="default" />
- </form>
-</div>
-<script type="text/javascript">$('#searchbox').show(0);</script>
-{%- endif %}
-
-<h3>quicklinks</h3>
-<div style="text-align: left; font-size: 100%; vertical-align: middle;">
-<table>
-<tr>
-<td>
- <a href="{{ pathto('index') }}">home</a>
-</td><td>
- <a href="{{ pathto('examples') }}">examples</a>
-</td></tr><tr><td>
- <a href="{{ pathto('install') }}">install</a>
-</td><td>
- <a href="{{ pathto('changelog') }}">changelog</a>
-</td></tr><tr><td>
- <a href="{{ pathto('config') }}">config</a>
-</td><td>
- <a href="https://bitbucket.org/hpk42/tox/issues?status=new&status=open">issues[bb]</a>
-</td></tr><tr><td>
- <a href="{{ pathto('support') }}">support</a>
-</td><td>
-</td></tr></table>
-</div>
-{% extends "basic/localtoc.html" %}
-
diff --git a/doc/announce/release-0.5.txt b/doc/announce/release-0.5.txt
deleted file mode 100644
index f4c30eb..0000000
--- a/doc/announce/release-0.5.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-tox 0.5: a generic virtualenv and test management tool for Python
-===========================================================================
-
-I have been talking about with various people in the last year and
-am happy to now announce the first release of ``tox``. It aims
-to automate tedious Python related test activities driven
-from a simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments
-* installing your package into each of them
-* running your test tool of choice (including e.g. running sphinx checks)
-* testing packages against each other without needing to upload to PyPI
-
-``tox`` runs well on Python2.4 up until Python3.1 and integrates
-well with Continuous Integration servers Jenkins. There are many
-real-life examples and a good chunk of docs. Read it up on
-
- http://codespeak.net/tox
-
-and please report any issues. This is a fresh project and
-i'd like to drive further improvements from real world needs.
-
-best,
-
-holger krekel
-
diff --git a/doc/announce/release-1.0.txt b/doc/announce/release-1.0.txt
deleted file mode 100644
index ae46d41..0000000
--- a/doc/announce/release-1.0.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-tox 1.0: the rapid multi-python test automatizer
-===========================================================================
-
-I am happy to announce tox 1.0, mostly a stabilization and streamlined
-release. TOX automates tedious test activities driven from a
-simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments with
- different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or
- other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-Docs and examples are at:
-
- http://tox.readthedocs.org
-
-Installation:
-
- pip install -U tox
-
-Note that code hosting and issue tracking has moved from Google to Bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-The 1.0 release includes contributions and is based on feedback and
-work from Chris Rose, Ronny Pfannschmidt, Jannis Leidel, Jakob Kaplan-Moss,
-Sridhar Ratnakumar, Carl Meyer and others. Many thanks!
-
-best,
-Holger Krekel
-
-CHANGES
----------------------
-
-- fix issue24: introduce a way to set environment variables for
- for test commands (thanks Chris Rose)
-- fix issue22: require virtualenv-1.6.1, obsoleting virtualenv5 (thanks Jannis Leidel)
- and making things work with pypy-1.5 and python3 more seemlessly
-- toxbootstrap.py (used by jenkins build slaves) now follows the latest release of virtualenv
-- fix issue20: document format of URLs for specifying dependencies
-- fix issue19: substitute Hudson for Jenkins everywhere following the renaming
- of the project. NOTE: if you used the special [tox:hudson]
- section it will now need to be named [tox:jenkins].
-- fix issue 23 / apply some ReST fixes
-- change the positional argument specifier to use {posargs:} syntax and
- fix issues #15 and #10 by refining the argument parsing method (Chris Rose)
-- remove use of inipkg lazy importing logic -
- the namespace/imports are anyway very small with tox.
-- fix a fspath related assertion to work with debian installs which uses
- symlinks
-- show path of the underlying virtualenv invocation and bootstrap
- virtualenv.py into a working subdir
-- added a CONTRIBUTORS file
diff --git a/doc/announce/release-1.1.txt b/doc/announce/release-1.1.txt
deleted file mode 100644
index 8ab78db..0000000
--- a/doc/announce/release-1.1.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-tox 1.1: the rapid multi-python test automatizer
-===========================================================================
-
-I am happy to announce tox 1.1, a bug fix release easing some commong
-workflows. TOX automates tedious test activities driven from a simple
-``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments with
- different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or
- other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-It works well on virtually all Python interpreters that support virtualenv.
-
-Docs and examples are at:
-
- http://tox.readthedocs.org
-
-Installation:
-
- pip install -U tox
-
-Note that code hosting and issue tracking has moved from Google to Bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-The 1.0 release includes contributions and is based on feedback and
-work from Chris Rose, Ronny Pfannschmidt, Jannis Leidel, Jakob Kaplan-Moss,
-Sridhar Ratnakumar, Carl Meyer and others. Many thanks!
-
-best,
-Holger Krekel
-
-CHANGES
----------------------
-
-- fix issue5 - don't require argparse for python versions that have it
-- fix issue6 - recreate virtualenv if installing dependencies failed
-- fix issue3 - fix example on frontpage
-- fix issue2 - warn if a test command does not come from the test
- environment
-- fixed/enhanced: except for initial install always call "-U
- --no-deps" for installing the sdist package to ensure that a package
- gets upgraded even if its version number did not change. (reported on
- TIP mailing list and IRC)
-- inline virtualenv.py (1.6.1) script to avoid a number of issues,
- particularly failing to install python3 environents from a python2
- virtualenv installation.
diff --git a/doc/announce/release-1.2.txt b/doc/announce/release-1.2.txt
deleted file mode 100644
index 139d812..0000000
--- a/doc/announce/release-1.2.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-tox 1.2: the virtualenv-based test run automatizer
-===========================================================================
-
-I am happy to announce tox 1.2, now using and depending on the latest
-virtualenv code and containing some bug fixes. TOX automates tedious
-test activities driven from a simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments with
- different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or
- other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-It works well on virtually all Python interpreters that support virtualenv.
-
-Docs and examples are at:
-
- http://tox.testrun.org/
-
-Installation:
-
- pip install -U tox
-
-code hosting and issue tracking on bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-best,
-Holger Krekel
-
-1.2 compared to 1.1
----------------------
-
-- remove the virtualenv.py that was distributed with tox and depend
- on virtualenv-1.6.4 (possible now since the latter fixes a few bugs
- that the inling tried to work around)
-- fix issue10: work around UnicodeDecodeError when inokving pip (thanks
- Marc Abramowitz)
-- fix a problem with parsing {posargs} in tox commands (spotted by goodwill)
-- fix the warning check for commands to be installed in testevironment
- (thanks Michael Foord for reporting)
diff --git a/doc/announce/release-1.3.txt b/doc/announce/release-1.3.txt
deleted file mode 100644
index b88fc39..0000000
--- a/doc/announce/release-1.3.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-tox 1.3: the virtualenv-based test run automatizer
-===========================================================================
-
-I am happy to announce tox 1.3, containing a few improvements
-over 1.2. TOX automates tedious test activities driven from a
-simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments
- with different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-Docs and examples are at:
-
- http://tox.testrun.org/
-
-Installation:
-
- pip install -U tox
-
-code hosting and issue tracking on bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-best,
-Holger Krekel
-
-1.3
------------------
-
-- fix: allow to specify wildcard filesystem paths when
- specifiying dependencies such that tox searches for
- the highest version
-
-- fix issue issue21: clear PIP_REQUIRES_VIRTUALENV which avoids
- pip installing to the wrong environment, thanks to bb's streeter
-
-- make the install step honour a testenv's setenv setting
- (thanks Ralf Schmitt)
-
diff --git a/doc/announce/release-1.4.3.txt b/doc/announce/release-1.4.3.txt
deleted file mode 100644
index ca0bb19..0000000
--- a/doc/announce/release-1.4.3.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-tox 1.4.3: the Python virtualenv-based testing automatizer
-=============================================================================
-
-tox 1.4.3 fixes some bugs and introduces a new script and two new options:
-
-- "tox-quickstart" - run this script, answer a few questions, and
- get a tox.ini created for you (thanks Marc Abramowitz)
-
-- "tox -l" lists configured environment names (thanks Lukasz Balcerzak)
-
-- (experimental) "--installpkg=localpath" option which will skip the
- sdist-creation of a package and instead install the given localpath package.
-
-- use pip-script.py instead of pip.exe on win32 to avoid windows locking
- the .exe
-
-Note that the sister project "detox" should continue to work - it's a
-separately released project which drives tox test runs on multiple CPUs
-in parallel.
-
-More documentation:
-
- http://tox.testrun.org/
-
-Installation:
-
- pip install -U tox
-
-repository hosting and issue tracking on bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-
-What is tox?
-----------------
-
-tox standardizes and automates tedious python driven test activities
-driven from a simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments
- with different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-best,
-Holger Krekel
-
-
-CHANGELOG
-================
-
-1.4.3 (compared to 1.4.2)
---------------------------------
-
-- introduce -l|--listenv option to list configured environments
- (thanks Lukasz Balcerzak)
-
-- fix downloadcache determination to work according to docs: Only
- make pip use a download cache if PIP_DOWNLOAD_CACHE or a
- downloadcache=PATH testenv setting is present. (The ENV setting
- takes precedence)
-
-- fix issue84 - pypy on windows creates a bin not a scripts venv directory
- (thanks Lukasz Balcerzak)
-
-- experimentally introduce --installpkg=PATH option to install a package rather than
- create/install an sdist package. This will still require and use
- tox.ini and tests from the current working dir (and not from the remote
- package).
-
-- substitute {envsitepackagesdir} with the package installation directory (closes #72)
- (thanks g2p)
-
-- issue #70 remove PYTHONDONTWRITEBYTECODE workaround now that
- virtualenv behaves properly (thanks g2p)
-
-- merged tox-quickstart command, contributed by Marc Abramowitz, which
- generates a default tox.ini after asking a few questions
-
-- fix #48 - win32 detection of pypy and other interpreters that are on PATH
- (thanks Gustavo Picon)
-
-- fix grouping of index servers, it is now done by name instead of
- indexserver url, allowing to use it to separate dependencies
- into groups even if using the same default indexserver.
-
-- look for "tox.ini" files in parent dirs of current dir (closes #34)
-
-- the "py" environment now by default uses the current interpreter
- (sys.executable) make tox' own setup.py test execute tests with it
- (closes #46)
-
-- change tests to not rely on os.path.expanduser (closes #60),
- also make mock session return args[1:] for more precise checking (closes #61)
- thanks to Barry Warszaw for both.
-
diff --git a/doc/announce/release-1.4.txt b/doc/announce/release-1.4.txt
deleted file mode 100644
index d0e6644..0000000
--- a/doc/announce/release-1.4.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-tox 1.4: the virtualenv-based test run automatizer
-=============================================================================
-
-I am happy to announce tox 1.4 which brings:
-
-- improvements with configuration file syntax, now allowing re-using
- selected settings across config file sections. see http://testrun.org/tox/latest/config.html#substitution-for-values-from-other-sections
-
-- terminal reporting was simplified and streamlined. Now with
- verbosity==0 (the default), less information will be shown
- and you can use one or multiple "-v" options to increase verbosity.
-
-- internal re-organisation so that the separately released "detox"
- tool can reuse tox code to implement a fully distributed tox run.
-
-More documentation:
-
- http://tox.testrun.org/
-
-Installation:
-
- pip install -U tox
-
-code hosting and issue tracking on bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-What is tox?
-----------------
-
-tox standardizes and automates tedious test activities driven from a
-simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments
- with different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-best,
-Holger Krekel
-
-
-1.4
------------------
-
-- fix issue26 - no warnings on absolute or relative specified paths for commands
-- fix issue33 - commentchars are ignored in key-value settings allowing
- for specifying commands like: python -c "import sys ; print sys"
- which would formerly raise irritating errors because the ";"
- was considered a comment
-- tweak and improve reporting
-- refactor reporting and virtualenv manipulation
- to be more accessible from 3rd party tools
-- support value substitution from other sections
- with the {[section]key} syntax
-- fix issue29 - correctly point to pytest explanation
- for importing modules fully qualified
-- fix issue32 - use --system-site-packages and don't pass --no-site-packages
-- add python3.3 to the default env list, so early adopters can test
-- drop python2.4 support (you can still have your tests run on
- python-2.4, just tox itself requires 2.5 or higher.
diff --git a/doc/announce/release-1.8.txt b/doc/announce/release-1.8.txt
deleted file mode 100644
index b8a2218..0000000
--- a/doc/announce/release-1.8.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-tox 1.8: Generative/combinatorial environments specs
-=============================================================================
-
-I am happy to announce tox 1.8 which implements parametrized environments.
-
-See https://tox.testrun.org/latest/config.html#generating-environments-conditional-settings
-for examples and the new backward compatible syntax in your tox.ini file.
-
-Many thanks to Alexander Schepanovski for implementing and refining
-it based on the specifcation draft.
-
-More documentation about tox in general:
-
- http://tox.testrun.org/
-
-Installation:
-
- pip install -U tox
-
-code hosting and issue tracking on bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-What is tox?
-----------------
-
-tox standardizes and automates tedious test activities driven from a
-simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments
- with different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-best,
-Holger Krekel, merlinux GmbH
-
-
-Changes 1.8 (compared to 1.7.2)
----------------------------------------
-
-- new multi-dimensional configuration support. Many thanks to
- Alexander Schepanovski for the complete PR with docs.
- And to Mike Bayer and others for testing and feedback.
-
-- fix issue148: remove "__PYVENV_LAUNCHER__" from os.environ when starting
- subprocesses. Thanks Steven Myint.
-
-- fix issue152: set VIRTUAL_ENV when running test commands,
- thanks Florian Ludwig.
-
-- better report if we can't get version_info from an interpreter
- executable. Thanks Floris Bruynooghe.
diff --git a/doc/announce/release-1.9.txt b/doc/announce/release-1.9.txt
deleted file mode 100644
index 96379b9..0000000
--- a/doc/announce/release-1.9.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-tox-1.9: refinements, fixes (+detox-0.9.4)
-==========================================
-
-tox-1.9 was released to pypi, a maintenance release with mostly
-backward-compatible enhancements and fixes. However, tox now defaults
-to pip-installing only non-development releases and you have to set "pip_pre =
-True" in your testenv section to have it install development ("pre") releases.
-
-In addition, there is a new detox-0.9.4 out which allow to run tox test
-environments in parallel and fixes a compat problem with eventlet.
-
-Thanks to Alexander Schepanosvki, Florian Schulze and others for the
-contributed fixes and improvements.
-
-More documentation about tox in general:
-
- http://tox.testrun.org/
-
-Installation:
-
- pip install -U tox
-
-code hosting and issue tracking on bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-What is tox?
-----------------
-
-tox standardizes and automates tedious test activities driven from a
-simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments
- with different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-best,
-Holger Krekel, merlinux GmbH
-
-
-1.9.0
------------
-
-- fix issue193: Remove ``--pre`` from the default ``install_command``; by
- default tox will now only install final releases from PyPI for unpinned
- dependencies. Use ``pip_pre = true`` in a testenv or the ``--pre``
- command-line option to restore the previous behavior.
-
-- fix issue199: fill resultlog structure ahead of virtualenv creation
-
-- refine determination if we run from Jenkins, thanks Borge Lanes.
-
-- echo output to stdout when ``--report-json`` is used
-
-- fix issue11: add a ``skip_install`` per-testenv setting which
- prevents the installation of a package. Thanks Julian Krause.
-
-- fix issue124: ignore command exit codes; when a command has a "-" prefix,
- tox will ignore the exit code of that command
-
-- fix issue198: fix broken envlist settings, e.g. {py26,py27}{-lint,}
-
-- fix issue191: lessen factor-use checks
-
diff --git a/doc/announce/release-2.0.txt b/doc/announce/release-2.0.txt
deleted file mode 100644
index e05af6c..0000000
--- a/doc/announce/release-2.0.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-tox-2.0: plugins, platform, env isolation
-==========================================
-
-tox-2.0 was released to pypi, a major new release with *mostly*
-backward-compatible enhancements and fixes:
-
-- experimental support for plugins, see https://testrun.org/tox/latest/plugins.html
- which includes also a refined internal registration mechanism for new testenv
- ini options. You can now ask tox which testenv ini parameters exist
- with ``tox --help-ini``.
-
-- ENV isolation: only pass through very few environment variables from the
- tox invocation to the test environments. This may break test runs that
- previously worked with tox-1.9 -- you need to either use the
- ``setenv`` or ``passenv`` ini variables to set appropriate environment
- variables.
-
-- PLATFORM support: you can set ``platform=REGEX`` in your testenv sections
- which lets tox skip the environment if the REGEX does not match ``sys.platform``.
-
-- tox now stops execution of test commands if the first of them fails unless
- you set ``ignore_errors=True``.
-
-Thanks to Volodymyr Vitvitski, Daniel Hahler, Marc Abramowitz, Anthon van
-der Neuth and others for contributions.
-
-More documentation about tox in general:
-
- http://tox.testrun.org/
-
-Installation:
-
- pip install -U tox
-
-code hosting and issue tracking on bitbucket:
-
- https://bitbucket.org/hpk42/tox
-
-What is tox?
-----------------
-
-tox standardizes and automates tedious test activities driven from a
-simple ``tox.ini`` file, including:
-
-* creation and management of different virtualenv environments
- with different Python interpreters
-* packaging and installing your package into each of them
-* running your test tool of choice, be it nose, py.test or unittest2 or other tools such as "sphinx" doc checks
-* testing dev packages against each other without needing to upload to PyPI
-
-best,
-Holger Krekel, merlinux GmbH
-
-2.0.0
------------
-
-- (new) introduce environment variable isolation:
- tox now only passes the PATH and PIP_INDEX_URL variable from the tox
- invocation environment to the test environment and on Windows
- also ``SYSTEMROOT``, ``PATHEXT``, ``TEMP`` and ``TMP`` whereas
- on unix additionally ``TMPDIR`` is passed. If you need to pass
- through further environment variables you can use the new ``passenv`` setting,
- a space-separated list of environment variable names. Each name
- can make use of fnmatch-style glob patterns. All environment
- variables which exist in the tox-invocation environment will be copied
- to the test environment.
-
-- a new ``--help-ini`` option shows all possible testenv settings and
- their defaults.
-
-- (new) introduce a way to specify on which platform a testenvironment is to
- execute: the new per-venv "platform" setting allows to specify
- a regular expression which is matched against sys.platform.
- If platform is set and doesn't match the platform spec in the test
- environment the test environment is ignored, no setup or tests are attempted.
-
-- (new) add per-venv "ignore_errors" setting, which defaults to False.
- If ``True``, a non-zero exit code from one command will be ignored and
- further commands will be executed (which was the default behavior in tox <
- 2.0). If ``False`` (the default), then a non-zero exit code from one command
- will abort execution of commands for that environment.
-
-- show and store in json the version dependency information for each venv
-
-- remove the long-deprecated "distribute" option as it has no effect these days.
-
-- fix issue233: avoid hanging with tox-setuptools integration example. Thanks simonb.
-
-- fix issue120: allow substitution for the commands section. Thanks
- Volodymyr Vitvitski.
-
-- fix issue235: fix AttributeError with --installpkg. Thanks
- Volodymyr Vitvitski.
-
-- tox has now somewhat pep8 clean code, thanks to Volodymyr Vitvitski.
-
-- fix issue240: allow to specify empty argument list without it being
- rewritten to ".". Thanks Daniel Hahler.
-
-- introduce experimental (not much documented yet) plugin system
- based on pytest's externalized "pluggy" system.
- See tox/hookspecs.py for the current hooks.
-
-- introduce parser.add_testenv_attribute() to register an ini-variable
- for testenv sections. Can be used from plugins through the
- tox_add_option hook.
-
-- rename internal files -- tox offers no external API except for the
- experimental plugin hooks, use tox internals at your own risk.
-
-- DEPRECATE distshare in documentation
diff --git a/doc/changelog.txt b/doc/changelog.txt
deleted file mode 100644
index 504f36c..0000000
--- a/doc/changelog.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-.. _changelog:
-
-Changelog history
-=================================
-
-.. include:: ../CHANGELOG
diff --git a/doc/check_sphinx.py b/doc/check_sphinx.py
deleted file mode 100644
index 26f6b11..0000000
--- a/doc/check_sphinx.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import py
-import subprocess
-def test_build_docs(tmpdir):
- doctrees = tmpdir.join("doctrees")
- htmldir = tmpdir.join("html")
- subprocess.check_call([
- "sphinx-build", "-bhtml",
- "-d", str(doctrees), ".", str(htmldir)])
-
-def test_linkcheck(tmpdir):
- doctrees = tmpdir.join("doctrees")
- htmldir = tmpdir.join("html")
- subprocess.check_call(
- ["sphinx-build", "-blinkcheck",
- "-d", str(doctrees), ".", str(htmldir)])
-
-
diff --git a/doc/conf.py b/doc/conf.py
deleted file mode 100644
index 6094f60..0000000
--- a/doc/conf.py
+++ /dev/null
@@ -1,272 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# tox documentation build configuration file, created by
-# sphinx-quickstart on Sat May 29 10:42:26 2010.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys, os
-
-# The short X.Y version.
-sys.path.insert(0, os.path.dirname(__file__))
-import _getdoctarget
-
-version = _getdoctarget.get_minor_version_string()
-release = _getdoctarget.get_version_string()
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.append(os.path.abspath('.'))
-
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.txt'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'tox'
-copyright = u'2015, holger krekel and others'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The full version, including alpha/beta/rc tags.
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-
-# -- Options for HTML output ---------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. Major themes that come with
-# Sphinx are currently 'default' and 'sphinxdoc'.
-html_theme = 'sphinxdoc'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {'index': 'indexsidebar.html'}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {'index': 'indexsidebar.html'}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-html_show_sourcelink = False
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = ''
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'toxdoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-# The paper size ('letter' or 'a4').
-#latex_paper_size = 'a4'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '12pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
- ('index', 'tox.tex', u'tox Documentation',
- u'holger krekel', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# 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_domain_indices = True
-
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- ('index', 'tox', u'tox Documentation',
- [u'holger krekel'], 1)
-]
-
-
-# -- Options for Epub output ---------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = u'tox'
-epub_author = u'holger krekel'
-epub_publisher = u'holger krekel'
-epub_copyright = u'2010, holger krekel'
-
-# The language of the text. It defaults to the language option
-# or en if the language is not set.
-#epub_language = ''
-
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#epub_identifier = ''
-
-# A unique identification for the text.
-#epub_uid = ''
-
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_pre_files = []
-
-# HTML files shat should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_post_files = []
-
-# A list of files that should not be packed into the epub file.
-#epub_exclude_files = []
-
-# The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
-
-
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'http://docs.python.org/': None}
-
-def setup(app):
- #from sphinx.ext.autodoc import cut_lines
- #app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
- app.add_description_unit('confval', 'confval',
- objname='configuration value',
- indextemplate='pair: %s; configuration value')
-
-
-linkcheck_timeout = 30
-linkcheck_ignore = [r'http://holgerkrekel.net']
diff --git a/doc/config-v2.txt b/doc/config-v2.txt
deleted file mode 100644
index c639652..0000000
--- a/doc/config-v2.txt
+++ /dev/null
@@ -1,292 +0,0 @@
-V2: new tox multi-dimensional, platform-specific configuration
---------------------------------------------------------------------
-
-.. note::
-
- This is a draft document sketching a to-be-done implementation.
- It does not fully specify each change yet but should give a good
- idea of where things are heading. For feedback, mail the
- testing-in-python mailing list or open a pull request on
- https://bitbucket.org/hpk42/tox/src/84d8cf3c2a95fefd874f22c8b2d257e94365472f/doc/config-v2.txt?at=default
-
-**Abstract**: Adding multi-dimensional configuration, platform-specification
-and multiple installers to tox.ini.
-
-**Target audience**: Developers using or wanting to use tox for testing
-their python projects.
-
-Issues with current tox (1.4) configuration
-------------------------------------------------
-
-Tox is used as a tool for creating and managing virtualenv environments
-and running tests in them. As of tox-1.4 there are some issues frequently
-coming up with its configuration language:
-
-- there is no way to instruct tox to parametrize testenv specifications
- other than to list all combinations by specifying a ``[testenv:...]``
- section for each combination. Examples of real life situations
- arising from this:
-
- * https://github.com/tomchristie/django-rest-framework/blob/b001a146d73348af18cfc4c943d87f2f389349c9/tox.ini
-
- * https://bitbucket.org/tabo/django-treebeard/src/93b579395a9c/tox.ini
-
-- there is no way to have platform specific settings other than to
- define specific testenvs and invoke tox with a platform-specific
- testenv list.
-
-- there is no way to specify the platforms against which a project
- shall successfully run.
-
-- tox always uses pip for installing packages currently. This has
- several issues:
-
- - no way to check if installing via easy_install works
- - no installs of packages with compiled c-extensions (win32 standard)
-
-
-Goals, resolving those issues
-------------------------------------
-
-This document discusses a possible solution for each of these issues,
-namely these goals:
-
-- allow to more easily define and run dependency/interpreter variants
- with testenvs
-- allow platform-specific settings
-- allow to specify platforms against which tests should run
-- allow to run installer-variants (easy_install or pip, xxx)
-- try to mimick/re-use bash-style syntax to ease learning curve.
-
-
-Example: Generating and selecting variants
-----------------------------------------------
-
-Suppose you want to test your package against python2.6, python2.7 and on the
-windows and linux platforms. Today you would have to
-write down 2*2 = 4 ``[testenv:*]`` sections and then instruct
-tox to run a specific list of environments on each platform.
-
-With tox-1.X you can directlys specify combinations::
-
- # combination syntax gives 2 * 2 = 4 testenv names
- #
- envlist = {py26,py27}-{win,linux}
-
- [testenv]
- deps = pytest
- platform =
- win: windows
- linux: linux
- basepython =
- py26: python2.6
- py27: python2.7
- commands = py.test
-
-Let's go through this step by step::
-
- envlist = {py26,py27}-{windows,linux}
-
-This is bash-style syntax and will create ``2*2=4`` environment names
-like this::
-
- py26-windows
- py26-linux
- py27-windows
- py27-linux
-
-Our ``[testenv]`` uses a new templating style for the ``platform`` definition::
-
- platform=
- windows: windows
- linux: linux
-
-These two conditional settings will lead to either ``windows`` or
-``linux`` as the platform string. When the test environment is run,
-its platform string needs to be contained in the string returned
-from ``platform.platform()``. Otherwise the environment will be skipped.
-
-The next configuration item in the ``testenv`` section deals with
-the python interpreter::
-
- basepython =
- py26: python2.6
- py27: python2.7
-
-This defines a python executable, depending on if ``py26`` or ``py27``
-appears in the environment name.
-
-The last config item is simply the invocation of the test runner::
-
- commands = py.test
-
-Nothing special here :)
-
-.. note::
-
- Tox provides good defaults for platform and basepython
- settings, so the above ini-file can be further reduced::
-
- [tox]
- envlist = {py26,py27}-{win,linux}
-
- [testenv]
- deps = pytest
- commands = py.test
-
- Voila, this multi-dimensional ``tox.ini`` configuration
- defines 2*2=4 environments.
-
-
-The new "platform" setting
---------------------------------------
-
-A testenv can define a new ``platform`` setting. If its value
-is not contained in the string obtained from calling
-``sys.platform`` the environment will be skipped.
-
-Expanding the ``envlist`` setting
-----------------------------------------------------------
-
-The new ``envlist`` setting allows to use ``{}`` bash-style
-expressions. XXX explanation or pointer to bash-docs
-
-Templating based on environments names
--------------------------------------------------
-
-For a given environment name, all lines in a testenv section which
-start with "NAME: ..." will be checked for being part in the environment
-name. If they are part of it, the remainder will be the new line.
-If they are not part of it, the whole line will be left out.
-Parts of an environment name are obtained by ``-``-splitting it.
-
-Variant specification with [variant:VARNAME]
-
-Showing all expanded sections
--------------------------------
-
-To help with understanding how the variants will produce section values,
-you can ask tox to show their expansion with a new option::
-
- $ tox -l [XXX output ommitted for now]
-
-Making sure your packages installs with easy_install
-------------------------------------------------------
-
-The new "installer" testenv setting allows to specify the tool for
-installation in a given test environment::
-
- [testenv]
- installer =
- easy: easy_install
- pip: pip
-
-If you want to have your package installed with both easy_install
-and pip, you can list them in your envlist likes this::
-
- [tox]
- envlist = py[26,27,32]-django[13,14]-[easy,pip]
-
-If no installer is specified, ``pip`` will be used.
-
-Default settings related to environments names/variants
----------------------------------------------------------------
-
-tox comes with predefined settings for certain variants, namely:
-
-* ``{easy,pip}`` use easy_install or pip respectively
-* ``{py24,py25,py26,py27,py31,py32,py33,py34,pypy19]`` use the respective
- pythonNN or PyPy interpreter
-* ``{win32,linux,darwin}`` defines the according ``platform``.
-
-You can use those in your “envlist” specification
-without the need to define them yourself.
-
-
-Use more bash-style syntax
---------------------------------------
-
-tox leverages bash-style syntax if you specify mintoxversion = 1.4:
-
-- $VARNAME or ${...} syntax instead of the older {} substitution.
-- XXX go through config.txt and see how it would need to be changed
-
-
-Transforming the examples: django-rest
-------------------------------------------------
-
-The original `django-rest-framework tox.ini
-<https://github.com/tomchristie/django-rest-framework/blob/b001a146d73348af18cfc4c943d87f2f389349c9/tox.ini>`_
-file has 159 lines and a lot of repetition, the new one would +have 20
-lines and almost no repetition::
-
- [tox]
- envlist = {py25,py26,py27}-{django12,django13}{,-example}
-
- [testenv]
- deps=
- coverage==3.4
- unittest-xml-reporting==1.2
- Pyyaml==3.10
- django12: django==1.2.4
- django13: django==1.3.1
- # some more deps for running examples
- example: wsgiref==0.1.2
- example: Pygments==1.4
- example: httplib2==0.6.0
- example: Markdown==2.0.3
-
- commands =
- !example: python setup.py test
- example: python examples/runtests.py
-
-
-Note that ``{,-example}`` in the envlist denotes two values, an empty
-one and a ``example`` one. The empty value means that there are no specific
-settings and thus no need to define a variant name.
-
-Transforming the examples: django-treebeard
-------------------------------------------------
-
-Another `tox.ini
-<https://bitbucket.org/tabo/django-treebeard/raw/93b579395a9c/tox.ini>`_
-has 233 lines and runs tests against multiple Postgres and Mysql
-engines. It also performs backend-specific test commands, passing
-different command line options to the test script. With the new tox-1.X
-we not only can do the same with 32 non-repetive configuration lines but
-we also produce 36 specific testenvs with specific dependencies and test
-commands::
-
- [tox]
- envlist =
- {py24,py25,py26,py27}-{django11,django12,django13}-{nodb,pg,mysql}, docs
-
- [testenv:docs]
- changedir = docs
- deps =
- Sphinx
- Django
- commands =
- make clean
- make html
-
- [testenv]
- deps=
- coverage
- pysqlite
- django11: django==1.1.4
- django12: django==1.2.7
- django13: django==1.3.1
- django14: django==1.4
- nodb: pysqlite
- pg: psycopg2
- mysql: MySQL-python
-
- commands =
- nodb: {envpython} runtests.py {posargs}
- pg: {envpython} runtests.py {posargs} \
- --DATABASE_ENGINE=postgresql_psycopg2 \
- --DATABASE_USER=postgres {posargs}
- mysql: {envpython} runtests.py --DATABASE_ENGINE=mysql \
- --DATABASE_USER=root {posargs}
-
diff --git a/doc/config.txt b/doc/config.txt
deleted file mode 100644
index d99e91c..0000000
--- a/doc/config.txt
+++ /dev/null
@@ -1,633 +0,0 @@
-.. be in -*- rst -*- mode!
-
-tox configuration specification
-===============================
-
-.. _ConfigParser: http://docs.python.org/library/configparser.html
-
-``tox.ini`` files uses the standard ConfigParser_ "ini-style" format.
-Below you find the specification, but you might want to skim some
-:doc:`examples` first and use this page as a reference.
-
-Tox global settings
--------------------
-
-List of optional global options::
-
- [tox]
- minversion=ver # minimally required tox version
- toxworkdir=path # tox working directory, defaults to {toxinidir}/.tox
- setupdir=path # defaults to {toxinidir}
- distdir=path # defaults to {toxworkdir}/dist
- distshare=path # (DEPRECATED) defaults to {homedir}/.tox/distshare
- envlist=ENVLIST # defaults to the list of all environments
- skipsdist=BOOL # defaults to false
-
-
-``tox`` autodetects if it is running in a Jenkins_ context
-(by checking for existence of the ``JENKINS_URL`` environment variable)
-and will first lookup global tox settings in this section::
-
- [tox:jenkins]
- ... # override [tox] settings for the jenkins context
- # note: for jenkins distshare defaults to ``{toxworkdir}/distshare`` (DEPRECATED)
-
-.. confval:: skip_missing_interpreters=BOOL
-
- .. versionadded:: 1.7.2
-
- Setting this to ``True`` is equivalent of passing the
- ``--skip-missing-interpreters`` command line option, and will force ``tox`` to
- return success even if some of the specified environments were missing. This is
- useful for some CI systems or running on a developer box, where you might only
- have a subset of all your supported interpreters installed but don't want to
- mark the build as failed because of it. As expected, the command line switch
- always overrides this setting if passed on the invokation.
- **Default:** ``False``
-
-.. confval:: envlist=CSV
-
- Determining the environment list that ``tox`` is to operate on
- happens in this order (if any is found, no further lookups are made):
-
- * command line option ``-eENVLIST``
- * environment variable ``TOXENV``
- * ``tox.ini`` file's ``envlist``
-
-
-Virtualenv test environment settings
-------------------------------------
-
-Test environments are defined by a::
-
- [testenv:NAME]
- ...
-
-section. The ``NAME`` will be the name of the virtual environment.
-Defaults for each setting in this section are looked up in the::
-
- [testenv]
- ...
-
-testenvironment default section.
-
-Complete list of settings that you can put into ``testenv*`` sections:
-
-.. confval:: basepython=NAME-OR-PATH
-
- name or path to a Python interpreter which will be used for creating
- the virtual environment. **default**: interpreter used for tox invocation.
-
-.. confval:: commands=ARGVLIST
-
- the commands to be called for testing. Each command is defined
- by one or more lines; a command can have multiple lines if a line
- ends with the ``\`` character in which case the subsequent line
- will be appended (and may contain another ``\`` character ...).
- For eventually performing a call to ``subprocess.Popen(args, ...)``
- ``args`` are determined by splitting the whole command by whitespace.
- Similar to ``make`` recipe lines, any command with a leading ``-``
- will ignore the exit code.
-
-.. confval:: install_command=ARGV
-
- .. versionadded:: 1.6
-
- the ``install_command`` setting is used for installing packages into
- the virtual environment; both the package under test
- and any defined dependencies. Must contain the substitution key
- ``{packages}`` which will be replaced by the packages to
- install. You should also accept ``{opts}`` if you are using
- pip or easy_install -- it will contain index server options
- if you have configured them via :confval:`indexserver`
- and the deprecated :confval:`downloadcache` option
- if you have configured it.
-
- **default**::
-
- pip install {opts} {packages}
-
-
-.. confval:: list_dependencies_command
-
- .. versionadded:: 2.4
-
- the ``list_dependencies_command`` setting is used for listing
- the packages installed into the virtual environment.
-
- **default**::
-
- pip freeze
-
-
-.. confval:: ignore_errors=True|False(default)
-
- .. versionadded:: 2.0
-
- If ``True``, a non-zero exit code from one command will be ignored and
- further commands will be executed (which was the default behavior in tox <
- 2.0). If ``False`` (the default), then a non-zero exit code from one command
- will abort execution of commands for that environment.
-
- It may be helpful to note that this setting is analogous to the ``-i`` or
- ``ignore-errors`` option of GNU Make. A similar name was chosen to reflect the
- similarity in function.
-
- Note that in tox 2.0, the default behavior of tox with respect to
- treating errors from commands changed. Tox < 2.0 would ignore errors by
- default. Tox >= 2.0 will abort on an error by default, which is safer and more
- typical of CI and command execution tools, as it doesn't make sense to
- run tests if installing some prerequisite failed and it doesn't make sense to
- try to deploy if tests failed.
-
-.. confval:: pip_pre=True|False(default)
-
- .. versionadded:: 1.9
-
- If ``True``, adds ``--pre`` to the ``opts`` passed to
- :confval:`install_command`. If :confval:`install_command` uses pip, this
- will cause it to install the latest available pre-release of any
- dependencies without a specified version. If ``False`` (the default), pip
- will only install final releases of unpinned dependencies.
-
- Passing the ``--pre`` command-line option to tox will force this to
- ``True`` for all testenvs.
-
- Don't set this option if your :confval:`install_command` does not use pip.
-
-.. confval:: whitelist_externals=MULTI-LINE-LIST
-
- each line specifies a command name (in glob-style pattern format)
- which can be used in the ``commands`` section without triggering
- a "not installed in virtualenv" warning. Example: if you use the
- unix ``make`` for running tests you can list ``whitelist_externals=make``
- or ``whitelist_externals=/usr/bin/make`` if you want more precision.
- If you don't want tox to issue a warning in any case, just use
- ``whitelist_externals=*`` which will match all commands (not recommended).
-
-.. confval:: changedir=path
-
- change to this working directory when executing the test command.
- **default**: ``{toxinidir}``
-
-.. confval:: deps=MULTI-LINE-LIST
-
- test-specific dependencies - to be installed into the environment prior to project
- package installation. Each line defines a dependency, which will be
- passed to the installer command for processing. Each line specifies a file,
- a URL or a package name. You can additionally specify
- an :confval:`indexserver` to use for installing this dependency
- but this functionality is deprecated since tox-2.3.
- All derived dependencies (deps required by the dep) will then be
- retrieved from the specified indexserver::
-
- deps = :myindexserver:pkg
-
- (Experimentally introduced in 1.6.1) all installer commands are executed
- using the ``{toxinidir}`` as the current working directory.
-
-.. confval:: platform=REGEX
-
- A testenv can define a new ``platform`` setting as a regular expression.
- If a non-empty expression is defined and does not match against the
- ``sys.platform`` string the test environment will be skipped.
-
-.. confval:: setenv=MULTI-LINE-LIST
-
- .. versionadded:: 0.9
-
- each line contains a NAME=VALUE environment variable setting which
- will be used for all test command invocations as well as for installing
- the sdist package into a virtual environment.
-
-.. confval:: passenv=SPACE-SEPARATED-GLOBNAMES
-
- .. versionadded:: 2.0
-
- A list of wildcard environment variable names which
- shall be copied from the tox invocation environment to the test
- environment when executing test commands. If a specified environment
- variable doesn't exist in the tox invocation environment it is ignored.
- You can use ``*`` and ``?`` to match multiple environment variables with
- one name.
-
- Note that the ``PATH``, ``LANG`` and ``PIP_INDEX_URL`` variables are
- unconditionally passed down and on Windows ``SYSTEMROOT``, ``PATHEXT``,
- ``TEMP`` and ``TMP`` will be passed down as well whereas on unix
- ``TMPDIR`` will be passed down. You can override these variables
- with the ``setenv`` option.
-
- If defined the ``TOX_TESTENV_PASSENV`` environment variable (in the tox
- invocation environment) can define additional space-separated variable
- names that are to be passed down to the test command environment.
-
-.. confval:: recreate=True|False(default)
-
- Always recreate virtual environment if this option is True.
-
-.. confval:: downloadcache=path
-
- **DEPRECATED** -- as of August 2013 this option is not very
- useful because of pypi's CDN and because of caching pypi
- server solutions like `devpi <http://doc.devpi.net>`_.
-
- use this directory for caching downloads. This value is overriden
- by the environment variable ``PIP_DOWNLOAD_CACHE`` if it exists. If
- you specify a custom :confval:`install_command` that uses an
- installer other than pip, your installer must support the
- `--download-cache` command-line option.
- **default**: no download cache will be used.
-
-.. confval:: sitepackages=True|False
-
- Set to ``True`` if you want to create virtual environments that also
- have access to globally installed packages.
-
- **default:** False, meaning that virtualenvs will be
- created without inheriting the global site packages.
-
-.. confval:: args_are_paths=BOOL
-
- treat positional arguments passed to ``tox`` as file system paths
- and - if they exist on the filesystem - rewrite them according
- to the ``changedir``.
- **default**: True (due to the exists-on-filesystem check it's
- usually safe to try rewriting).
-
-.. confval:: envtmpdir=path
-
- defines a temporary directory for the virtualenv which will be cleared
- each time before the group of test commands is invoked.
- **default**: ``{envdir}/tmp``
-
-.. confval:: envlogdir=path
-
- defines a directory for logging where tox will put logs of tool
- invocation.
- **default**: ``{envdir}/log``
-
-.. confval:: indexserver
-
- .. versionadded:: 0.9
-
- (DEPRECATED, will be removed in a future version) Multi-line ``name =
- URL`` definitions of python package servers. Dependencies can
- specify using a specified index server through the
- ``:indexservername:depname`` pattern. The ``default`` indexserver
- definition determines where unscoped dependencies and the sdist install
- installs from. Example::
-
- [tox]
- indexserver =
- default = http://mypypi.org
-
- will make tox install all dependencies from this PYPI index server
- (including when installing the project sdist package).
-
-
-.. confval:: envdir
-
- .. versionadded:: 1.5
-
- User can set specific path for environment. If path would not be absolute it
- would be treated as relative to ``{toxinidir}``. **default**:
- ``{toxworkdir}/{envname}``
-
-.. confval:: usedevelop=BOOL
-
- .. versionadded:: 1.6
-
- Install the current package in development mode with "setup.py
- develop" instead of installing from the ``sdist`` package. (This
- uses pip's `-e` option, so should be avoided if you've specified a
- custom :confval:`install_command` that does not support ``-e``).
-
- **default**: ``False``
-
-.. confval:: skip_install=BOOL
-
- .. versionadded:: 1.9
-
- Do not install the current package. This can be used when you need the
- virtualenv management but do not want to install the current package
- into that environment.
-
- **default**: ``False``
-
-.. confval:: ignore_outcome=BOOL
-
- .. versionadded:: 2.2
-
- If set to True a failing result of this testenv will not make tox fail,
- only a warning will be produced.
-
- **default**: ``False``
-
-
-Substitutions
--------------
-
-Any ``key=value`` setting in an ini-file can make use
-of value substitution through the ``{...}`` string-substitution pattern.
-
-You can escape curly braces with the ``\`` character if you need them, for example::
-
- commands = echo "\{posargs\}" = {posargs}
-
-Globally available substitutions
-++++++++++++++++++++++++++++++++
-
-``{toxinidir}``
- the directory where tox.ini is located
-
-``{toxworkdir}``
- the directory where virtual environments are created and sub directories
- for packaging reside.
-
-``{homedir}``
- the user-home directory path.
-
-``{distdir}``
- the directory where sdist-packages will be created in
-
-``{distshare}``
- (DEPRECATED) the directory where sdist-packages will be copied to so that
- they may be accessed by other processes or tox runs.
-
-substitutions for virtualenv-related sections
-+++++++++++++++++++++++++++++++++++++++++++++
-
-``{envname}``
- the name of the virtual environment
-``{envpython}``
- path to the virtual Python interpreter
-``{envdir}``
- directory of the virtualenv hierarchy
-``{envbindir}``
- directory where executables are located
-``{envsitepackagesdir}``
- directory where packages are installed.
- Note that architecture-specific files may appear in a different directory.
-``{envtmpdir}``
- the environment temporary directory
-``{envlogdir}``
- the environment log directory
-
-
-environment variable substitutions
-++++++++++++++++++++++++++++++++++
-
-If you specify a substitution string like this::
-
- {env:KEY}
-
-then the value will be retrieved as ``os.environ['KEY']``
-and raise an Error if the environment variable
-does not exist.
-
-
-environment variable substitutions with default values
-++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-If you specify a substitution string like this::
-
- {env:KEY:DEFAULTVALUE}
-
-then the value will be retrieved as ``os.environ['KEY']``
-and replace with DEFAULTVALUE if the environment variable does not
-exist.
-
-If you specify a substitution string like this::
-
- {env:KEY:}
-
-then the value will be retrieved as ``os.environ['KEY']``
-and replace with and empty string if the environment variable does not
-exist.
-
-.. _`command positional substitution`:
-.. _`positional substitution`:
-
-substitutions for positional arguments in commands
-++++++++++++++++++++++++++++++++++++++++++++++++++
-
-.. versionadded:: 1.0
-
-If you specify a substitution string like this::
-
- {posargs:DEFAULTS}
-
-then the value will be replaced with positional arguments as provided
-to the tox command::
-
- tox arg1 arg2
-
-In this instance, the positional argument portion will be replaced with
-``arg1 arg2``. If no positional arguments were specified, the value of
-DEFAULTS will be used instead. If DEFAULTS contains other substitution
-strings, such as ``{env:*}``, they will be interpreted.,
-
-Use a double ``--`` if you also want to pass options to an underlying
-test command, for example::
-
- tox -- --opt1 ARG1
-
-will make the ``--opt1 ARG1`` appear in all test commands where ``[]`` or
-``{posargs}`` was specified. By default (see ``args_are_paths``
-setting), ``tox`` rewrites each positional argument if it is a relative
-path and exists on the filesystem to become a path relative to the
-``changedir`` setting.
-
-Previous versions of tox supported the ``[.*]`` pattern to denote
-positional arguments with defaults. This format has been deprecated.
-Use ``{posargs:DEFAULTS}`` to specify those.
-
-
-Substitution for values from other sections
-+++++++++++++++++++++++++++++++++++++++++++
-
-.. versionadded:: 1.4
-
-Values from other sections can be refered to via::
-
- {[sectionname]valuename}
-
-which you can use to avoid repetition of config values.
-You can put default values in one section and reference them in others to avoid repeating the same values::
-
- [base]
- deps =
- pytest
- mock
- pytest-xdist
-
- [testenv:dulwich]
- deps =
- dulwich
- {[base]deps}
-
- [testenv:mercurial]
- deps =
- mercurial
- {[base]deps}
-
-
-Generating environments, conditional settings
----------------------------------------------
-
-.. versionadded:: 1.8
-
-Suppose you want to test your package against python2.6, python2.7 and against
-several versions of a dependency, say Django 1.5 and Django 1.6. You can
-accomplish that by writing down 2*2 = 4 ``[testenv:*]`` sections and then
-listing all of them in ``envlist``.
-
-However, a better approach looks like this::
-
- [tox]
- envlist = {py26,py27}-django{15,16}
-
- [testenv]
- basepython =
- py26: python2.6
- py27: python2.7
- deps =
- pytest
- django15: Django>=1.5,<1.6
- django16: Django>=1.6,<1.7
- py26: unittest2
- commands = py.test
-
-This uses two new facilities of tox-1.8:
-
-- generative envlist declarations where each envname
- consists of environment parts or "factors"
-
-- "factor" specific settings
-
-Let's go through this step by step.
-
-
-.. _generative-envlist:
-
-Generative envlist
-+++++++++++++++++++++++
-
-::
-
- envlist = {py26,py27}-django{15,16}
-
-This is bash-style syntax and will create ``2*2=4`` environment names
-like this::
-
- py26-django15
- py26-django16
- py27-django15
- py27-django16
-
-You can still list environments explicitly along with generated ones::
-
- envlist = {py26,py27}-django{15,16}, docs, flake
-
-.. note::
-
- To help with understanding how the variants will produce section values,
- you can ask tox to show their expansion with a new option::
-
- $ tox -l
- py26-django15
- py26-django16
- py27-django15
- py27-django16
- docs
- flake
-
-
-.. _factors:
-
-Factors and factor-conditional settings
-++++++++++++++++++++++++++++++++++++++++
-
-Parts of an environment name delimited by hyphens are called factors and can
-be used to set values conditionally::
-
- basepython =
- py26: python2.6
- py27: python2.7
-
-This conditional setting will lead to either ``python2.6`` or
-``python2.7`` used as base python, e.g. ``python2.6`` is selected if current
-environment contains ``py26`` factor.
-
-In list settings such as ``deps`` or ``commands`` you can freely intermix
-optional lines with unconditional ones::
-
- deps =
- pytest
- django15: Django>=1.5,<1.6
- django16: Django>=1.6,<1.7
- py26: unittest2
-
-Reading it line by line:
-
-- ``pytest`` will be included unconditionally,
-- ``Django>=1.5,<1.6`` will be included for environments containing ``django15`` factor,
-- ``Django>=1.6,<1.7`` similarly depends on ``django16`` factor,
-- ``unittest`` will be loaded for Python 2.6 environments.
-
-.. note::
-
- Tox provides good defaults for basepython setting, so the above
- ini-file can be further reduced by omitting the ``basepython``
- setting.
-
-
-Complex factor conditions
-+++++++++++++++++++++++++
-
-Sometimes you need to specify the same line for several factors or create a
-special case for a combination of factors. Here is how you do it::
-
- [tox]
- envlist = py{26,27,33}-django{15,16}-{sqlite,mysql}
-
- [testenv]
- deps =
- py33-mysql: PyMySQL ; use if both py33 and mysql are in an env name
- py26,py27: urllib3 ; use if any of py26 or py27 are in an env name
- py{26,27}-sqlite: mock ; mocking sqlite in python 2.x
-
-Take a look at first ``deps`` line. It shows how you can special case something
-for a combination of factors, you just join combining factors with a hyphen.
-This particular line states that ``PyMySQL`` will be loaded for python 3.3,
-mysql environments, e.g. ``py33-django15-mysql`` and ``py33-django16-mysql``.
-
-The second line shows how you use same line for several factors - by listing
-them delimited by commas. It's possible to list not only simple factors, but
-also their combinations like ``py26-sqlite,py27-sqlite``.
-
-Finally, factor expressions are expanded the same way as envlist, so last
-example could be rewritten as ``py{26,27}-sqlite``.
-
-.. note::
-
- Factors don't do substring matching against env name, instead every
- hyphenated expression is split by ``-`` and if ALL the factors in an
- expression are also factors of an env then that condition is considered
- hold.
-
- For example, environment ``py26-mysql``:
-
- - could be matched with expressions ``py26``, ``py26-mysql``,
- ``mysql-py26``,
- - but not with ``py2`` or ``py26-sql``.
-
-
-Other Rules and notes
-=====================
-
-* ``path`` specifications: if a specified ``path`` is a relative path
- it will be considered as relative to the ``toxinidir``, the directory
- where the configuration file resides.
-
-.. include:: links.txt
diff --git a/doc/drafts/extend-envs-and-packagebuilds.md b/doc/drafts/extend-envs-and-packagebuilds.md
deleted file mode 100644
index b2cdc0e..0000000
--- a/doc/drafts/extend-envs-and-packagebuilds.md
+++ /dev/null
@@ -1,155 +0,0 @@
-# Extension of environment handling and building packages
-
-Issue reference: #338
-
-*Notes from a discussion at the pytest sprint 2016*
-
-Goal: drive building of packages and the environments needed to test them, exercising the tests and report the results for more than just virtualenvs and python virtualenvs
-
-### Problems
-
-* No concept of mapping environments to specific packages (versioned packages)
-* no control over when it happens for specific environment
-* no control over how it happens (e.g. which python interpreter is used to create the package)
-* No way of triggering build only if there is an environment that needs a specific build trigger it only if an environment actually needs it
-* package definition that might match on everything might be a problem for which environments test? Not clear?
-
-### Solution
-
-It should be possible to build other kinds of packages than just the standard sdist and it should also be possible to create different kinds of builds that can be used from different environments. To make this possible there has to be some concept of factorized package definitions and a way to match these factorized builds to environments with a similar way of matching like what is in place already to generate environments. sdist would for example would match to a "sdist" factor to only be matched against virtualenvs as the default.
-
-This could then be used to hae virtualenv, conda, nixos, docker, pyenv, rpm, deb, etc. builds and tie them to concrete test environments.
-
-To summarize - we would need a:
-
- * packagedef (how to build a package)
- * envdef (how to build an environment)
- * way of matching envs to concrete packages (at package definition level) (e.g `{py27,py34}-{win32,linux}-{venv,conda,pyenv}-[...]`)
-
-## Beginnings of configuration examples (not thought out yet)
-
- [tox]
- envlist={py,27,py34}-{win32, linux}-{conda,virtualenv}
-
- [packagedef:sdist]
- # how to build (e.g. {py27,py34}-{sdist})
- # how to match (e.g. {py27,py34}-{sdist})
-
- [packagedef:conda]
- # how to build (e.g. {py27,py34}-{conda})
- # how to match (e.g. {py27,py34}-{conda})
-
- [packagedef:wheel]
- # how to build
- # how to match
-
-#### integrate detox
-
-* reporting in detox is minimal (would need to improve)
-* restricting processes would be necessary depending on power of the machine
- (creating 16 processe on a dual core machine might be overkill)
-* port it from eventlets to threads?
-
-### Concrete use case conda integration (started by Bruno)
-
-* Asynchronicity / detox not taken into account yet
-* Conda activation might do anything (change filesys, start DBs)
-* Can I activate environments in parallel
-* Packages would need to be created (from conda.yml)
-* Activation is a problem
-
-
-### Unsorted discussion notes
-
-* Simplify for the common case: most packages are universal, so it should be simple
-one to one relationship from environment to directory
-* Floris: metadata driven. Package has metadata to the env with what env it is compatible
-* Holger: configuration driven. explicitly configuring which packages should be used (default sdist to be used, overridable by concrete env)
-* Ronny: "package definitions" (this package, this setup command) + matching definitions (matching packages (with wildcards) for environments)
-
-
-## Proposal
-
-This feature shall allow to specify how plugins can specify new types of package formats and environments to run test
-commands in.
-
-Such plugins would take care of setting up the environment, create packages and run test commands using hooks provided
-by tox. The actual knowledge how to create a certain package format is implement in the plugin.
-
-Plugin decides which is the required python interpreter to use in order to create the relevant package format.
-
-
-```ini
-[tox]
-plugins=conda # virtualenv plugin is builtin; intention here is to bail out early in case the specified plugins
- # are not installed
-envlist=py27,py35
-
-[testenv]
-package_formats= # new option to specify wanted package formats for test environment using tox factors feature
- # defaults to "sdist" if not set
- py35: sdist wheel conda # names here are provided by plugins (reserved keywords)
- py27: sdist conda
-commands = py.test
-```
-
-Lising tox environments (`tox --list`) would display the following output:
-
-```
-(sdist) py27
-(conda) py27
-(sdist) py35
-(wheel) py35
-(conda) py35
-```
-
-To remain backward-compatible, the package format will not be displayed if only a single package format is specified.
-
-
-
-How to skip building a package for a specific factor?
-
-Illustrate how to exclude a certain package format for a factor:
-
-```ini
-[tox]
-plugins=conda
-envlist={py27,py35}, py27-xdist
-
-[testenv]
-package_formats=sdist wheel conda
-commands = py.test
-exclude_package_formats= # new option which filters out packages
- py27-xdist: wheel
-```
-
-Output of `tox --list`:
-
-```
-(sdist) py27
-(conda) py27
-(sdist) py35
-(wheel) py35
-(conda) py35
-(sdist) py27-xdist
-(conda) py27-xdist
-```
-
-
-### Implemenation Details
-
-```
-tox_package_formats() -> ['conda'] # ['sdist', 'wheel']
-tox_testenv_create(env_meta, package_type) -> # creates an environment for given package, using
- # information from env_meta (like .envdir)
- # returns: an "env" object which is forwaded to the next hooks
-tox_testenv_install(env_meta, package_type, env) -> # installs deps and package into environment
-tox_testenv_runtest(env_meta, package_type, env) -> # activates enviroment and runs test commands
-
-tox_testenv_updated(env_meta, package_type) -> # returns True if hte environment is already up to date
- # otherwise, tox will remove the environment completely and
- # create a new one
-```
-
-
-
diff --git a/doc/drafts/tox_conda_notes_niccodemus.md b/doc/drafts/tox_conda_notes_niccodemus.md
deleted file mode 100644
index a54189a..0000000
--- a/doc/drafts/tox_conda_notes_niccodemus.md
+++ /dev/null
@@ -1,84 +0,0 @@
-[tox]
-envlist=py27,py35
-
-[testenv]
-commands= py.test --timeout=180 {posargs:tests}
-deps=pytest>=2.3.5
- pytest-timeout
-
-# USE CASE 1: plain conda, with deps on tox.ini
-create_env_command = conda create --prefix {envdir} python={python_version}
-install_command = conda install --prefix {envdir} {opts} {packages}
-list_dependencies_command = conda list --prefix {envdir}
-
-# deprecated: see tox_create_popen hook
-linux:env_activate_command=source activate {envdir}
-win:env_activate_command=activate.bat {envdir}
-
-# USE CASE 2: plain conda, using requirements.txt
-install_command = conda install --prefix {envdir} {opts} --file requirements.txt
-
-# USE CASE 3: conda env
-create_env_command = conda env create --prefix {envdir} python={python_version} --file environment.yml
-install_command =
-
-[testenv]
-type=virtualenv
-type=venv
-type=conda
-type=conda-reqs
-type=conda-env
-
-1. Create a new ``create_env_command`` option.
-;2. Create a new ``env_activate_command`` option (also consider how to make that platform dependent).
-2. New substitution variable: {python_version} ('3.4', '2.7', etc')
-3. env type concept: different types change the default options.
-
-1. tox_addoption can now add new "testenv" sections to tox.ini:
-
-[virtualenv]
-[conda]
-[venv]
-
-2. extend hooks:
-
- * tox_addoption
- * tox_configure
- for each requested env in config:
- tox_testenv_up_to_date(envmeta)
- tox_testenv_create(envmeta)
- tox_testenv_install_deps(envmeta, env)
- tox_runtest_pre(envmeta, env)
- tox_runtest(envmeta, env, popen)
- tox_runtest_post(envmeta, env)
-
-3. separate virtualenv details from "VirtualEnv" class into a plugin.
-
-[tox]
-envlist={py27,py35}-{sdist,wheel,conda}
-
-[package-sdist]
-command = python setup.py sdist
-
-[package-wheel]
-command = python setup.py bdist_wheel
-
-[package-conda]
-command = conda build ./conda-recipe
-
-[testenv:{sdist,wheel}]
-commands = py.test
-
-[testenv:conda]
-packages = sdist,wheel
-commands = py.test --conda-only
-
-* tox_addoption
-* tox_get_python_executable
-* tox_configure
-for each requested env in config:
- tox_testenv_create(envmeta)
- tox_testenv_install_deps(envmeta, env)
- tox_runtest_pre(envmeta, env)
- tox_runtest(envmeta, env, popen)
- tox_runtest_post(envmeta, env)
diff --git a/doc/example/basic.txt b/doc/example/basic.txt
deleted file mode 100644
index 84fed34..0000000
--- a/doc/example/basic.txt
+++ /dev/null
@@ -1,313 +0,0 @@
-Basic usage
-=============================================
-
-a simple tox.ini / default environments
------------------------------------------------
-
-Put basic information about your project and the test environments you
-want your project to run in into a ``tox.ini`` file that should
-reside next to your ``setup.py`` file::
-
- # content of: tox.ini , put in same dir as setup.py
- [tox]
- envlist = py26,py27
- [testenv]
- deps=pytest # or 'nose' or ...
- commands=py.test # or 'nosetests' or ...
-
-To sdist-package, install and test your project, you can
-now type at the command prompt::
-
- tox
-
-This will sdist-package your current project, create two virtualenv_
-Environments, install the sdist-package into the environments and run
-the specified command in each of them. With::
-
- tox -e py26
-
-you can run restrict the test run to the python2.6 environment.
-
-Available "default" test environments names are::
-
- py
- py24
- py25
- py26
- py27
- py30
- py31
- py32
- py33
- py34
- jython
- pypy
- pypy3
-
-The environment ``py`` uses the version of Python used to invoke tox.
-
-However, you can also create your own test environment names,
-see some of the examples in :doc:`examples <../examples>`.
-
-specifying a platform
------------------------------------------------
-
-.. versionadded:: 2.0
-
-If you want to specify which platform(s) your test environment
-runs on you can set a platform regular expression like this::
-
- platform = linux2|darwin
-
-If the expression does not match against ``sys.platform``
-the test environment will be skipped.
-
-whitelisting non-virtualenv commands
------------------------------------------------
-
-.. versionadded:: 1.5
-
-Sometimes you may want to use tools not contained in your
-virtualenv such as ``make``, ``bash`` or others. To avoid
-warnings you can use the ``whitelist_externals`` testenv
-configuration::
-
- # content of tox.ini
- [testenv]
- whitelist_externals = make
- /bin/bash
-
-
-.. _virtualenv: http://pypi.python.org/pypi/virtualenv
-
-.. _multiindex:
-
-depending on requirements.txt
------------------------------------------------
-
-.. versionadded:: 1.6.1
-
-(experimental) If you have a ``requirements.txt`` file
-you can add it to your ``deps`` variable like this::
-
- deps = -rrequirements.txt
-
-All installation commands are executed using ``{toxinidir}``
-(the directory where ``tox.ini`` resides) as the current
-working directory. Therefore, the underlying ``pip`` installation
-will assume ``requirements.txt`` to exist at ``{toxinidir}/requirements.txt``.
-
-using a different default PyPI url
------------------------------------------------
-
-.. versionadded:: 0.9
-
-To install dependencies and packages from a different
-default PyPI server you can type interactively::
-
- tox -i http://pypi.testrun.org
-
-This causes tox to install dependencies and the sdist install step
-to use the specificied url as the index server.
-
-You can cause the same effect by this ``tox.ini`` content::
-
- [tox]
- indexserver =
- default = http://pypi.testrun.org
-
-installing dependencies from multiple PyPI servers
----------------------------------------------------
-
-.. versionadded:: 0.9
-
-You can instrument tox to install dependencies from
-different PyPI servers, example::
-
- [tox]
- indexserver =
- DEV = http://mypypiserver.org
-
- [testenv]
- deps =
- docutils # comes from standard PyPI
- :DEV:mypackage # will be installed from custom "DEV" pypi url
-
-This configuration will install ``docutils`` from the default
-Python PYPI server and will install the ``mypackage`` from
-our ``DEV`` indexserver, and the respective ``http://mypypiserver.org``
-url. You can override config file settings from the command line
-like this::
-
- tox -i DEV=http://pypi.python.org/simple # changes :DEV: package URLs
- tox -i http://pypi.python.org/simple # changes default
-
-further customizing installation
----------------------------------
-
-.. versionadded:: 1.6
-
-By default tox uses `pip`_ to install packages, both the
-package-under-test and any dependencies you specify in ``tox.ini``.
-You can fully customize tox's install-command through the
-testenv-specific :confval:`install_command=ARGV` setting.
-For instance, to use ``easy_install`` instead of `pip`_::
-
- [testenv]
- install_command = easy_install {opts} {packages}
-
-Or to use pip's ``--find-links`` and ``--no-index`` options to specify
-an alternative source for your dependencies::
-
- [testenv]
- install_command = pip install --pre --find-links http://packages.example.com --no-index {opts} {packages}
-
-.. _pip: http://pip-installer.org
-
-forcing re-creation of virtual environments
------------------------------------------------
-
-.. versionadded:: 0.9
-
-To force tox to recreate a (particular) virtual environment::
-
- tox --recreate -e py27
-
-would trigger a complete reinstallation of the existing py27 environment
-(or create it afresh if it doesn't exist).
-
-passing down environment variables
--------------------------------------------
-
-.. versionadded:: 2.0
-
-By default tox will only pass the ``PATH`` environment variable (and on
-windows ``SYSTEMROOT`` and ``PATHEXT``) from the tox invocation to the
-test environments. If you want to pass down additional environment
-variables you can use the ``passenv`` option::
-
- [testenv]
- passenv = LANG
-
-When your test commands execute they will execute with
-the same LANG setting as the one with which tox was invoked.
-
-setting environment variables
--------------------------------------------
-
-.. versionadded:: 1.0
-
-If you need to set an environment variable like ``PYTHONPATH`` you
-can use the ``setenv`` directive::
-
- [testenv]
- setenv =
- PYTHONPATH = {toxinidir}/subdir
-
-When your test commands execute they will execute with
-a PYTHONPATH setting that will lead Python to also import
-from the ``subdir`` below the directory where your ``tox.ini``
-file resides.
-
-special handling of PYTHONHASHSEED
--------------------------------------------
-
-.. versionadded:: 1.6.2
-
-By default, Tox sets PYTHONHASHSEED_ for test commands to a random integer
-generated when ``tox`` is invoked. This mimics Python's hash randomization
-enabled by default starting `in Python 3.3`_. To aid in reproducing test
-failures, Tox displays the value of ``PYTHONHASHSEED`` in the test output.
-
-You can tell Tox to use an explicit hash seed value via the ``--hashseed``
-command-line option to ``tox``. You can also override the hash seed value
-per test environment in ``tox.ini`` as follows::
-
- [testenv]
- setenv =
- PYTHONHASHSEED = 100
-
-If you wish to disable this feature, you can pass the command line option
-``--hashseed=noset`` when ``tox`` is invoked. You can also disable it from the
-``tox.ini`` by setting ``PYTHONHASHSEED = 0`` as described above.
-
-.. _`in Python 3.3`: http://docs.python.org/3/whatsnew/3.3.html#builtin-functions-and-types
-.. _PYTHONHASHSEED: http://docs.python.org/using/cmdline.html#envvar-PYTHONHASHSEED
-
-Integration with setuptools/distribute test commands
-----------------------------------------------------
-
-Distribute/Setuptools support test requirements
-and you can extend its test command to trigger
-a test run when ``python setup.py test`` is issued::
-
- from setuptools.command.test import test as TestCommand
- import sys
-
- class Tox(TestCommand):
- user_options = [('tox-args=', 'a', "Arguments to pass to tox")]
- def initialize_options(self):
- TestCommand.initialize_options(self)
- self.tox_args = None
- def finalize_options(self):
- TestCommand.finalize_options(self)
- self.test_args = []
- self.test_suite = True
- def run_tests(self):
- #import here, cause outside the eggs aren't loaded
- import tox
- import shlex
- args = self.tox_args
- if args:
- args = shlex.split(self.tox_args)
- tox.cmdline(args=args)
-
- setup(
- #...,
- tests_require=['tox'],
- cmdclass = {'test': Tox},
- )
-
-Now if you run::
-
- python setup.py test
-
-this will install tox and then run tox. You can pass arguments to ``tox``
-using the ``--tox-args`` or ``-a`` command-line options. For example::
-
- python setup.py test -a "-epy27"
-
-is equivalent to running ``tox -epy27``.
-
-Ignoring a command exit code
-----------------------------
-
-In some cases, you may want to ignore a command exit code. For example::
-
- [testenv:py27]
- commands = coverage erase
- {envbindir}/python setup.py develop
- coverage run -p setup.py test
- coverage combine
- - coverage html
- {envbindir}/flake8 loads
-
-By using the ``-`` prefix, similar to a ``make`` recipe line, you can ignore
-the exit code for that command.
-
-Compressing dependency matrix
------------------------------
-
-If you have a large matrix of dependencies, python versions and/or environments you can
-use :ref:`generative-envlist` and :ref:`conditional settings <factors>` to express that in a concise form::
-
- [tox]
- envlist = py{26,27,33}-django{15,16}-{sqlite,mysql}
-
- [testenv]
- deps =
- django15: Django>=1.5,<1.6
- django16: Django>=1.6,<1.7
- py33-mysql: PyMySQL ; use if both py33 and mysql are in an env name
- py26,py27: urllib3 ; use if any of py26 or py27 are in an env name
- py{26,27}-sqlite: mock ; mocking sqlite in python 2.x
diff --git a/doc/example/devenv.txt b/doc/example/devenv.txt
deleted file mode 100644
index f4afc37..0000000
--- a/doc/example/devenv.txt
+++ /dev/null
@@ -1,78 +0,0 @@
-=======================
-Development environment
-=======================
-
-Tox can be used for just preparing different virtual environments required by a
-project.
-
-This feature can be used by deployment tools when preparing deployed project
-environments. It can also be used for setting up normalized project development
-environments and thus help reduce the risk of different team members using
-mismatched development environments.
-
-Here are some examples illustrating how to set up a project's development
-environment using tox. For illustration purposes, let us call the development
-environment ``devenv``.
-
-
-Example 1: Basic scenario
-=========================
-
-Step 1 - Configure the development environment
-----------------------------------------------
-
-First, we prepare the tox configuration for our development environment by
-defining a ``[testenv:devenv]`` section in the project's ``tox.ini``
-configuration file::
-
- [testenv:devenv]
- envdir = devenv
- basepython = python2.7
- usedevelop = True
-
-In it we state:
-
-- what directory to locate the environment in,
-- what Python executable to use in the environment,
-- that our project should be installed into the environment using ``setup.py
- develop``, as opposed to building and installing its source distribution using
- ``setup.py install``.
-
-Actually, we can configure a lot more, and these are only the required settings.
-For example, we can add the following to our configuration, telling tox not to
-reuse ``commands`` or ``deps`` settings from the base ``[testenv]``
-configuration::
-
- commands =
- deps =
-
-
-Step 2 - Create the development environment
--------------------------------------------
-
-Once the ``[testenv:devenv]`` configuration section has been defined, we create
-the actual development environment by running the following::
-
- tox -e devenv
-
-This creates the environment at the path specified by the environment's
-``envdir`` configuration value.
-
-
-Example 2: A more complex scenario
-==================================
-
-Let us say we want our project development environment to:
-
-- be located in the ``devenv`` directory,
-- use Python executable ``python2.7``,
-- pull packages from ``requirements.txt``, located in the same directory as
- ``tox.ini``.
-
-Here is an example configuration for the described scenario::
-
- [testenv:devenv]
- envdir = devenv
- basepython = python2.7
- usedevelop = True
- deps = -rrequirements.txt
diff --git a/doc/example/general.txt b/doc/example/general.txt
deleted file mode 100644
index 1a27549..0000000
--- a/doc/example/general.txt
+++ /dev/null
@@ -1,182 +0,0 @@
-.. be in -*- rst -*- mode!
-
-General tips and tricks
-================================
-
-Interactively passing positional arguments
------------------------------------------------
-
-If you invoke ``tox`` like this::
-
- tox -- -x tests/test_something.py
-
-the arguments after the ``--`` will be substituted
-everywhere where you specify ``{posargs}`` in your
-test commands, for example using ``py.test``::
-
- # in the testenv or testenv:NAME section of your tox.ini
- commands =
- py.test {posargs}
-
-or using ``nosetests``::
-
- commands =
- nosetests {posargs}
-
-the above ``tox`` invocation will trigger the test runners to
-stop after the first failure and to only run a particular test file.
-
-You can specify defaults for the positional arguments using this
-syntax::
-
- commands =
- nosetests {posargs:--with-coverage}
-
-.. _`sphinx checks`:
-
-Integrating "sphinx" documentation checks
-----------------------------------------------
-
-In a ``testenv`` environment you can specify any command and
-thus you can easily integrate sphinx_ documentation integrity during
-a tox test run. Here is an example ``tox.ini`` configuration::
-
- [testenv:docs]
- basepython=python
- changedir=doc
- deps=sphinx
- commands=
- sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
-
-This will create a dedicated ``docs`` virtual environment and install
-the ``sphinx`` dependency which itself will install the ``sphinx-build`` tool
-which you can then use as a test command. Note that sphinx output is redirected
-to the virtualenv environment temporary directory to prevent sphinx
-from caching results between runs.
-
-You can now call::
-
- tox
-
-which will make the sphinx tests part of your test run.
-
-
-.. _`TOXENV`:
-
-Selecting one or more environments to run tests against
---------------------------------------------------------
-
-Using the ``-e ENV[,ENV2,...]`` option you explicitely list
-the environments where you want to run tests against. For
-example, given the previous sphinx example you may call::
-
- tox -e docs
-
-which will make ``tox`` only manage the ``docs`` environment
-and call its test commands. You may specify more than
-one environment like this::
-
- tox -e py25,py26
-
-which would run the commands of the ``py25`` and ``py26`` testenvironments
-respectively. The special value ``ALL`` selects all environments.
-
-You can also specify an environment list in your ``tox.ini``::
-
- [tox]
- envlist = py25,py26
-
-or override it from the command line or from the environment variable
-``TOXENV``::
-
- export TOXENV=py25,py26 # in bash style shells
-
-.. _artifacts:
-
-Access package artifacts between multiple tox-runs
---------------------------------------------------------
-
-If you have multiple projects using tox you can make use of
-a ``distshare`` directory where ``tox`` will copy in sdist-packages so
-that another tox run can find the "latest" dependency. This feature
-allows to test a package against an unreleased development version
-or even an uncommitted version on your own machine.
-
-By default, ``{homedir}/.tox/distshare`` will be used for
-copying in and copying out artifacts (i.e. Python packages).
-
-For project ``two`` to depend on the ``one`` package you use
-the following entry::
-
- # example two/tox.ini
- [testenv]
- deps=
- {distshare}/one-*.zip # install latest package from "one" project
-
-That's all. Tox running on project ``one`` will copy the sdist-package
-into the ``distshare`` directory after which a ``tox`` run on project
-``two`` will grab it because ``deps`` contain an entry with the
-``one-*.zip`` pattern. If there is more than one matching package the
-highest version will be taken. ``tox`` uses verlib_ to compare version
-strings which must be compliant with :pep:`386`.
-
-If you want to use this with Jenkins_, also checkout the :ref:`jenkins artifact example`.
-
-.. _verlib: https://bitbucket.org/tarek/distutilsversion/
-
-basepython defaults, overriding
-++++++++++++++++++++++++++++++++++++++++++
-
-By default, for any ``pyXY`` test environment name
-the underlying "pythonX.Y" executable will be searched in
-your system ``PATH``. It must exist in order to successfully create
-virtualenv environments. On Windows a ``pythonX.Y`` named executable
-will be searched in typical default locations using the
-``C:\PythonX.Y\python.exe`` pattern.
-
-For ``jython`` and ``pypy`` the respective ``jython``
-and ``pypy-c`` names will be looked for.
-
-You can override any of the default settings by defining
-the ``basepython`` variable in a specific test environment
-section, for example::
-
- [testenv:py27]
- basepython=/my/path/to/python2.7
-
-Avoiding expensive sdist
-------------------------
-
-Some projects are large enough that running an sdist, followed by
-an install every time can be prohibitively costly. To solve this,
-there are two different options you can add to the ``tox`` section. First,
-you can simply ask tox to please not make an sdist::
-
- [tox]
- skipsdist=True
-
-If you do this, your local software package will not be installed into
-the virtualenv. You should probably be okay with that, or take steps
-to deal with it in your commands section::
-
- [testenv]
- commands =
- python setup.py develop
- py.test
-
-Running ``setup.py develop`` is a common enough model that it has its own
-option::
-
- [testenv]
- usedevelop=True
-
-And a corresponding command line option ``--develop``, which will set
-``skipsdist`` to True and then perform the ``setup.py develop``
-step at the place where ``tox`` normally perfoms the installation of the sdist.
-Specifically, it actually runs ``pip install -e .`` behind the scenes, which
-itself calls ``setup.py develop``.
-
-There is an optimization coded in to not bother re-running the command if
-``$projectname.egg-info`` is newer than ``setup.py`` or ``setup.cfg``.
-
-.. include:: ../links.txt
diff --git a/doc/example/jenkins.txt b/doc/example/jenkins.txt
deleted file mode 100644
index 94cb22d..0000000
--- a/doc/example/jenkins.txt
+++ /dev/null
@@ -1,174 +0,0 @@
-
-Using Tox with the Jenkins Integration Server
-=================================================
-
-Using Jenkins multi-configuration jobs
--------------------------------------------
-
-The Jenkins_ continuous integration server allows to define "jobs" with
-"build steps" which can be test invocations. If you :doc:`install <../install>` ``tox`` on your
-default Python installation on each Jenkins slave, you can easily create
-a Jenkins multi-configuration job that will drive your tox runs from the CI-server side,
-using these steps:
-
-* install the Python plugin for Jenkins under "manage jenkins"
-* create a "multi-configuration" job, give it a name of your choice
-* configure your repository so that Jenkins can pull it
-* (optional) configure multiple nodes so that tox-runs are performed
- on multiple hosts
-* configure ``axes`` by using :ref:`TOXENV <TOXENV>` as an axis
- name and as values provide space-separated test environment names
- you want Jenkins/tox to execute.
-
-* add a **Python-build step** with this content (see also next example)::
-
- import tox
- tox.cmdline() # environment is selected by ``TOXENV`` env variable
-
-* check ``Publish JUnit test result report`` and enter
- ``**/junit-*.xml`` as the pattern so that Jenkins collects
- test results in the JUnit XML format.
-
-The last point requires that your test command creates JunitXML files,
-for example with ``py.test`` it is done like this:
-
-.. code-block:: ini
-
- commands = py.test --junitxml=junit-{envname}.xml
-
-
-
-**zero-installation** for slaves
--------------------------------------------------------------
-
-.. note::
-
- This feature is broken currently because "toxbootstrap.py"
- has been removed. Please file an issue if you'd like to
- see it back.
-
-If you manage many Jenkins slaves and want to use the latest officially
-released tox (or latest development version) and want to skip manually
-installing ``tox`` then substitute the above **Python build step** code
-with this::
-
- import urllib, os
- url = "https://bitbucket.org/hpk42/tox/raw/default/toxbootstrap.py"
- #os.environ['USETOXDEV']="1" # use tox dev version
- d = dict(__file__='toxbootstrap.py')
- exec urllib.urlopen(url).read() in d
- d['cmdline'](['--recreate'])
-
-The downloaded `toxbootstrap.py` file downloads all neccessary files to
-install ``tox`` in a virtual sub environment. Notes:
-
-* uncomment the line containing ``USETOXDEV`` to use the latest
- development-release version of tox instead of the
- latest released version.
-
-* adapt the options in the last line as needed (the example code
- will cause tox to reinstall all virtual environments all the time
- which is often what one wants in CI server contexts)
-
-
-Integrating "sphinx" documentation checks in a Jenkins job
-----------------------------------------------------------------
-
-If you are using a multi-configuration Jenkins job which collects
-JUnit Test results you will run into problems using the previous
-method of running the sphinx-build command because it will not
-generate JUnit results. To accomodate this issue one solution
-is to have ``py.test`` wrap the sphinx-checks and create a
-JUnit result file which wraps the result of calling sphinx-build.
-Here is an example:
-
-1. create a ``docs`` environment in your ``tox.ini`` file like this::
-
- [testenv:docs]
- basepython=python
- changedir=doc # or whereever you keep your sphinx-docs
- deps=sphinx
- py
- commands=
- py.test --tb=line -v --junitxml=junit-{envname}.xml check_sphinx.py
-
-2. create a ``doc/check_sphinx.py`` file like this::
-
- import py
- import subprocess
- def test_linkcheck(tmpdir):
- doctrees = tmpdir.join("doctrees")
- htmldir = tmpdir.join("html")
- subprocess.check_call(
- ["sphinx-build", "-W", "-blinkcheck",
- "-d", str(doctrees), ".", str(htmldir)])
- def test_build_docs(tmpdir):
- doctrees = tmpdir.join("doctrees")
- htmldir = tmpdir.join("html")
- subprocess.check_call([
- "sphinx-build", "-W", "-bhtml",
- "-d", str(doctrees), ".", str(htmldir)])
-
-3. run ``tox -e docs`` and then you may integrate this environment
- along with your other environments into Jenkins.
-
-Note that ``py.test`` is only installed into the docs environment
-and does not need to be in use or installed with any other environment.
-
-.. _`jenkins artifact example`:
-
-Access package artifacts between Jenkins jobs
---------------------------------------------------------
-
-.. _`Jenkins Copy Artifact plugin`: http://wiki.jenkins-ci.org/display/HUDSON/Copy+Artifact+Plugin
-
-In an extension to :ref:`artifacts` you can also configure Jenkins jobs to
-access each others artifacts. ``tox`` uses the ``distshare`` directory
-to access artifacts and in a Jenkins context (detected via existence
-of the environment variable ``HUDSON_URL``); it defaults to
-to ``{toxworkdir}/distshare``.
-
-This means that each workspace will have its own ``distshare``
-directory and we need to configure Jenkins to perform artifact copying.
-The recommend way to do this is to install the `Jenkins Copy Artifact plugin`_
-and for each job which "receives" artifacts you add a **Copy artifacts from another project** build step using roughly this configuration::
-
- Project-name: name of the other (tox-managed) job you want the artifact from
- Artifacts to copy: .tox/dist/*.zip # where tox jobs create artifacts
- Target directory: .tox/distshare # where we want it to appear for us
- Flatten Directories: CHECK # create no subdir-structure
-
-You also need to configure the "other" job to archive artifacts; This
-is done by checking ``Archive the artifacts`` and entering::
-
- Files to archive: .tox/dist/*.zip
-
-So our "other" job will create an sdist-package artifact and
-the "copy-artifacts" plugin will copy it to our ``distshare`` area.
-Now everything proceeds as :ref:`artifacts` shows it.
-
-So if you are using defaults you can re-use and debug exactly the
-same ``tox.ini`` file and make use of automatic sharing of
-your artifacts between runs or Jenkins jobs.
-
-
-Avoiding the "path too long" error with long shebang lines
----------------------------------------------------------------
-
-If you are using Jenkins builds you might run into the issue
-that tox can not call ``pip`` because the so called "shebang"
-line is too long. There is a limit of 127 chars on some systems.
-Probably the best way to fix the problem is to use the
-new ``--workdir`` option which tells tox to use a specific
-directory for its virtualenvironments. Set it to some unique
-enough short path. If somebody is interested to do a PR
-you could add a new option to tox which uses a random
-directory for storing its workdir results and removes
-it after the tox run finishes. This could be used
-from CI environments where you probably anyway want
-to recreate everything on new runs.
-
-
-.. include:: ../links.txt
-
-
diff --git a/doc/example/nose.txt b/doc/example/nose.txt
deleted file mode 100644
index ec97f18..0000000
--- a/doc/example/nose.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-
-nose and tox
-=================================
-
-It is easy to integrate `nosetests`_ runs with tox.
-For starters here is a simple ``tox.ini`` config to configure your project
-for running with nose:
-
-Basic nosetests example
---------------------------
-
-Assuming the following layout::
-
- tox.ini # see below for content
- setup.py # a classic distutils/setuptools setup.py file
-
-and the following ``tox.ini`` content::
-
- [testenv]
- deps=nose
- commands=
- nosetests \
- [] # substitute with tox' positional arguments
-
-you can invoke ``tox`` in the directory where your ``tox.ini`` resides.
-``tox`` will sdist-package your project create two virtualenv environments
-with the ``python2.6`` and ``python2.5`` interpreters, respectively, and will
-then run the specified test command.
-
-
-More examples?
-------------------------------------------
-
-You can use and combine other features of ``tox`` with your tox runs,
-e.g. :ref:`sphinx checks`. If you figure out some particular configurations
-for nose/tox interactions please submit them.
-
-Also you might want to checkout :doc:`general`.
-
-.. include:: ../links.txt
-
diff --git a/doc/example/pytest.txt b/doc/example/pytest.txt
deleted file mode 100755
index 6f98cf3..0000000
--- a/doc/example/pytest.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-
-py.test and tox
-=================================
-
-It is easy to integrate `py.test`_ runs with tox. If you encounter
-issues, please check if they are `listed as a known issue`_ and/or use
-the :doc:`support channels <../support>`.
-
-Basic example
---------------------------
-
-Assuming the following layout::
-
- tox.ini # see below for content
- setup.py # a classic distutils/setuptools setup.py file
-
-and the following ``tox.ini`` content::
-
- [tox]
- envlist = py26,py31
-
- [testenv]
- deps=pytest # PYPI package providing py.test
- commands=
- py.test \
- {posargs} # substitute with tox' positional arguments
-
-you can now invoke ``tox`` in the directory where your ``tox.ini`` resides.
-``tox`` will sdist-package your project, create two virtualenv environments
-with the ``python2.6`` and ``python3.1`` interpreters, respectively, and will
-then run the specified test command in each of them.
-
-Extended example: change dir before test and use per-virtualenv tempdir
---------------------------------------------------------------------------
-
-Assuming the following layout::
-
- tox.ini # see below for content
- setup.py # a classic distutils/setuptools setup.py file
- tests # the directory containing tests
-
-and the following ``tox.ini`` content::
-
- [tox]
- envlist = py26,py31
- [testenv]
- changedir=tests
- deps=pytest
- commands=
- py.test \
- --basetemp={envtmpdir} \ # py.test tempdir setting
- {posargs} # substitute with tox' positional arguments
-
-you can invoke ``tox`` in the directory where your ``tox.ini`` resides.
-Differently than in the previous example the ``py.test`` command
-will be executed with a current working directory set to ``tests``
-and the test run will use the per-virtualenv temporary directory.
-
-.. _`passing positional arguments`:
-
-Using multiple CPUs for test runs
------------------------------------
-
-``py.test`` supports distributing tests to multiple processes and hosts
-through the `pytest-xdist`_ plugin. Here is an example configuration
-to make ``tox`` use this feature::
-
- [testenv]
- deps=pytest-xdist
- changedir=tests
- commands=
- py.test \
- --basetemp={envtmpdir} \
- --confcutdir=.. \
- -n 3 \ # use three sub processes
- {posargs}
-
-.. _`listed as a known issue`:
-
-Known Issues and limitations
------------------------------
-
-**Too long filenames**. you may encounter "too long filenames" for temporarily
-created files in your py.test run. Try to not use the "--basetemp" parameter.
-
-**installed-versus-checkout version**. ``py.test`` collects test
-modules on the filesystem and then tries to import them under their
-`fully qualified name`_. This means that if your test files are
-importable from somewhere then your ``py.test`` invocation may end up
-importing the package from the checkout directory rather than the
-installed package.
-
-There are a few ways to prevent this.
-
-With installed tests (the tests packages are known to ``setup.py``), a
-safe and explicit option is to give the explicit path
-``{envsitepackagesdir}/mypkg`` to pytest.
-Alternatively, it is possible to use ``changedir`` so that checked-out
-files are outside the import path, then pass ``--pyargs mypkg`` to
-pytest.
-
-With tests that won't be installed, the simplest way to run them
-against your installed package is to avoid ``__init__.py`` files in test
-directories; pytest will still find and import them by adding their
-parent directory to ``sys.path`` but they won't be copied to
-other places or be found by Python's import system outside of pytest.
-
-.. _`fully qualified name`: http://pytest.org/latest/goodpractises.html#test-package-name
-
-
-.. include:: ../links.txt
diff --git a/doc/example/result.txt b/doc/example/result.txt
deleted file mode 100644
index b3b95b4..0000000
--- a/doc/example/result.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-
-Writing a json result file
---------------------------------------------------------
-
-.. versionadded: 1.6
-
-You can instruct tox to write a json-report file via::
-
- tox --result-json=PATH
-
-This will create a json-formatted result file using this schema::
-
- {
- "testenvs": {
- "py27": {
- "python": {
- "executable": "/home/hpk/p/tox/.tox/py27/bin/python",
- "version": "2.7.3 (default, Aug 1 2012, 05:14:39) \n[GCC 4.6.3]",
- "version_info": [ 2, 7, 3, "final", 0 ]
- },
- "test": [
- {
- "output": "...",
- "command": [
- "/home/hpk/p/tox/.tox/py27/bin/py.test",
- "--instafail",
- "--junitxml=/home/hpk/p/tox/.tox/py27/log/junit-py27.xml",
- "tests/test_config.py"
- ],
- "retcode": "0"
- }
- ],
- "setup": []
- }
- },
- "platform": "linux2",
- "installpkg": {
- "basename": "tox-1.6.0.dev1.zip",
- "sha256": "b6982dde5789a167c4c35af0d34ef72176d0575955f5331ad04aee9f23af4326",
- "md5": "27ead99fd7fa39ee7614cede6bf175a6"
- },
- "toxversion": "1.6.0.dev1",
- "reportversion": "1"
- }
diff --git a/doc/example/unittest.txt b/doc/example/unittest.txt
deleted file mode 100644
index 5dcaa8e..0000000
--- a/doc/example/unittest.txt
+++ /dev/null
@@ -1,89 +0,0 @@
-
-unittest2, discover and tox
-===============================
-
-Running unittests with 'discover'
-------------------------------------------
-
-.. _Pygments: http://pypi.python.org/pypi/Pygments
-
-The discover_ project allows to discover and run unittests
-and we can easily integrate it in a ``tox`` run. As an example,
-perform a checkout of Pygments_::
-
- hg clone https://bitbucket.org/birkenfeld/pygments-main
-
-and add the following ``tox.ini`` to it::
-
- [tox]
- envlist = py25,py26,py27
-
- [testenv]
- changedir=tests
- commands=discover
- deps=discover
-
-If you now invoke ``tox`` you will see the creation of
-three virtual environments and a unittest-run performed
-in each of them.
-
-Running unittest2 and sphinx tests in one go
------------------------------------------------------
-
-.. _`Michael Foord`: http://www.voidspace.org.uk/
-.. _tox.ini: http://code.google.com/p/mock/source/browse/tox.ini
-
-`Michael Foord`_ has contributed a ``tox.ini`` file that
-allows you to run all tests for his mock_ project,
-including some sphinx-based doctests. If you checkout
-its repository with:
-
- hg clone https://code.google.com/p/mock/
-
-the checkout has a tox.ini_ that looks like this::
-
- [tox]
- envlist = py24,py25,py26,py27
-
- [testenv]
- deps=unittest2
- commands=unit2 discover []
-
- [testenv:py26]
- commands=
- unit2 discover []
- sphinx-build -b doctest docs html
- sphinx-build docs html
- deps =
- unittest2
- sphinx
-
- [testenv:py27]
- commands=
- unit2 discover []
- sphinx-build -b doctest docs html
- sphinx-build docs html
- deps =
- unittest2
- sphinx
-
-mock uses unittest2_ to run the tests. Invoking ``tox`` starts test
-discovery by executing the ``unit2 discover``
-commands on Python 2.4, 2.5, 2.6 and 2.7 respectively. Against
-Python2.6 and Python2.7 it will additionally run sphinx-mediated
-doctests. If building the docs fails, due to a reST error, or
-any of the doctests fails, it will be reported by the tox run.
-
-The ``[]`` parentheses in the commands provide :ref:`positional substitution` which means
-you can e.g. type::
-
- tox -- -f -s SOMEPATH
-
-which will ultimately invoke::
-
- unit2 discover -f -s SOMEPATH
-
-in each of the environments. This allows you to customize test discovery
-in your ``tox`` runs.
-
-.. include:: ../links.txt
diff --git a/doc/examples.txt b/doc/examples.txt
deleted file mode 100644
index a3e9d91..0000000
--- a/doc/examples.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-tox configuration and usage examples
-==============================================================================
-
-.. toctree::
- :maxdepth: 2
-
- example/basic.txt
- example/pytest.txt
- example/unittest
- example/nose.txt
- example/general.txt
- example/jenkins.txt
- example/devenv.txt
-
diff --git a/doc/index.txt b/doc/index.txt
deleted file mode 100644
index e1bc20e..0000000
--- a/doc/index.txt
+++ /dev/null
@@ -1,123 +0,0 @@
-Welcome to the tox automation project
-===============================================
-
-vision: standardize testing in Python
----------------------------------------------
-
-``tox`` aims to automate and standardize testing in Python. It is part
-of a larger vision of easing the packaging, testing and release process
-of Python software.
-
-What is Tox?
---------------------
-
-Tox is a generic virtualenv_ management and test command line tool you can use for:
-
-* checking your package installs correctly with different Python versions and
- interpreters
-
-* running your tests in each of the environments, configuring your test tool of choice
-
-* acting as a frontend to Continuous Integration servers, greatly
- reducing boilerplate and merging CI and shell-based testing.
-
-
-Basic example
------------------
-
-First, install ``tox`` with ``pip install tox`` or ``easy_install tox``.
-Then put basic information about your project and the test environments you
-want your project to run in into a ``tox.ini`` file residing
-right next to your ``setup.py`` file::
-
- # content of: tox.ini , put in same dir as setup.py
- [tox]
- envlist = py26,py27
- [testenv]
- deps=pytest # install pytest in the venvs
- commands=py.test # or 'nosetests' or ...
-
-You can also try generating a ``tox.ini`` file automatically, by running
-``tox-quickstart`` and then answering a few simple questions.
-
-To sdist-package, install and test your project against Python2.6 and Python2.7, just type::
-
- tox
-
-and watch things happening (you must have python2.6 and python2.7 installed in your
-environment otherwise you will see errors). When you run ``tox`` a second time
-you'll note that it runs much faster because it keeps track of virtualenv details
-and will not recreate or re-install dependencies. You also might want to
-checkout :doc:`examples` to get some more ideas.
-
-Current features
--------------------
-
-* **automation of tedious Python related test activities**
-
-* **test your Python package against many interpreter and dependency configs**
-
- - automatic customizable (re)creation of virtualenv_ test environments
-
- - installs your ``setup.py`` based project into each virtual environment
-
- - test-tool agnostic: runs py.test, nose or unittests in a uniform manner
-
-* :doc:`(new in 2.0) plugin system <plugins>` to modify tox execution with simple hooks.
-
-* uses pip_ and setuptools_ by default. Support for configuring the installer command
- through :confval:`install_command=ARGV`.
-
-* **cross-Python compatible**: CPython-2.6, 2.7, 3.2 and higher,
- Jython and pypy_.
-
-* **cross-platform**: Windows and Unix style environments
-
-* **integrates with continuous integration servers** like Jenkins_
- (formerly known as Hudson) and helps you to avoid boilerplatish
- and platform-specific build-step hacks.
-
-* **full interoperability with devpi**: is integrated with and
- is used for testing in the devpi_ system, a versatile pypi
- index server and release managing tool.
-
-* **driven by a simple ini-style config file**
-
-* **documented** :doc:`examples <examples>` and :doc:`configuration <config>`
-
-* **concise reporting** about tool invocations and configuration errors
-
-* **professionally** :doc:`supported <support>`
-
-* supports :ref:`using different / multiple PyPI index servers <multiindex>`
-
-
-.. _pypy: http://pypy.org
-
-.. _`tox.ini`: :doc:configfile
-
-.. toctree::
- :hidden:
-
- install
- examples
- config
- config-v2
- support
- changelog
- links
- plugins
- example/result
- announce/release-0.5
- announce/release-1.0
- announce/release-1.1
- announce/release-1.2
- announce/release-1.3
- announce/release-1.4
- announce/release-1.4.3
- announce/release-1.8
- announce/release-1.9
- announce/release-2.0
-
-
-.. include:: links.txt
diff --git a/doc/install.txt b/doc/install.txt
deleted file mode 100644
index 982cefb..0000000
--- a/doc/install.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-tox installation
-==================================
-
-Install info in a nutshell
-----------------------------------
-
-**Pythons**: CPython 2.6-3.5, Jython-2.5.1, pypy-1.9ff
-
-**Operating systems**: Linux, Windows, OSX, Unix
-
-**Installer Requirements**: setuptools_
-
-**License**: MIT license
-
-**hg repository**: https://bitbucket.org/hpk42/tox
-
-Installation with pip/easy_install
---------------------------------------
-
-Use one of the following commands::
-
- pip install tox
- easy_install tox
-
-It is fine to install ``tox`` itself into a virtualenv_ environment.
-
-Install from Checkout
--------------------------
-
-Consult the Bitbucket page to get a checkout of the mercurial repository:
-
- https://bitbucket.org/hpk42/tox
-
-and then install in your environment with something like::
-
- python setup.py install
-
-or just activate your checkout in your environment like this::
-
- python setup.py develop
-
-so that you can do changes and submit patches.
-
-.. include:: links.txt
diff --git a/doc/links.txt b/doc/links.txt
deleted file mode 100644
index 9c16034..0000000
--- a/doc/links.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-
-.. _devpi: http://doc.devpi.net
-.. _Python: http://www.python.org
-.. _virtualenv: https://pypi.python.org/pypi/virtualenv
-.. _virtualenv3: https://pypi.python.org/pypi/virtualenv3
-.. _virtualenv5: https://pypi.python.org/pypi/virtualenv5
-.. _`py.test`: http://pytest.org
-.. _nosetests:
-.. _`nose`: https://pypi.python.org/pypi/nose
-.. _`Holger Krekel`: https://twitter.com/hpk42
-.. _`pytest-xdist`: https://pypi.python.org/pypi/pytest-xdist
-
-.. _`easy_install`: http://peak.telecommunity.com/DevCenter/EasyInstall
-.. _pip: https://pypi.python.org/pypi/pip
-.. _setuptools: https://pypi.python.org/pypi/setuptools
-.. _`jenkins`: http://jenkins-ci.org/
-.. _sphinx: https://pypi.python.org/pypi/Sphinx
-.. _discover: https://pypi.python.org/pypi/discover
-.. _unittest2: https://pypi.python.org/pypi/unittest2
-.. _mock: https://pypi.python.org/pypi/mock/
diff --git a/doc/plugins.txt b/doc/plugins.txt
deleted file mode 100644
index be3665a..0000000
--- a/doc/plugins.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-.. be in -*- rst -*- mode!
-
-tox plugins
-===========
-
-.. versionadded:: 2.0
-
-With tox-2.0 a few aspects of tox running can be experimentally modified
-by writing hook functions. The list of of available hook function is
-to grow over time on a per-need basis.
-
-
-writing a setuptools entrypoints plugin
----------------------------------------
-
-If you have a ``tox_MYPLUGIN.py`` module you could use the following
-rough ``setup.py`` to make it into a package which you can upload to the
-Python packaging index::
-
- # content of setup.py
- from setuptools import setup
-
- if __name__ == "__main__":
- setup(
- name='tox-MYPLUGIN',
- description='tox plugin decsription',
- license="MIT license",
- version='0.1',
- py_modules=['tox_MYPLUGIN'],
- entry_points={'tox': ['MYPLUGIN = tox_MYPLUGIN']},
- install_requires=['tox>=2.0'],
- )
-
-If installed, the ``entry_points`` part will make tox see and integrate
-your plugin during startup.
-
-You can install the plugin for development ("in-place") via::
-
- pip install -e .
-
-and later publish it via something like::
-
- python setup.py sdist register upload
-
-
-Writing hook implementations
-----------------------------
-
-A plugin module defines one or more hook implementation functions
-by decorating them with tox's ``hookimpl`` marker::
-
- from tox import hookimpl
-
- @hookimpl
- def tox_addoption(parser):
- # add your own command line options
-
-
- @hookimpl
- def tox_configure(config):
- # post process tox configuration after cmdline/ini file have
- # been parsed
-
-If you put this into a module and make it pypi-installable with the ``tox``
-entry point you'll get your code executed as part of a tox run.
-
-
-
-tox hook specifications and related API
----------------------------------------
-
-.. automodule:: tox.hookspecs
- :members:
-
-.. autoclass:: tox.config.Parser()
- :members:
-
-.. autoclass:: tox.config.Config()
- :members:
-
-.. autoclass:: tox.config.TestenvConfig()
- :members:
-
-.. autoclass:: tox.venv.VirtualEnv()
- :members:
-
-.. autoclass:: tox.session.Session()
- :members:
diff --git a/doc/support.txt b/doc/support.txt
deleted file mode 100644
index 29962e7..0000000
--- a/doc/support.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-
-.. _support:
-
-support and contact channels
-=====================================
-
-Getting in contact:
-
-* join the `Testing In Python (TIP) mailing list`_ for general and tox/test-tool
- interaction questions.
-* file a `report on the issue tracker`_
-* hang out on the irc.freenode.net #pylib channel
-* `clone the mercurial repository`_ and submit patches
-* the `tetamap blog`_, `holger's twitter presence`_ or
- for private inquiries holger krekel at gmail.
-
-professional support
-----------------------------
-
-.. note:: Upcoming: `professional testing with pytest and tox <`http://www.python-academy.com/courses/specialtopics/python_course_testing.html>`_ , 24th-26th June 2013, Leipzig.
-
-If you are looking for on-site teaching or consulting support,
-contact holger at `merlinux.eu`_, an association of
-experienced well-known Python developers.
-
-.. _`Maciej Fijalkowski`: http://www.ohloh.net/accounts/fijal
-.. _`Benjamin Peterson`: http://www.ohloh.net/accounts/gutworth
-.. _`Testing In Python (TIP) mailing list`: http://lists.idyll.org/listinfo/testing-in-python
-.. _`holger's twitter presence`: http://twitter.com/hpk42
-.. _`merlinux.eu`: http://merlinux.eu
-.. _`report on the issue tracker`: https://bitbucket.org/hpk42/tox/issues?status=new&status=open
-.. _`tetamap blog`: http://holgerkrekel.net
-.. _`tox-dev`: http://codespeak.net/mailman/listinfo/tox-dev
-.. _`tox-commit`: http://codespeak.net/mailman/listinfo/tox-commit
-.. _`clone the mercurial repository`: https://bitbucket.org/hpk42/tox
-
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index fcf263d..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,13 +0,0 @@
-[build_sphinx]
-source-dir = doc/
-build-dir = doc/build
-all_files = 1
-
-[upload_sphinx]
-upload-dir = doc/en/build/html
-
-[bdist_wheel]
-universal = 1
-
-[devpi:upload]
-formats = sdist.tgz,bdist_wheel
diff --git a/setup.py b/setup.py
deleted file mode 100644
index cc49e89..0000000
--- a/setup.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import sys
-import setuptools
-from setuptools.command.test import test as TestCommand
-
-
-
-class Tox(TestCommand):
- def finalize_options(self):
- TestCommand.finalize_options(self)
- self.test_args = ["-v", "-epy"]
- self.test_suite = True
-
- def run_tests(self):
- #import here, cause outside the eggs aren't loaded
- import tox
- tox.cmdline(self.test_args)
-
-def has_environment_marker_support():
- """
- Tests that setuptools has support for PEP-426 environment marker support.
-
- The first known release to support it is 0.7 (and the earliest on PyPI seems to be 0.7.2
- so we're using that), see: http://pythonhosted.org/setuptools/history.html#id142
-
- References:
-
- * https://wheel.readthedocs.org/en/latest/index.html#defining-conditional-dependencies
- * https://www.python.org/dev/peps/pep-0426/#environment-markers
- """
- import pkg_resources
- try:
- return pkg_resources.parse_version(setuptools.__version__) >= pkg_resources.parse_version('0.7.2')
- except Exception as exc:
- sys.stderr.write("Could not test setuptool's version: %s\n" % exc)
- return False
-
-def main():
- version = sys.version_info[:2]
- install_requires = ['virtualenv>=1.11.2', 'py>=1.4.17', 'pluggy>=0.3.0,<0.5.0']
- extras_require = {}
- if has_environment_marker_support():
- extras_require[':python_version=="2.6"'] = ['argparse']
- else:
- if version < (2, 7):
- install_requires += ['argparse']
- setuptools.setup(
- name='tox',
- description='virtualenv-based automation of test activities',
- long_description=open("README.rst").read(),
- url='http://tox.testrun.org/',
- version='2.4.0.dev1',
- license='http://opensource.org/licenses/MIT',
- platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
- author='holger krekel',
- author_email='holger@merlinux.eu',
- packages=['tox'],
- entry_points={'console_scripts': 'tox=tox:cmdline\ntox-quickstart=tox._quickstart:main'},
- # we use a public tox version to test, see tox.ini's testenv
- # "deps" definition for the required dependencies
- tests_require=['tox'],
- cmdclass={"test": Tox},
- install_requires=install_requires,
- extras_require=extras_require,
- 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',
- 'Programming Language :: Python :: 3'],
- )
-
-if __name__ == '__main__':
- main()
diff --git a/tests/conftest.py b/tests/conftest.py
deleted file mode 100644
index 3e2493b..0000000
--- a/tests/conftest.py
+++ /dev/null
@@ -1,2 +0,0 @@
-
-from tox._pytestplugin import * # noqa
diff --git a/tests/test_config.py b/tests/test_config.py
deleted file mode 100644
index d685ac8..0000000
--- a/tests/test_config.py
+++ /dev/null
@@ -1,2060 +0,0 @@
-import sys
-from textwrap import dedent
-
-import py
-import pytest
-import tox
-import tox.config
-from tox.config import * # noqa
-from tox.venv import VirtualEnv
-
-
-class TestVenvConfig:
- def test_config_parsing_minimal(self, tmpdir, newconfig):
- config = newconfig([], """
- [testenv:py1]
- """)
- assert len(config.envconfigs) == 1
- assert config.toxworkdir.realpath() == tmpdir.join(".tox").realpath()
- assert config.envconfigs['py1'].basepython == sys.executable
- assert config.envconfigs['py1'].deps == []
- assert config.envconfigs['py1'].platform == ".*"
-
- def test_config_parsing_multienv(self, tmpdir, newconfig):
- config = newconfig([], """
- [tox]
- toxworkdir = %s
- indexserver =
- xyz = xyz_repo
- [testenv:py1]
- deps=hello
- [testenv:py2]
- deps=
- world1
- :xyz:http://hello/world
- """ % (tmpdir, ))
- assert config.toxworkdir == tmpdir
- assert len(config.envconfigs) == 2
- assert config.envconfigs['py1'].envdir == tmpdir.join("py1")
- dep = config.envconfigs['py1'].deps[0]
- assert dep.name == "hello"
- assert dep.indexserver is None
- assert config.envconfigs['py2'].envdir == tmpdir.join("py2")
- dep1, dep2 = config.envconfigs['py2'].deps
- assert dep1.name == "world1"
- assert dep2.name == "http://hello/world"
- assert dep2.indexserver.name == "xyz"
- assert dep2.indexserver.url == "xyz_repo"
-
- def test_envdir_set_manually(self, tmpdir, newconfig):
- config = newconfig([], """
- [testenv:devenv]
- envdir = devenv
- """)
- envconfig = config.envconfigs['devenv']
- assert envconfig.envdir == tmpdir.join('devenv')
-
- def test_envdir_set_manually_with_substitutions(self, tmpdir, newconfig):
- config = newconfig([], """
- [testenv:devenv]
- envdir = {toxworkdir}/foobar
- """)
- envconfig = config.envconfigs['devenv']
- assert envconfig.envdir == config.toxworkdir.join('foobar')
-
- def test_force_dep_version(self, initproj):
- """
- Make sure we can override dependencies configured in tox.ini when using the command line
- option --force-dep.
- """
- initproj("example123-0.5", filedefs={
- 'tox.ini': '''
- [tox]
-
- [testenv]
- deps=
- dep1==1.0
- dep2>=2.0
- dep3
- dep4==4.0
- '''
- })
- config = parseconfig(
- ['--force-dep=dep1==1.5', '--force-dep=dep2==2.1',
- '--force-dep=dep3==3.0'])
- assert config.option.force_dep == [
- 'dep1==1.5', 'dep2==2.1', 'dep3==3.0']
- assert [str(x) for x in config.envconfigs['python'].deps] == [
- 'dep1==1.5', 'dep2==2.1', 'dep3==3.0', 'dep4==4.0',
- ]
-
- def test_force_dep_with_url(self, initproj):
- initproj("example123-0.5", filedefs={
- 'tox.ini': '''
- [tox]
-
- [testenv]
- deps=
- dep1==1.0
- https://pypi.python.org/xyz/pkg1.tar.gz
- '''
- })
- config = parseconfig(
- ['--force-dep=dep1==1.5'])
- assert config.option.force_dep == [
- 'dep1==1.5'
- ]
- assert [str(x) for x in config.envconfigs['python'].deps] == [
- 'dep1==1.5', 'https://pypi.python.org/xyz/pkg1.tar.gz'
- ]
-
- def test_is_same_dep(self):
- """
- Ensure correct parseini._is_same_dep is working with a few samples.
- """
- assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3')
- assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3>=2.0')
- assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3>2.0')
- assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3<2.0')
- assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3<=2.0')
- assert not DepOption._is_same_dep('pkg_hello-world3==1.0', 'otherpkg>=2.0')
-
-
-class TestConfigPlatform:
- def test_config_parse_platform(self, newconfig):
- config = newconfig([], """
- [testenv:py1]
- platform = linux2
- """)
- assert len(config.envconfigs) == 1
- assert config.envconfigs['py1'].platform == "linux2"
-
- def test_config_parse_platform_rex(self, newconfig, mocksession, monkeypatch):
- config = newconfig([], """
- [testenv:py1]
- platform = a123|b123
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['py1']
- venv = VirtualEnv(envconfig, session=mocksession)
- assert not venv.matching_platform()
- monkeypatch.setattr(sys, "platform", "a123")
- assert venv.matching_platform()
- monkeypatch.setattr(sys, "platform", "b123")
- assert venv.matching_platform()
- monkeypatch.undo()
- assert not venv.matching_platform()
-
- @pytest.mark.parametrize("plat", ["win", "lin", ])
- def test_config_parse_platform_with_factors(self, newconfig, plat, monkeypatch):
- monkeypatch.setattr(sys, "platform", "win32")
- config = newconfig([], """
- [tox]
- envlist = py27-{win,lin,osx}
- [testenv]
- platform =
- win: win32
- lin: linux2
- """)
- assert len(config.envconfigs) == 3
- platform = config.envconfigs['py27-' + plat].platform
- expected = {"win": "win32", "lin": "linux2"}.get(plat)
- assert platform == expected
-
-
-class TestConfigPackage:
- def test_defaults(self, tmpdir, newconfig):
- config = newconfig([], "")
- assert config.setupdir.realpath() == tmpdir.realpath()
- assert config.toxworkdir.realpath() == tmpdir.join(".tox").realpath()
- envconfig = config.envconfigs['python']
- assert envconfig.args_are_paths
- assert not envconfig.recreate
- assert not envconfig.pip_pre
-
- def test_defaults_distshare(self, tmpdir, newconfig):
- config = newconfig([], "")
- assert config.distshare == config.homedir.join(".tox", "distshare")
-
- def test_defaults_changed_dir(self, tmpdir, newconfig):
- tmpdir.mkdir("abc").chdir()
- config = newconfig([], "")
- assert config.setupdir.realpath() == tmpdir.realpath()
- assert config.toxworkdir.realpath() == tmpdir.join(".tox").realpath()
-
- def test_project_paths(self, tmpdir, newconfig):
- config = newconfig("""
- [tox]
- toxworkdir=%s
- """ % tmpdir)
- assert config.toxworkdir == tmpdir
-
-
-class TestParseconfig:
- def test_search_parents(self, tmpdir):
- b = tmpdir.mkdir("a").mkdir("b")
- toxinipath = tmpdir.ensure("tox.ini")
- old = b.chdir()
- try:
- config = parseconfig([])
- finally:
- old.chdir()
- assert config.toxinipath == toxinipath
-
-
-def test_get_homedir(monkeypatch):
- monkeypatch.setattr(py.path.local, "_gethomedir",
- classmethod(lambda x: {}[1]))
- assert not get_homedir()
- monkeypatch.setattr(py.path.local, "_gethomedir",
- classmethod(lambda x: 0 / 0))
- assert not get_homedir()
- monkeypatch.setattr(py.path.local, "_gethomedir",
- classmethod(lambda x: "123"))
- assert get_homedir() == "123"
-
-
-class TestGetcontextname:
- def test_blank(self, monkeypatch):
- monkeypatch.setattr(os, "environ", {})
- assert getcontextname() is None
-
- def test_jenkins(self, monkeypatch):
- monkeypatch.setattr(os, "environ", {"JENKINS_URL": "xyz"})
- assert getcontextname() == "jenkins"
-
- def test_hudson_legacy(self, monkeypatch):
- monkeypatch.setattr(os, "environ", {"HUDSON_URL": "xyz"})
- assert getcontextname() == "jenkins"
-
-
-class TestIniParserAgainstCommandsKey:
- """Test parsing commands with substitutions"""
-
- def test_command_substitution_from_other_section(self, newconfig):
- config = newconfig("""
- [section]
- key = whatever
- [testenv]
- commands =
- echo {[section]key}
- """)
- reader = SectionReader("testenv", config._cfg)
- x = reader.getargvlist("commands")
- assert x == [["echo", "whatever"]]
-
- def test_command_substitution_from_other_section_multiline(self, newconfig):
- """Ensure referenced multiline commands form from other section injected
- as multiple commands."""
- config = newconfig("""
- [section]
- commands =
- cmd1 param11 param12
- # comment is omitted
- cmd2 param21 \
- param22
- [base]
- commands = cmd 1 \
- 2 3 4
- cmd 2
- [testenv]
- commands =
- {[section]commands}
- {[section]commands}
- # comment is omitted
- echo {[base]commands}
- """)
- reader = SectionReader("testenv", config._cfg)
- x = reader.getargvlist("commands")
- assert x == [
- "cmd1 param11 param12".split(),
- "cmd2 param21 param22".split(),
- "cmd1 param11 param12".split(),
- "cmd2 param21 param22".split(),
- ["echo", "cmd", "1", "2", "3", "4", "cmd", "2"],
- ]
-
- def test_command_substitution_from_other_section_posargs(self, newconfig):
- """Ensure subsitition from other section with posargs succeeds"""
- config = newconfig("""
- [section]
- key = thing {posargs} arg2
- [testenv]
- commands =
- {[section]key}
- """)
- reader = SectionReader("testenv", config._cfg)
- reader.addsubstitutions([r"argpos"])
- x = reader.getargvlist("commands")
- assert x == [['thing', 'argpos', 'arg2']]
-
- def test_command_section_and_posargs_substitution(self, newconfig):
- """Ensure subsitition from other section with posargs succeeds"""
- config = newconfig("""
- [section]
- key = thing arg1
- [testenv]
- commands =
- {[section]key} {posargs} endarg
- """)
- reader = SectionReader("testenv", config._cfg)
- reader.addsubstitutions([r"argpos"])
- x = reader.getargvlist("commands")
- assert x == [['thing', 'arg1', 'argpos', 'endarg']]
-
- def test_command_env_substitution(self, newconfig):
- """Ensure referenced {env:key:default} values are substituted correctly."""
- config = newconfig("""
- [testenv:py27]
- setenv =
- TEST=testvalue
- commands =
- ls {env:TEST}
- """)
- envconfig = config.envconfigs["py27"]
- assert envconfig.commands == [["ls", "testvalue"]]
- assert envconfig.setenv["TEST"] == "testvalue"
-
-
-class TestIniParser:
- def test_getstring_single(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key=value
- """)
- reader = SectionReader("section", config._cfg)
- x = reader.getstring("key")
- assert x == "value"
- assert not reader.getstring("hello")
- x = reader.getstring("hello", "world")
- assert x == "world"
-
- def test_missing_substitution(self, tmpdir, newconfig):
- config = newconfig("""
- [mydefault]
- key2={xyz}
- """)
- reader = SectionReader("mydefault", config._cfg, fallbacksections=['mydefault'])
- assert reader is not None
- with py.test.raises(tox.exception.ConfigError):
- reader.getstring("key2")
-
- def test_getstring_fallback_sections(self, tmpdir, newconfig):
- config = newconfig("""
- [mydefault]
- key2=value2
- [section]
- key=value
- """)
- reader = SectionReader("section", config._cfg, fallbacksections=['mydefault'])
- x = reader.getstring("key2")
- assert x == "value2"
- x = reader.getstring("key3")
- assert not x
- x = reader.getstring("key3", "world")
- assert x == "world"
-
- def test_getstring_substitution(self, tmpdir, newconfig):
- config = newconfig("""
- [mydefault]
- key2={value2}
- [section]
- key={value}
- """)
- reader = SectionReader("section", config._cfg, fallbacksections=['mydefault'])
- reader.addsubstitutions(value="newvalue", value2="newvalue2")
- x = reader.getstring("key2")
- assert x == "newvalue2"
- x = reader.getstring("key3")
- assert not x
- x = reader.getstring("key3", "{value2}")
- assert x == "newvalue2"
-
- def test_getlist(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key2=
- item1
- {item2}
- """)
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions(item1="not", item2="grr")
- x = reader.getlist("key2")
- assert x == ['item1', 'grr']
-
- def test_getdict(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key2=
- key1=item1
- key2={item2}
- """)
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions(item1="not", item2="grr")
- x = reader.getdict("key2")
- assert 'key1' in x
- assert 'key2' in x
- assert x['key1'] == 'item1'
- assert x['key2'] == 'grr'
-
- x = reader.getdict("key3", {1: 2})
- assert x == {1: 2}
-
- def test_getstring_environment_substitution(self, monkeypatch, newconfig):
- monkeypatch.setenv("KEY1", "hello")
- config = newconfig("""
- [section]
- key1={env:KEY1}
- key2={env:KEY2}
- """)
- reader = SectionReader("section", config._cfg)
- x = reader.getstring("key1")
- assert x == "hello"
- with py.test.raises(tox.exception.ConfigError):
- reader.getstring("key2")
-
- def test_getstring_environment_substitution_with_default(self, monkeypatch, newconfig):
- monkeypatch.setenv("KEY1", "hello")
- config = newconfig("""
- [section]
- key1={env:KEY1:DEFAULT_VALUE}
- key2={env:KEY2:DEFAULT_VALUE}
- key3={env:KEY3:}
- """)
- reader = SectionReader("section", config._cfg)
- x = reader.getstring("key1")
- assert x == "hello"
- x = reader.getstring("key2")
- assert x == "DEFAULT_VALUE"
- x = reader.getstring("key3")
- assert x == ""
-
- def test_value_matches_section_substituion(self):
- assert is_section_substitution("{[setup]commands}")
-
- def test_value_doesn_match_section_substitution(self):
- assert is_section_substitution("{[ ]commands}") is None
- assert is_section_substitution("{[setup]}") is None
- assert is_section_substitution("{[setup] commands}") is None
-
- def test_getstring_other_section_substitution(self, newconfig):
- config = newconfig("""
- [section]
- key = rue
- [testenv]
- key = t{[section]key}
- """)
- reader = SectionReader("testenv", config._cfg)
- x = reader.getstring("key")
- assert x == "true"
-
- def test_argvlist(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key2=
- cmd1 {item1} {item2}
- cmd2 {item2}
- """)
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions(item1="with space", item2="grr")
- # py.test.raises(tox.exception.ConfigError,
- # "reader.getargvlist('key1')")
- assert reader.getargvlist('key1') == []
- x = reader.getargvlist("key2")
- assert x == [["cmd1", "with", "space", "grr"],
- ["cmd2", "grr"]]
-
- def test_argvlist_windows_escaping(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- comm = py.test {posargs}
- """)
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions([r"hello\this"])
- argv = reader.getargv("comm")
- assert argv == ["py.test", "hello\\this"]
-
- def test_argvlist_multiline(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key2=
- cmd1 {item1} \
- {item2}
- """)
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions(item1="with space", item2="grr")
- # py.test.raises(tox.exception.ConfigError,
- # "reader.getargvlist('key1')")
- assert reader.getargvlist('key1') == []
- x = reader.getargvlist("key2")
- assert x == [["cmd1", "with", "space", "grr"]]
-
- def test_argvlist_quoting_in_command(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key1=
- cmd1 'part one' \
- 'part two'
- """)
- reader = SectionReader("section", config._cfg)
- x = reader.getargvlist("key1")
- assert x == [["cmd1", "part one", "part two"]]
-
- def test_argvlist_comment_after_command(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key1=
- cmd1 --flag # run the flag on the command
- """)
- reader = SectionReader("section", config._cfg)
- x = reader.getargvlist("key1")
- assert x == [["cmd1", "--flag"]]
-
- def test_argvlist_command_contains_hash(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key1=
- cmd1 --re "use the # symbol for an arg"
- """)
- reader = SectionReader("section", config._cfg)
- x = reader.getargvlist("key1")
- assert x == [["cmd1", "--re", "use the # symbol for an arg"]]
-
- def test_argvlist_positional_substitution(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key2=
- cmd1 []
- cmd2 {posargs:{item2} \
- other}
- """)
- reader = SectionReader("section", config._cfg)
- posargs = ['hello', 'world']
- reader.addsubstitutions(posargs, item2="value2")
- # py.test.raises(tox.exception.ConfigError,
- # "reader.getargvlist('key1')")
- assert reader.getargvlist('key1') == []
- argvlist = reader.getargvlist("key2")
- assert argvlist[0] == ["cmd1"] + posargs
- assert argvlist[1] == ["cmd2"] + posargs
-
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions([], item2="value2")
- # py.test.raises(tox.exception.ConfigError,
- # "reader.getargvlist('key1')")
- assert reader.getargvlist('key1') == []
- argvlist = reader.getargvlist("key2")
- assert argvlist[0] == ["cmd1"]
- assert argvlist[1] == ["cmd2", "value2", "other"]
-
- def test_argvlist_quoted_posargs(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key2=
- cmd1 --foo-args='{posargs}'
- cmd2 -f '{posargs}'
- cmd3 -f {posargs}
- """)
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions(["foo", "bar"])
- assert reader.getargvlist('key1') == []
- x = reader.getargvlist("key2")
- assert x == [["cmd1", "--foo-args=foo bar"],
- ["cmd2", "-f", "foo bar"],
- ["cmd3", "-f", "foo", "bar"]]
-
- def test_argvlist_posargs_with_quotes(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key2=
- cmd1 -f {posargs}
- """)
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions(["foo", "'bar", "baz'"])
- assert reader.getargvlist('key1') == []
- x = reader.getargvlist("key2")
- assert x == [["cmd1", "-f", "foo", "bar baz"]]
-
- def test_positional_arguments_are_only_replaced_when_standing_alone(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key=
- cmd0 []
- cmd1 -m '[abc]'
- cmd2 -m '\'something\'' []
- cmd3 something[]else
- """)
- reader = SectionReader("section", config._cfg)
- posargs = ['hello', 'world']
- reader.addsubstitutions(posargs)
-
- argvlist = reader.getargvlist('key')
- assert argvlist[0] == ['cmd0'] + posargs
- assert argvlist[1] == ['cmd1', '-m', '[abc]']
- assert argvlist[2] == ['cmd2', '-m', "something"] + posargs
- assert argvlist[3] == ['cmd3', 'something[]else']
-
- def test_substitution_with_multiple_words(self, newconfig):
- inisource = """
- [section]
- key = py.test -n5 --junitxml={envlogdir}/junit-{envname}.xml []
- """
- config = newconfig(inisource)
- reader = SectionReader("section", config._cfg)
- posargs = ['hello', 'world']
- reader.addsubstitutions(posargs, envlogdir='ENV_LOG_DIR', envname='ENV_NAME')
-
- expected = [
- 'py.test', '-n5', '--junitxml=ENV_LOG_DIR/junit-ENV_NAME.xml', 'hello', 'world'
- ]
- assert reader.getargvlist('key')[0] == expected
-
- def test_getargv(self, newconfig):
- config = newconfig("""
- [section]
- key=some command "with quoting"
- """)
- reader = SectionReader("section", config._cfg)
- expected = ['some', 'command', 'with quoting']
- assert reader.getargv('key') == expected
-
- def test_getpath(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- path1={HELLO}
- """)
- reader = SectionReader("section", config._cfg)
- reader.addsubstitutions(toxinidir=tmpdir, HELLO="mypath")
- x = reader.getpath("path1", tmpdir)
- assert x == tmpdir.join("mypath")
-
- def test_getbool(self, tmpdir, newconfig):
- config = newconfig("""
- [section]
- key1=True
- key2=False
- key1a=true
- key2a=falsE
- key5=yes
- """)
- reader = SectionReader("section", config._cfg)
- assert reader.getbool("key1") is True
- assert reader.getbool("key1a") is True
- assert reader.getbool("key2") is False
- assert reader.getbool("key2a") is False
- py.test.raises(KeyError, 'reader.getbool("key3")')
- py.test.raises(tox.exception.ConfigError, 'reader.getbool("key5")')
-
-
-class TestIniParserPrefix:
- def test_basic_section_access(self, tmpdir, newconfig):
- config = newconfig("""
- [p:section]
- key=value
- """)
- reader = SectionReader("section", config._cfg, prefix="p")
- x = reader.getstring("key")
- assert x == "value"
- assert not reader.getstring("hello")
- x = reader.getstring("hello", "world")
- assert x == "world"
-
- def test_fallback_sections(self, tmpdir, newconfig):
- config = newconfig("""
- [p:mydefault]
- key2=value2
- [p:section]
- key=value
- """)
- reader = SectionReader("section", config._cfg, prefix="p",
- fallbacksections=['p:mydefault'])
- x = reader.getstring("key2")
- assert x == "value2"
- x = reader.getstring("key3")
- assert not x
- x = reader.getstring("key3", "world")
- assert x == "world"
-
- def test_value_matches_prefixed_section_substituion(self):
- assert is_section_substitution("{[p:setup]commands}")
-
- def test_value_doesn_match_prefixed_section_substitution(self):
- assert is_section_substitution("{[p: ]commands}") is None
- assert is_section_substitution("{[p:setup]}") is None
- assert is_section_substitution("{[p:setup] commands}") is None
-
- def test_other_section_substitution(self, newconfig):
- config = newconfig("""
- [p:section]
- key = rue
- [p:testenv]
- key = t{[p:section]key}
- """)
- reader = SectionReader("testenv", config._cfg, prefix="p")
- x = reader.getstring("key")
- assert x == "true"
-
-
-class TestConfigTestEnv:
- def test_commentchars_issue33(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv] # hello
- deps = http://abc#123
- commands=
- python -c "x ; y"
- """)
- envconfig = config.envconfigs["python"]
- assert envconfig.deps[0].name == "http://abc#123"
- assert envconfig.commands[0] == ["python", "-c", "x ; y"]
-
- def test_defaults(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- commands=
- xyz --abc
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert envconfig.commands == [["xyz", "--abc"]]
- assert envconfig.changedir == config.setupdir
- assert envconfig.sitepackages is False
- assert envconfig.usedevelop is False
- assert envconfig.ignore_errors is False
- assert envconfig.envlogdir == envconfig.envdir.join("log")
- assert list(envconfig.setenv.definitions.keys()) == ['PYTHONHASHSEED']
- hashseed = envconfig.setenv['PYTHONHASHSEED']
- assert isinstance(hashseed, str)
- # The following line checks that hashseed parses to an integer.
- int_hashseed = int(hashseed)
- # hashseed is random by default, so we can't assert a specific value.
- assert int_hashseed > 0
- assert envconfig.ignore_outcome is False
-
- def test_sitepackages_switch(self, tmpdir, newconfig):
- config = newconfig(["--sitepackages"], "")
- envconfig = config.envconfigs['python']
- assert envconfig.sitepackages is True
-
- def test_installpkg_tops_develop(self, newconfig):
- config = newconfig(["--installpkg=abc"], """
- [testenv]
- usedevelop = True
- """)
- assert not config.envconfigs["python"].usedevelop
-
- def test_specific_command_overrides(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- commands=xyz
- [testenv:py]
- commands=abc
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['py']
- assert envconfig.commands == [["abc"]]
-
- def test_whitelist_externals(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- whitelist_externals = xyz
- commands=xyz
- [testenv:x]
-
- [testenv:py]
- whitelist_externals = xyz2
- commands=abc
- """)
- assert len(config.envconfigs) == 2
- envconfig = config.envconfigs['py']
- assert envconfig.commands == [["abc"]]
- assert envconfig.whitelist_externals == ["xyz2"]
- envconfig = config.envconfigs['x']
- assert envconfig.whitelist_externals == ["xyz"]
-
- def test_changedir(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- changedir=xyz
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert envconfig.changedir.basename == "xyz"
- assert envconfig.changedir == config.toxinidir.join("xyz")
-
- def test_ignore_errors(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- ignore_errors=True
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert envconfig.ignore_errors is True
-
- def test_envbindir(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- basepython=python
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert envconfig.envpython == envconfig.envbindir.join("python")
-
- @pytest.mark.parametrize("bp", ["jython", "pypy", "pypy3"])
- def test_envbindir_jython(self, tmpdir, newconfig, bp):
- config = newconfig("""
- [testenv]
- basepython=%s
- """ % bp)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- # on win32 and linux virtualenv uses "bin" for pypy/jython
- assert envconfig.envbindir.basename == "bin"
- if bp == "jython":
- assert envconfig.envpython == envconfig.envbindir.join(bp)
-
- @pytest.mark.parametrize("plat", ["win32", "linux2"])
- def test_passenv_as_multiline_list(self, tmpdir, newconfig, monkeypatch, plat):
- monkeypatch.setattr(sys, "platform", plat)
- monkeypatch.setenv("A123A", "a")
- monkeypatch.setenv("A123B", "b")
- monkeypatch.setenv("BX23", "0")
- config = newconfig("""
- [testenv]
- passenv =
- A123*
- # isolated comment
- B?23
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- if plat == "win32":
- assert "PATHEXT" in envconfig.passenv
- assert "SYSTEMDRIVE" in envconfig.passenv
- assert "SYSTEMROOT" in envconfig.passenv
- assert "TEMP" in envconfig.passenv
- assert "TMP" in envconfig.passenv
- else:
- assert "TMPDIR" in envconfig.passenv
- assert "PATH" in envconfig.passenv
- assert "PIP_INDEX_URL" in envconfig.passenv
- assert "LANG" in envconfig.passenv
- assert "LD_LIBRARY_PATH" in envconfig.passenv
- assert "A123A" in envconfig.passenv
- assert "A123B" in envconfig.passenv
-
- @pytest.mark.parametrize("plat", ["win32", "linux2"])
- def test_passenv_as_space_separated_list(self, tmpdir, newconfig, monkeypatch, plat):
- monkeypatch.setattr(sys, "platform", plat)
- monkeypatch.setenv("A123A", "a")
- monkeypatch.setenv("A123B", "b")
- monkeypatch.setenv("BX23", "0")
- config = newconfig("""
- [testenv]
- passenv =
- # comment
- A123* B?23
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- if plat == "win32":
- assert "PATHEXT" in envconfig.passenv
- assert "SYSTEMDRIVE" in envconfig.passenv
- assert "SYSTEMROOT" in envconfig.passenv
- assert "TEMP" in envconfig.passenv
- assert "TMP" in envconfig.passenv
- else:
- assert "TMPDIR" in envconfig.passenv
- assert "PATH" in envconfig.passenv
- assert "PIP_INDEX_URL" in envconfig.passenv
- assert "LANG" in envconfig.passenv
- assert "A123A" in envconfig.passenv
- assert "A123B" in envconfig.passenv
-
- def test_passenv_with_factor(self, tmpdir, newconfig, monkeypatch):
- monkeypatch.setenv("A123A", "a")
- monkeypatch.setenv("A123B", "b")
- monkeypatch.setenv("A123C", "c")
- monkeypatch.setenv("A123D", "d")
- monkeypatch.setenv("BX23", "0")
- monkeypatch.setenv("CCA43", "3")
- monkeypatch.setenv("CB21", "4")
- config = newconfig("""
- [tox]
- envlist = {x1,x2}
- [testenv]
- passenv =
- x1: A123A CC*
- x1: CB21
- # passed to both environments
- A123C
- x2: A123B A123D
- """)
- assert len(config.envconfigs) == 2
-
- assert "A123A" in config.envconfigs["x1"].passenv
- assert "A123C" in config.envconfigs["x1"].passenv
- assert "CCA43" in config.envconfigs["x1"].passenv
- assert "CB21" in config.envconfigs["x1"].passenv
- assert "A123B" not in config.envconfigs["x1"].passenv
- assert "A123D" not in config.envconfigs["x1"].passenv
- assert "BX23" not in config.envconfigs["x1"].passenv
-
- assert "A123B" in config.envconfigs["x2"].passenv
- assert "A123D" in config.envconfigs["x2"].passenv
- assert "A123A" not in config.envconfigs["x2"].passenv
- assert "A123C" in config.envconfigs["x2"].passenv
- assert "CCA43" not in config.envconfigs["x2"].passenv
- assert "CB21" not in config.envconfigs["x2"].passenv
- assert "BX23" not in config.envconfigs["x2"].passenv
-
- def test_passenv_from_global_env(self, tmpdir, newconfig, monkeypatch):
- monkeypatch.setenv("A1", "a1")
- monkeypatch.setenv("A2", "a2")
- monkeypatch.setenv("TOX_TESTENV_PASSENV", "A1")
- config = newconfig("""
- [testenv]
- passenv = A2
- """)
- env = config.envconfigs["python"]
- assert "A1" in env.passenv
- assert "A2" in env.passenv
-
- def test_changedir_override(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- changedir=xyz
- [testenv:python]
- changedir=abc
- basepython=python2.6
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert envconfig.changedir.basename == "abc"
- assert envconfig.changedir == config.setupdir.join("abc")
-
- def test_install_command_setting(self, newconfig):
- config = newconfig("""
- [testenv]
- install_command=some_install {packages}
- """)
- envconfig = config.envconfigs['python']
- assert envconfig.install_command == [
- 'some_install', '{packages}']
-
- def test_install_command_must_contain_packages(self, newconfig):
- py.test.raises(tox.exception.ConfigError, newconfig, """
- [testenv]
- install_command=pip install
- """)
-
- def test_install_command_substitutions(self, newconfig):
- config = newconfig("""
- [testenv]
- install_command=some_install --arg={toxinidir}/foo \
- {envname} {opts} {packages}
- """)
- envconfig = config.envconfigs['python']
- assert envconfig.install_command == [
- 'some_install', '--arg=%s/foo' % config.toxinidir, 'python',
- '{opts}', '{packages}']
-
- def test_pip_pre(self, newconfig):
- config = newconfig("""
- [testenv]
- pip_pre=true
- """)
- envconfig = config.envconfigs['python']
- assert envconfig.pip_pre
-
- def test_pip_pre_cmdline_override(self, newconfig):
- config = newconfig(
- ['--pre'],
- """
- [testenv]
- pip_pre=false
- """)
- envconfig = config.envconfigs['python']
- assert envconfig.pip_pre
-
- def test_downloadcache(self, newconfig, monkeypatch):
- monkeypatch.delenv("PIP_DOWNLOAD_CACHE", raising=False)
- config = newconfig("""
- [testenv]
- downloadcache=thecache
- """)
- envconfig = config.envconfigs['python']
- assert envconfig.downloadcache.basename == 'thecache'
-
- def test_downloadcache_env_override(self, newconfig, monkeypatch):
- monkeypatch.setenv("PIP_DOWNLOAD_CACHE", 'fromenv')
- config = newconfig("""
- [testenv]
- downloadcache=somepath
- """)
- envconfig = config.envconfigs['python']
- assert envconfig.downloadcache.basename == "fromenv"
-
- def test_downloadcache_only_if_in_config(self, newconfig, tmpdir,
- monkeypatch):
- monkeypatch.setenv("PIP_DOWNLOAD_CACHE", tmpdir)
- config = newconfig('')
- envconfig = config.envconfigs['python']
- assert not envconfig.downloadcache
-
- def test_simple(tmpdir, newconfig):
- config = newconfig("""
- [testenv:py26]
- basepython=python2.6
- [testenv:py27]
- basepython=python2.7
- """)
- assert len(config.envconfigs) == 2
- assert "py26" in config.envconfigs
- assert "py27" in config.envconfigs
-
- def test_substitution_error(tmpdir, newconfig):
- py.test.raises(tox.exception.ConfigError, newconfig, """
- [testenv:py27]
- basepython={xyz}
- """)
-
- def test_substitution_defaults(tmpdir, newconfig):
- config = newconfig("""
- [testenv:py27]
- commands =
- {toxinidir}
- {toxworkdir}
- {envdir}
- {envbindir}
- {envtmpdir}
- {envpython}
- {homedir}
- {distshare}
- {envlogdir}
- """)
- conf = config.envconfigs['py27']
- argv = conf.commands
- assert argv[0][0] == config.toxinidir
- assert argv[1][0] == config.toxworkdir
- assert argv[2][0] == conf.envdir
- assert argv[3][0] == conf.envbindir
- assert argv[4][0] == conf.envtmpdir
- assert argv[5][0] == conf.envpython
- assert argv[6][0] == str(config.homedir)
- assert argv[7][0] == config.homedir.join(".tox", "distshare")
- assert argv[8][0] == conf.envlogdir
-
- def test_substitution_notfound_issue246(tmpdir, newconfig):
- config = newconfig("""
- [testenv:py27]
- setenv =
- FOO={envbindir}
- BAR={envsitepackagesdir}
- """)
- conf = config.envconfigs['py27']
- env = conf.setenv
- assert 'FOO' in env
- assert 'BAR' in env
-
- def test_substitution_positional(self, newconfig):
- inisource = """
- [testenv:py27]
- commands =
- cmd1 [hello] \
- world
- cmd1 {posargs:hello} \
- world
- """
- conf = newconfig([], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ["cmd1", "[hello]", "world"]
- assert argv[1] == ["cmd1", "hello", "world"]
- conf = newconfig(['brave', 'new'], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ["cmd1", "[hello]", "world"]
- assert argv[1] == ["cmd1", "brave", "new", "world"]
-
- def test_substitution_noargs_issue240(self, newconfig):
- inisource = """
- [testenv]
- commands = echo {posargs:foo}
- """
- conf = newconfig([""], inisource).envconfigs['python']
- argv = conf.commands
- assert argv[0] == ["echo"]
-
- def test_substitution_double(self, newconfig):
- inisource = """
- [params]
- foo = bah
- foo2 = [params]foo
-
- [testenv:py27]
- commands =
- echo {{[params]foo2}}
- """
- conf = newconfig([], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ['echo', 'bah']
-
- def test_posargs_backslashed_or_quoted(self, tmpdir, newconfig):
- inisource = """
- [testenv:py27]
- commands =
- echo "\{posargs\}" = {posargs}
- echo "posargs = " "{posargs}"
- """
- conf = newconfig([], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ['echo', '{posargs}', '=']
- assert argv[1] == ['echo', 'posargs = ', ""]
-
- conf = newconfig(['dog', 'cat'], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ['echo', '{posargs}', '=', 'dog', 'cat']
- assert argv[1] == ['echo', 'posargs = ', 'dog cat']
-
- def test_rewrite_posargs(self, tmpdir, newconfig):
- inisource = """
- [testenv:py27]
- args_are_paths = True
- changedir = tests
- commands = cmd1 {posargs:hello}
- """
- conf = newconfig([], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ["cmd1", "hello"]
-
- conf = newconfig(["tests/hello"], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ["cmd1", "tests/hello"]
-
- tmpdir.ensure("tests", "hello")
- conf = newconfig(["tests/hello"], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ["cmd1", "hello"]
-
- def test_rewrite_simple_posargs(self, tmpdir, newconfig):
- inisource = """
- [testenv:py27]
- args_are_paths = True
- changedir = tests
- commands = cmd1 {posargs}
- """
- conf = newconfig([], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ["cmd1"]
-
- conf = newconfig(["tests/hello"], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ["cmd1", "tests/hello"]
-
- tmpdir.ensure("tests", "hello")
- conf = newconfig(["tests/hello"], inisource).envconfigs['py27']
- argv = conf.commands
- assert argv[0] == ["cmd1", "hello"]
-
- @pytest.mark.parametrize('envlist, deps', [
- (['py27'], ('pytest', 'pytest-cov')),
- (['py27', 'py34'], ('pytest', 'py{27,34}: pytest-cov')),
- ])
- def test_take_dependencies_from_other_testenv(
- self,
- newconfig,
- envlist,
- deps
- ):
- inisource = """
- [tox]
- envlist = {envlist}
- [testenv]
- deps={deps}
- [testenv:py27]
- deps=
- {{[testenv]deps}}
- fun
- """.format(
- envlist=','.join(envlist),
- deps='\n' + '\n'.join([' ' * 17 + d for d in deps])
- )
- conf = newconfig([], inisource).envconfigs['py27']
- packages = [dep.name for dep in conf.deps]
- assert packages == list(deps) + ['fun']
-
- def test_take_dependencies_from_other_section(self, newconfig):
- inisource = """
- [testing:pytest]
- deps=
- pytest
- pytest-cov
- [testing:mock]
- deps=
- mock
- [testenv]
- deps=
- {[testing:pytest]deps}
- {[testing:mock]deps}
- fun
- """
- conf = newconfig([], inisource)
- env = conf.envconfigs['python']
- packages = [dep.name for dep in env.deps]
- assert packages == ['pytest', 'pytest-cov', 'mock', 'fun']
-
- def test_multilevel_substitution(self, newconfig):
- inisource = """
- [testing:pytest]
- deps=
- pytest
- pytest-cov
- [testing:mock]
- deps=
- mock
-
- [testing]
- deps=
- {[testing:pytest]deps}
- {[testing:mock]deps}
-
- [testenv]
- deps=
- {[testing]deps}
- fun
- """
- conf = newconfig([], inisource)
- env = conf.envconfigs['python']
- packages = [dep.name for dep in env.deps]
- assert packages == ['pytest', 'pytest-cov', 'mock', 'fun']
-
- def test_recursive_substitution_cycle_fails(self, newconfig):
- inisource = """
- [testing:pytest]
- deps=
- {[testing:mock]deps}
- [testing:mock]
- deps=
- {[testing:pytest]deps}
-
- [testenv]
- deps=
- {[testing:pytest]deps}
- """
- py.test.raises(ValueError, newconfig, [], inisource)
-
- def test_single_value_from_other_secton(self, newconfig, tmpdir):
- inisource = """
- [common]
- changedir = testing
- [testenv]
- changedir = {[common]changedir}
- """
- conf = newconfig([], inisource).envconfigs['python']
- assert conf.changedir.basename == 'testing'
- assert conf.changedir.dirpath().realpath() == tmpdir.realpath()
-
- def test_factors(self, newconfig):
- inisource = """
- [tox]
- envlist = a-x,b
-
- [testenv]
- deps=
- dep-all
- a: dep-a
- b: dep-b
- x: dep-x
- """
- conf = newconfig([], inisource)
- configs = conf.envconfigs
- assert [dep.name for dep in configs['a-x'].deps] == \
- ["dep-all", "dep-a", "dep-x"]
- assert [dep.name for dep in configs['b'].deps] == ["dep-all", "dep-b"]
-
- def test_factor_ops(self, newconfig):
- inisource = """
- [tox]
- envlist = {a,b}-{x,y}
-
- [testenv]
- deps=
- a,b: dep-a-or-b
- a-x: dep-a-and-x
- {a,b}-y: dep-ab-and-y
- """
- configs = newconfig([], inisource).envconfigs
- get_deps = lambda env: [dep.name for dep in configs[env].deps]
- assert get_deps("a-x") == ["dep-a-or-b", "dep-a-and-x"]
- assert get_deps("a-y") == ["dep-a-or-b", "dep-ab-and-y"]
- assert get_deps("b-x") == ["dep-a-or-b"]
- assert get_deps("b-y") == ["dep-a-or-b", "dep-ab-and-y"]
-
- def test_default_factors(self, newconfig):
- inisource = """
- [tox]
- envlist = py{26,27,33,34}-dep
-
- [testenv]
- deps=
- dep: dep
- """
- conf = newconfig([], inisource)
- configs = conf.envconfigs
- for name, config in configs.items():
- assert config.basepython == 'python%s.%s' % (name[2], name[3])
-
- @pytest.mark.issue188
- def test_factors_in_boolean(self, newconfig):
- inisource = """
- [tox]
- envlist = py{27,33}
-
- [testenv]
- recreate =
- py27: True
- """
- configs = newconfig([], inisource).envconfigs
- assert configs["py27"].recreate
- assert not configs["py33"].recreate
-
- @pytest.mark.issue190
- def test_factors_in_setenv(self, newconfig):
- inisource = """
- [tox]
- envlist = py27,py26
-
- [testenv]
- setenv =
- py27: X = 1
- """
- configs = newconfig([], inisource).envconfigs
- assert configs["py27"].setenv["X"] == "1"
- assert "X" not in configs["py26"].setenv
-
- @pytest.mark.issue191
- def test_factor_use_not_checked(self, newconfig):
- inisource = """
- [tox]
- envlist = py27-{a,b}
-
- [testenv]
- deps = b: test
- """
- configs = newconfig([], inisource).envconfigs
- assert set(configs.keys()) == set(['py27-a', 'py27-b'])
-
- @pytest.mark.issue198
- def test_factors_groups_touch(self, newconfig):
- inisource = """
- [tox]
- envlist = {a,b}{-x,}
-
- [testenv]
- deps=
- a,b,x,y: dep
- """
- configs = newconfig([], inisource).envconfigs
- assert set(configs.keys()) == set(['a', 'a-x', 'b', 'b-x'])
-
- def test_period_in_factor(self, newconfig):
- inisource = """
- [tox]
- envlist = py27-{django1.6,django1.7}
-
- [testenv]
- deps =
- django1.6: Django==1.6
- django1.7: Django==1.7
- """
- configs = newconfig([], inisource).envconfigs
- assert sorted(configs) == ["py27-django1.6", "py27-django1.7"]
- assert [d.name for d in configs["py27-django1.6"].deps] \
- == ["Django==1.6"]
-
- def test_ignore_outcome(self, newconfig):
- inisource = """
- [testenv]
- ignore_outcome=True
- """
- config = newconfig([], inisource).envconfigs
- assert config["python"].ignore_outcome is True
-
-
-class TestGlobalOptions:
- def test_notest(self, newconfig):
- config = newconfig([], "")
- assert not config.option.notest
- config = newconfig(["--notest"], "")
- assert config.option.notest
-
- def test_verbosity(self, newconfig):
- config = newconfig([], "")
- assert config.option.verbosity == 0
- config = newconfig(["-v"], "")
- assert config.option.verbosity == 1
- config = newconfig(["-vv"], "")
- assert config.option.verbosity == 2
-
- def test_substitution_jenkins_default(self, tmpdir,
- monkeypatch, newconfig):
- monkeypatch.setenv("HUDSON_URL", "xyz")
- config = newconfig("""
- [testenv:py27]
- commands =
- {distshare}
- """)
- conf = config.envconfigs['py27']
- argv = conf.commands
- expect_path = config.toxworkdir.join("distshare")
- assert argv[0][0] == expect_path
-
- def test_substitution_jenkins_context(self, tmpdir, monkeypatch, newconfig):
- monkeypatch.setenv("HUDSON_URL", "xyz")
- monkeypatch.setenv("WORKSPACE", tmpdir)
- config = newconfig("""
- [tox:jenkins]
- distshare = {env:WORKSPACE}/hello
- [testenv:py27]
- commands =
- {distshare}
- """)
- conf = config.envconfigs['py27']
- argv = conf.commands
- assert argv[0][0] == config.distshare
- assert config.distshare == tmpdir.join("hello")
-
- def test_sdist_specification(self, tmpdir, newconfig):
- config = newconfig("""
- [tox]
- sdistsrc = {distshare}/xyz.zip
- """)
- assert config.sdistsrc == config.distshare.join("xyz.zip")
- config = newconfig([], "")
- assert not config.sdistsrc
-
- def test_env_selection(self, tmpdir, newconfig, monkeypatch):
- inisource = """
- [tox]
- envlist = py26
- [testenv:py26]
- basepython=python2.6
- [testenv:py31]
- basepython=python3.1
- [testenv:py27]
- basepython=python2.7
- """
- # py.test.raises(tox.exception.ConfigError,
- # "newconfig(['-exyz'], inisource)")
- config = newconfig([], inisource)
- assert config.envlist == ["py26"]
- config = newconfig(["-epy31"], inisource)
- assert config.envlist == ["py31"]
- monkeypatch.setenv("TOXENV", "py31,py26")
- config = newconfig([], inisource)
- assert config.envlist == ["py31", "py26"]
- monkeypatch.setenv("TOXENV", "ALL")
- config = newconfig([], inisource)
- assert config.envlist == ['py26', 'py27', 'py31']
- config = newconfig(["-eALL"], inisource)
- assert config.envlist == ['py26', 'py27', 'py31']
-
- def test_py_venv(self, tmpdir, newconfig, monkeypatch):
- config = newconfig(["-epy"], "")
- env = config.envconfigs['py']
- assert str(env.basepython) == sys.executable
-
- def test_default_environments(self, tmpdir, newconfig, monkeypatch):
- envs = "py26,py27,py32,py33,py34,py35,py36,jython,pypy,pypy3"
- inisource = """
- [tox]
- envlist = %s
- """ % envs
- config = newconfig([], inisource)
- envlist = envs.split(",")
- assert config.envlist == envlist
- for name in config.envlist:
- env = config.envconfigs[name]
- if name == "jython":
- assert env.basepython == "jython"
- elif name.startswith("pypy"):
- assert env.basepython == name
- else:
- assert name.startswith("py")
- bp = "python%s.%s" % (name[2], name[3])
- assert env.basepython == bp
-
- def test_envlist_expansion(self, newconfig):
- inisource = """
- [tox]
- envlist = py{26,27},docs
- """
- config = newconfig([], inisource)
- assert config.envlist == ["py26", "py27", "docs"]
-
- def test_envlist_cross_product(self, newconfig):
- inisource = """
- [tox]
- envlist = py{26,27}-dep{1,2}
- """
- config = newconfig([], inisource)
- assert config.envlist == \
- ["py26-dep1", "py26-dep2", "py27-dep1", "py27-dep2"]
-
- def test_envlist_multiline(self, newconfig):
- inisource = """
- [tox]
- envlist =
- py27
- py34
- """
- config = newconfig([], inisource)
- assert config.envlist == \
- ["py27", "py34"]
-
- def test_minversion(self, tmpdir, newconfig, monkeypatch):
- inisource = """
- [tox]
- minversion = 10.0
- """
- with py.test.raises(tox.exception.MinVersionError):
- newconfig([], inisource)
-
- def test_skip_missing_interpreters_true(self, tmpdir, newconfig, monkeypatch):
- inisource = """
- [tox]
- skip_missing_interpreters = True
- """
- config = newconfig([], inisource)
- assert config.option.skip_missing_interpreters
-
- def test_skip_missing_interpreters_false(self, tmpdir, newconfig, monkeypatch):
- inisource = """
- [tox]
- skip_missing_interpreters = False
- """
- config = newconfig([], inisource)
- assert not config.option.skip_missing_interpreters
-
- def test_defaultenv_commandline(self, tmpdir, newconfig, monkeypatch):
- config = newconfig(["-epy27"], "")
- env = config.envconfigs['py27']
- assert env.basepython == "python2.7"
- assert not env.commands
-
- def test_defaultenv_partial_override(self, tmpdir, newconfig, monkeypatch):
- inisource = """
- [tox]
- envlist = py27
- [testenv:py27]
- commands= xyz
- """
- config = newconfig([], inisource)
- env = config.envconfigs['py27']
- assert env.basepython == "python2.7"
- assert env.commands == [['xyz']]
-
-
-class TestHashseedOption:
-
- def _get_envconfigs(self, newconfig, args=None, tox_ini=None,
- make_hashseed=None):
- if args is None:
- args = []
- if tox_ini is None:
- tox_ini = """
- [testenv]
- """
- if make_hashseed is None:
- make_hashseed = lambda: '123456789'
- original_make_hashseed = tox.config.make_hashseed
- tox.config.make_hashseed = make_hashseed
- try:
- config = newconfig(args, tox_ini)
- finally:
- tox.config.make_hashseed = original_make_hashseed
- return config.envconfigs
-
- def _get_envconfig(self, newconfig, args=None, tox_ini=None):
- envconfigs = self._get_envconfigs(newconfig, args=args,
- tox_ini=tox_ini)
- return envconfigs["python"]
-
- def _check_hashseed(self, envconfig, expected):
- assert envconfig.setenv['PYTHONHASHSEED'] == expected
-
- def _check_testenv(self, newconfig, expected, args=None, tox_ini=None):
- envconfig = self._get_envconfig(newconfig, args=args, tox_ini=tox_ini)
- self._check_hashseed(envconfig, expected)
-
- def test_default(self, tmpdir, newconfig):
- self._check_testenv(newconfig, '123456789')
-
- def test_passing_integer(self, tmpdir, newconfig):
- args = ['--hashseed', '1']
- self._check_testenv(newconfig, '1', args=args)
-
- def test_passing_string(self, tmpdir, newconfig):
- args = ['--hashseed', 'random']
- self._check_testenv(newconfig, 'random', args=args)
-
- def test_passing_empty_string(self, tmpdir, newconfig):
- args = ['--hashseed', '']
- self._check_testenv(newconfig, '', args=args)
-
- @pytest.mark.xfail(sys.version_info >= (3, 2),
- reason="at least Debian python 3.2/3.3 have a bug: "
- "http://bugs.python.org/issue11884")
- def test_passing_no_argument(self, tmpdir, newconfig):
- """Test that passing no arguments to --hashseed is not allowed."""
- args = ['--hashseed']
- try:
- self._check_testenv(newconfig, '', args=args)
- except SystemExit:
- e = sys.exc_info()[1]
- assert e.code == 2
- return
- assert False # getting here means we failed the test.
-
- def test_setenv(self, tmpdir, newconfig):
- """Check that setenv takes precedence."""
- tox_ini = """
- [testenv]
- setenv =
- PYTHONHASHSEED = 2
- """
- self._check_testenv(newconfig, '2', tox_ini=tox_ini)
- args = ['--hashseed', '1']
- self._check_testenv(newconfig, '2', args=args, tox_ini=tox_ini)
-
- def test_noset(self, tmpdir, newconfig):
- args = ['--hashseed', 'noset']
- envconfig = self._get_envconfig(newconfig, args=args)
- assert not envconfig.setenv.definitions
-
- def test_noset_with_setenv(self, tmpdir, newconfig):
- tox_ini = """
- [testenv]
- setenv =
- PYTHONHASHSEED = 2
- """
- args = ['--hashseed', 'noset']
- self._check_testenv(newconfig, '2', args=args, tox_ini=tox_ini)
-
- def test_one_random_hashseed(self, tmpdir, newconfig):
- """Check that different testenvs use the same random seed."""
- tox_ini = """
- [testenv:hash1]
- [testenv:hash2]
- """
- next_seed = [1000]
- # This function is guaranteed to generate a different value each time.
-
- def make_hashseed():
- next_seed[0] += 1
- return str(next_seed[0])
- # Check that make_hashseed() works.
- assert make_hashseed() == '1001'
- envconfigs = self._get_envconfigs(newconfig, tox_ini=tox_ini,
- make_hashseed=make_hashseed)
- self._check_hashseed(envconfigs["hash1"], '1002')
- # Check that hash2's value is not '1003', for example.
- self._check_hashseed(envconfigs["hash2"], '1002')
-
- def test_setenv_in_one_testenv(self, tmpdir, newconfig):
- """Check using setenv in one of multiple testenvs."""
- tox_ini = """
- [testenv:hash1]
- setenv =
- PYTHONHASHSEED = 2
- [testenv:hash2]
- """
- envconfigs = self._get_envconfigs(newconfig, tox_ini=tox_ini)
- self._check_hashseed(envconfigs["hash1"], '2')
- self._check_hashseed(envconfigs["hash2"], '123456789')
-
-
-class TestSetenv:
- def test_getdict_lazy(self, tmpdir, newconfig, monkeypatch):
- monkeypatch.setenv("X", "2")
- config = newconfig("""
- [testenv:X]
- key0 =
- key1 = {env:X}
- key2 = {env:Y:1}
- """)
- envconfig = config.envconfigs["X"]
- val = envconfig._reader.getdict_setenv("key0")
- assert val["key1"] == "2"
- assert val["key2"] == "1"
-
- def test_getdict_lazy_update(self, tmpdir, newconfig, monkeypatch):
- monkeypatch.setenv("X", "2")
- config = newconfig("""
- [testenv:X]
- key0 =
- key1 = {env:X}
- key2 = {env:Y:1}
- """)
- envconfig = config.envconfigs["X"]
- val = envconfig._reader.getdict_setenv("key0")
- d = {}
- d.update(val)
- assert d == {"key1": "2", "key2": "1"}
-
- def test_setenv_uses_os_environ(self, tmpdir, newconfig, monkeypatch):
- monkeypatch.setenv("X", "1")
- config = newconfig("""
- [testenv:env1]
- setenv =
- X = {env:X}
- """)
- assert config.envconfigs["env1"].setenv["X"] == "1"
-
- def test_setenv_default_os_environ(self, tmpdir, newconfig, monkeypatch):
- monkeypatch.delenv("X", raising=False)
- config = newconfig("""
- [testenv:env1]
- setenv =
- X = {env:X:2}
- """)
- assert config.envconfigs["env1"].setenv["X"] == "2"
-
- def test_setenv_uses_other_setenv(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv:env1]
- setenv =
- Y = 5
- X = {env:Y}
- """)
- assert config.envconfigs["env1"].setenv["X"] == "5"
-
- def test_setenv_recursive_direct(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv:env1]
- setenv =
- X = {env:X:3}
- """)
- assert config.envconfigs["env1"].setenv["X"] == "3"
-
- def test_setenv_overrides(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- setenv =
- PYTHONPATH = something
- ANOTHER_VAL=else
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert 'PYTHONPATH' in envconfig.setenv
- assert 'ANOTHER_VAL' in envconfig.setenv
- assert envconfig.setenv['PYTHONPATH'] == 'something'
- assert envconfig.setenv['ANOTHER_VAL'] == 'else'
-
- def test_setenv_with_envdir_and_basepython(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- setenv =
- VAL = {envdir}
- basepython = {env:VAL}
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert 'VAL' in envconfig.setenv
- assert envconfig.setenv['VAL'] == envconfig.envdir
- assert envconfig.basepython == envconfig.envdir
-
- def test_setenv_ordering_1(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- setenv=
- VAL={envdir}
- commands=echo {env:VAL}
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert 'VAL' in envconfig.setenv
- assert envconfig.setenv['VAL'] == envconfig.envdir
- assert str(envconfig.envdir) in envconfig.commands[0]
-
- def test_setenv_cross_section_subst_issue294(self, monkeypatch, newconfig):
- """test that we can do cross-section substitution with setenv"""
- monkeypatch.delenv('TEST', raising=False)
- config = newconfig("""
- [section]
- x =
- NOT_TEST={env:TEST:defaultvalue}
-
- [testenv]
- setenv = {[section]x}
- """)
- envconfig = config.envconfigs["python"]
- assert envconfig.setenv["NOT_TEST"] == "defaultvalue"
-
- def test_setenv_cross_section_subst_twice(self, monkeypatch, newconfig):
- """test that we can do cross-section substitution with setenv"""
- monkeypatch.delenv('TEST', raising=False)
- config = newconfig("""
- [section]
- x = NOT_TEST={env:TEST:defaultvalue}
- [section1]
- y = {[section]x}
-
- [testenv]
- setenv = {[section1]y}
- """)
- envconfig = config.envconfigs["python"]
- assert envconfig.setenv["NOT_TEST"] == "defaultvalue"
-
- def test_setenv_cross_section_mixed(self, monkeypatch, newconfig):
- """test that we can do cross-section substitution with setenv"""
- monkeypatch.delenv('TEST', raising=False)
- config = newconfig("""
- [section]
- x = NOT_TEST={env:TEST:defaultvalue}
-
- [testenv]
- setenv = {[section]x}
- y = 7
- """)
- envconfig = config.envconfigs["python"]
- assert envconfig.setenv["NOT_TEST"] == "defaultvalue"
- assert envconfig.setenv["y"] == "7"
-
-
-class TestIndexServer:
- def test_indexserver(self, tmpdir, newconfig):
- config = newconfig("""
- [tox]
- indexserver =
- name1 = XYZ
- name2 = ABC
- """)
- assert config.indexserver['default'].url is None
- assert config.indexserver['name1'].url == "XYZ"
- assert config.indexserver['name2'].url == "ABC"
-
- def test_parse_indexserver(self, newconfig):
- inisource = """
- [tox]
- indexserver =
- default = http://pypi.testrun.org
- name1 = whatever
- """
- config = newconfig([], inisource)
- assert config.indexserver['default'].url == "http://pypi.testrun.org"
- assert config.indexserver['name1'].url == "whatever"
- config = newconfig(['-i', 'qwe'], inisource)
- assert config.indexserver['default'].url == "qwe"
- assert config.indexserver['name1'].url == "whatever"
- config = newconfig(['-i', 'name1=abc', '-i', 'qwe2'], inisource)
- assert config.indexserver['default'].url == "qwe2"
- assert config.indexserver['name1'].url == "abc"
-
- config = newconfig(["-i", "ALL=xzy"], inisource)
- assert len(config.indexserver) == 2
- assert config.indexserver["default"].url == "xzy"
- assert config.indexserver["name1"].url == "xzy"
-
- def test_multiple_homedir_relative_local_indexservers(self, newconfig):
- inisource = """
- [tox]
- indexserver =
- default = file://{homedir}/.pip/downloads/simple
- local1 = file://{homedir}/.pip/downloads/simple
- local2 = file://{toxinidir}/downloads/simple
- pypi = http://pypi.python.org/simple
- """
- config = newconfig([], inisource)
- expected = "file://%s/.pip/downloads/simple" % config.homedir
- assert config.indexserver['default'].url == expected
- assert config.indexserver['local1'].url == config.indexserver['default'].url
-
-
-class TestParseEnv:
-
- def test_parse_recreate(self, newconfig):
- inisource = ""
- config = newconfig([], inisource)
- assert not config.envconfigs['python'].recreate
- config = newconfig(['--recreate'], inisource)
- assert config.envconfigs['python'].recreate
- config = newconfig(['-r'], inisource)
- assert config.envconfigs['python'].recreate
- inisource = """
- [testenv:hello]
- recreate = True
- """
- config = newconfig([], inisource)
- assert config.envconfigs['hello'].recreate
-
-
-class TestCmdInvocation:
- def test_help(self, cmd):
- result = cmd.run("tox", "-h")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*help*",
- ])
-
- def test_version(self, cmd):
- result = cmd.run("tox", "--version")
- assert not result.ret
- stdout = result.stdout.str()
- assert tox.__version__ in stdout
- assert "imported from" in stdout
-
- def test_listenvs(self, cmd, initproj):
- initproj('listenvs', filedefs={
- 'tox.ini': '''
- [tox]
- envlist=py26,py27,py33,pypy,docs
-
- [testenv:notincluded]
- changedir = whatever
-
- [testenv:docs]
- changedir = docs
- ''',
- })
- result = cmd.run("tox", "-l")
- result.stdout.fnmatch_lines("""
- *py26*
- *py27*
- *py33*
- *pypy*
- *docs*
- """)
-
- def test_config_specific_ini(self, tmpdir, cmd):
- ini = tmpdir.ensure("hello.ini")
- result = cmd.run("tox", "-c", ini, "--showconfig")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*config-file*hello.ini*",
- ])
-
- def test_no_tox_ini(self, cmd, initproj):
- initproj("noini-0.5", )
- result = cmd.run("tox")
- assert result.ret
- result.stderr.fnmatch_lines([
- "*ERROR*tox.ini*not*found*",
- ])
-
- def test_override_workdir(self, tmpdir, cmd, initproj):
- baddir = "badworkdir-123"
- gooddir = "overridden-234"
- initproj("overrideworkdir-0.5", filedefs={
- 'tox.ini': '''
- [tox]
- toxworkdir=%s
- ''' % baddir,
- })
- result = cmd.run("tox", "--workdir", gooddir, "--showconfig")
- assert not result.ret
- stdout = result.stdout.str()
- assert gooddir in stdout
- assert baddir not in stdout
- assert py.path.local(gooddir).check()
- assert not py.path.local(baddir).check()
-
- def test_showconfig_with_force_dep_version(self, cmd, initproj):
- initproj('force_dep_version', filedefs={
- 'tox.ini': '''
- [tox]
-
- [testenv]
- deps=
- dep1==2.3
- dep2
- ''',
- })
- result = cmd.run("tox", "--showconfig")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- r'*deps*dep1==2.3, dep2*',
- ])
- # override dep1 specific version, and force version for dep2
- result = cmd.run("tox", "--showconfig", "--force-dep=dep1",
- "--force-dep=dep2==5.0")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- r'*deps*dep1, dep2==5.0*',
- ])
-
-
-@pytest.mark.parametrize("cmdline,envlist", [
- ("-e py26", ['py26']),
- ("-e py26,py33", ['py26', 'py33']),
- ("-e py26,py26", ['py26', 'py26']),
- ("-e py26,py33 -e py33,py27", ['py26', 'py33', 'py33', 'py27'])
-])
-def test_env_spec(cmdline, envlist):
- args = cmdline.split()
- config = parseconfig(args)
- assert config.envlist == envlist
-
-
-class TestCommandParser:
-
- def test_command_parser_for_word(self):
- p = CommandParser('word')
- # import pytest; pytest.set_trace()
- assert list(p.words()) == ['word']
-
- def test_command_parser_for_posargs(self):
- p = CommandParser('[]')
- assert list(p.words()) == ['[]']
-
- def test_command_parser_for_multiple_words(self):
- p = CommandParser('w1 w2 w3 ')
- assert list(p.words()) == ['w1', ' ', 'w2', ' ', 'w3']
-
- def test_command_parser_for_substitution_with_spaces(self):
- p = CommandParser('{sub:something with spaces}')
- assert list(p.words()) == ['{sub:something with spaces}']
-
- def test_command_parser_with_complex_word_set(self):
- complex_case = (
- 'word [] [literal] {something} {some:other thing} w{ord} w{or}d w{ord} '
- 'w{o:rd} w{o:r}d {w:or}d w[]ord {posargs:{a key}}')
- p = CommandParser(complex_case)
- parsed = list(p.words())
- expected = [
- 'word', ' ', '[]', ' ', '[literal]', ' ', '{something}', ' ', '{some:other thing}',
- ' ', 'w', '{ord}', ' ', 'w', '{or}', 'd', ' ', 'w', '{ord}', ' ', 'w', '{o:rd}', ' ',
- 'w', '{o:r}', 'd', ' ', '{w:or}', 'd',
- ' ', 'w[]ord', ' ', '{posargs:{a key}}',
- ]
-
- assert parsed == expected
-
- def test_command_with_runs_of_whitespace(self):
- cmd = "cmd1 {item1}\n {item2}"
- p = CommandParser(cmd)
- parsed = list(p.words())
- assert parsed == ['cmd1', ' ', '{item1}', '\n ', '{item2}']
-
- def test_command_with_split_line_in_subst_arguments(self):
- cmd = dedent(""" cmd2 {posargs:{item2}
- other}""")
- p = CommandParser(cmd)
- parsed = list(p.words())
- assert parsed == ['cmd2', ' ', '{posargs:{item2}\n other}']
-
- def test_command_parsing_for_issue_10(self):
- cmd = "nosetests -v -a !deferred --with-doctest []"
- p = CommandParser(cmd)
- parsed = list(p.words())
- assert parsed == [
- 'nosetests', ' ', '-v', ' ', '-a', ' ', '!deferred', ' ',
- '--with-doctest', ' ', '[]'
- ]
-
- @pytest.mark.skipif("sys.platform != 'win32'")
- def test_commands_with_backslash(self, newconfig):
- config = newconfig([r"hello\world"], """
- [testenv:py26]
- commands = some {posargs}
- """)
- envconfig = config.envconfigs["py26"]
- assert envconfig.commands[0] == ["some", r"hello\world"]
diff --git a/tests/test_interpreters.py b/tests/test_interpreters.py
deleted file mode 100644
index c658380..0000000
--- a/tests/test_interpreters.py
+++ /dev/null
@@ -1,112 +0,0 @@
-import sys
-import os
-
-import pytest
-from tox.interpreters import * # noqa
-from tox.config import get_plugin_manager
-
-
-@pytest.fixture
-def interpreters():
- pm = get_plugin_manager()
- return Interpreters(hook=pm.hook)
-
-
-@pytest.mark.skipif("sys.platform != 'win32'")
-def test_locate_via_py(monkeypatch):
- class PseudoPy:
- def sysexec(self, *args):
- assert args[0] == '-3.2'
- assert args[1] == '-c'
- # Return value needs to actually exist!
- return sys.executable
-
- @staticmethod
- def ret_pseudopy(name):
- assert name == 'py'
- return PseudoPy()
- # Monkeypatch py.path.local.sysfind to return PseudoPy
- monkeypatch.setattr(py.path.local, 'sysfind', ret_pseudopy)
- assert locate_via_py('3', '2') == sys.executable
-
-
-def test_tox_get_python_executable():
- class envconfig:
- basepython = sys.executable
- envname = "pyxx"
- p = tox_get_python_executable(envconfig)
- assert p == py.path.local(sys.executable)
- for ver in [""] + "2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3".split():
- name = "python%s" % ver
- if sys.platform == "win32":
- pydir = "python%s" % ver.replace(".", "")
- x = py.path.local("c:\%s" % pydir)
- print(x)
- if not x.check():
- continue
- else:
- if not py.path.local.sysfind(name):
- continue
- envconfig.basepython = name
- p = tox_get_python_executable(envconfig)
- assert p
- popen = py.std.subprocess.Popen([str(p), '-V'],
- stderr=py.std.subprocess.PIPE)
- stdout, stderr = popen.communicate()
- assert ver in py.builtin._totext(stderr, "ascii")
-
-
-def test_find_executable_extra(monkeypatch):
- @staticmethod
- def sysfind(x):
- return "hello"
- monkeypatch.setattr(py.path.local, "sysfind", sysfind)
-
- class envconfig:
- basepython = "1lk23j"
- envname = "pyxx"
-
- t = tox_get_python_executable(envconfig)
- assert t == "hello"
-
-
-def test_run_and_get_interpreter_info():
- name = os.path.basename(sys.executable)
- info = run_and_get_interpreter_info(name, sys.executable)
- assert info.version_info == tuple(sys.version_info)
- assert info.name == name
- assert info.executable == sys.executable
-
-
-class TestInterpreters:
-
- def test_get_executable(self, interpreters):
- class envconfig:
- basepython = sys.executable
- envname = "pyxx"
-
- x = interpreters.get_executable(envconfig)
- assert x == sys.executable
- info = interpreters.get_info(envconfig)
- assert info.version_info == tuple(sys.version_info)
- assert info.executable == sys.executable
- assert info.runnable
-
- def test_get_executable_no_exist(self, interpreters):
- class envconfig:
- basepython = "1lkj23"
- envname = "pyxx"
- assert not interpreters.get_executable(envconfig)
- info = interpreters.get_info(envconfig)
- assert not info.version_info
- assert info.name == "1lkj23"
- assert not info.executable
- assert not info.runnable
-
- def test_get_sitepackagesdir_error(self, interpreters):
- class envconfig:
- basepython = sys.executable
- envname = "123"
- info = interpreters.get_info(envconfig)
- s = interpreters.get_sitepackagesdir(info, "")
- assert s
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
deleted file mode 100644
index 5aaacc2..0000000
--- a/tests/test_quickstart.py
+++ /dev/null
@@ -1,491 +0,0 @@
-import pytest
-import tox._quickstart
-
-
-@pytest.fixture(autouse=True)
-def cleandir(tmpdir):
- tmpdir.chdir()
-
-
-class TestToxQuickstartMain(object):
-
- def mock_term_input_return_values(self, return_values):
- for return_val in return_values:
- yield return_val
-
- def get_mock_term_input(self, return_values):
- generator = self.mock_term_input_return_values(return_values)
-
- def mock_term_input(prompt):
- try:
- return next(generator)
- except NameError:
- return generator.next()
-
- return mock_term_input
-
- def test_quickstart_main_choose_individual_pythons_and_pytest(
- self,
- monkeypatch):
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '4', # Python versions: choose one by one
- 'Y', # py26
- 'Y', # py27
- 'Y', # py32
- 'Y', # py33
- 'Y', # py34
- 'Y', # py35
- 'Y', # pypy
- 'N', # jython
- 'py.test', # command to run tests
- 'pytest' # test dependencies
- ]
- )
- )
-
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34, py35, pypy
-
-[testenv]
-commands = py.test
-deps =
- pytest
-""".lstrip()
- result = open('tox.ini').read()
- assert(result == expected_tox_ini)
-
- def test_quickstart_main_choose_individual_pythons_and_nose_adds_deps(
- self,
- monkeypatch):
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '4', # Python versions: choose one by one
- 'Y', # py26
- 'Y', # py27
- 'Y', # py32
- 'Y', # py33
- 'Y', # py34
- 'Y', # py35
- 'Y', # pypy
- 'N', # jython
- 'nosetests', # command to run tests
- '' # test dependencies
- ]
- )
- )
-
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34, py35, pypy
-
-[testenv]
-commands = nosetests
-deps =
- nose
-""".lstrip()
- result = open('tox.ini').read()
- assert(result == expected_tox_ini)
-
- def test_quickstart_main_choose_individual_pythons_and_trial_adds_deps(
- self,
- monkeypatch):
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '4', # Python versions: choose one by one
- 'Y', # py26
- 'Y', # py27
- 'Y', # py32
- 'Y', # py33
- 'Y', # py34
- 'Y', # py35
- 'Y', # pypy
- 'N', # jython
- 'trial', # command to run tests
- '' # test dependencies
- ]
- )
- )
-
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34, py35, pypy
-
-[testenv]
-commands = trial
-deps =
- twisted
-""".lstrip()
- result = open('tox.ini').read()
- assert(result == expected_tox_ini)
-
- def test_quickstart_main_choose_individual_pythons_and_pytest_adds_deps(
- self,
- monkeypatch):
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '4', # Python versions: choose one by one
- 'Y', # py26
- 'Y', # py27
- 'Y', # py32
- 'Y', # py33
- 'Y', # py34
- 'Y', # py35
- 'Y', # pypy
- 'N', # jython
- 'py.test', # command to run tests
- '' # test dependencies
- ]
- )
- )
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34, py35, pypy
-
-[testenv]
-commands = py.test
-deps =
- pytest
-""".lstrip()
- result = open('tox.ini').read()
- assert(result == expected_tox_ini)
-
- def test_quickstart_main_choose_py27_and_pytest_adds_deps(
- self,
- monkeypatch):
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '1', # py27
- 'py.test', # command to run tests
- '' # test dependencies
- ]
- )
- )
-
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py27
-
-[testenv]
-commands = py.test
-deps =
- pytest
-""".lstrip()
- result = open('tox.ini').read()
- assert(result == expected_tox_ini)
-
- def test_quickstart_main_choose_py27_and_py33_and_pytest_adds_deps(
- self,
- monkeypatch):
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '2', # py27 and py33
- 'py.test', # command to run tests
- '' # test dependencies
- ]
- )
- )
-
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py27, py33
-
-[testenv]
-commands = py.test
-deps =
- pytest
-""".lstrip()
- result = open('tox.ini').read()
- assert(result == expected_tox_ini)
-
- def test_quickstart_main_choose_all_pythons_and_pytest_adds_deps(
- self,
- monkeypatch):
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '3', # all Python versions
- 'py.test', # command to run tests
- '' # test dependencies
- ]
- )
- )
-
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34, py35, pypy, jython
-
-[testenv]
-commands = py.test
-deps =
- pytest
-""".lstrip()
- result = open('tox.ini').read()
- assert(result == expected_tox_ini)
-
- def test_quickstart_main_choose_individual_pythons_and_defaults(
- self,
- monkeypatch):
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '4', # Python versions: choose one by one
- '', # py26
- '', # py27
- '', # py32
- '', # py33
- '', # py34
- '', # py35
- '', # pypy
- '', # jython
- '', # command to run tests
- '' # test dependencies
- ]
- )
- )
-
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34, py35, pypy, jython
-
-[testenv]
-commands = {envpython} setup.py test
-deps =
-
-""".lstrip()
- result = open('tox.ini').read()
- assert(result == expected_tox_ini)
-
- def test_quickstart_main_existing_tox_ini(self, monkeypatch):
- try:
- f = open('tox.ini', 'w')
- f.write('foo bar\n')
- finally:
- f.close()
-
- monkeypatch.setattr(
- tox._quickstart, 'term_input',
- self.get_mock_term_input(
- [
- '4', # Python versions: choose one by one
- '', # py26
- '', # py27
- '', # py32
- '', # py33
- '', # py34
- '', # py35
- '', # pypy
- '', # jython
- '', # command to run tests
- '', # test dependencies
- '', # tox.ini already exists; overwrite?
- ]
- )
- )
-
- tox._quickstart.main(argv=['tox-quickstart'])
-
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34, py35, pypy, jython
-
-[testenv]
-commands = {envpython} setup.py test
-deps =
-
-""".lstrip()
- result = open('tox-generated.ini').read()
- assert(result == expected_tox_ini)
-
-
-class TestToxQuickstart(object):
- def test_pytest(self):
- d = {
- 'py26': True,
- 'py27': True,
- 'py32': True,
- 'py33': True,
- 'py34': True,
- 'pypy': True,
- 'commands': 'py.test',
- 'deps': 'pytest',
- }
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34, pypy
-
-[testenv]
-commands = py.test
-deps =
- pytest
-""".lstrip()
- d = tox._quickstart.process_input(d)
- tox._quickstart.generate(d)
- result = open('tox.ini').read()
- # print(result)
- assert(result == expected_tox_ini)
-
- def test_setup_py_test(self):
- d = {
- 'py26': True,
- 'py27': True,
- 'commands': 'python setup.py test',
- 'deps': '',
- }
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py26, py27
-
-[testenv]
-commands = python setup.py test
-deps =
-
-""".lstrip()
- d = tox._quickstart.process_input(d)
- tox._quickstart.generate(d)
- result = open('tox.ini').read()
- # print(result)
- assert(result == expected_tox_ini)
-
- def test_trial(self):
- d = {
- 'py27': True,
- 'commands': 'trial',
- 'deps': 'Twisted',
- }
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py27
-
-[testenv]
-commands = trial
-deps =
- Twisted
-""".lstrip()
- d = tox._quickstart.process_input(d)
- tox._quickstart.generate(d)
- result = open('tox.ini').read()
- # print(result)
- assert(result == expected_tox_ini)
-
- def test_nosetests(self):
- d = {
- 'py27': True,
- 'py32': True,
- 'py33': True,
- 'py34': True,
- 'py35': True,
- 'pypy': True,
- 'commands': 'nosetests -v',
- 'deps': 'nose',
- }
- expected_tox_ini = """
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = py27, py32, py33, py34, py35, pypy
-
-[testenv]
-commands = nosetests -v
-deps =
- nose
-""".lstrip()
- d = tox._quickstart.process_input(d)
- tox._quickstart.generate(d)
- result = open('tox.ini').read()
- # print(result)
- assert(result == expected_tox_ini)
diff --git a/tests/test_result.py b/tests/test_result.py
deleted file mode 100644
index 48dd831..0000000
--- a/tests/test_result.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import sys
-import py
-from tox.result import ResultLog
-import tox
-import pytest
-
-
-@pytest.fixture
-def pkg(tmpdir):
- p = tmpdir.join("hello-1.0.tar.gz")
- p.write("whatever")
- return p
-
-
-def test_pre_set_header(pkg):
- replog = ResultLog()
- d = replog.dict
- assert replog.dict == d
- assert replog.dict["reportversion"] == "1"
- assert replog.dict["toxversion"] == tox.__version__
- assert replog.dict["platform"] == sys.platform
- assert replog.dict["host"] == py.std.socket.getfqdn()
- data = replog.dumps_json()
- replog2 = ResultLog.loads_json(data)
- assert replog2.dict == replog.dict
-
-
-def test_set_header(pkg):
- replog = ResultLog()
- d = replog.dict
- replog.set_header(installpkg=pkg)
- assert replog.dict == d
- assert replog.dict["reportversion"] == "1"
- assert replog.dict["toxversion"] == tox.__version__
- assert replog.dict["platform"] == sys.platform
- assert replog.dict["host"] == py.std.socket.getfqdn()
- assert replog.dict["installpkg"] == {
- "basename": "hello-1.0.tar.gz",
- "md5": pkg.computehash("md5"),
- "sha256": pkg.computehash("sha256")}
- data = replog.dumps_json()
- replog2 = ResultLog.loads_json(data)
- assert replog2.dict == replog.dict
-
-
-def test_addenv_setpython(pkg):
- replog = ResultLog()
- replog.set_header(installpkg=pkg)
- envlog = replog.get_envlog("py26")
- envlog.set_python_info(py.path.local(sys.executable))
- assert envlog.dict["python"]["version_info"] == list(sys.version_info)
- assert envlog.dict["python"]["version"] == sys.version
- assert envlog.dict["python"]["executable"] == sys.executable
-
-
-def test_get_commandlog(pkg):
- replog = ResultLog()
- replog.set_header(installpkg=pkg)
- envlog = replog.get_envlog("py26")
- assert "setup" not in envlog.dict
- setuplog = envlog.get_commandlog("setup")
- setuplog.add_command(["virtualenv", "..."], "venv created", 0)
- assert setuplog.list == [{"command": ["virtualenv", "..."],
- "output": "venv created",
- "retcode": "0"}]
- assert envlog.dict["setup"]
- setuplog2 = replog.get_envlog("py26").get_commandlog("setup")
- assert setuplog2.list == setuplog.list
diff --git a/tests/test_venv.py b/tests/test_venv.py
deleted file mode 100644
index 86fbc46..0000000
--- a/tests/test_venv.py
+++ /dev/null
@@ -1,699 +0,0 @@
-import py
-import tox
-import pytest
-import os
-import sys
-import tox.config
-from tox.venv import * # noqa
-from tox.hookspecs import hookimpl
-from tox.interpreters import NoInterpreterInfo
-
-
-# def test_global_virtualenv(capfd):
-# v = VirtualEnv()
-# l = v.list()
-# assert l
-# out, err = capfd.readouterr()
-# assert not out
-# assert not err
-#
-
-
-def test_getdigest(tmpdir):
- assert getdigest(tmpdir) == "0" * 32
-
-
-def test_getsupportedinterpreter(monkeypatch, newconfig, mocksession):
- config = newconfig([], """
- [testenv:python]
- basepython=%s
- """ % sys.executable)
- venv = VirtualEnv(config.envconfigs['python'], session=mocksession)
- interp = venv.getsupportedinterpreter()
- # realpath needed for debian symlinks
- assert py.path.local(interp).realpath() == py.path.local(sys.executable).realpath()
- monkeypatch.setattr(sys, 'platform', "win32")
- monkeypatch.setattr(venv.envconfig, 'basepython', 'jython')
- py.test.raises(tox.exception.UnsupportedInterpreter,
- venv.getsupportedinterpreter)
- monkeypatch.undo()
- monkeypatch.setattr(venv.envconfig, "envname", "py1")
- monkeypatch.setattr(venv.envconfig, 'basepython', 'notexistingpython')
- py.test.raises(tox.exception.InterpreterNotFound,
- venv.getsupportedinterpreter)
- monkeypatch.undo()
- # check that we properly report when no version_info is present
- info = NoInterpreterInfo(name=venv.name)
- info.executable = "something"
- monkeypatch.setattr(config.interpreters, "get_info", lambda *args, **kw: info)
- pytest.raises(tox.exception.InvocationError, venv.getsupportedinterpreter)
-
-
-def test_create(monkeypatch, mocksession, newconfig):
- config = newconfig([], """
- [testenv:py123]
- """)
- envconfig = config.envconfigs['py123']
- venv = VirtualEnv(envconfig, session=mocksession)
- assert venv.path == envconfig.envdir
- assert not venv.path.check()
- action = mocksession.newaction(venv, "getenv")
- tox_testenv_create(action=action, venv=venv)
- l = mocksession._pcalls
- assert len(l) >= 1
- args = l[0].args
- assert "virtualenv" == str(args[2])
- if sys.platform != "win32":
- # realpath is needed for stuff like the debian symlinks
- assert py.path.local(sys.executable).realpath() == py.path.local(args[0]).realpath()
- # assert Envconfig.toxworkdir in args
- assert venv.getcommandpath("easy_install", cwd=py.path.local())
- interp = venv._getliveconfig().python
- assert interp == venv.envconfig.python_info.executable
- assert venv.path_config.check(exists=False)
-
-
-@pytest.mark.skipif("sys.platform == 'win32'")
-def test_commandpath_venv_precendence(tmpdir, monkeypatch,
- mocksession, newconfig):
- config = newconfig([], """
- [testenv:py123]
- """)
- envconfig = config.envconfigs['py123']
- venv = VirtualEnv(envconfig, session=mocksession)
- tmpdir.ensure("easy_install")
- monkeypatch.setenv("PATH", str(tmpdir), prepend=os.pathsep)
- envconfig.envbindir.ensure("easy_install")
- p = venv.getcommandpath("easy_install")
- assert py.path.local(p).relto(envconfig.envbindir), p
-
-
-def test_create_sitepackages(monkeypatch, mocksession, newconfig):
- config = newconfig([], """
- [testenv:site]
- sitepackages=True
-
- [testenv:nosite]
- sitepackages=False
- """)
- envconfig = config.envconfigs['site']
- venv = VirtualEnv(envconfig, session=mocksession)
- action = mocksession.newaction(venv, "getenv")
- tox_testenv_create(action=action, venv=venv)
- l = mocksession._pcalls
- assert len(l) >= 1
- args = l[0].args
- assert "--system-site-packages" in map(str, args)
- mocksession._clearmocks()
-
- envconfig = config.envconfigs['nosite']
- venv = VirtualEnv(envconfig, session=mocksession)
- action = mocksession.newaction(venv, "getenv")
- tox_testenv_create(action=action, venv=venv)
- l = mocksession._pcalls
- assert len(l) >= 1
- args = l[0].args
- assert "--system-site-packages" not in map(str, args)
- assert "--no-site-packages" not in map(str, args)
-
-
-def test_install_deps_wildcard(newmocksession):
- mocksession = newmocksession([], """
- [tox]
- distshare = {toxworkdir}/distshare
- [testenv:py123]
- deps=
- {distshare}/dep1-*
- """)
- venv = mocksession.getenv("py123")
- action = mocksession.newaction(venv, "getenv")
- tox_testenv_create(action=action, venv=venv)
- l = mocksession._pcalls
- assert len(l) == 1
- distshare = venv.session.config.distshare
- distshare.ensure("dep1-1.0.zip")
- distshare.ensure("dep1-1.1.zip")
-
- tox_testenv_install_deps(action=action, venv=venv)
- assert len(l) == 2
- args = l[-1].args
- assert l[-1].cwd == venv.envconfig.config.toxinidir
- assert "pip" in str(args[0])
- assert args[1] == "install"
- # arg = "--download-cache=" + str(venv.envconfig.downloadcache)
- # assert arg in args[2:]
- args = [arg for arg in args if str(arg).endswith("dep1-1.1.zip")]
- assert len(args) == 1
-
-
-@pytest.mark.parametrize("envdc", [True, False])
-def test_install_downloadcache(newmocksession, monkeypatch, tmpdir, envdc):
- if envdc:
- monkeypatch.setenv("PIP_DOWNLOAD_CACHE", tmpdir)
- else:
- monkeypatch.delenv("PIP_DOWNLOAD_CACHE", raising=False)
- mocksession = newmocksession([], """
- [testenv:py123]
- deps=
- dep1
- dep2
- """)
- venv = mocksession.getenv("py123")
- action = mocksession.newaction(venv, "getenv")
- tox_testenv_create(action=action, venv=venv)
- l = mocksession._pcalls
- assert len(l) == 1
-
- tox_testenv_install_deps(action=action, venv=venv)
- assert len(l) == 2
- args = l[-1].args
- assert l[-1].cwd == venv.envconfig.config.toxinidir
- assert "pip" in str(args)
- assert args[1] == "install"
- assert "dep1" in args
- assert "dep2" in args
- deps = list(filter(None, [x[1] for x in venv._getliveconfig().deps]))
- assert deps == ['dep1', 'dep2']
-
-
-def test_install_deps_indexserver(newmocksession):
- mocksession = newmocksession([], """
- [tox]
- indexserver =
- abc = ABC
- abc2 = ABC
- [testenv:py123]
- deps=
- dep1
- :abc:dep2
- :abc2:dep3
- """)
- venv = mocksession.getenv('py123')
- action = mocksession.newaction(venv, "getenv")
- tox_testenv_create(action=action, venv=venv)
- l = mocksession._pcalls
- assert len(l) == 1
- l[:] = []
-
- tox_testenv_install_deps(action=action, venv=venv)
- # two different index servers, two calls
- assert len(l) == 3
- args = " ".join(l[0].args)
- assert "-i " not in args
- assert "dep1" in args
-
- args = " ".join(l[1].args)
- assert "-i ABC" in args
- assert "dep2" in args
- args = " ".join(l[2].args)
- assert "-i ABC" in args
- assert "dep3" in args
-
-
-def test_install_deps_pre(newmocksession):
- mocksession = newmocksession([], """
- [testenv]
- pip_pre=true
- deps=
- dep1
- """)
- venv = mocksession.getenv('python')
- action = mocksession.newaction(venv, "getenv")
- tox_testenv_create(action=action, venv=venv)
- l = mocksession._pcalls
- assert len(l) == 1
- l[:] = []
-
- tox_testenv_install_deps(action=action, venv=venv)
- assert len(l) == 1
- args = " ".join(l[0].args)
- assert "--pre " in args
- assert "dep1" in args
-
-
-def test_installpkg_indexserver(newmocksession, tmpdir):
- mocksession = newmocksession([], """
- [tox]
- indexserver =
- default = ABC
- """)
- venv = mocksession.getenv('python')
- l = mocksession._pcalls
- p = tmpdir.ensure("distfile.tar.gz")
- mocksession.installpkg(venv, p)
- # two different index servers, two calls
- assert len(l) == 1
- args = " ".join(l[0].args)
- assert "-i ABC" in args
-
-
-def test_install_recreate(newmocksession, tmpdir):
- pkg = tmpdir.ensure("package.tar.gz")
- mocksession = newmocksession(['--recreate'], """
- [testenv]
- deps=xyz
- """)
- venv = mocksession.getenv('python')
-
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- mocksession.installpkg(venv, pkg)
- mocksession.report.expect("verbosity0", "*create*")
- venv.update(action)
- mocksession.report.expect("verbosity0", "*recreate*")
-
-
-def test_test_hashseed_is_in_output(newmocksession):
- original_make_hashseed = tox.config.make_hashseed
- tox.config.make_hashseed = lambda: '123456789'
- try:
- mocksession = newmocksession([], '''
- [testenv]
- ''')
- finally:
- tox.config.make_hashseed = original_make_hashseed
- venv = mocksession.getenv('python')
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- venv.test()
- mocksession.report.expect("verbosity0", "python runtests: PYTHONHASHSEED='123456789'")
-
-
-def test_test_runtests_action_command_is_in_output(newmocksession):
- mocksession = newmocksession([], '''
- [testenv]
- commands = echo foo bar
- ''')
- venv = mocksession.getenv('python')
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- venv.test()
- mocksession.report.expect("verbosity0", "*runtests*commands?0? | echo foo bar")
-
-
-def test_install_error(newmocksession, monkeypatch):
- mocksession = newmocksession(['--recreate'], """
- [testenv]
- deps=xyz
- commands=
- qwelkqw
- """)
- venv = mocksession.getenv('python')
- venv.test()
- mocksession.report.expect("error", "*not find*qwelkqw*")
- assert venv.status == "commands failed"
-
-
-def test_install_command_not_installed(newmocksession, monkeypatch):
- mocksession = newmocksession(['--recreate'], """
- [testenv]
- commands=
- py.test
- """)
- venv = mocksession.getenv('python')
- venv.test()
- mocksession.report.expect("warning", "*test command found but not*")
- assert venv.status == 0
-
-
-def test_install_command_whitelisted(newmocksession, monkeypatch):
- mocksession = newmocksession(['--recreate'], """
- [testenv]
- whitelist_externals = py.test
- xy*
- commands=
- py.test
- xyz
- """)
- venv = mocksession.getenv('python')
- venv.test()
- mocksession.report.expect("warning", "*test command found but not*",
- invert=True)
- assert venv.status == "commands failed"
-
-
-@pytest.mark.skipif("not sys.platform.startswith('linux')")
-def test_install_command_not_installed_bash(newmocksession):
- mocksession = newmocksession(['--recreate'], """
- [testenv]
- commands=
- bash
- """)
- venv = mocksession.getenv('python')
- venv.test()
- mocksession.report.expect("warning", "*test command found but not*")
-
-
-def test_install_python3(tmpdir, newmocksession):
- if not py.path.local.sysfind('python3.3'):
- pytest.skip("needs python3.3")
- mocksession = newmocksession([], """
- [testenv:py123]
- basepython=python3.3
- deps=
- dep1
- dep2
- """)
- venv = mocksession.getenv('py123')
- action = mocksession.newaction(venv, "getenv")
- tox_testenv_create(action=action, venv=venv)
- l = mocksession._pcalls
- assert len(l) == 1
- args = l[0].args
- assert str(args[2]) == 'virtualenv'
- l[:] = []
- action = mocksession.newaction(venv, "hello")
- venv._install(["hello"], action=action)
- assert len(l) == 1
- args = l[0].args
- assert "pip" in args[0]
- for x in args:
- assert "--download-cache" not in args, args
-
-
-class TestCreationConfig:
-
- def test_basic(self, newconfig, mocksession, tmpdir):
- config = newconfig([], "")
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
- cconfig = venv._getliveconfig()
- assert cconfig.matches(cconfig)
- path = tmpdir.join("configdump")
- cconfig.writeconfig(path)
- newconfig = CreationConfig.readconfig(path)
- assert newconfig.matches(cconfig)
- assert cconfig.matches(newconfig)
-
- def test_matchingdependencies(self, newconfig, mocksession):
- config = newconfig([], """
- [testenv]
- deps=abc
- """)
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
- cconfig = venv._getliveconfig()
- config = newconfig([], """
- [testenv]
- deps=xyz
- """)
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
- otherconfig = venv._getliveconfig()
- assert not cconfig.matches(otherconfig)
-
- def test_matchingdependencies_file(self, newconfig, mocksession):
- config = newconfig([], """
- [tox]
- distshare={toxworkdir}/distshare
- [testenv]
- deps=abc
- {distshare}/xyz.zip
- """)
- xyz = config.distshare.join("xyz.zip")
- xyz.ensure()
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
- cconfig = venv._getliveconfig()
- assert cconfig.matches(cconfig)
- xyz.write("hello")
- newconfig = venv._getliveconfig()
- assert not cconfig.matches(newconfig)
-
- def test_matchingdependencies_latest(self, newconfig, mocksession):
- config = newconfig([], """
- [tox]
- distshare={toxworkdir}/distshare
- [testenv]
- deps={distshare}/xyz-*
- """)
- config.distshare.ensure("xyz-1.2.0.zip")
- xyz2 = config.distshare.ensure("xyz-1.2.1.zip")
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
- cconfig = venv._getliveconfig()
- md5, path = cconfig.deps[0]
- assert path == xyz2
- assert md5 == path.computehash()
-
- def test_python_recreation(self, tmpdir, newconfig, mocksession):
- pkg = tmpdir.ensure("package.tar.gz")
- config = newconfig([], "")
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
- cconfig = venv._getliveconfig()
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- assert not venv.path_config.check()
- mocksession.installpkg(venv, pkg)
- assert venv.path_config.check()
- assert mocksession._pcalls
- args1 = map(str, mocksession._pcalls[0].args)
- assert 'virtualenv' in " ".join(args1)
- mocksession.report.expect("*", "*create*")
- # modify config and check that recreation happens
- mocksession._clearmocks()
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- mocksession.report.expect("*", "*reusing*")
- mocksession._clearmocks()
- action = mocksession.newaction(venv, "update")
- cconfig.python = py.path.local("balla")
- cconfig.writeconfig(venv.path_config)
- venv.update(action)
- mocksession.report.expect("verbosity0", "*recreate*")
-
- def test_dep_recreation(self, newconfig, mocksession):
- config = newconfig([], "")
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- cconfig = venv._getliveconfig()
- cconfig.deps[:] = [("1" * 32, "xyz.zip")]
- cconfig.writeconfig(venv.path_config)
- mocksession._clearmocks()
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- mocksession.report.expect("*", "*recreate*")
-
- def test_develop_recreation(self, newconfig, mocksession):
- config = newconfig([], "")
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- cconfig = venv._getliveconfig()
- cconfig.usedevelop = True
- cconfig.writeconfig(venv.path_config)
- mocksession._clearmocks()
- action = mocksession.newaction(venv, "update")
- venv.update(action)
- mocksession.report.expect("verbosity0", "*recreate*")
-
-
-class TestVenvTest:
-
- def test_envbinddir_path(self, newmocksession, monkeypatch):
- monkeypatch.setenv("PIP_RESPECT_VIRTUALENV", "1")
- mocksession = newmocksession([], """
- [testenv:python]
- commands=abc
- """)
- venv = mocksession.getenv("python")
- action = mocksession.newaction(venv, "getenv")
- monkeypatch.setenv("PATH", "xyz")
- l = []
- monkeypatch.setattr("py.path.local.sysfind", classmethod(
- lambda *args, **kwargs: l.append(kwargs) or 0 / 0))
-
- with pytest.raises(ZeroDivisionError):
- venv._install(list('123'), action=action)
- assert l.pop()["paths"] == [venv.envconfig.envbindir]
- with pytest.raises(ZeroDivisionError):
- venv.test(action)
- assert l.pop()["paths"] == [venv.envconfig.envbindir]
- with pytest.raises(ZeroDivisionError):
- venv.run_install_command(['qwe'], action=action)
- assert l.pop()["paths"] == [venv.envconfig.envbindir]
- monkeypatch.setenv("PIP_RESPECT_VIRTUALENV", "1")
- monkeypatch.setenv("PIP_REQUIRE_VIRTUALENV", "1")
- monkeypatch.setenv("__PYVENV_LAUNCHER__", "1")
- py.test.raises(ZeroDivisionError, "venv.run_install_command(['qwe'], action=action)")
- assert 'PIP_RESPECT_VIRTUALENV' not in os.environ
- assert 'PIP_REQUIRE_VIRTUALENV' not in os.environ
- assert '__PYVENV_LAUNCHER__' not in os.environ
-
-
-def test_env_variables_added_to_pcall(tmpdir, mocksession, newconfig, monkeypatch):
- pkg = tmpdir.ensure("package.tar.gz")
- monkeypatch.setenv("X123", "123")
- monkeypatch.setenv("YY", "456")
- config = newconfig([], """
- [testenv:python]
- commands=python -V
- passenv = x123
- setenv =
- ENV_VAR = value
- """)
- mocksession._clearmocks()
-
- venv = VirtualEnv(config.envconfigs['python'], session=mocksession)
- # import pdb; pdb.set_trace()
- mocksession.installpkg(venv, pkg)
- venv.test()
-
- l = mocksession._pcalls
- assert len(l) == 2
- for x in l:
- env = x.env
- assert env is not None
- assert 'ENV_VAR' in env
- assert env['ENV_VAR'] == 'value'
- assert env['VIRTUAL_ENV'] == str(venv.path)
- assert env['X123'] == "123"
- # all env variables are passed for installation
- assert l[0].env["YY"] == "456"
- assert "YY" not in l[1].env
-
- assert set(["ENV_VAR", "VIRTUAL_ENV", "PYTHONHASHSEED", "X123", "PATH"])\
- .issubset(l[1].env)
-
- # for e in os.environ:
- # assert e in env
-
-
-def test_installpkg_no_upgrade(tmpdir, newmocksession):
- pkg = tmpdir.ensure("package.tar.gz")
- mocksession = newmocksession([], "")
- venv = mocksession.getenv('python')
- venv.just_created = True
- venv.envconfig.envdir.ensure(dir=1)
- mocksession.installpkg(venv, pkg)
- l = mocksession._pcalls
- assert len(l) == 1
- assert '-U' not in l[0].args
-
-
-def test_installpkg_upgrade(newmocksession, tmpdir):
- pkg = tmpdir.ensure("package.tar.gz")
- mocksession = newmocksession([], "")
- venv = mocksession.getenv('python')
- assert not hasattr(venv, 'just_created')
- mocksession.installpkg(venv, pkg)
- l = mocksession._pcalls
- assert len(l) == 1
- index = l[0].args.index(str(pkg))
- assert index >= 0
- assert '-U' in l[0].args[:index]
- assert '--no-deps' in l[0].args[:index]
-
-
-def test_run_install_command(newmocksession):
- mocksession = newmocksession([], "")
- venv = mocksession.getenv('python')
- venv.just_created = True
- venv.envconfig.envdir.ensure(dir=1)
- action = mocksession.newaction(venv, "hello")
- venv.run_install_command(packages=["whatever"], action=action)
- l = mocksession._pcalls
- assert len(l) == 1
- assert 'pip' in l[0].args[0]
- assert 'install' in l[0].args
- env = l[0].env
- assert env is not None
-
-
-def test_run_custom_install_command(newmocksession):
- mocksession = newmocksession([], """
- [testenv]
- install_command=easy_install {opts} {packages}
- """)
- venv = mocksession.getenv('python')
- venv.just_created = True
- venv.envconfig.envdir.ensure(dir=1)
- action = mocksession.newaction(venv, "hello")
- venv.run_install_command(packages=["whatever"], action=action)
- l = mocksession._pcalls
- assert len(l) == 1
- assert 'easy_install' in l[0].args[0]
- assert l[0].args[1:] == ['whatever']
-
-
-def test_command_relative_issue26(newmocksession, tmpdir, monkeypatch):
- mocksession = newmocksession([], """
- [testenv]
- """)
- x = tmpdir.ensure("x")
- venv = mocksession.getenv("python")
- x2 = venv.getcommandpath("./x", cwd=tmpdir)
- assert x == x2
- mocksession.report.not_expect("warning", "*test command found but not*")
- x3 = venv.getcommandpath("/bin/bash", cwd=tmpdir)
- assert x3 == "/bin/bash"
- mocksession.report.not_expect("warning", "*test command found but not*")
- monkeypatch.setenv("PATH", str(tmpdir))
- x4 = venv.getcommandpath("x", cwd=tmpdir)
- assert x4.endswith(os.sep + 'x')
- mocksession.report.expect("warning", "*test command found but not*")
-
-
-def test_ignore_outcome_failing_cmd(newmocksession):
- mocksession = newmocksession([], """
- [testenv]
- commands=testenv_fail
- ignore_outcome=True
- """)
-
- venv = mocksession.getenv('python')
- venv.test()
- assert venv.status == "ignored failed command"
- mocksession.report.expect("warning", "*command failed but result from "
- "testenv is ignored*")
-
-
-def test_tox_testenv_create(newmocksession):
- l = []
-
- class Plugin:
- @hookimpl
- def tox_testenv_create(self, action, venv):
- l.append(1)
-
- @hookimpl
- def tox_testenv_install_deps(self, action, venv):
- l.append(2)
-
- mocksession = newmocksession([], """
- [testenv]
- commands=testenv_fail
- ignore_outcome=True
- """, plugins=[Plugin()])
-
- venv = mocksession.getenv('python')
- venv.update(action=mocksession.newaction(venv, "getenv"))
- assert l == [1, 2]
-
-
-def test_tox_testenv_pre_post(newmocksession):
- l = []
-
- class Plugin:
- @hookimpl
- def tox_runtest_pre(self, venv):
- l.append('started')
-
- @hookimpl
- def tox_runtest_post(self, venv):
- l.append('finished')
-
- mocksession = newmocksession([], """
- [testenv]
- commands=testenv_fail
- """, plugins=[Plugin()])
-
- venv = mocksession.getenv('python')
- venv.status = None
- assert l == []
- mocksession.runtestenv(venv)
- assert l == ['started', 'finished']
diff --git a/tests/test_z_cmdline.py b/tests/test_z_cmdline.py
deleted file mode 100644
index a98d211..0000000
--- a/tests/test_z_cmdline.py
+++ /dev/null
@@ -1,760 +0,0 @@
-import tox
-import py
-import pytest
-from tox._pytestplugin import ReportExpectMock
-try:
- import json
-except ImportError:
- import simplejson as json
-
-pytest_plugins = "pytester"
-
-from tox.session import Session
-from tox.config import parseconfig
-
-
-def test_report_protocol(newconfig):
- config = newconfig([], """
- [testenv:mypython]
- deps=xy
- """)
-
- class Popen:
- def __init__(self, *args, **kwargs):
- pass
-
- def communicate(self):
- return "", ""
-
- def wait(self):
- pass
-
- session = Session(config, popen=Popen,
- Report=ReportExpectMock)
- report = session.report
- report.expect("using")
- venv = session.getvenv("mypython")
- action = session.newaction(venv, "update")
- venv.update(action)
- report.expect("logpopen")
-
-
-def test__resolve_pkg(tmpdir, mocksession):
- distshare = tmpdir.join("distshare")
- spec = distshare.join("pkg123-*")
- py.test.raises(tox.exception.MissingDirectory,
- 'mocksession._resolve_pkg(spec)')
- distshare.ensure(dir=1)
- py.test.raises(tox.exception.MissingDependency,
- 'mocksession._resolve_pkg(spec)')
- distshare.ensure("pkg123-1.3.5.zip")
- p = distshare.ensure("pkg123-1.4.5.zip")
-
- mocksession.report.clear()
- result = mocksession._resolve_pkg(spec)
- assert result == p
- mocksession.report.expect("info", "determin*pkg123*")
- distshare.ensure("pkg123-1.4.7dev.zip")
- mocksession._clearmocks()
- result = mocksession._resolve_pkg(spec)
- mocksession.report.expect("warning", "*1.4.7*")
- assert result == p
- mocksession._clearmocks()
- distshare.ensure("pkg123-1.4.5a1.tar.gz")
- result = mocksession._resolve_pkg(spec)
- assert result == p
-
-
-def test__resolve_pkg_doubledash(tmpdir, mocksession):
- distshare = tmpdir.join("distshare")
- p = distshare.ensure("pkg-mine-1.3.0.zip")
- res = mocksession._resolve_pkg(distshare.join("pkg-mine*"))
- assert res == p
- distshare.ensure("pkg-mine-1.3.0a1.zip")
- res = mocksession._resolve_pkg(distshare.join("pkg-mine*"))
- assert res == p
-
-
-class TestSession:
- def test_make_sdist(self, initproj):
- initproj("example123-0.5", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- '''
- })
- config = parseconfig([])
- session = Session(config)
- sdist = session.get_installpkg_path()
- assert sdist.check()
- assert sdist.ext == ".zip"
- assert sdist == config.distdir.join(sdist.basename)
- sdist2 = session.get_installpkg_path()
- assert sdist2 == sdist
- sdist.write("hello")
- assert sdist.stat().size < 10
- sdist_new = Session(config).get_installpkg_path()
- assert sdist_new == sdist
- assert sdist_new.stat().size > 10
-
- def test_make_sdist_distshare(self, tmpdir, initproj):
- distshare = tmpdir.join("distshare")
- initproj("example123-0.6", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [tox]
- distshare=%s
- ''' % distshare
- })
- config = parseconfig([])
- session = Session(config)
- sdist = session.get_installpkg_path()
- assert sdist.check()
- assert sdist.ext == ".zip"
- assert sdist == config.distdir.join(sdist.basename)
- sdist_share = config.distshare.join(sdist.basename)
- assert sdist_share.check()
- assert sdist_share.read("rb") == sdist.read("rb"), (sdist_share, sdist)
-
- def test_log_pcall(self, mocksession):
- mocksession.config.logdir.ensure(dir=1)
- assert not mocksession.config.logdir.listdir()
- action = mocksession.newaction(None, "something")
- action.popen(["echo", ])
- match = mocksession.report.getnext("logpopen")
- assert match[1].outpath.relto(mocksession.config.logdir)
- assert match[1].shell is False
-
- def test_summary_status(self, initproj, capfd):
- initproj("logexample123-0.5", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [testenv:hello]
- [testenv:world]
- '''
- })
- config = parseconfig([])
- session = Session(config)
- envs = session.venvlist
- assert len(envs) == 2
- env1, env2 = envs
- env1.status = "FAIL XYZ"
- assert env1.status
- env2.status = 0
- assert not env2.status
- session._summary()
- out, err = capfd.readouterr()
- exp = "%s: FAIL XYZ" % env1.envconfig.envname
- assert exp in out
- exp = "%s: commands succeeded" % env2.envconfig.envname
- assert exp in out
-
- def test_getvenv(self, initproj, capfd):
- initproj("logexample123-0.5", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [testenv:hello]
- [testenv:world]
- '''
- })
- config = parseconfig([])
- session = Session(config)
- venv1 = session.getvenv("hello")
- venv2 = session.getvenv("hello")
- assert venv1 is venv2
- venv1 = session.getvenv("world")
- venv2 = session.getvenv("world")
- assert venv1 is venv2
- pytest.raises(LookupError, lambda: session.getvenv("qwe"))
-
-
-# not sure we want this option ATM
-def XXX_test_package(cmd, initproj):
- initproj("myproj-0.6", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'MANIFEST.in': """
- include doc
- include myproj
- """,
- 'tox.ini': ''
- })
- result = cmd.run("tox", "package")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*created sdist package at*",
- ])
-
-
-def test_minversion(cmd, initproj):
- initproj("interp123-0.5", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [tox]
- minversion = 6.0
- '''
- })
- result = cmd.run("tox", "-v")
- result.stdout.fnmatch_lines([
- "*ERROR*tox version is * required is at least 6.0*"
- ])
- assert result.ret
-
-
-def test_run_custom_install_command_error(cmd, initproj):
- initproj("interp123-0.5", filedefs={
- 'tox.ini': '''
- [testenv]
- install_command=./tox.ini {opts} {packages}
- '''
- })
- result = cmd.run("tox")
- result.stdout.fnmatch_lines([
- "ERROR: invocation failed (errno *), args: ['*/tox.ini*",
- ])
- assert result.ret
-
-
-def test_unknown_interpreter_and_env(cmd, initproj):
- initproj("interp123-0.5", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [testenv:python]
- basepython=xyz_unknown_interpreter
- [testenv]
- changedir=tests
- '''
- })
- result = cmd.run("tox")
- assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*InterpreterNotFound*xyz_unknown_interpreter*",
- ])
-
- result = cmd.run("tox", "-exyz")
- assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*unknown*",
- ])
-
-
-def test_unknown_interpreter(cmd, initproj):
- initproj("interp123-0.5", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [testenv:python]
- basepython=xyz_unknown_interpreter
- [testenv]
- changedir=tests
- '''
- })
- result = cmd.run("tox")
- assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*InterpreterNotFound*xyz_unknown_interpreter*",
- ])
-
-
-def test_skip_platform_mismatch(cmd, initproj):
- initproj("interp123-0.5", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [testenv]
- changedir=tests
- platform=x123
- '''
- })
- result = cmd.run("tox")
- assert not result.ret
- result.stdout.fnmatch_lines("""
- SKIPPED*platform mismatch*
- """)
-
-
-def test_skip_unknown_interpreter(cmd, initproj):
- initproj("interp123-0.5", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [testenv:python]
- basepython=xyz_unknown_interpreter
- [testenv]
- changedir=tests
- '''
- })
- result = cmd.run("tox", "--skip-missing-interpreters")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*SKIPPED*InterpreterNotFound*xyz_unknown_interpreter*",
- ])
-
-
-def test_unknown_dep(cmd, initproj):
- initproj("dep123-0.7", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [testenv]
- deps=qweqwe123
- changedir=tests
- '''
- })
- result = cmd.run("tox", )
- assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*could not install*qweqwe123*",
- ])
-
-
-def test_venv_special_chars_issue252(cmd, initproj):
- initproj("pkg123-0.7", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'tox.ini': '''
- [tox]
- envlist = special&&1
- [testenv:special&&1]
- changedir=tests
- '''
- })
- result = cmd.run("tox", )
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*installed*pkg123*"
- ])
-
-
-def test_unknown_environment(cmd, initproj):
- initproj("env123-0.7", filedefs={
- 'tox.ini': ''
- })
- result = cmd.run("tox", "-e", "qpwoei")
- assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*unknown*environment*qpwoei*",
- ])
-
-
-def test_skip_sdist(cmd, initproj):
- initproj("pkg123-0.7", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'setup.py': """
- syntax error
- """,
- 'tox.ini': '''
- [tox]
- skipsdist=True
- [testenv]
- commands=python -c "print('done')"
- '''
- })
- result = cmd.run("tox", )
- assert result.ret == 0
-
-
-def test_minimal_setup_py_empty(cmd, initproj):
- initproj("pkg123-0.7", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'setup.py': """
- """,
- 'tox.ini': ''
-
- })
- result = cmd.run("tox", )
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*ERROR*empty*",
- ])
-
-
-def test_minimal_setup_py_comment_only(cmd, initproj):
- initproj("pkg123-0.7", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'setup.py': """\n# some comment
-
- """,
- 'tox.ini': ''
-
- })
- result = cmd.run("tox", )
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*ERROR*empty*",
- ])
-
-
-def test_minimal_setup_py_non_functional(cmd, initproj):
- initproj("pkg123-0.7", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'setup.py': """
- import sys
-
- """,
- 'tox.ini': ''
-
- })
- result = cmd.run("tox", )
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*ERROR*check setup.py*",
- ])
-
-
-def test_sdist_fails(cmd, initproj):
- initproj("pkg123-0.7", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'setup.py': """
- syntax error
- """,
- 'tox.ini': '',
- })
- result = cmd.run("tox", )
- assert result.ret
- result.stdout.fnmatch_lines([
- "*FAIL*could not package project*",
- ])
-
-
-def test_package_install_fails(cmd, initproj):
- initproj("pkg123-0.7", filedefs={
- 'tests': {'test_hello.py': "def test_hello(): pass"},
- 'setup.py': """
- from setuptools import setup
- setup(
- name='pkg123',
- description='pkg123 project',
- version='0.7',
- license='MIT',
- platforms=['unix', 'win32'],
- packages=['pkg123',],
- install_requires=['qweqwe123'],
- )
- """,
- 'tox.ini': '',
- })
- result = cmd.run("tox", )
- assert result.ret
- result.stdout.fnmatch_lines([
- "*InvocationError*",
- ])
-
-
-class TestToxRun:
- @pytest.fixture
- def example123(self, initproj):
- initproj("example123-0.5", filedefs={
- 'tests': {
- 'test_hello.py': """
- def test_hello(pytestconfig):
- pass
- """,
- },
- 'tox.ini': '''
- [testenv]
- changedir=tests
- commands= py.test --basetemp={envtmpdir} \
- --junitxml=junit-{envname}.xml
- deps=pytest
- '''
- })
-
- def test_toxuone_env(self, cmd, example123):
- result = cmd.run("tox")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*junit-python.xml*",
- "*1 passed*",
- ])
- result = cmd.run("tox", "-epython", )
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*summary*",
- "*python: commands succeeded"
- ])
-
- def test_different_config_cwd(self, cmd, example123, monkeypatch):
- # see that things work with a different CWD
- monkeypatch.chdir(cmd.tmpdir)
- result = cmd.run("tox", "-c", "example123/tox.ini")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*summary*",
- "*python: commands succeeded"
- ])
-
- def test_json(self, cmd, example123):
- # see that tests can also fail and retcode is correct
- testfile = py.path.local("tests").join("test_hello.py")
- assert testfile.check()
- testfile.write("def test_fail(): assert 0")
- jsonpath = cmd.tmpdir.join("res.json")
- result = cmd.run("tox", "--result-json", jsonpath)
- assert result.ret == 1
- data = json.load(jsonpath.open("r"))
- verify_json_report_format(data)
- result.stdout.fnmatch_lines([
- "*1 failed*",
- "*summary*",
- "*python: *failed*",
- ])
-
-
-def test_develop(initproj, cmd):
- initproj("example123", filedefs={'tox.ini': """
- """})
- result = cmd.run("tox", "-vv", "--develop")
- assert not result.ret
- assert "sdist-make" not in result.stdout.str()
-
-
-def test_usedevelop(initproj, cmd):
- initproj("example123", filedefs={'tox.ini': """
- [testenv]
- usedevelop=True
- """})
- result = cmd.run("tox", "-vv")
- assert not result.ret
- assert "sdist-make" not in result.stdout.str()
-
-
-def test_usedevelop_mixed(initproj, cmd):
- initproj("example123", filedefs={'tox.ini': """
- [testenv:devenv]
- usedevelop=True
- [testenv:nondev]
- usedevelop=False
- """})
-
- # running only 'devenv' should not do sdist
- result = cmd.run("tox", "-vv", "-e", "devenv")
- assert not result.ret
- assert "sdist-make" not in result.stdout.str()
-
- # running all envs should do sdist
- result = cmd.run("tox", "-vv")
- assert not result.ret
- assert "sdist-make" in result.stdout.str()
-
-
-def test_test_usedevelop(cmd, initproj):
- initproj("example123-0.5", filedefs={
- 'tests': {
- 'test_hello.py': """
- def test_hello(pytestconfig):
- pass
- """,
- },
- 'tox.ini': '''
- [testenv]
- usedevelop=True
- changedir=tests
- commands=
- py.test --basetemp={envtmpdir} --junitxml=junit-{envname}.xml []
- deps=pytest
- '''
- })
- result = cmd.run("tox", "-v")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*junit-python.xml*",
- "*1 passed*",
- ])
- assert "sdist-make" not in result.stdout.str()
- result = cmd.run("tox", "-epython", )
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*summary*",
- "*python: commands succeeded"
- ])
- # see that things work with a different CWD
- old = cmd.tmpdir.chdir()
- result = cmd.run("tox", "-c", "example123/tox.ini")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*summary*",
- "*python: commands succeeded"
- ])
- old.chdir()
- # see that tests can also fail and retcode is correct
- testfile = py.path.local("tests").join("test_hello.py")
- assert testfile.check()
- testfile.write("def test_fail(): assert 0")
- result = cmd.run("tox", )
- assert result.ret
- result.stdout.fnmatch_lines([
- "*1 failed*",
- "*summary*",
- "*python: *failed*",
- ])
-
-
-def test_test_piphelp(initproj, cmd):
- initproj("example123", filedefs={'tox.ini': """
- # content of: tox.ini
- [testenv]
- commands=pip -h
- [testenv:py26]
- basepython=python
- [testenv:py27]
- basepython=python
- """})
- result = cmd.run("tox")
- assert not result.ret
-
-
-def test_notest(initproj, cmd):
- initproj("example123", filedefs={'tox.ini': """
- # content of: tox.ini
- [testenv:py26]
- basepython=python
- """})
- result = cmd.run("tox", "-v", "--notest")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*summary*",
- "*py26*skipped tests*",
- ])
- result = cmd.run("tox", "-v", "--notest", "-epy26")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*py26*reusing*",
- ])
-
-
-def test_PYC(initproj, cmd, monkeypatch):
- initproj("example123", filedefs={'tox.ini': ''})
- monkeypatch.setenv("PYTHONDOWNWRITEBYTECODE", 1)
- result = cmd.run("tox", "-v", "--notest")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*create*",
- ])
-
-
-def test_env_VIRTUALENV_PYTHON(initproj, cmd, monkeypatch):
- initproj("example123", filedefs={'tox.ini': ''})
- monkeypatch.setenv("VIRTUALENV_PYTHON", '/FOO')
- result = cmd.run("tox", "-v", "--notest")
- assert not result.ret, result.stdout.lines
- result.stdout.fnmatch_lines([
- "*create*",
- ])
-
-
-def test_sdistonly(initproj, cmd):
- initproj("example123", filedefs={'tox.ini': """
- """})
- result = cmd.run("tox", "-v", "--sdistonly")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*sdist-make*setup.py*",
- ])
- assert "-mvirtualenv" not in result.stdout.str()
-
-
-def test_separate_sdist_no_sdistfile(cmd, initproj):
- distshare = cmd.tmpdir.join("distshare")
- initproj(("pkg123-foo", "0.7"), filedefs={
- 'tox.ini': """
- [tox]
- distshare=%s
- """ % distshare
- })
- result = cmd.run("tox", "--sdistonly")
- assert not result.ret
- l = distshare.listdir()
- assert len(l) == 1
- sdistfile = l[0]
- assert 'pkg123-foo-0.7.zip' in str(sdistfile)
-
-
-def test_separate_sdist(cmd, initproj):
- distshare = cmd.tmpdir.join("distshare")
- initproj("pkg123-0.7", filedefs={
- 'tox.ini': """
- [tox]
- distshare=%s
- sdistsrc={distshare}/pkg123-0.7.zip
- """ % distshare
- })
- result = cmd.run("tox", "--sdistonly")
- assert not result.ret
- l = distshare.listdir()
- assert len(l) == 1
- sdistfile = l[0]
- result = cmd.run("tox", "-v", "--notest")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*inst*%s*" % sdistfile,
- ])
-
-
-def test_sdist_latest(tmpdir, newconfig):
- distshare = tmpdir.join("distshare")
- config = newconfig([], """
- [tox]
- distshare=%s
- sdistsrc={distshare}/pkg123-*
- """ % distshare)
- p = distshare.ensure("pkg123-1.4.5.zip")
- distshare.ensure("pkg123-1.4.5a1.zip")
- session = Session(config)
- sdist_path = session.get_installpkg_path()
- assert sdist_path == p
-
-
-def test_installpkg(tmpdir, newconfig):
- p = tmpdir.ensure("pkg123-1.0.zip")
- config = newconfig(["--installpkg=%s" % p], "")
- session = Session(config)
- sdist_path = session.get_installpkg_path()
- assert sdist_path == p
-
-
-@pytest.mark.xfail("sys.platform == 'win32'", reason="test needs better impl")
-def test_envsitepackagesdir(cmd, initproj):
- initproj("pkg512-0.0.5", filedefs={
- 'tox.ini': """
- [testenv]
- commands=
- python -c "print(r'X:{envsitepackagesdir}')"
- """})
- result = cmd.run("tox")
- assert result.ret == 0
- result.stdout.fnmatch_lines("""
- X:*tox*site-packages*
- """)
-
-
-@pytest.mark.xfail("sys.platform == 'win32'", reason="test needs better impl")
-def test_envsitepackagesdir_skip_missing_issue280(cmd, initproj):
- initproj("pkg513-0.0.5", filedefs={
- 'tox.ini': """
- [testenv]
- basepython=/usr/bin/qwelkjqwle
- commands=
- {envsitepackagesdir}
- """})
- result = cmd.run("tox", "--skip-missing-interpreters")
- assert result.ret == 0
- result.stdout.fnmatch_lines("""
- SKIPPED:*qwelkj*
- """)
-
-
-def verify_json_report_format(data, testenvs=True):
- assert data["reportversion"] == "1"
- assert data["toxversion"] == tox.__version__
- if testenvs:
- for envname, envdata in data["testenvs"].items():
- for commandtype in ("setup", "test"):
- if commandtype not in envdata:
- continue
- for command in envdata[commandtype]:
- assert command["output"]
- assert command["retcode"]
- if envname != "GLOB":
- assert isinstance(envdata["installed_packages"], list)
- pyinfo = envdata["python"]
- assert isinstance(pyinfo["version_info"], list)
- assert pyinfo["version"]
- assert pyinfo["executable"]
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index a2bbd96..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,63 +0,0 @@
-[tox]
-envlist=py27,py26,py34,py33,py35,pypy,flakes,py26-bare
-
-[testenv:X]
-commands=echo {posargs}
-
-[testenv]
-commands= py.test --timeout=180 {posargs:tests}
-
-deps=pytest>=2.3.5
- pytest-timeout
-
-[testenv:py26-bare]
-deps =
-commands = tox -h
-install_command = pip install {opts} {packages}
-list_dependencies_command = pip freeze
-
-[testenv:py26]
-install_command = pip install {opts} {packages}
-list_dependencies_command = pip freeze
-
-
-[testenv:docs]
-basepython=python
-changedir=doc
-deps=sphinx
- {[testenv]deps}
-commands=
- py.test -v check_sphinx.py {posargs}
-
-[testenv:flakes]
-platform=linux
-deps = pytest-flakes>=0.2
- pytest-pep8
-
-commands =
- py.test --flakes -m flakes tox tests
- py.test --pep8 -m pep8 tox tests
-
-[testenv:dev]
-# required to make looponfail reload on every source code change
-usedevelop = True
-
-deps =
- pytest-xdist>=1.11
-commands = {posargs:py.test -s -x -f -v}
-
-[pytest]
-rsyncdirs = tests tox
-addopts = -rsxX
-# pytest-xdist plugin configuration
-looponfailroots = tox tests
-norecursedirs = .hg .tox
-
-# pytest-pep8 plugin configuration
-pep8maxlinelength = 99
-# W503 - line break before binary operator
-# E402 - module level import not at top of file
-# E731 - do not assign a lambda expression, use a def
-pep8ignore =
- *.py W503 E402 E731
-flakes-ignore = ImportStarUsage
diff --git a/tox/__init__.py b/tox/__init__.py
deleted file mode 100644
index baf651b..0000000
--- a/tox/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-__version__ = '2.4.0.dev1'
-
-from .hookspecs import hookspec, hookimpl # noqa
-
-
-class exception:
- class Error(Exception):
- def __str__(self):
- return "%s: %s" % (self.__class__.__name__, self.args[0])
-
- class ConfigError(Error):
- """ error in tox configuration. """
- class UnsupportedInterpreter(Error):
- "signals an unsupported Interpreter"
- class InterpreterNotFound(Error):
- "signals that an interpreter could not be found"
- class InvocationError(Error):
- """ an error while invoking a script. """
- class MissingFile(Error):
- """ an error while invoking a script. """
- class MissingDirectory(Error):
- """ a directory did not exist. """
- class MissingDependency(Error):
- """ a dependency could not be found or determined. """
- class MinVersionError(Error):
- """ the installed tox version is lower than requested minversion. """
-
- def __init__(self, message):
- self.message = message
- super(exception.MinVersionError, self).__init__(message)
-
-from tox.session import main as cmdline # noqa
diff --git a/tox/__main__.py b/tox/__main__.py
deleted file mode 100644
index e28d746..0000000
--- a/tox/__main__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from tox.session import main
-
-if __name__ == "__main__":
- main()
diff --git a/tox/_pytestplugin.py b/tox/_pytestplugin.py
deleted file mode 100644
index 785070d..0000000
--- a/tox/_pytestplugin.py
+++ /dev/null
@@ -1,333 +0,0 @@
-import py
-import pytest
-import tox
-import os
-import sys
-from py.builtin import _isbytes, _istext, print_
-from fnmatch import fnmatch
-import time
-from .config import parseconfig
-from .venv import VirtualEnv
-from .session import Action
-from .result import ResultLog
-
-
-def pytest_configure():
- if 'TOXENV' in os.environ:
- del os.environ['TOXENV']
- if 'HUDSON_URL' in os.environ:
- del os.environ['HUDSON_URL']
-
-
-def pytest_addoption(parser):
- parser.addoption("--no-network", action="store_true",
- dest="no_network",
- help="don't run tests requiring network")
-
-
-def pytest_report_header():
- return "tox comes from: %r" % (tox.__file__)
-
-
-@pytest.fixture
-def newconfig(request, tmpdir):
- def newconfig(args, source=None, plugins=()):
- if source is None:
- source = args
- args = []
- s = py.std.textwrap.dedent(source)
- p = tmpdir.join("tox.ini")
- p.write(s)
- old = tmpdir.chdir()
- try:
- return parseconfig(args, plugins=plugins)
- finally:
- old.chdir()
- return newconfig
-
-
-@pytest.fixture
-def cmd(request):
- if request.config.option.no_network:
- pytest.skip("--no-network was specified, test cannot run")
- return Cmd(request)
-
-
-class ReportExpectMock:
- def __init__(self, session):
- self._calls = []
- self._index = -1
- self.session = session
-
- def clear(self):
- self._calls[:] = []
-
- def __getattr__(self, name):
- if name[0] == "_":
- raise AttributeError(name)
-
- def generic_report(*args, **kwargs):
- self._calls.append((name,) + args)
- print("%s" % (self._calls[-1], ))
- return generic_report
-
- def action(self, venv, msg, *args):
- self._calls.append(("action", venv, msg))
- print("%s" % (self._calls[-1], ))
- return Action(self.session, venv, msg, args)
-
- def getnext(self, cat):
- __tracebackhide__ = True
- newindex = self._index + 1
- while newindex < len(self._calls):
- call = self._calls[newindex]
- lcat = call[0]
- if fnmatch(lcat, cat):
- self._index = newindex
- return call
- newindex += 1
- raise LookupError(
- "looking for %r, no reports found at >=%d in %r" %
- (cat, self._index + 1, self._calls))
-
- def expect(self, cat, messagepattern="*", invert=False):
- __tracebackhide__ = True
- if not messagepattern.startswith("*"):
- messagepattern = "*" + messagepattern
- while self._index < len(self._calls):
- try:
- call = self.getnext(cat)
- except LookupError:
- break
- for lmsg in call[1:]:
- lmsg = str(lmsg).replace("\n", " ")
- if fnmatch(lmsg, messagepattern):
- if invert:
- raise AssertionError("found %s(%r), didn't expect it" %
- (cat, messagepattern))
- return
- if not invert:
- raise AssertionError(
- "looking for %s(%r), no reports found at >=%d in %r" %
- (cat, messagepattern, self._index + 1, self._calls))
-
- def not_expect(self, cat, messagepattern="*"):
- return self.expect(cat, messagepattern, invert=True)
-
-
-class pcallMock:
- def __init__(self, args, cwd, env, stdout, stderr, shell):
- self.arg0 = args[0]
- self.args = args[1:]
- self.cwd = cwd
- self.env = env
- self.stdout = stdout
- self.stderr = stderr
- self.shell = shell
-
- def communicate(self):
- return "", ""
-
- def wait(self):
- pass
-
-
-@pytest.fixture
-def mocksession(request):
- from tox.session import Session
-
- class MockSession(Session):
- def __init__(self):
- self._clearmocks()
- self.config = request.getfuncargvalue("newconfig")([], "")
- self.resultlog = ResultLog()
- self._actions = []
-
- def getenv(self, name):
- return VirtualEnv(self.config.envconfigs[name], session=self)
-
- def _clearmocks(self):
- self._pcalls = []
- self._spec2pkg = {}
- self.report = ReportExpectMock(self)
-
- def make_emptydir(self, path):
- pass
-
- def popen(self, args, cwd, shell=None,
- universal_newlines=False,
- stdout=None, stderr=None, env=None):
- pm = pcallMock(args, cwd, env, stdout, stderr, shell)
- self._pcalls.append(pm)
- return pm
- return MockSession()
-
-
-@pytest.fixture
-def newmocksession(request):
- mocksession = request.getfuncargvalue("mocksession")
- newconfig = request.getfuncargvalue("newconfig")
-
- def newmocksession(args, source, plugins=()):
- mocksession.config = newconfig(args, source, plugins=plugins)
- return mocksession
- return newmocksession
-
-
-class Cmd:
- def __init__(self, request):
- self.tmpdir = request.getfuncargvalue("tmpdir")
- self.request = request
- current = py.path.local()
- self.request.addfinalizer(current.chdir)
-
- def chdir(self, target):
- target.chdir()
-
- def popen(self, argv, stdout, stderr, **kw):
- if not hasattr(py.std, 'subprocess'):
- py.test.skip("no subprocess module")
- env = os.environ.copy()
- env['PYTHONPATH'] = ":".join(filter(None, [
- str(os.getcwd()), env.get('PYTHONPATH', '')]))
- kw['env'] = env
- # print "env", env
- return py.std.subprocess.Popen(argv, stdout=stdout, stderr=stderr, **kw)
-
- def run(self, *argv):
- if argv[0] == "tox" and sys.version_info[:2] < (2, 7):
- pytest.skip("can not run tests involving calling tox on python2.6. "
- "(and python2.6 is about to be deprecated anyway)")
- argv = [str(x) for x in argv]
- assert py.path.local.sysfind(str(argv[0])), argv[0]
- p1 = self.tmpdir.join("stdout")
- p2 = self.tmpdir.join("stderr")
- print("%s$ %s" % (os.getcwd(), " ".join(argv)))
- f1 = p1.open("wb")
- f2 = p2.open("wb")
- now = time.time()
- popen = self.popen(argv, stdout=f1, stderr=f2,
- close_fds=(sys.platform != "win32"))
- ret = popen.wait()
- f1.close()
- f2.close()
- out = p1.read("rb")
- out = getdecoded(out).splitlines()
- err = p2.read("rb")
- err = getdecoded(err).splitlines()
-
- def dump_lines(lines, fp):
- try:
- for line in lines:
- py.builtin.print_(line, file=fp)
- except UnicodeEncodeError:
- print("couldn't print to %s because of encoding" % (fp,))
- dump_lines(out, sys.stdout)
- dump_lines(err, sys.stderr)
- return RunResult(ret, out, err, time.time() - now)
-
-
-def getdecoded(out):
- try:
- return out.decode("utf-8")
- except UnicodeDecodeError:
- return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
- py.io.saferepr(out),)
-
-
-class RunResult:
- def __init__(self, ret, outlines, errlines, duration):
- self.ret = ret
- self.outlines = outlines
- self.errlines = errlines
- self.stdout = LineMatcher(outlines)
- self.stderr = LineMatcher(errlines)
- self.duration = duration
-
-
-class LineMatcher:
- def __init__(self, lines):
- self.lines = lines
-
- def str(self):
- return "\n".join(self.lines)
-
- def fnmatch_lines(self, lines2):
- if isinstance(lines2, str):
- lines2 = py.code.Source(lines2)
- if isinstance(lines2, py.code.Source):
- lines2 = lines2.strip().lines
-
- from fnmatch import fnmatch
- lines1 = self.lines[:]
- nextline = None
- extralines = []
- __tracebackhide__ = True
- for line in lines2:
- nomatchprinted = False
- while lines1:
- nextline = lines1.pop(0)
- if line == nextline:
- print_("exact match:", repr(line))
- break
- elif fnmatch(nextline, line):
- print_("fnmatch:", repr(line))
- print_(" with:", repr(nextline))
- break
- else:
- if not nomatchprinted:
- print_("nomatch:", repr(line))
- nomatchprinted = True
- print_(" and:", repr(nextline))
- extralines.append(nextline)
- else:
- assert line == nextline
-
-
-@pytest.fixture
-def initproj(request, tmpdir):
- """ create a factory function for creating example projects. """
- def initproj(nameversion, filedefs=None):
- if filedefs is None:
- filedefs = {}
- if _istext(nameversion) or _isbytes(nameversion):
- parts = nameversion.split("-")
- if len(parts) == 1:
- parts.append("0.1")
- name, version = parts
- else:
- name, version = nameversion
- base = tmpdir.ensure(name, dir=1)
- create_files(base, filedefs)
- if 'setup.py' not in filedefs:
- create_files(base, {'setup.py': '''
- from setuptools import setup
- setup(
- name='%(name)s',
- description='%(name)s project',
- version='%(version)s',
- license='MIT',
- platforms=['unix', 'win32'],
- packages=['%(name)s', ],
- )
- ''' % locals()})
- if name not in filedefs:
- create_files(base, {
- name: {'__init__.py': '__version__ = %r' % version}
- })
- manifestlines = []
- for p in base.visit(lambda x: x.check(file=1)):
- manifestlines.append("include %s" % p.relto(base))
- create_files(base, {"MANIFEST.in": "\n".join(manifestlines)})
- print("created project in %s" % (base,))
- base.chdir()
- return initproj
-
-
-def create_files(base, filedefs):
- for key, value in filedefs.items():
- if isinstance(value, dict):
- create_files(base.ensure(key, dir=1), value)
- elif isinstance(value, str):
- s = py.std.textwrap.dedent(value)
- base.join(key).write(s)
diff --git a/tox/_quickstart.py b/tox/_quickstart.py
deleted file mode 100644
index 59ee48e..0000000
--- a/tox/_quickstart.py
+++ /dev/null
@@ -1,275 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- tox._quickstart
- ~~~~~~~~~~~~~~~~~
-
- Command-line script to quickly setup tox.ini for a Python project
-
- This file was heavily inspired by and uses code from ``sphinx-quickstart``
- in the BSD-licensed `Sphinx project`_.
-
- .. Sphinx project_: http://sphinx.pocoo.org/
-
- License for Sphinx
- ==================
-
- Copyright (c) 2007-2011 by the Sphinx team (see AUTHORS file).
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""
-
-import sys
-from os import path
-from codecs import open
-
-TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
-
-from tox import __version__
-
-# function to get input from terminal -- overridden by the test suite
-try:
- # this raw_input is not converted by 2to3
- term_input = raw_input
-except NameError:
- term_input = input
-
-
-all_envs = ['py26', 'py27', 'py32', 'py33', 'py34', 'py35', 'pypy', 'jython']
-
-PROMPT_PREFIX = '> '
-
-QUICKSTART_CONF = '''\
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions. To use it, "pip install tox"
-# and then run "tox" from this directory.
-
-[tox]
-envlist = %(envlist)s
-
-[testenv]
-commands = %(commands)s
-deps = %(deps)s
-'''
-
-
-class ValidationError(Exception):
- """Raised for validation errors."""
-
-
-def nonempty(x):
- if not x:
- raise ValidationError("Please enter some text.")
- return x
-
-
-def choice(*l):
- def val(x):
- if x not in l:
- raise ValidationError('Please enter one of %s.' % ', '.join(l))
- return x
- return val
-
-
-def boolean(x):
- if x.upper() not in ('Y', 'YES', 'N', 'NO'):
- raise ValidationError("Please enter either 'y' or 'n'.")
- return x.upper() in ('Y', 'YES')
-
-
-def suffix(x):
- if not (x[0:1] == '.' and len(x) > 1):
- raise ValidationError("Please enter a file suffix, "
- "e.g. '.rst' or '.txt'.")
- return x
-
-
-def ok(x):
- return x
-
-
-def do_prompt(d, key, text, default=None, validator=nonempty):
- while True:
- if default:
- prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default)
- else:
- prompt = PROMPT_PREFIX + text + ': '
- x = term_input(prompt)
- if default and not x:
- x = default
- if sys.version_info < (3, ) and not isinstance(x, unicode): # noqa
- # for Python 2.x, try to get a Unicode string out of it
- if x.decode('ascii', 'replace').encode('ascii', 'replace') != x:
- if TERM_ENCODING:
- x = x.decode(TERM_ENCODING)
- else:
- print('* Note: non-ASCII characters entered '
- 'and terminal encoding unknown -- assuming '
- 'UTF-8 or Latin-1.')
- try:
- x = x.decode('utf-8')
- except UnicodeDecodeError:
- x = x.decode('latin1')
- try:
- x = validator(x)
- except ValidationError:
- err = sys.exc_info()[1]
- print('* ' + str(err))
- continue
- break
- d[key] = x
-
-
-def ask_user(d):
- """Ask the user for quickstart values missing from *d*.
-
- """
-
- print('Welcome to the Tox %s quickstart utility.' % __version__)
- print('''
-This utility will ask you a few questions and then generate a simple tox.ini
-file to help get you started using tox.
-
-Please enter values for the following settings (just press Enter to
-accept a default value, if one is given in brackets).''')
-
- sys.stdout.write('\n')
-
- print('''
-What Python versions do you want to test against? Choices:
- [1] py27
- [2] py27, py33
- [3] (All versions) %s
- [4] Choose each one-by-one''' % ', '.join(all_envs))
- do_prompt(d, 'canned_pyenvs', 'Enter the number of your choice',
- '3', choice('1', '2', '3', '4'))
-
- if d['canned_pyenvs'] == '1':
- d['py27'] = True
- elif d['canned_pyenvs'] == '2':
- for pyenv in ('py27', 'py33'):
- d[pyenv] = True
- elif d['canned_pyenvs'] == '3':
- for pyenv in all_envs:
- d[pyenv] = True
- elif d['canned_pyenvs'] == '4':
- for pyenv in all_envs:
- if pyenv not in d:
- do_prompt(d, pyenv, 'Test your project with %s (Y/n)' % pyenv, 'Y', boolean)
-
- print('''
-What command should be used to test your project -- examples:
- - py.test
- - python setup.py test
- - nosetests package.module
- - trial package.module''')
- do_prompt(d, 'commands', 'Command to run to test project', '{envpython} setup.py test')
-
- default_deps = ' '
- if 'py.test' in d['commands']:
- default_deps = 'pytest'
- if 'nosetests' in d['commands']:
- default_deps = 'nose'
- if 'trial' in d['commands']:
- default_deps = 'twisted'
-
- print('''
-What extra dependencies do your tests have?''')
- do_prompt(d, 'deps', 'Comma-separated list of dependencies', default_deps)
-
-
-def process_input(d):
- d['envlist'] = ', '.join([env for env in all_envs if d.get(env) is True])
- d['deps'] = '\n' + '\n'.join([
- ' %s' % dep.strip()
- for dep in d['deps'].split(',')])
-
- return d
-
-
-def rtrim_right(text):
- lines = []
- for line in text.split("\n"):
- lines.append(line.rstrip())
- return "\n".join(lines)
-
-
-def generate(d, overwrite=True, silent=False):
- """Generate project based on values in *d*."""
-
- conf_text = QUICKSTART_CONF % d
- conf_text = rtrim_right(conf_text)
-
- def write_file(fpath, mode, content):
- print('Creating file %s.' % fpath)
- f = open(fpath, mode, encoding='utf-8')
- try:
- f.write(content)
- finally:
- f.close()
-
- sys.stdout.write('\n')
-
- fpath = 'tox.ini'
-
- if path.isfile(fpath) and not overwrite:
- print('File %s already exists.' % fpath)
- do_prompt(d, 'fpath', 'Alternative path to write tox.ini contents to', 'tox-generated.ini')
- fpath = d['fpath']
-
- write_file(fpath, 'w', conf_text)
-
- if silent:
- return
- sys.stdout.write('\n')
- print('Finished: A tox.ini file has been created. For information on this file, '
- 'see http://tox.testrun.org/latest/config.html')
- print('''
-Execute `tox` to test your project.
-''')
-
-
-def main(argv=sys.argv):
- d = {}
-
- if len(argv) > 3:
- print('Usage: tox-quickstart [root]')
- sys.exit(1)
- elif len(argv) == 2:
- d['path'] = argv[1]
-
- try:
- ask_user(d)
- except (KeyboardInterrupt, EOFError):
- print()
- print('[Interrupted.]')
- return
-
- d = process_input(d)
- generate(d, overwrite=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/tox/_verlib.py b/tox/_verlib.py
deleted file mode 100644
index a2e7471..0000000
--- a/tox/_verlib.py
+++ /dev/null
@@ -1,335 +0,0 @@
-"""
-
-PEP386-version comparison algorithm.
-
-(c) Tarek Ziade and others
-extracted unmodified from https://bitbucket.org/tarek/distutilsversion
-licensed under the PSF license (i guess)
-
-"""
-
-import re
-
-
-class IrrationalVersionError(Exception):
- """This is an irrational version."""
- pass
-
-
-class HugeMajorVersionNumError(IrrationalVersionError):
- """An irrational version because the major version number is huge
- (often because a year or date was used).
-
- See `error_on_huge_major_num` option in `NormalizedVersion` for details.
- This guard can be disabled by setting that option False.
- """
- pass
-
-# A marker used in the second and third parts of the `parts` tuple, for
-# versions that don't have those segments, to sort properly. An example
-# of versions in sort order ('highest' last):
-# 1.0b1 ((1,0), ('b',1), ('f',))
-# 1.0.dev345 ((1,0), ('f',), ('dev', 345))
-# 1.0 ((1,0), ('f',), ('f',))
-# 1.0.post256.dev345 ((1,0), ('f',), ('f', 'post', 256, 'dev', 345))
-# 1.0.post345 ((1,0), ('f',), ('f', 'post', 345, 'f'))
-# ^ ^ ^
-# 'b' < 'f' ---------------------/ | |
-# | |
-# 'dev' < 'f' < 'post' -------------------/ |
-# |
-# 'dev' < 'f' ----------------------------------------------/
-# Other letters would do, but 'f' for 'final' is kind of nice.
-FINAL_MARKER = ('f',)
-
-VERSION_RE = re.compile(r'''
- ^
- (?P<version>\d+\.\d+) # minimum 'N.N'
- (?P<extraversion>(?:\.\d+)*) # any number of extra '.N' segments
- (?:
- (?P<prerel>[abc]|rc) # 'a'=alpha, 'b'=beta, 'c'=release candidate
- # 'rc'= alias for release candidate
- (?P<prerelversion>\d+(?:\.\d+)*)
- )?
- (?P<postdev>(\.post(?P<post>\d+))?(\.dev(?P<dev>\d+))?)?
- $''', re.VERBOSE)
-
-
-class NormalizedVersion(object):
- """A rational version.
-
- Good:
- 1.2 # equivalent to "1.2.0"
- 1.2.0
- 1.2a1
- 1.2.3a2
- 1.2.3b1
- 1.2.3c1
- 1.2.3.4
- TODO: fill this out
-
- Bad:
- 1 # mininum two numbers
- 1.2a # release level must have a release serial
- 1.2.3b
- """
- def __init__(self, s, error_on_huge_major_num=True):
- """Create a NormalizedVersion instance from a version string.
-
- @param s {str} The version string.
- @param error_on_huge_major_num {bool} Whether to consider an
- apparent use of a year or full date as the major version number
- an error. Default True. One of the observed patterns on PyPI before
- the introduction of `NormalizedVersion` was version numbers like this:
- 2009.01.03
- 20040603
- 2005.01
- This guard is here to strongly encourage the package author to
- use an alternate version, because a release deployed into PyPI
- and, e.g. downstream Linux package managers, will forever remove
- the possibility of using a version number like "1.0" (i.e.
- where the major number is less than that huge major number).
- """
- self._parse(s, error_on_huge_major_num)
-
- @classmethod
- def from_parts(cls, version, prerelease=FINAL_MARKER,
- devpost=FINAL_MARKER):
- return cls(cls.parts_to_str((version, prerelease, devpost)))
-
- def _parse(self, s, error_on_huge_major_num=True):
- """Parses a string version into parts."""
- match = VERSION_RE.search(s)
- if not match:
- raise IrrationalVersionError(s)
-
- groups = match.groupdict()
- parts = []
-
- # main version
- block = self._parse_numdots(groups['version'], s, False, 2)
- extraversion = groups.get('extraversion')
- if extraversion not in ('', None):
- block += self._parse_numdots(extraversion[1:], s)
- parts.append(tuple(block))
-
- # prerelease
- prerel = groups.get('prerel')
- if prerel is not None:
- block = [prerel]
- block += self._parse_numdots(groups.get('prerelversion'), s,
- pad_zeros_length=1)
- parts.append(tuple(block))
- else:
- parts.append(FINAL_MARKER)
-
- # postdev
- if groups.get('postdev'):
- post = groups.get('post')
- dev = groups.get('dev')
- postdev = []
- if post is not None:
- postdev.extend([FINAL_MARKER[0], 'post', int(post)])
- if dev is None:
- postdev.append(FINAL_MARKER[0])
- if dev is not None:
- postdev.extend(['dev', int(dev)])
- parts.append(tuple(postdev))
- else:
- parts.append(FINAL_MARKER)
- self.parts = tuple(parts)
- if error_on_huge_major_num and self.parts[0][0] > 1980:
- raise HugeMajorVersionNumError(
- "huge major version number, %r, "
- "which might cause future problems: %r" % (self.parts[0][0], s))
-
- def _parse_numdots(self, s, full_ver_str, drop_trailing_zeros=True,
- pad_zeros_length=0):
- """Parse 'N.N.N' sequences, return a list of ints.
-
- @param s {str} 'N.N.N..." sequence to be parsed
- @param full_ver_str {str} The full version string from which this
- comes. Used for error strings.
- @param drop_trailing_zeros {bool} Whether to drop trailing zeros
- from the returned list. Default True.
- @param pad_zeros_length {int} The length to which to pad the
- returned list with zeros, if necessary. Default 0.
- """
- nums = []
- for n in s.split("."):
- if len(n) > 1 and n[0] == '0':
- raise IrrationalVersionError(
- "cannot have leading zero in "
- "version number segment: '%s' in %r" % (n, full_ver_str))
- nums.append(int(n))
- if drop_trailing_zeros:
- while nums and nums[-1] == 0:
- nums.pop()
- while len(nums) < pad_zeros_length:
- nums.append(0)
- return nums
-
- def __str__(self):
- return self.parts_to_str(self.parts)
-
- @classmethod
- def parts_to_str(cls, parts):
- """Transforms a version expressed in tuple into its string
- representation."""
- # XXX This doesn't check for invalid tuples
- main, prerel, postdev = parts
- s = '.'.join(str(v) for v in main)
- if prerel is not FINAL_MARKER:
- s += prerel[0]
- s += '.'.join(str(v) for v in prerel[1:])
- if postdev and postdev is not FINAL_MARKER:
- if postdev[0] == 'f':
- postdev = postdev[1:]
- i = 0
- while i < len(postdev):
- if i % 2 == 0:
- s += '.'
- s += str(postdev[i])
- i += 1
- return s
-
- def __repr__(self):
- return "%s('%s')" % (self.__class__.__name__, self)
-
- def _cannot_compare(self, other):
- raise TypeError("cannot compare %s and %s"
- % (type(self).__name__, type(other).__name__))
-
- def __eq__(self, other):
- if not isinstance(other, NormalizedVersion):
- self._cannot_compare(other)
- return self.parts == other.parts
-
- def __lt__(self, other):
- if not isinstance(other, NormalizedVersion):
- self._cannot_compare(other)
- return self.parts < other.parts
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __gt__(self, other):
- return not (self.__lt__(other) or self.__eq__(other))
-
- def __le__(self, other):
- return self.__eq__(other) or self.__lt__(other)
-
- def __ge__(self, other):
- return self.__eq__(other) or self.__gt__(other)
-
-
-def suggest_normalized_version(s):
- """Suggest a normalized version close to the given version string.
-
- If you have a version string that isn't rational (i.e. NormalizedVersion
- doesn't like it) then you might be able to get an equivalent (or close)
- rational version from this function.
-
- This does a number of simple normalizations to the given string, based
- on observation of versions currently in use on PyPI. Given a dump of
- those version during PyCon 2009, 4287 of them:
- - 2312 (53.93%) match NormalizedVersion without change
- - with the automatic suggestion
- - 3474 (81.04%) match when using this suggestion method
-
- @param s {str} An irrational version string.
- @returns A rational version string, or None, if couldn't determine one.
- """
- try:
- NormalizedVersion(s)
- return s # already rational
- except IrrationalVersionError:
- pass
-
- rs = s.lower()
-
- # part of this could use maketrans
- for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'),
- ('beta', 'b'), ('rc', 'c'), ('-final', ''),
- ('-pre', 'c'),
- ('-release', ''), ('.release', ''), ('-stable', ''),
- ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''),
- ('final', '')):
- rs = rs.replace(orig, repl)
-
- # if something ends with dev or pre, we add a 0
- rs = re.sub(r"pre$", r"pre0", rs)
- rs = re.sub(r"dev$", r"dev0", rs)
-
- # if we have something like "b-2" or "a.2" at the end of the
- # version, that is pobably beta, alpha, etc
- # let's remove the dash or dot
- rs = re.sub(r"([abc|rc])[\-\.](\d+)$", r"\1\2", rs)
-
- # 1.0-dev-r371 -> 1.0.dev371
- # 0.1-dev-r79 -> 0.1.dev79
- rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs)
-
- # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1
- rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs)
-
- # Clean: v0.3, v1.0
- if rs.startswith('v'):
- rs = rs[1:]
-
- # Clean leading '0's on numbers.
- # TODO: unintended side-effect on, e.g., "2003.05.09"
- # PyPI stats: 77 (~2%) better
- rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs)
-
- # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers
- # zero.
- # PyPI stats: 245 (7.56%) better
- rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs)
-
- # the 'dev-rNNN' tag is a dev tag
- rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs)
-
- # clean the - when used as a pre delimiter
- rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs)
-
- # a terminal "dev" or "devel" can be changed into ".dev0"
- rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs)
-
- # a terminal "dev" can be changed into ".dev0"
- rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs)
-
- # a terminal "final" or "stable" can be removed
- rs = re.sub(r"(final|stable)$", "", rs)
-
- # The 'r' and the '-' tags are post release tags
- # 0.4a1.r10 -> 0.4a1.post10
- # 0.9.33-17222 -> 0.9.3.post17222
- # 0.9.33-r17222 -> 0.9.3.post17222
- rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs)
-
- # Clean 'r' instead of 'dev' usage:
- # 0.9.33+r17222 -> 0.9.3.dev17222
- # 1.0dev123 -> 1.0.dev123
- # 1.0.git123 -> 1.0.dev123
- # 1.0.bzr123 -> 1.0.dev123
- # 0.1a0dev.123 -> 0.1a0.dev123
- # PyPI stats: ~150 (~4%) better
- rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs)
-
- # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage:
- # 0.2.pre1 -> 0.2c1
- # 0.2-c1 -> 0.2c1
- # 1.0preview123 -> 1.0c123
- # PyPI stats: ~21 (0.62%) better
- rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs)
-
- # Tcl/Tk uses "px" for their post release markers
- rs = re.sub(r"p(\d+)$", r".post\1", rs)
-
- try:
- NormalizedVersion(rs)
- return rs # already rational
- except IrrationalVersionError:
- pass
- return None
diff --git a/tox/config.py b/tox/config.py
deleted file mode 100644
index d6b4c52..0000000
--- a/tox/config.py
+++ /dev/null
@@ -1,1247 +0,0 @@
-import argparse
-import os
-import random
-from fnmatch import fnmatchcase
-import sys
-import re
-import shlex
-import string
-import pkg_resources
-import itertools
-import pluggy
-
-import tox.interpreters
-from tox import hookspecs
-from tox._verlib import NormalizedVersion
-
-import py
-
-import tox
-
-iswin32 = sys.platform == "win32"
-
-default_factors = {'jython': 'jython', 'pypy': 'pypy', 'pypy3': 'pypy3',
- 'py': sys.executable}
-for version in '26,27,32,33,34,35,36'.split(','):
- default_factors['py' + version] = 'python%s.%s' % tuple(version)
-
-hookimpl = pluggy.HookimplMarker("tox")
-
-_dummy = object()
-
-
-def get_plugin_manager(plugins=()):
- # initialize plugin manager
- import tox.venv
- pm = pluggy.PluginManager("tox")
- pm.add_hookspecs(hookspecs)
- pm.register(tox.config)
- pm.register(tox.interpreters)
- pm.register(tox.venv)
- pm.register(tox.session)
- pm.load_setuptools_entrypoints("tox")
- for plugin in plugins:
- pm.register(plugin)
- pm.check_pending()
- return pm
-
-
-class Parser:
- """ command line and ini-parser control object. """
-
- def __init__(self):
- self.argparser = argparse.ArgumentParser(
- description="tox options", add_help=False)
- self._testenv_attr = []
-
- def add_argument(self, *args, **kwargs):
- """ add argument to command line parser. This takes the
- same arguments that ``argparse.ArgumentParser.add_argument``.
- """
- return self.argparser.add_argument(*args, **kwargs)
-
- def add_testenv_attribute(self, name, type, help, default=None, postprocess=None):
- """ add an ini-file variable for "testenv" section.
-
- Types are specified as strings like "bool", "line-list", "string", "argv", "path",
- "argvlist".
-
- The ``postprocess`` function will be called for each testenv
- like ``postprocess(testenv_config=testenv_config, value=value)``
- where ``value`` is the value as read from the ini (or the default value)
- and ``testenv_config`` is a :py:class:`tox.config.TestenvConfig` instance
- which will receive all ini-variables as object attributes.
-
- Any postprocess function must return a value which will then be set
- as the final value in the testenv section.
- """
- self._testenv_attr.append(VenvAttribute(name, type, default, help, postprocess))
-
- def add_testenv_attribute_obj(self, obj):
- """ add an ini-file variable as an object.
-
- This works as the ``add_testenv_attribute`` function but expects
- "name", "type", "help", and "postprocess" attributes on the object.
- """
- assert hasattr(obj, "name")
- assert hasattr(obj, "type")
- assert hasattr(obj, "help")
- assert hasattr(obj, "postprocess")
- self._testenv_attr.append(obj)
-
- def _parse_args(self, args):
- return self.argparser.parse_args(args)
-
- def _format_help(self):
- return self.argparser.format_help()
-
-
-class VenvAttribute:
- def __init__(self, name, type, default, help, postprocess):
- self.name = name
- self.type = type
- self.default = default
- self.help = help
- self.postprocess = postprocess
-
-
-class DepOption:
- name = "deps"
- type = "line-list"
- help = "each line specifies a dependency in pip/setuptools format."
- default = ()
-
- def postprocess(self, testenv_config, value):
- deps = []
- config = testenv_config.config
- for depline in value:
- m = re.match(r":(\w+):\s*(\S+)", depline)
- if m:
- iname, name = m.groups()
- ixserver = config.indexserver[iname]
- else:
- name = depline.strip()
- ixserver = None
- name = self._replace_forced_dep(name, config)
- deps.append(DepConfig(name, ixserver))
- return deps
-
- def _replace_forced_dep(self, name, config):
- """
- Override the given dependency config name taking --force-dep-version
- option into account.
-
- :param name: dep config, for example ["pkg==1.0", "other==2.0"].
- :param config: Config instance
- :return: the new dependency that should be used for virtual environments
- """
- if not config.option.force_dep:
- return name
- for forced_dep in config.option.force_dep:
- if self._is_same_dep(forced_dep, name):
- return forced_dep
- return name
-
- @classmethod
- def _is_same_dep(cls, dep1, dep2):
- """
- Returns True if both dependency definitions refer to the
- same package, even if versions differ.
- """
- dep1_name = pkg_resources.Requirement.parse(dep1).project_name
- try:
- dep2_name = pkg_resources.Requirement.parse(dep2).project_name
- except pkg_resources.RequirementParseError:
- # we couldn't parse a version, probably a URL
- return False
- return dep1_name == dep2_name
-
-
-class PosargsOption:
- name = "args_are_paths"
- type = "bool"
- default = True
- help = "treat positional args in commands as paths"
-
- def postprocess(self, testenv_config, value):
- config = testenv_config.config
- args = config.option.args
- if args:
- if value:
- args = []
- for arg in config.option.args:
- if arg:
- origpath = config.invocationcwd.join(arg, abs=True)
- if origpath.check():
- arg = testenv_config.changedir.bestrelpath(origpath)
- args.append(arg)
- testenv_config._reader.addsubstitutions(args)
- return value
-
-
-class InstallcmdOption:
- name = "install_command"
- type = "argv"
- default = "pip install {opts} {packages}"
- help = "install command for dependencies and package under test."
-
- def postprocess(self, testenv_config, value):
- if '{packages}' not in value:
- raise tox.exception.ConfigError(
- "'install_command' must contain '{packages}' substitution")
- return value
-
-
-def parseconfig(args=None, plugins=()):
- """
- :param list[str] args: Optional list of arguments.
- :type pkg: str
- :rtype: :class:`Config`
- :raise SystemExit: toxinit file is not found
- """
-
- pm = get_plugin_manager(plugins)
-
- if args is None:
- args = sys.argv[1:]
-
- # prepare command line options
- parser = Parser()
- pm.hook.tox_addoption(parser=parser)
-
- # parse command line options
- option = parser._parse_args(args)
- interpreters = tox.interpreters.Interpreters(hook=pm.hook)
- config = Config(pluginmanager=pm, option=option, interpreters=interpreters)
- config._parser = parser
- config._testenv_attr = parser._testenv_attr
-
- # parse ini file
- basename = config.option.configfile
- if os.path.isabs(basename):
- inipath = py.path.local(basename)
- else:
- for path in py.path.local().parts(reverse=True):
- inipath = path.join(basename)
- if inipath.check():
- break
- else:
- inipath = py.path.local().join('setup.cfg')
- if not inipath.check():
- feedback("toxini file %r not found" % (basename), sysexit=True)
-
- try:
- parseini(config, inipath)
- except tox.exception.InterpreterNotFound:
- exn = sys.exc_info()[1]
- # Use stdout to match test expectations
- py.builtin.print_("ERROR: " + str(exn))
-
- # post process config object
- pm.hook.tox_configure(config=config)
-
- return config
-
-
-def feedback(msg, sysexit=False):
- py.builtin.print_("ERROR: " + msg, file=sys.stderr)
- if sysexit:
- raise SystemExit(1)
-
-
-class VersionAction(argparse.Action):
- def __call__(self, argparser, *args, **kwargs):
- version = tox.__version__
- py.builtin.print_("%s imported from %s" % (version, tox.__file__))
- raise SystemExit(0)
-
-
-class CountAction(argparse.Action):
- def __call__(self, parser, namespace, values, option_string=None):
- if hasattr(namespace, self.dest):
- setattr(namespace, self.dest, int(getattr(namespace, self.dest)) + 1)
- else:
- setattr(namespace, self.dest, 0)
-
-
-class SetenvDict:
- def __init__(self, dict, reader):
- self.reader = reader
- self.definitions = dict
- self.resolved = {}
- self._lookupstack = []
-
- def __contains__(self, name):
- return name in self.definitions
-
- def get(self, name, default=None):
- try:
- return self.resolved[name]
- except KeyError:
- try:
- if name in self._lookupstack:
- raise KeyError(name)
- val = self.definitions[name]
- except KeyError:
- return os.environ.get(name, default)
- self._lookupstack.append(name)
- try:
- self.resolved[name] = res = self.reader._replace(val)
- finally:
- self._lookupstack.pop()
- return res
-
- def __getitem__(self, name):
- x = self.get(name, _dummy)
- if x is _dummy:
- raise KeyError(name)
- return x
-
- def keys(self):
- return self.definitions.keys()
-
- def __setitem__(self, name, value):
- self.definitions[name] = value
- self.resolved[name] = value
-
-
-@hookimpl
-def tox_addoption(parser):
- # formatter_class=argparse.ArgumentDefaultsHelpFormatter)
- parser.add_argument("--version", nargs=0, action=VersionAction,
- dest="version",
- help="report version information to stdout.")
- parser.add_argument("-h", "--help", action="store_true", dest="help",
- help="show help about options")
- parser.add_argument("--help-ini", "--hi", action="store_true", dest="helpini",
- help="show help about ini-names")
- parser.add_argument("-v", nargs=0, action=CountAction, default=0,
- dest="verbosity",
- help="increase verbosity of reporting output.")
- parser.add_argument("--showconfig", action="store_true",
- help="show configuration information for all environments. ")
- parser.add_argument("-l", "--listenvs", action="store_true",
- dest="listenvs", help="show list of test environments")
- parser.add_argument("-c", action="store", default="tox.ini",
- dest="configfile",
- help="use the specified config file name.")
- parser.add_argument("-e", action="append", dest="env",
- metavar="envlist",
- help="work against specified environments (ALL selects all).")
- parser.add_argument("--notest", action="store_true", dest="notest",
- help="skip invoking test commands.")
- parser.add_argument("--sdistonly", action="store_true", dest="sdistonly",
- help="only perform the sdist packaging activity.")
- parser.add_argument("--installpkg", action="store", default=None,
- metavar="PATH",
- help="use specified package for installation into venv, instead of "
- "creating an sdist.")
- parser.add_argument("--develop", action="store_true", dest="develop",
- help="install package in the venv using 'setup.py develop' via "
- "'pip -e .'")
- parser.add_argument('-i', action="append",
- dest="indexurl", metavar="URL",
- help="set indexserver url (if URL is of form name=url set the "
- "url for the 'name' indexserver, specifically)")
- parser.add_argument("--pre", action="store_true", dest="pre",
- help="install pre-releases and development versions of dependencies. "
- "This will pass the --pre option to install_command "
- "(pip by default).")
- parser.add_argument("-r", "--recreate", action="store_true",
- dest="recreate",
- help="force recreation of virtual environments")
- parser.add_argument("--result-json", action="store",
- dest="resultjson", metavar="PATH",
- help="write a json file with detailed information "
- "about all commands and results involved.")
-
- # We choose 1 to 4294967295 because it is the range of PYTHONHASHSEED.
- parser.add_argument("--hashseed", action="store",
- metavar="SEED", default=None,
- help="set PYTHONHASHSEED to SEED before running commands. "
- "Defaults to a random integer in the range [1, 4294967295] "
- "([1, 1024] on Windows). "
- "Passing 'noset' suppresses this behavior.")
- parser.add_argument("--force-dep", action="append",
- metavar="REQ", default=None,
- help="Forces a certain version of one of the dependencies "
- "when configuring the virtual environment. REQ Examples "
- "'pytest<2.7' or 'django>=1.6'.")
- parser.add_argument("--sitepackages", action="store_true",
- help="override sitepackages setting to True in all envs")
- parser.add_argument("--skip-missing-interpreters", action="store_true",
- help="don't fail tests for missing interpreters")
- parser.add_argument("--workdir", action="store",
- dest="workdir", metavar="PATH", default=None,
- help="tox working directory")
-
- parser.add_argument("args", nargs="*",
- help="additional arguments available to command positional substitution")
-
- parser.add_testenv_attribute(
- name="envdir", type="path", default="{toxworkdir}/{envname}",
- help="venv directory")
-
- # add various core venv interpreter attributes
- def setenv(testenv_config, value):
- setenv = value
- config = testenv_config.config
- if "PYTHONHASHSEED" not in setenv and config.hashseed is not None:
- setenv['PYTHONHASHSEED'] = config.hashseed
- return setenv
-
- parser.add_testenv_attribute(
- name="setenv", type="dict_setenv", postprocess=setenv,
- help="list of X=Y lines with environment variable settings")
-
- def basepython_default(testenv_config, value):
- if value is None:
- for f in testenv_config.factors:
- if f in default_factors:
- return default_factors[f]
- return sys.executable
- return str(value)
-
- parser.add_testenv_attribute(
- name="basepython", type="string", default=None, postprocess=basepython_default,
- help="executable name or path of interpreter used to create a "
- "virtual test environment.")
-
- parser.add_testenv_attribute(
- name="envtmpdir", type="path", default="{envdir}/tmp",
- help="venv temporary directory")
-
- parser.add_testenv_attribute(
- name="envlogdir", type="path", default="{envdir}/log",
- help="venv log directory")
-
- def downloadcache(testenv_config, value):
- if value:
- # env var, if present, takes precedence
- downloadcache = os.environ.get("PIP_DOWNLOAD_CACHE", value)
- return py.path.local(downloadcache)
-
- parser.add_testenv_attribute(
- name="downloadcache", type="string", default=None, postprocess=downloadcache,
- help="(deprecated) set PIP_DOWNLOAD_CACHE.")
-
- parser.add_testenv_attribute(
- name="changedir", type="path", default="{toxinidir}",
- help="directory to change to when running commands")
-
- parser.add_testenv_attribute_obj(PosargsOption())
-
- parser.add_testenv_attribute(
- name="skip_install", type="bool", default=False,
- help="Do not install the current package. This can be used when "
- "you need the virtualenv management but do not want to install "
- "the current package")
-
- parser.add_testenv_attribute(
- name="ignore_errors", type="bool", default=False,
- help="if set to True all commands will be executed irrespective of their "
- "result error status.")
-
- def recreate(testenv_config, value):
- if testenv_config.config.option.recreate:
- return True
- return value
-
- parser.add_testenv_attribute(
- name="recreate", type="bool", default=False, postprocess=recreate,
- help="always recreate this test environment.")
-
- def passenv(testenv_config, value):
- # Flatten the list to deal with space-separated values.
- value = list(
- itertools.chain.from_iterable(
- [x.split(' ') for x in value]))
-
- passenv = set(["PATH", "PIP_INDEX_URL", "LANG", "LD_LIBRARY_PATH"])
-
- # read in global passenv settings
- p = os.environ.get("TOX_TESTENV_PASSENV", None)
- if p is not None:
- passenv.update(x for x in p.split() if x)
-
- # we ensure that tmp directory settings are passed on
- # we could also set it to the per-venv "envtmpdir"
- # but this leads to very long paths when run with jenkins
- # so we just pass it on by default for now.
- if sys.platform == "win32":
- passenv.add("SYSTEMDRIVE") # needed for pip6
- passenv.add("SYSTEMROOT") # needed for python's crypto module
- passenv.add("PATHEXT") # needed for discovering executables
- passenv.add("TEMP")
- passenv.add("TMP")
- else:
- passenv.add("TMPDIR")
- for spec in value:
- for name in os.environ:
- if fnmatchcase(name.upper(), spec.upper()):
- passenv.add(name)
- return passenv
-
- parser.add_testenv_attribute(
- name="passenv", type="line-list", postprocess=passenv,
- help="environment variables needed during executing test commands "
- "(taken from invocation environment). Note that tox always "
- "passes through some basic environment variables which are "
- "needed for basic functioning of the Python system. "
- "See --showconfig for the eventual passenv setting.")
-
- parser.add_testenv_attribute(
- name="whitelist_externals", type="line-list",
- help="each lines specifies a path or basename for which tox will not warn "
- "about it coming from outside the test environment.")
-
- parser.add_testenv_attribute(
- name="platform", type="string", default=".*",
- help="regular expression which must match against ``sys.platform``. "
- "otherwise testenv will be skipped.")
-
- def sitepackages(testenv_config, value):
- return testenv_config.config.option.sitepackages or value
-
- parser.add_testenv_attribute(
- name="sitepackages", type="bool", default=False, postprocess=sitepackages,
- help="Set to ``True`` if you want to create virtual environments that also "
- "have access to globally installed packages.")
-
- def pip_pre(testenv_config, value):
- return testenv_config.config.option.pre or value
-
- parser.add_testenv_attribute(
- name="pip_pre", type="bool", default=False, postprocess=pip_pre,
- help="If ``True``, adds ``--pre`` to the ``opts`` passed to "
- "the install command. ")
-
- def develop(testenv_config, value):
- option = testenv_config.config.option
- return not option.installpkg and (value or option.develop)
-
- parser.add_testenv_attribute(
- name="usedevelop", type="bool", postprocess=develop, default=False,
- help="install package in develop/editable mode")
-
- parser.add_testenv_attribute_obj(InstallcmdOption())
-
- parser.add_testenv_attribute(
- name="list_dependencies_command",
- type="argv",
- default="pip freeze",
- help="list dependencies for a virtual environment")
-
- parser.add_testenv_attribute_obj(DepOption())
-
- parser.add_testenv_attribute(
- name="commands", type="argvlist", default="",
- help="each line specifies a test command and can use substitution.")
-
- parser.add_testenv_attribute(
- "ignore_outcome", type="bool", default=False,
- help="if set to True a failing result of this testenv will not make "
- "tox fail, only a warning will be produced")
-
-
-class Config(object):
- """ Global Tox config object. """
- def __init__(self, pluginmanager, option, interpreters):
- #: dictionary containing envname to envconfig mappings
- self.envconfigs = {}
- self.invocationcwd = py.path.local()
- self.interpreters = interpreters
- self.pluginmanager = pluginmanager
- #: option namespace containing all parsed command line options
- self.option = option
-
- @property
- def homedir(self):
- homedir = get_homedir()
- if homedir is None:
- homedir = self.toxinidir # XXX good idea?
- return homedir
-
-
-class TestenvConfig:
- """ Testenv Configuration object.
- In addition to some core attributes/properties this config object holds all
- per-testenv ini attributes as attributes, see "tox --help-ini" for an overview.
- """
- def __init__(self, envname, config, factors, reader):
- #: test environment name
- self.envname = envname
- #: global tox config object
- self.config = config
- #: set of factors
- self.factors = factors
- self._reader = reader
-
- def get_envbindir(self):
- """ path to directory where scripts/binaries reside. """
- if (sys.platform == "win32"
- and "jython" not in self.basepython
- and "pypy" not in self.basepython):
- return self.envdir.join("Scripts")
- else:
- return self.envdir.join("bin")
-
- @property
- def envbindir(self):
- return self.get_envbindir()
-
- @property
- def envpython(self):
- """ path to python executable. """
- return self.get_envpython()
-
- def get_envpython(self):
- """ path to python/jython executable. """
- if "jython" in str(self.basepython):
- name = "jython"
- else:
- name = "python"
- return self.envbindir.join(name)
-
- def get_envsitepackagesdir(self):
- """ return sitepackagesdir of the virtualenv environment.
- (only available during execution, not parsing)
- """
- x = self.config.interpreters.get_sitepackagesdir(
- info=self.python_info,
- envdir=self.envdir)
- return x
-
- @property
- def python_info(self):
- """ return sitepackagesdir of the virtualenv environment. """
- return self.config.interpreters.get_info(envconfig=self)
-
- def getsupportedinterpreter(self):
- if sys.platform == "win32" and self.basepython and \
- "jython" in self.basepython:
- raise tox.exception.UnsupportedInterpreter(
- "Jython/Windows does not support installing scripts")
- info = self.config.interpreters.get_info(envconfig=self)
- if not info.executable:
- raise tox.exception.InterpreterNotFound(self.basepython)
- if not info.version_info:
- raise tox.exception.InvocationError(
- 'Failed to get version_info for %s: %s' % (info.name, info.err))
- if info.version_info < (2, 6):
- raise tox.exception.UnsupportedInterpreter(
- "python2.5 is not supported anymore, sorry")
- return info.executable
-
-
-testenvprefix = "testenv:"
-
-
-def get_homedir():
- try:
- return py.path.local._gethomedir()
- except Exception:
- return None
-
-
-def make_hashseed():
- max_seed = 4294967295
- if sys.platform == 'win32':
- max_seed = 1024
- return str(random.randint(1, max_seed))
-
-
-class parseini:
- def __init__(self, config, inipath):
- config.toxinipath = inipath
- config.toxinidir = config.toxinipath.dirpath()
-
- self._cfg = py.iniconfig.IniConfig(config.toxinipath)
- config._cfg = self._cfg
- self.config = config
-
- if inipath.basename == 'setup.cfg':
- prefix = 'tox'
- else:
- prefix = None
- ctxname = getcontextname()
- if ctxname == "jenkins":
- reader = SectionReader("tox:jenkins", self._cfg, prefix=prefix,
- fallbacksections=['tox'])
- distshare_default = "{toxworkdir}/distshare"
- elif not ctxname:
- reader = SectionReader("tox", self._cfg, prefix=prefix)
- distshare_default = "{homedir}/.tox/distshare"
- else:
- raise ValueError("invalid context")
-
- if config.option.hashseed is None:
- hashseed = make_hashseed()
- elif config.option.hashseed == 'noset':
- hashseed = None
- else:
- hashseed = config.option.hashseed
- config.hashseed = hashseed
-
- reader.addsubstitutions(toxinidir=config.toxinidir,
- homedir=config.homedir)
- # As older versions of tox may have bugs or incompatabilities that
- # prevent parsing of tox.ini this must be the first thing checked.
- config.minversion = reader.getstring("minversion", None)
- if config.minversion:
- minversion = NormalizedVersion(self.config.minversion)
- toxversion = NormalizedVersion(tox.__version__)
- if toxversion < minversion:
- raise tox.exception.MinVersionError(
- "tox version is %s, required is at least %s" % (
- toxversion, minversion))
- if config.option.workdir is None:
- config.toxworkdir = reader.getpath("toxworkdir", "{toxinidir}/.tox")
- else:
- config.toxworkdir = config.toxinidir.join(config.option.workdir, abs=True)
-
- if not config.option.skip_missing_interpreters:
- config.option.skip_missing_interpreters = \
- reader.getbool("skip_missing_interpreters", False)
-
- # determine indexserver dictionary
- config.indexserver = {'default': IndexServerConfig('default')}
- prefix = "indexserver"
- for line in reader.getlist(prefix):
- name, url = map(lambda x: x.strip(), line.split("=", 1))
- config.indexserver[name] = IndexServerConfig(name, url)
-
- override = False
- if config.option.indexurl:
- for urldef in config.option.indexurl:
- m = re.match(r"\W*(\w+)=(\S+)", urldef)
- if m is None:
- url = urldef
- name = "default"
- else:
- name, url = m.groups()
- if not url:
- url = None
- if name != "ALL":
- config.indexserver[name].url = url
- else:
- override = url
- # let ALL override all existing entries
- if override:
- for name in config.indexserver:
- config.indexserver[name] = IndexServerConfig(name, override)
-
- reader.addsubstitutions(toxworkdir=config.toxworkdir)
- config.distdir = reader.getpath("distdir", "{toxworkdir}/dist")
- reader.addsubstitutions(distdir=config.distdir)
- config.distshare = reader.getpath("distshare", distshare_default)
- reader.addsubstitutions(distshare=config.distshare)
- config.sdistsrc = reader.getpath("sdistsrc", None)
- config.setupdir = reader.getpath("setupdir", "{toxinidir}")
- config.logdir = config.toxworkdir.join("log")
-
- config.envlist, all_envs = self._getenvdata(reader)
-
- # factors used in config or predefined
- known_factors = self._list_section_factors("testenv")
- known_factors.update(default_factors)
- known_factors.add("python")
-
- # factors stated in config envlist
- stated_envlist = reader.getstring("envlist", replace=False)
- if stated_envlist:
- for env in _split_env(stated_envlist):
- known_factors.update(env.split('-'))
-
- # configure testenvs
- for name in all_envs:
- section = testenvprefix + name
- factors = set(name.split('-'))
- if section in self._cfg or factors <= known_factors:
- config.envconfigs[name] = \
- self.make_envconfig(name, section, reader._subs, config)
-
- all_develop = all(name in config.envconfigs
- and config.envconfigs[name].usedevelop
- for name in config.envlist)
-
- config.skipsdist = reader.getbool("skipsdist", all_develop)
-
- def _list_section_factors(self, section):
- factors = set()
- if section in self._cfg:
- for _, value in self._cfg[section].items():
- exprs = re.findall(r'^([\w{}\.,-]+)\:\s+', value, re.M)
- factors.update(*mapcat(_split_factor_expr, exprs))
- return factors
-
- def make_envconfig(self, name, section, subs, config):
- factors = set(name.split('-'))
- reader = SectionReader(section, self._cfg, fallbacksections=["testenv"],
- factors=factors)
- vc = TestenvConfig(config=config, envname=name, factors=factors, reader=reader)
- reader.addsubstitutions(**subs)
- reader.addsubstitutions(envname=name)
- reader.addsubstitutions(envbindir=vc.get_envbindir,
- envsitepackagesdir=vc.get_envsitepackagesdir,
- envpython=vc.get_envpython)
-
- for env_attr in config._testenv_attr:
- atype = env_attr.type
- if atype in ("bool", "path", "string", "dict", "dict_setenv", "argv", "argvlist"):
- meth = getattr(reader, "get" + atype)
- res = meth(env_attr.name, env_attr.default)
- elif atype == "space-separated-list":
- res = reader.getlist(env_attr.name, sep=" ")
- elif atype == "line-list":
- res = reader.getlist(env_attr.name, sep="\n")
- else:
- raise ValueError("unknown type %r" % (atype,))
-
- if env_attr.postprocess:
- res = env_attr.postprocess(testenv_config=vc, value=res)
- setattr(vc, env_attr.name, res)
-
- if atype == "path":
- reader.addsubstitutions(**{env_attr.name: res})
-
- return vc
-
- def _getenvdata(self, reader):
- envstr = self.config.option.env \
- or os.environ.get("TOXENV") \
- or reader.getstring("envlist", replace=False) \
- or []
- envlist = _split_env(envstr)
-
- # collect section envs
- all_envs = set(envlist) - set(["ALL"])
- for section in self._cfg:
- if section.name.startswith(testenvprefix):
- all_envs.add(section.name[len(testenvprefix):])
- if not all_envs:
- all_envs.add("python")
-
- if not envlist or "ALL" in envlist:
- envlist = sorted(all_envs)
-
- return envlist, all_envs
-
-
-def _split_env(env):
- """if handed a list, action="append" was used for -e """
- if not isinstance(env, list):
- if '\n' in env:
- env = ','.join(env.split('\n'))
- env = [env]
- return mapcat(_expand_envstr, env)
-
-
-def _split_factor_expr(expr):
- partial_envs = _expand_envstr(expr)
- return [set(e.split('-')) for e in partial_envs]
-
-
-def _expand_envstr(envstr):
- # split by commas not in groups
- tokens = re.split(r'((?:\{[^}]+\})+)|,', envstr)
- envlist = [''.join(g).strip()
- for k, g in itertools.groupby(tokens, key=bool) if k]
-
- def expand(env):
- tokens = re.split(r'\{([^}]+)\}', env)
- parts = [token.split(',') for token in tokens]
- return [''.join(variant) for variant in itertools.product(*parts)]
-
- return mapcat(expand, envlist)
-
-
-def mapcat(f, seq):
- return list(itertools.chain.from_iterable(map(f, seq)))
-
-
-class DepConfig:
- def __init__(self, name, indexserver=None):
- self.name = name
- self.indexserver = indexserver
-
- def __str__(self):
- if self.indexserver:
- if self.indexserver.name == "default":
- return self.name
- return ":%s:%s" % (self.indexserver.name, self.name)
- return str(self.name)
- __repr__ = __str__
-
-
-class IndexServerConfig:
- def __init__(self, name, url=None):
- self.name = name
- self.url = url
-
-
-#: Check value matches substitution form
-#: of referencing value from other section. E.g. {[base]commands}
-is_section_substitution = re.compile("{\[[^{}\s]+\]\S+?}").match
-
-
-class SectionReader:
- def __init__(self, section_name, cfgparser, fallbacksections=None,
- factors=(), prefix=None):
- if prefix is None:
- self.section_name = section_name
- else:
- self.section_name = "%s:%s" % (prefix, section_name)
- self._cfg = cfgparser
- self.fallbacksections = fallbacksections or []
- self.factors = factors
- self._subs = {}
- self._subststack = []
- self._setenv = None
-
- def get_environ_value(self, name):
- if self._setenv is None:
- return os.environ.get(name)
- return self._setenv.get(name)
-
- def addsubstitutions(self, _posargs=None, **kw):
- self._subs.update(kw)
- if _posargs:
- self.posargs = _posargs
-
- def getpath(self, name, defaultpath):
- toxinidir = self._subs['toxinidir']
- path = self.getstring(name, defaultpath)
- if path is not None:
- return toxinidir.join(path, abs=True)
-
- def getlist(self, name, sep="\n"):
- s = self.getstring(name, None)
- if s is None:
- return []
- return [x.strip() for x in s.split(sep) if x.strip()]
-
- def getdict(self, name, default=None, sep="\n"):
- value = self.getstring(name, None)
- return self._getdict(value, default=default, sep=sep)
-
- def getdict_setenv(self, name, default=None, sep="\n"):
- value = self.getstring(name, None, replace=True, crossonly=True)
- definitions = self._getdict(value, default=default, sep=sep)
- self._setenv = SetenvDict(definitions, reader=self)
- return self._setenv
-
- def _getdict(self, value, default, sep):
- if value is None:
- return default or {}
-
- d = {}
- for line in value.split(sep):
- if line.strip():
- name, rest = line.split('=', 1)
- d[name.strip()] = rest.strip()
-
- return d
-
- def getbool(self, name, default=None):
- s = self.getstring(name, default)
- if not s:
- s = default
- if s is None:
- raise KeyError("no config value [%s] %s found" % (
- self.section_name, name))
-
- if not isinstance(s, bool):
- if s.lower() == "true":
- s = True
- elif s.lower() == "false":
- s = False
- else:
- raise tox.exception.ConfigError(
- "boolean value %r needs to be 'True' or 'False'")
- return s
-
- def getargvlist(self, name, default=""):
- s = self.getstring(name, default, replace=False)
- return _ArgvlistReader.getargvlist(self, s)
-
- def getargv(self, name, default=""):
- return self.getargvlist(name, default)[0]
-
- def getstring(self, name, default=None, replace=True, crossonly=False):
- x = None
- for s in [self.section_name] + self.fallbacksections:
- try:
- x = self._cfg[s][name]
- break
- except KeyError:
- continue
-
- if x is None:
- x = default
- else:
- x = self._apply_factors(x)
-
- if replace and x and hasattr(x, 'replace'):
- x = self._replace(x, name=name, crossonly=crossonly)
- # print "getstring", self.section_name, name, "returned", repr(x)
- return x
-
- def _apply_factors(self, s):
- def factor_line(line):
- m = re.search(r'^([\w{}\.,-]+)\:\s+(.+)', line)
- if not m:
- return line
-
- expr, line = m.groups()
- if any(fs <= self.factors for fs in _split_factor_expr(expr)):
- return line
-
- lines = s.strip().splitlines()
- return '\n'.join(filter(None, map(factor_line, lines)))
-
- def _replace(self, value, name=None, section_name=None, crossonly=False):
- if '{' not in value:
- return value
-
- section_name = section_name if section_name else self.section_name
- self._subststack.append((section_name, name))
- try:
- return Replacer(self, crossonly=crossonly).do_replace(value)
- finally:
- assert self._subststack.pop() == (section_name, name)
-
-
-class Replacer:
- RE_ITEM_REF = re.compile(
- r'''
- (?<!\\)[{]
- (?:(?P<sub_type>[^[:{}]+):)? # optional sub_type for special rules
- (?P<substitution_value>[^,{}]*) # substitution key
- [}]
- ''', re.VERBOSE)
-
- def __init__(self, reader, crossonly=False):
- self.reader = reader
- self.crossonly = crossonly
-
- def do_replace(self, x):
- return self.RE_ITEM_REF.sub(self._replace_match, x)
-
- def _replace_match(self, match):
- g = match.groupdict()
- sub_value = g['substitution_value']
- if self.crossonly:
- if sub_value.startswith("["):
- return self._substitute_from_other_section(sub_value)
- # in crossonly we return all other hits verbatim
- start, end = match.span()
- return match.string[start:end]
-
- # special case: opts and packages. Leave {opts} and
- # {packages} intact, they are replaced manually in
- # _venv.VirtualEnv.run_install_command.
- if sub_value in ('opts', 'packages'):
- return '{%s}' % sub_value
-
- try:
- sub_type = g['sub_type']
- except KeyError:
- raise tox.exception.ConfigError(
- "Malformed substitution; no substitution type provided")
-
- if sub_type == "env":
- return self._replace_env(match)
- if sub_type is not None:
- raise tox.exception.ConfigError(
- "No support for the %s substitution type" % sub_type)
- return self._replace_substitution(match)
-
- def _replace_env(self, match):
- match_value = match.group('substitution_value')
- if not match_value:
- raise tox.exception.ConfigError(
- 'env: requires an environment variable name')
-
- default = None
- envkey_split = match_value.split(':', 1)
-
- if len(envkey_split) is 2:
- envkey, default = envkey_split
- else:
- envkey = match_value
-
- envvalue = self.reader.get_environ_value(envkey)
- if envvalue is None:
- if default is None:
- raise tox.exception.ConfigError(
- "substitution env:%r: unknown environment variable %r "
- " or recursive definition." %
- (envkey, envkey))
- return default
- return envvalue
-
- def _substitute_from_other_section(self, key):
- if key.startswith("[") and "]" in key:
- i = key.find("]")
- section, item = key[1:i], key[i + 1:]
- cfg = self.reader._cfg
- if section in cfg and item in cfg[section]:
- if (section, item) in self.reader._subststack:
- raise ValueError('%s already in %s' % (
- (section, item), self.reader._subststack))
- x = str(cfg[section][item])
- return self.reader._replace(x, name=item, section_name=section,
- crossonly=self.crossonly)
-
- raise tox.exception.ConfigError(
- "substitution key %r not found" % key)
-
- def _replace_substitution(self, match):
- sub_key = match.group('substitution_value')
- val = self.reader._subs.get(sub_key, None)
- if val is None:
- val = self._substitute_from_other_section(sub_key)
- if py.builtin.callable(val):
- val = val()
- return str(val)
-
-
-class _ArgvlistReader:
- @classmethod
- def getargvlist(cls, reader, value):
- """Parse ``commands`` argvlist multiline string.
-
- :param str name: Key name in a section.
- :param str value: Content stored by key.
-
- :rtype: list[list[str]]
- :raise :class:`tox.exception.ConfigError`:
- line-continuation ends nowhere while resolving for specified section
- """
- commands = []
- current_command = ""
- for line in value.splitlines():
- line = line.rstrip()
- if not line:
- continue
- if line.endswith("\\"):
- current_command += " " + line[:-1]
- continue
- current_command += line
-
- if is_section_substitution(current_command):
- replaced = reader._replace(current_command, crossonly=True)
- commands.extend(cls.getargvlist(reader, replaced))
- else:
- commands.append(cls.processcommand(reader, current_command))
- current_command = ""
- else:
- if current_command:
- raise tox.exception.ConfigError(
- "line-continuation ends nowhere while resolving for [%s] %s" %
- (reader.section_name, "commands"))
- return commands
-
- @classmethod
- def processcommand(cls, reader, command):
- posargs = getattr(reader, "posargs", None)
-
- # Iterate through each word of the command substituting as
- # appropriate to construct the new command string. This
- # string is then broken up into exec argv components using
- # shlex.
- newcommand = ""
- for word in CommandParser(command).words():
- if word == "{posargs}" or word == "[]":
- if posargs:
- newcommand += " ".join(posargs)
- continue
- elif word.startswith("{posargs:") and word.endswith("}"):
- if posargs:
- newcommand += " ".join(posargs)
- continue
- else:
- word = word[9:-1]
- new_arg = ""
- new_word = reader._replace(word)
- new_word = reader._replace(new_word)
- new_word = new_word.replace('\\{', '{').replace('\\}', '}')
- new_arg += new_word
- newcommand += new_arg
-
- # Construct shlex object that will not escape any values,
- # use all values as is in argv.
- shlexer = shlex.shlex(newcommand, posix=True)
- shlexer.whitespace_split = True
- shlexer.escape = ''
- argv = list(shlexer)
- return argv
-
-
-class CommandParser(object):
-
- class State(object):
- def __init__(self):
- self.word = ''
- self.depth = 0
- self.yield_words = []
-
- def __init__(self, command):
- self.command = command
-
- def words(self):
- ps = CommandParser.State()
-
- def word_has_ended():
- return ((cur_char in string.whitespace and ps.word and
- ps.word[-1] not in string.whitespace) or
- (cur_char == '{' and ps.depth == 0 and not ps.word.endswith('\\')) or
- (ps.depth == 0 and ps.word and ps.word[-1] == '}') or
- (cur_char not in string.whitespace and ps.word and
- ps.word.strip() == ''))
-
- def yield_this_word():
- yieldword = ps.word
- ps.word = ''
- if yieldword:
- ps.yield_words.append(yieldword)
-
- def yield_if_word_ended():
- if word_has_ended():
- yield_this_word()
-
- def accumulate():
- ps.word += cur_char
-
- def push_substitution():
- ps.depth += 1
-
- def pop_substitution():
- ps.depth -= 1
-
- for cur_char in self.command:
- if cur_char in string.whitespace:
- if ps.depth == 0:
- yield_if_word_ended()
- accumulate()
- elif cur_char == '{':
- yield_if_word_ended()
- accumulate()
- push_substitution()
- elif cur_char == '}':
- accumulate()
- pop_substitution()
- else:
- yield_if_word_ended()
- accumulate()
-
- if ps.word.strip():
- yield_this_word()
- return ps.yield_words
-
-
-def getcontextname():
- if any(env in os.environ for env in ['JENKINS_URL', 'HUDSON_URL']):
- return 'jenkins'
- return None
diff --git a/tox/hookspecs.py b/tox/hookspecs.py
deleted file mode 100644
index 22e231d..0000000
--- a/tox/hookspecs.py
+++ /dev/null
@@ -1,59 +0,0 @@
-""" Hook specifications for tox.
-
-"""
-
-from pluggy import HookspecMarker, HookimplMarker
-
-hookspec = HookspecMarker("tox")
-hookimpl = HookimplMarker("tox")
-
-
-@hookspec
-def tox_addoption(parser):
- """ add command line options to the argparse-style parser object."""
-
-
-@hookspec
-def tox_configure(config):
- """ called after command line options have been parsed and the ini-file has
- been read. Please be aware that the config object layout may change as its
- API was not designed yet wrt to providing stability (it was an internal
- thing purely before tox-2.0). """
-
-
-@hookspec(firstresult=True)
-def tox_get_python_executable(envconfig):
- """ return a python executable for the given python base name.
- The first plugin/hook which returns an executable path will determine it.
-
- ``envconfig`` is the testenv configuration which contains
- per-testenv configuration, notably the ``.envname`` and ``.basepython``
- setting.
- """
-
-
-@hookspec
-def tox_testenv_create(venv, action):
- """ [experimental] perform creation action for this venv.
- """
-
-
-@hookspec
-def tox_testenv_install_deps(venv, action):
- """ [experimental] perform install dependencies action for this venv. """
-
-
-@hookspec
-def tox_runtest_pre(venv):
- """ [experimental] perform arbitrary action before running tests for this venv.
-
- This could be used to indicate that tests for a given venv have started, for instance.
- """
-
-
-@hookspec
-def tox_runtest_post(venv):
- """ [experimental] perform arbitrary action after running tests for this venv.
-
- This could be used to have per-venv test reporting of pass/fail status.
- """
diff --git a/tox/interpreters.py b/tox/interpreters.py
deleted file mode 100644
index e049f1d..0000000
--- a/tox/interpreters.py
+++ /dev/null
@@ -1,184 +0,0 @@
-import sys
-import py
-import re
-import inspect
-from tox import hookimpl
-
-
-class Interpreters:
- def __init__(self, hook):
- self.name2executable = {}
- self.executable2info = {}
- self.hook = hook
-
- def get_executable(self, envconfig):
- """ return path object to the executable for the given
- name (e.g. python2.6, python2.7, python etc.)
- if name is already an existing path, return name.
- If an interpreter cannot be found, return None.
- """
- try:
- return self.name2executable[envconfig.envname]
- except KeyError:
- exe = self.hook.tox_get_python_executable(envconfig=envconfig)
- self.name2executable[envconfig.envname] = exe
- return exe
-
- def get_info(self, envconfig):
- executable = self.get_executable(envconfig)
- name = envconfig.basepython
- if not executable:
- return NoInterpreterInfo(name=name)
- try:
- return self.executable2info[executable]
- except KeyError:
- info = run_and_get_interpreter_info(name, executable)
- self.executable2info[executable] = info
- return info
-
- def get_sitepackagesdir(self, info, envdir):
- if not info.executable:
- return ""
- envdir = str(envdir)
- try:
- res = exec_on_interpreter(info.executable,
- [inspect.getsource(sitepackagesdir),
- "print(sitepackagesdir(%r))" % envdir])
- except ExecFailed:
- val = sys.exc_info()[1]
- print("execution failed: %s -- %s" % (val.out, val.err))
- return ""
- else:
- return res["dir"]
-
-
-def run_and_get_interpreter_info(name, executable):
- assert executable
- try:
- result = exec_on_interpreter(executable,
- [inspect.getsource(pyinfo), "print(pyinfo())"])
- except ExecFailed:
- val = sys.exc_info()[1]
- return NoInterpreterInfo(name, executable=val.executable,
- out=val.out, err=val.err)
- else:
- return InterpreterInfo(name, executable, **result)
-
-
-def exec_on_interpreter(executable, source):
- if isinstance(source, list):
- source = "\n".join(source)
- from subprocess import Popen, PIPE
- args = [str(executable)]
- popen = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- popen.stdin.write(source.encode("utf8"))
- out, err = popen.communicate()
- if popen.returncode:
- raise ExecFailed(executable, source, out, err)
- try:
- result = eval(out.strip())
- except Exception:
- raise ExecFailed(executable, source, out,
- "could not decode %r" % out)
- return result
-
-
-class ExecFailed(Exception):
- def __init__(self, executable, source, out, err):
- self.executable = executable
- self.source = source
- self.out = out
- self.err = err
-
-
-class InterpreterInfo:
- runnable = True
-
- def __init__(self, name, executable, version_info, sysplatform):
- assert executable and version_info
- self.name = name
- self.executable = executable
- self.version_info = version_info
- self.sysplatform = sysplatform
-
- def __str__(self):
- return "<executable at %s, version_info %s>" % (
- self.executable, self.version_info)
-
-
-class NoInterpreterInfo:
- runnable = False
-
- def __init__(self, name, executable=None,
- out=None, err="not found"):
- self.name = name
- self.executable = executable
- self.version_info = None
- self.out = out
- self.err = err
-
- def __str__(self):
- if self.executable:
- return "<executable at %s, not runnable>"
- else:
- return "<executable not found for: %s>" % self.name
-
-if sys.platform != "win32":
- @hookimpl
- def tox_get_python_executable(envconfig):
- return py.path.local.sysfind(envconfig.basepython)
-
-else:
- @hookimpl
- def tox_get_python_executable(envconfig):
- name = envconfig.basepython
- p = py.path.local.sysfind(name)
- if p:
- return p
- actual = None
- # Is this a standard PythonX.Y name?
- m = re.match(r"python(\d)\.(\d)", name)
- if m:
- # The standard names are in predictable places.
- actual = r"c:\python%s%s\python.exe" % m.groups()
- if not actual:
- actual = win32map.get(name, None)
- if actual:
- actual = py.path.local(actual)
- if actual.check():
- return actual
- # The standard executables can be found as a last resort via the
- # Python launcher py.exe
- if m:
- return locate_via_py(*m.groups())
-
- # Exceptions to the usual windows mapping
- win32map = {
- 'python': sys.executable,
- 'jython': "c:\jython2.5.1\jython.bat",
- }
-
- def locate_via_py(v_maj, v_min):
- ver = "-%s.%s" % (v_maj, v_min)
- script = "import sys; print(sys.executable)"
- py_exe = py.path.local.sysfind('py')
- if py_exe:
- try:
- exe = py_exe.sysexec(ver, '-c', script).strip()
- except py.process.cmdexec.Error:
- exe = None
- if exe:
- exe = py.path.local(exe)
- if exe.check():
- return exe
-
-
-def pyinfo():
- import sys
- return dict(version_info=tuple(sys.version_info),
- sysplatform=sys.platform)
-
-
-def sitepackagesdir(envdir):
- from distutils.sysconfig import get_python_lib
- return dict(dir=get_python_lib(prefix=envdir))
diff --git a/tox/result.py b/tox/result.py
deleted file mode 100644
index bad8cc3..0000000
--- a/tox/result.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import sys
-import py
-from tox import __version__ as toxver
-import json
-
-
-class ResultLog:
-
- def __init__(self, dict=None):
- if dict is None:
- dict = {}
- self.dict = dict
- self.dict.update({"reportversion": "1", "toxversion": toxver})
- self.dict["platform"] = sys.platform
- self.dict["host"] = py.std.socket.getfqdn()
-
- def set_header(self, installpkg):
- """
- :param py.path.local installpkg: Path ot the package.
- """
- self.dict["installpkg"] = dict(
- md5=installpkg.computehash("md5"),
- sha256=installpkg.computehash("sha256"),
- basename=installpkg.basename,
- )
-
- def get_envlog(self, name):
- testenvs = self.dict.setdefault("testenvs", {})
- d = testenvs.setdefault(name, {})
- return EnvLog(self, name, d)
-
- def dumps_json(self):
- return json.dumps(self.dict, indent=2)
-
- @classmethod
- def loads_json(cls, data):
- return cls(json.loads(data))
-
-
-class EnvLog:
- def __init__(self, reportlog, name, dict):
- self.reportlog = reportlog
- self.name = name
- self.dict = dict
-
- def set_python_info(self, pythonexecutable):
- pythonexecutable = py.path.local(pythonexecutable)
- out = pythonexecutable.sysexec("-c",
- "import sys; "
- "print(sys.executable);"
- "print(list(sys.version_info)); "
- "print(sys.version)")
- lines = out.splitlines()
- executable = lines.pop(0)
- version_info = eval(lines.pop(0))
- version = "\n".join(lines)
- self.dict["python"] = dict(
- executable=executable,
- version_info=version_info,
- version=version)
-
- def get_commandlog(self, name):
- l = self.dict.setdefault(name, [])
- return CommandLog(self, l)
-
- def set_installed(self, packages):
- self.dict["installed_packages"] = packages
-
-
-class CommandLog:
- def __init__(self, envlog, list):
- self.envlog = envlog
- self.list = list
-
- def add_command(self, argv, output, retcode):
- d = {}
- self.list.append(d)
- d["command"] = argv
- d["output"] = output
- d["retcode"] = str(retcode)
- return d
diff --git a/tox/session.py b/tox/session.py
deleted file mode 100644
index e29696e..0000000
--- a/tox/session.py
+++ /dev/null
@@ -1,682 +0,0 @@
-"""
-Automatically package and test a Python project against configurable
-Python2 and Python3 based virtual environments. Environments are
-setup by using virtualenv. Configuration is generally done through an
-INI-style "tox.ini" file.
-"""
-from __future__ import with_statement
-
-import tox
-import py
-import os
-import sys
-import subprocess
-from tox._verlib import NormalizedVersion, IrrationalVersionError
-from tox.venv import VirtualEnv
-from tox.config import parseconfig
-from tox.result import ResultLog
-from subprocess import STDOUT
-
-
-def now():
- return py.std.time.time()
-
-
-def prepare(args):
- config = parseconfig(args)
- if config.option.help:
- show_help(config)
- raise SystemExit(0)
- elif config.option.helpini:
- show_help_ini(config)
- raise SystemExit(0)
- return config
-
-
-def main(args=None):
- try:
- config = prepare(args)
- retcode = Session(config).runcommand()
- raise SystemExit(retcode)
- except KeyboardInterrupt:
- raise SystemExit(2)
- except tox.exception.MinVersionError as e:
- r = Reporter(None)
- r.error(e.message)
- raise SystemExit(1)
-
-
-def show_help(config):
- tw = py.io.TerminalWriter()
- tw.write(config._parser._format_help())
- tw.line()
- tw.line("Environment variables", bold=True)
- tw.line("TOXENV: comma separated list of environments "
- "(overridable by '-e')")
- tw.line("TOX_TESTENV_PASSENV: space-separated list of extra "
- "environment variables to be passed into test command "
- "environments")
-
-
-def show_help_ini(config):
- tw = py.io.TerminalWriter()
- tw.sep("-", "per-testenv attributes")
- for env_attr in config._testenv_attr:
- tw.line("%-15s %-8s default: %s" %
- (env_attr.name, "<" + env_attr.type + ">", env_attr.default), bold=True)
- tw.line(env_attr.help)
- tw.line()
-
-
-class Action(object):
- def __init__(self, session, venv, msg, args):
- self.venv = venv
- self.msg = msg
- self.activity = msg.split(" ", 1)[0]
- self.session = session
- self.report = session.report
- self.args = args
- self.id = venv and venv.envconfig.envname or "tox"
- self._popenlist = []
- if self.venv:
- self.venvname = self.venv.name
- else:
- self.venvname = "GLOB"
- if msg == "runtests":
- cat = "test"
- else:
- cat = "setup"
- envlog = session.resultlog.get_envlog(self.venvname)
- self.commandlog = envlog.get_commandlog(cat)
-
- def __enter__(self):
- self.report.logaction_start(self)
-
- def __exit__(self, *args):
- self.report.logaction_finish(self)
-
- def setactivity(self, name, msg):
- self.activity = name
- self.report.verbosity0("%s %s: %s" % (self.venvname, name, msg), bold=True)
-
- def info(self, name, msg):
- self.report.verbosity1("%s %s: %s" % (self.venvname, name, msg), bold=True)
-
- def _initlogpath(self, actionid):
- if self.venv:
- logdir = self.venv.envconfig.envlogdir
- else:
- logdir = self.session.config.logdir
- try:
- l = logdir.listdir("%s-*" % actionid)
- except py.error.ENOENT:
- logdir.ensure(dir=1)
- l = []
- num = len(l)
- path = logdir.join("%s-%s.log" % (actionid, num))
- f = path.open('w')
- f.flush()
- return f
-
- def popen(self, args, cwd=None, env=None, redirect=True, returnout=False, ignore_ret=False):
- stdout = outpath = None
- resultjson = self.session.config.option.resultjson
- if resultjson or redirect:
- fout = self._initlogpath(self.id)
- fout.write("actionid: %s\nmsg: %s\ncmdargs: %r\nenv: %s\n\n" % (
- self.id, self.msg, args, env))
- fout.flush()
- self.popen_outpath = outpath = py.path.local(fout.name)
- fin = outpath.open()
- fin.read() # read the header, so it won't be written to stdout
- stdout = fout
- elif returnout:
- stdout = subprocess.PIPE
- if cwd is None:
- # XXX cwd = self.session.config.cwd
- cwd = py.path.local()
- try:
- popen = self._popen(args, cwd, env=env,
- stdout=stdout, stderr=STDOUT)
- except OSError as e:
- self.report.error("invocation failed (errno %d), args: %s, cwd: %s" %
- (e.errno, args, cwd))
- raise
- popen.outpath = outpath
- popen.args = [str(x) for x in args]
- popen.cwd = cwd
- popen.action = self
- self._popenlist.append(popen)
- try:
- self.report.logpopen(popen, env=env)
- try:
- if resultjson and not redirect:
- assert popen.stderr is None # prevent deadlock
- out = None
- last_time = now()
- while 1:
- fin_pos = fin.tell()
- # we have to read one byte at a time, otherwise there
- # might be no output for a long time with slow tests
- data = fin.read(1)
- if data:
- sys.stdout.write(data)
- if '\n' in data or (now() - last_time) > 1:
- # we flush on newlines or after 1 second to
- # provide quick enough feedback to the user
- # when printing a dot per test
- sys.stdout.flush()
- last_time = now()
- elif popen.poll() is not None:
- if popen.stdout is not None:
- popen.stdout.close()
- break
- else:
- py.std.time.sleep(0.1)
- fin.seek(fin_pos)
- fin.close()
- else:
- out, err = popen.communicate()
- except KeyboardInterrupt:
- self.report.keyboard_interrupt()
- popen.wait()
- raise KeyboardInterrupt()
- ret = popen.wait()
- finally:
- self._popenlist.remove(popen)
- if ret and not ignore_ret:
- invoked = " ".join(map(str, popen.args))
- if outpath:
- self.report.error("invocation failed (exit code %d), logfile: %s" %
- (ret, outpath))
- out = outpath.read()
- self.report.error(out)
- if hasattr(self, "commandlog"):
- self.commandlog.add_command(popen.args, out, ret)
- raise tox.exception.InvocationError(
- "%s (see %s)" % (invoked, outpath), ret)
- else:
- raise tox.exception.InvocationError("%r" % (invoked, ), ret)
- if not out and outpath:
- out = outpath.read()
- if hasattr(self, "commandlog"):
- self.commandlog.add_command(popen.args, out, ret)
- return out
-
- def _rewriteargs(self, cwd, args):
- newargs = []
- for arg in args:
- if sys.platform != "win32" and isinstance(arg, py.path.local):
- arg = cwd.bestrelpath(arg)
- newargs.append(str(arg))
-
- # subprocess does not always take kindly to .py scripts
- # so adding the interpreter here.
- if sys.platform == "win32":
- ext = os.path.splitext(str(newargs[0]))[1].lower()
- if ext == '.py' and self.venv:
- newargs = [str(self.venv.envconfig.envpython)] + newargs
-
- return newargs
-
- def _popen(self, args, cwd, stdout, stderr, env=None):
- args = self._rewriteargs(cwd, args)
- if env is None:
- env = os.environ.copy()
- return self.session.popen(args, shell=False, cwd=str(cwd),
- universal_newlines=True,
- stdout=stdout, stderr=stderr, env=env)
-
-
-class Reporter(object):
- actionchar = "-"
-
- def __init__(self, session):
- self.tw = py.io.TerminalWriter()
- self.session = session
- self._reportedlines = []
- # self.cumulated_time = 0.0
-
- def _get_verbosity(self):
- if self.session:
- return self.session.config.option.verbosity
- else:
- return 2
-
- def logpopen(self, popen, env):
- """ log information about the action.popen() created process. """
- cmd = " ".join(map(str, popen.args))
- if popen.outpath:
- self.verbosity1(" %s$ %s >%s" % (popen.cwd, cmd, popen.outpath,))
- else:
- self.verbosity1(" %s$ %s " % (popen.cwd, cmd))
-
- def logaction_start(self, action):
- msg = action.msg + " " + " ".join(map(str, action.args))
- self.verbosity2("%s start: %s" % (action.venvname, msg), bold=True)
- assert not hasattr(action, "_starttime")
- action._starttime = now()
-
- def logaction_finish(self, action):
- duration = now() - action._starttime
- # self.cumulated_time += duration
- self.verbosity2("%s finish: %s after %.2f seconds" % (
- action.venvname, action.msg, duration), bold=True)
- delattr(action, '_starttime')
-
- def startsummary(self):
- self.tw.sep("_", "summary")
-
- def info(self, msg):
- if self._get_verbosity() >= 2:
- self.logline(msg)
-
- def using(self, msg):
- if self._get_verbosity() >= 1:
- self.logline("using %s" % (msg,), bold=True)
-
- def keyboard_interrupt(self):
- self.error("KEYBOARDINTERRUPT")
-
-# def venv_installproject(self, venv, pkg):
-# self.logline("installing to %s: %s" % (venv.envconfig.envname, pkg))
-
- def keyvalue(self, name, value):
- if name.endswith(":"):
- name += " "
- self.tw.write(name, bold=True)
- self.tw.write(value)
- self.tw.line()
-
- def line(self, msg, **opts):
- self.logline(msg, **opts)
-
- def good(self, msg):
- self.logline(msg, green=True)
-
- def warning(self, msg):
- self.logline("WARNING:" + msg, red=True)
-
- def error(self, msg):
- self.logline("ERROR: " + msg, red=True)
-
- def skip(self, msg):
- self.logline("SKIPPED:" + msg, yellow=True)
-
- def logline(self, msg, **opts):
- self._reportedlines.append(msg)
- self.tw.line("%s" % msg, **opts)
-
- def verbosity0(self, msg, **opts):
- if self._get_verbosity() >= 0:
- self.logline("%s" % msg, **opts)
-
- def verbosity1(self, msg, **opts):
- if self._get_verbosity() >= 1:
- self.logline("%s" % msg, **opts)
-
- def verbosity2(self, msg, **opts):
- if self._get_verbosity() >= 2:
- self.logline("%s" % msg, **opts)
-
- # def log(self, msg):
- # py.builtin.print_(msg, file=sys.stderr)
-
-
-class Session:
- """ (unstable API). the session object that ties
- together configuration, reporting, venv creation, testing. """
-
- def __init__(self, config, popen=subprocess.Popen, Report=Reporter):
- self.config = config
- self.popen = popen
- self.resultlog = ResultLog()
- self.report = Report(self)
- self.make_emptydir(config.logdir)
- config.logdir.ensure(dir=1)
- # self.report.using("logdir %s" %(self.config.logdir,))
- self.report.using("tox.ini: %s" % (self.config.toxinipath,))
- self._spec2pkg = {}
- self._name2venv = {}
- try:
- self.venvlist = [
- self.getvenv(x)
- for x in self.config.envlist
- ]
- except LookupError:
- raise SystemExit(1)
- self._actions = []
-
- @property
- def hook(self):
- return self.config.pluginmanager.hook
-
- def _makevenv(self, name):
- envconfig = self.config.envconfigs.get(name, None)
- if envconfig is None:
- self.report.error("unknown environment %r" % name)
- raise LookupError(name)
- venv = VirtualEnv(envconfig=envconfig, session=self)
- self._name2venv[name] = venv
- return venv
-
- def getvenv(self, name):
- """ return a VirtualEnv controler object for the 'name' env. """
- try:
- return self._name2venv[name]
- except KeyError:
- return self._makevenv(name)
-
- def newaction(self, venv, msg, *args):
- action = Action(self, venv, msg, args)
- self._actions.append(action)
- return action
-
- def runcommand(self):
- self.report.using("tox-%s from %s" % (tox.__version__, tox.__file__))
- if self.config.option.showconfig:
- self.showconfig()
- elif self.config.option.listenvs:
- self.showenvs()
- else:
- return self.subcommand_test()
-
- def _copyfiles(self, srcdir, pathlist, destdir):
- for relpath in pathlist:
- src = srcdir.join(relpath)
- if not src.check():
- self.report.error("missing source file: %s" % (src,))
- raise SystemExit(1)
- target = destdir.join(relpath)
- target.dirpath().ensure(dir=1)
- src.copy(target)
-
- def _makesdist(self):
- setup = self.config.setupdir.join("setup.py")
- if not setup.check():
- raise tox.exception.MissingFile(setup)
- action = self.newaction(None, "packaging")
- with action:
- action.setactivity("sdist-make", setup)
- self.make_emptydir(self.config.distdir)
- action.popen([sys.executable, setup, "sdist", "--formats=zip",
- "--dist-dir", self.config.distdir, ],
- cwd=self.config.setupdir)
- try:
- return self.config.distdir.listdir()[0]
- except py.error.ENOENT:
- # check if empty or comment only
- data = []
- with open(str(setup)) as fp:
- for line in fp:
- if line and line[0] == '#':
- continue
- data.append(line)
- if not ''.join(data).strip():
- self.report.error(
- 'setup.py is empty'
- )
- raise SystemExit(1)
- self.report.error(
- 'No dist directory found. Please check setup.py, e.g with:\n'
- ' python setup.py sdist'
- )
- raise SystemExit(1)
-
- def make_emptydir(self, path):
- if path.check():
- self.report.info(" removing %s" % path)
- py.std.shutil.rmtree(str(path), ignore_errors=True)
- path.ensure(dir=1)
-
- def setupenv(self, venv):
- if not venv.matching_platform():
- venv.status = "platform mismatch"
- return # we simply omit non-matching platforms
- action = self.newaction(venv, "getenv", venv.envconfig.envdir)
- with action:
- venv.status = 0
- envlog = self.resultlog.get_envlog(venv.name)
- try:
- status = venv.update(action=action)
- except tox.exception.InvocationError:
- status = sys.exc_info()[1]
- if status:
- commandlog = envlog.get_commandlog("setup")
- commandlog.add_command(["setup virtualenv"], str(status), 1)
- venv.status = status
- self.report.error(str(status))
- return False
- commandpath = venv.getcommandpath("python")
- envlog.set_python_info(commandpath)
- return True
-
- def finishvenv(self, venv):
- action = self.newaction(venv, "finishvenv")
- with action:
- venv.finish()
- return True
-
- def developpkg(self, venv, setupdir):
- action = self.newaction(venv, "developpkg", setupdir)
- with action:
- try:
- venv.developpkg(setupdir, action)
- return True
- except tox.exception.InvocationError:
- venv.status = sys.exc_info()[1]
- return False
-
- def installpkg(self, venv, path):
- """Install package in the specified virtual environment.
-
- :param :class:`tox.config.VenvConfig`: Destination environment
- :param str path: Path to the distribution package.
- :return: True if package installed otherwise False.
- :rtype: bool
- """
- self.resultlog.set_header(installpkg=py.path.local(path))
- action = self.newaction(venv, "installpkg", path)
- with action:
- try:
- venv.installpkg(path, action)
- return True
- except tox.exception.InvocationError:
- venv.status = sys.exc_info()[1]
- return False
-
- def get_installpkg_path(self):
- """
- :return: Path to the distribution
- :rtype: py.path.local
- """
- if not self.config.option.sdistonly and (self.config.sdistsrc or
- self.config.option.installpkg):
- path = self.config.option.installpkg
- if not path:
- path = self.config.sdistsrc
- path = self._resolve_pkg(path)
- self.report.info("using package %r, skipping 'sdist' activity " %
- str(path))
- else:
- try:
- path = self._makesdist()
- except tox.exception.InvocationError:
- v = sys.exc_info()[1]
- self.report.error("FAIL could not package project - v = %r" %
- v)
- return
- sdistfile = self.config.distshare.join(path.basename)
- if sdistfile != path:
- self.report.info("copying new sdistfile to %r" %
- str(sdistfile))
- try:
- sdistfile.dirpath().ensure(dir=1)
- except py.error.Error:
- self.report.warning("could not copy distfile to %s" %
- sdistfile.dirpath())
- else:
- path.copy(sdistfile)
- return path
-
- def subcommand_test(self):
- if self.config.skipsdist:
- self.report.info("skipping sdist step")
- path = None
- else:
- path = self.get_installpkg_path()
- if not path:
- return 2
- if self.config.option.sdistonly:
- return
- for venv in self.venvlist:
- if self.setupenv(venv):
- if venv.envconfig.usedevelop:
- self.developpkg(venv, self.config.setupdir)
- elif self.config.skipsdist or venv.envconfig.skip_install:
- self.finishvenv(venv)
- else:
- self.installpkg(venv, path)
-
- # write out version dependency information
- action = self.newaction(venv, "envreport")
- with action:
- args = venv.envconfig.list_dependencies_command
- output = venv._pcall(args,
- cwd=self.config.toxinidir,
- action=action)
- # the output contains a mime-header, skip it
- output = output.split("\n\n")[-1]
- packages = output.strip().split("\n")
- action.setactivity("installed", ",".join(packages))
- envlog = self.resultlog.get_envlog(venv.name)
- envlog.set_installed(packages)
-
- self.runtestenv(venv)
- retcode = self._summary()
- return retcode
-
- def runtestenv(self, venv, redirect=False):
- if not self.config.option.notest:
- if venv.status:
- return
- self.hook.tox_runtest_pre(venv=venv)
- venv.test(redirect=redirect)
- self.hook.tox_runtest_post(venv=venv)
- else:
- venv.status = "skipped tests"
-
- def _summary(self):
- self.report.startsummary()
- retcode = 0
- for venv in self.venvlist:
- status = venv.status
- if isinstance(status, tox.exception.InterpreterNotFound):
- msg = " %s: %s" % (venv.envconfig.envname, str(status))
- if self.config.option.skip_missing_interpreters:
- self.report.skip(msg)
- else:
- retcode = 1
- self.report.error(msg)
- elif status == "platform mismatch":
- msg = " %s: %s" % (venv.envconfig.envname, str(status))
- self.report.skip(msg)
- elif status and status == "ignored failed command":
- msg = " %s: %s" % (venv.envconfig.envname, str(status))
- self.report.good(msg)
- elif status and status != "skipped tests":
- msg = " %s: %s" % (venv.envconfig.envname, str(status))
- self.report.error(msg)
- retcode = 1
- else:
- if not status:
- status = "commands succeeded"
- self.report.good(" %s: %s" % (venv.envconfig.envname, status))
- if not retcode:
- self.report.good(" congratulations :)")
-
- path = self.config.option.resultjson
- if path:
- path = py.path.local(path)
- path.write(self.resultlog.dumps_json())
- self.report.line("wrote json report at: %s" % path)
- return retcode
-
- def showconfig(self):
- self.info_versions()
- self.report.keyvalue("config-file:", self.config.option.configfile)
- self.report.keyvalue("toxinipath: ", self.config.toxinipath)
- self.report.keyvalue("toxinidir: ", self.config.toxinidir)
- self.report.keyvalue("toxworkdir: ", self.config.toxworkdir)
- self.report.keyvalue("setupdir: ", self.config.setupdir)
- self.report.keyvalue("distshare: ", self.config.distshare)
- self.report.keyvalue("skipsdist: ", self.config.skipsdist)
- self.report.tw.line()
- for envconfig in self.config.envconfigs.values():
- self.report.line("[testenv:%s]" % envconfig.envname, bold=True)
- for attr in self.config._parser._testenv_attr:
- self.report.line(" %-15s = %s"
- % (attr.name, getattr(envconfig, attr.name)))
-
- def showenvs(self):
- for env in self.config.envlist:
- self.report.line("%s" % env)
-
- def info_versions(self):
- versions = ['tox-%s' % tox.__version__]
- try:
- version = py.process.cmdexec("virtualenv --version")
- except py.process.cmdexec.Error:
- versions.append("virtualenv-1.9.1 (vendored)")
- else:
- versions.append("virtualenv-%s" % version.strip())
- self.report.keyvalue("tool-versions:", " ".join(versions))
-
- def _resolve_pkg(self, pkgspec):
- try:
- return self._spec2pkg[pkgspec]
- except KeyError:
- self._spec2pkg[pkgspec] = x = self._resolvepkg(pkgspec)
- return x
-
- def _resolvepkg(self, pkgspec):
- if not os.path.isabs(str(pkgspec)):
- return pkgspec
- p = py.path.local(pkgspec)
- if p.check():
- return p
- if not p.dirpath().check(dir=1):
- raise tox.exception.MissingDirectory(p.dirpath())
- self.report.info("determining %s" % p)
- candidates = p.dirpath().listdir(p.basename)
- if len(candidates) == 0:
- raise tox.exception.MissingDependency(pkgspec)
- if len(candidates) > 1:
- items = []
- for x in candidates:
- ver = getversion(x.basename)
- if ver is not None:
- items.append((ver, x))
- else:
- self.report.warning("could not determine version of: %s" %
- str(x))
- items.sort()
- if not items:
- raise tox.exception.MissingDependency(pkgspec)
- return items[-1][1]
- else:
- return candidates[0]
-
-
-_rex_getversion = py.std.re.compile("[\w_\-\+\.]+-(.*)(\.zip|\.tar.gz)")
-
-
-def getversion(basename):
- m = _rex_getversion.match(basename)
- if m is None:
- return None
- version = m.group(1)
- try:
- return NormalizedVersion(version)
- except IrrationalVersionError:
- return None
diff --git a/tox/venv.py b/tox/venv.py
deleted file mode 100644
index 0461fc7..0000000
--- a/tox/venv.py
+++ /dev/null
@@ -1,416 +0,0 @@
-from __future__ import with_statement
-import os
-import sys
-import re
-import codecs
-import py
-import tox
-from .config import DepConfig, hookimpl
-
-
-class CreationConfig:
- def __init__(self, md5, python, version, sitepackages,
- usedevelop, deps):
- self.md5 = md5
- self.python = python
- self.version = version
- self.sitepackages = sitepackages
- self.usedevelop = usedevelop
- self.deps = deps
-
- def writeconfig(self, path):
- lines = ["%s %s" % (self.md5, self.python)]
- lines.append("%s %d %d" % (self.version, self.sitepackages, self.usedevelop))
- for dep in self.deps:
- lines.append("%s %s" % dep)
- path.ensure()
- path.write("\n".join(lines))
-
- @classmethod
- def readconfig(cls, path):
- try:
- lines = path.readlines(cr=0)
- value = lines.pop(0).split(None, 1)
- md5, python = value
- version, sitepackages, usedevelop = lines.pop(0).split(None, 3)
- sitepackages = bool(int(sitepackages))
- usedevelop = bool(int(usedevelop))
- deps = []
- for line in lines:
- md5, depstring = line.split(None, 1)
- deps.append((md5, depstring))
- return CreationConfig(md5, python, version, sitepackages, usedevelop, deps)
- except Exception:
- return None
-
- def matches(self, other):
- return (other and self.md5 == other.md5
- and self.python == other.python
- and self.version == other.version
- and self.sitepackages == other.sitepackages
- and self.usedevelop == other.usedevelop
- and self.deps == other.deps)
-
-
-class VirtualEnv(object):
- def __init__(self, envconfig=None, session=None):
- self.envconfig = envconfig
- self.session = session
-
- @property
- def hook(self):
- return self.envconfig.config.pluginmanager.hook
-
- @property
- def path(self):
- """ Path to environment base dir. """
- return self.envconfig.envdir
-
- @property
- def path_config(self):
- return self.path.join(".tox-config1")
-
- @property
- def name(self):
- """ test environment name. """
- return self.envconfig.envname
-
- def __repr__(self):
- return "<VirtualEnv at %r>" % (self.path)
-
- def getcommandpath(self, name, venv=True, cwd=None):
- """ Return absolute path (str or localpath) for specified command name.
- - If it's a local path we will rewrite it as as a relative path.
- - If venv is True we will check if the command is coming from the venv
- or is whitelisted to come from external.
- """
- name = str(name)
- if os.path.isabs(name):
- return name
- if os.path.split(name)[0] == ".":
- path = cwd.join(name)
- if path.check():
- return str(path)
-
- if venv:
- path = self._venv_lookup_and_check_external_whitelist(name)
- else:
- path = self._normal_lookup(name)
-
- if path is None:
- raise tox.exception.InvocationError(
- "could not find executable %r" % (name,))
-
- return str(path) # will not be rewritten for reporting
-
- def _venv_lookup_and_check_external_whitelist(self, name):
- path = self._venv_lookup(name)
- if path is None:
- path = self._normal_lookup(name)
- if path is not None:
- self._check_external_allowed_and_warn(path)
- return path
-
- def _venv_lookup(self, name):
- return py.path.local.sysfind(name, paths=[self.envconfig.envbindir])
-
- def _normal_lookup(self, name):
- return py.path.local.sysfind(name)
-
- def _check_external_allowed_and_warn(self, path):
- if not self.is_allowed_external(path):
- self.session.report.warning(
- "test command found but not installed in testenv\n"
- " cmd: %s\n"
- " env: %s\n"
- "Maybe you forgot to specify a dependency? "
- "See also the whitelist_externals envconfig setting." % (
- path, self.envconfig.envdir))
-
- def is_allowed_external(self, p):
- tryadd = [""]
- if sys.platform == "win32":
- tryadd += [
- os.path.normcase(x)
- for x in os.environ['PATHEXT'].split(os.pathsep)
- ]
- p = py.path.local(os.path.normcase(str(p)))
- for x in self.envconfig.whitelist_externals:
- for add in tryadd:
- if p.fnmatch(x + add):
- return True
- return False
-
- def _ispython3(self):
- return "python3" in str(self.envconfig.basepython)
-
- def update(self, action):
- """ return status string for updating actual venv to match configuration.
- if status string is empty, all is ok.
- """
- rconfig = CreationConfig.readconfig(self.path_config)
- if not self.envconfig.recreate and rconfig and \
- rconfig.matches(self._getliveconfig()):
- action.info("reusing", self.envconfig.envdir)
- return
- if rconfig is None:
- action.setactivity("create", self.envconfig.envdir)
- else:
- action.setactivity("recreate", self.envconfig.envdir)
- try:
- self.hook.tox_testenv_create(action=action, venv=self)
- self.just_created = True
- except tox.exception.UnsupportedInterpreter:
- return sys.exc_info()[1]
- except tox.exception.InterpreterNotFound:
- return sys.exc_info()[1]
- try:
- self.hook.tox_testenv_install_deps(action=action, venv=self)
- except tox.exception.InvocationError:
- v = sys.exc_info()[1]
- return "could not install deps %s; v = %r" % (
- self.envconfig.deps, v)
-
- def _getliveconfig(self):
- python = self.envconfig.python_info.executable
- md5 = getdigest(python)
- version = tox.__version__
- sitepackages = self.envconfig.sitepackages
- develop = self.envconfig.usedevelop
- deps = []
- for dep in self._getresolvedeps():
- raw_dep = dep.name
- md5 = getdigest(raw_dep)
- deps.append((md5, raw_dep))
- return CreationConfig(md5, python, version,
- sitepackages, develop, deps)
-
- def _getresolvedeps(self):
- l = []
- for dep in self.envconfig.deps:
- if dep.indexserver is None:
- res = self.session._resolve_pkg(dep.name)
- if res != dep.name:
- dep = dep.__class__(res)
- l.append(dep)
- return l
-
- def getsupportedinterpreter(self):
- return self.envconfig.getsupportedinterpreter()
-
- def matching_platform(self):
- return re.match(self.envconfig.platform, sys.platform)
-
- def finish(self):
- self._getliveconfig().writeconfig(self.path_config)
-
- def _needs_reinstall(self, setupdir, action):
- setup_py = setupdir.join('setup.py')
- setup_cfg = setupdir.join('setup.cfg')
- args = [self.envconfig.envpython, str(setup_py), '--name']
- output = action.popen(args, cwd=setupdir, redirect=False,
- returnout=True)
- name = output.strip()
- egg_info = setupdir.join('.'.join((name, 'egg-info')))
- for conf_file in (setup_py, setup_cfg):
- if (not egg_info.check()
- or (conf_file.check() and conf_file.mtime() > egg_info.mtime())):
- return True
- return False
-
- def developpkg(self, setupdir, action):
- assert action is not None
- if getattr(self, 'just_created', False):
- action.setactivity("develop-inst", setupdir)
- self.finish()
- extraopts = []
- else:
- if not self._needs_reinstall(setupdir, action):
- action.setactivity("develop-inst-noop", setupdir)
- return
- action.setactivity("develop-inst-nodeps", setupdir)
- extraopts = ['--no-deps']
- self._install(['-e', setupdir], extraopts=extraopts, action=action)
-
- def installpkg(self, sdistpath, action):
- assert action is not None
- if getattr(self, 'just_created', False):
- action.setactivity("inst", sdistpath)
- self.finish()
- extraopts = []
- else:
- action.setactivity("inst-nodeps", sdistpath)
- extraopts = ['-U', '--no-deps']
- self._install([sdistpath], extraopts=extraopts, action=action)
-
- def _installopts(self, indexserver):
- l = []
- if indexserver:
- l += ["-i", indexserver]
- if self.envconfig.downloadcache:
- self.envconfig.downloadcache.ensure(dir=1)
- l.append("--download-cache=%s" % self.envconfig.downloadcache)
- if self.envconfig.pip_pre:
- l.append("--pre")
- return l
-
- def run_install_command(self, packages, action, options=()):
- argv = self.envconfig.install_command[:]
- # use pip-script on win32 to avoid the executable locking
- i = argv.index('{packages}')
- argv[i:i + 1] = packages
- if '{opts}' in argv:
- i = argv.index('{opts}')
- argv[i:i + 1] = list(options)
-
- for x in ('PIP_RESPECT_VIRTUALENV', 'PIP_REQUIRE_VIRTUALENV',
- '__PYVENV_LAUNCHER__'):
- os.environ.pop(x, None)
-
- old_stdout = sys.stdout
- sys.stdout = codecs.getwriter('utf8')(sys.stdout)
- self._pcall(argv, cwd=self.envconfig.config.toxinidir, action=action)
- sys.stdout = old_stdout
-
- def _install(self, deps, extraopts=None, action=None):
- if not deps:
- return
- d = {}
- l = []
- for dep in deps:
- if isinstance(dep, (str, py.path.local)):
- dep = DepConfig(str(dep), None)
- assert isinstance(dep, DepConfig), dep
- if dep.indexserver is None:
- ixserver = self.envconfig.config.indexserver['default']
- else:
- ixserver = dep.indexserver
- d.setdefault(ixserver, []).append(dep.name)
- if ixserver not in l:
- l.append(ixserver)
- assert ixserver.url is None or isinstance(ixserver.url, str)
-
- for ixserver in l:
- packages = d[ixserver]
- options = self._installopts(ixserver.url)
- if extraopts:
- options.extend(extraopts)
- self.run_install_command(packages=packages, options=options,
- action=action)
-
- def _getenv(self, testcommand=False):
- if testcommand:
- # for executing tests we construct a clean environment
- env = {}
- for envname in self.envconfig.passenv:
- if envname in os.environ:
- env[envname] = os.environ[envname]
- else:
- # for executing non-test commands we use the full
- # invocation environment
- env = os.environ.copy()
-
- # in any case we honor per-testenv setenv configuration
- env.update(self.envconfig.setenv)
-
- env['VIRTUAL_ENV'] = str(self.path)
- return env
-
- def test(self, redirect=False):
- action = self.session.newaction(self, "runtests")
- with action:
- self.status = 0
- self.session.make_emptydir(self.envconfig.envtmpdir)
- cwd = self.envconfig.changedir
- env = self._getenv(testcommand=True)
- # Display PYTHONHASHSEED to assist with reproducibility.
- action.setactivity("runtests", "PYTHONHASHSEED=%r" % env.get('PYTHONHASHSEED'))
- for i, argv in enumerate(self.envconfig.commands):
- # have to make strings as _pcall changes argv[0] to a local()
- # happens if the same environment is invoked twice
- message = "commands[%s] | %s" % (i, ' '.join(
- [str(x) for x in argv]))
- action.setactivity("runtests", message)
- # check to see if we need to ignore the return code
- # if so, we need to alter the command line arguments
- if argv[0].startswith("-"):
- ignore_ret = True
- if argv[0] == "-":
- del argv[0]
- else:
- argv[0] = argv[0].lstrip("-")
- else:
- ignore_ret = False
-
- try:
- self._pcall(argv, cwd=cwd, action=action, redirect=redirect,
- ignore_ret=ignore_ret, testcommand=True)
- except tox.exception.InvocationError as err:
- if self.envconfig.ignore_outcome:
- self.session.report.warning(
- "command failed but result from testenv is ignored\n"
- " cmd: %s" % (str(err),))
- self.status = "ignored failed command"
- continue # keep processing commands
-
- self.session.report.error(str(err))
- self.status = "commands failed"
- if not self.envconfig.ignore_errors:
- break # Don't process remaining commands
- except KeyboardInterrupt:
- self.status = "keyboardinterrupt"
- self.session.report.error(self.status)
- raise
-
- def _pcall(self, args, cwd, venv=True, testcommand=False,
- action=None, redirect=True, ignore_ret=False):
- for name in ("VIRTUALENV_PYTHON", "PYTHONDONTWRITEBYTECODE"):
- os.environ.pop(name, None)
-
- cwd.ensure(dir=1)
- args[0] = self.getcommandpath(args[0], venv, cwd)
- env = self._getenv(testcommand=testcommand)
- bindir = str(self.envconfig.envbindir)
- env['PATH'] = p = os.pathsep.join([bindir, os.environ["PATH"]])
- self.session.report.verbosity2("setting PATH=%s" % p)
- return action.popen(args, cwd=cwd, env=env,
- redirect=redirect, ignore_ret=ignore_ret)
-
-
-def getdigest(path):
- path = py.path.local(path)
- if not path.check(file=1):
- return "0" * 32
- return path.computehash()
-
-
-@hookimpl
-def tox_testenv_create(venv, action):
- # if self.getcommandpath("activate").dirpath().check():
- # return
- config_interpreter = venv.getsupportedinterpreter()
- args = [sys.executable, '-m', 'virtualenv']
- if venv.envconfig.sitepackages:
- args.append('--system-site-packages')
- # add interpreter explicitly, to prevent using
- # default (virtualenv.ini)
- args.extend(['--python', str(config_interpreter)])
- # if sys.platform == "win32":
- # f, path, _ = py.std.imp.find_module("virtualenv")
- # f.close()
- # args[:1] = [str(config_interpreter), str(path)]
- # else:
- venv.session.make_emptydir(venv.path)
- basepath = venv.path.dirpath()
- basepath.ensure(dir=1)
- args.append(venv.path.basename)
- venv._pcall(args, venv=False, action=action, cwd=basepath)
-
-
-@hookimpl
-def tox_testenv_install_deps(venv, action):
- deps = venv._getresolvedeps()
- if deps:
- depinfo = ", ".join(map(str, deps))
- action.setactivity("installdeps", "%s" % depinfo)
- venv._install(deps, action=action)