Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog/2408.doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add new documentation for tox 4 - by :user:`gaborbernat`.
8 changes: 7 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@
nitpicky = True
nitpick_ignore = []
linkcheck_workers = 10
linkcheck_ignore = [re.escape(r"https://github.com/tox-dev/tox/issues/new?title=Trouble+with+development+environment")]
linkcheck_ignore = [
re.escape(i)
for i in (
r"https://github.com/tox-dev/tox/issues/new?title=Trouble+with+development+environment",
r"https://www.unix.org/version2/sample/abort.html",
)
]
extlinks_detect_hardcoded_links = True


Expand Down
47 changes: 31 additions & 16 deletions docs/config.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _configuration:

Configuration
+++++++++++++

Expand Down Expand Up @@ -102,10 +104,10 @@ Core
:default: <empty list>
:version_added: 3.2.0

Specify a list of `PEP-508 <https://www.python.org/dev/peps/pep-0508/>`_ compliant dependencies that must be
satisfied in the Python environment hosting tox when running the tox command. If any of these dependencies are not
satisfied will automatically create a provisioned tox environment that does not have this issue, and run the tox
command within that environment. See :ref:`provision_tox_env` for more details.
Specify a list of :pep:`508` compliant dependencies that must be satisfied in the Python environment hosting tox when
running the tox command. If any of these dependencies are not satisfied will automatically create a provisioned tox
environment that does not have this issue, and run the tox command within that environment. See
:ref:`provision_tox_env` for more details.

.. code-block:: ini

Expand Down Expand Up @@ -313,9 +315,9 @@ Base options
:default: <empty list>

Each line specifies a command name (in glob-style pattern format) which can be used in the commands section even if
it's located outside of the tox environment. For example: if you use the unix make command for running tests you can list
``allowlist_externals=make`` or ``allowlist_externals=/usr/bin/make``. If you want to allow all external commands
you can use ``allowlist_externals=*`` which will match all commands (not recommended).
it's located outside of the tox environment. For example: if you use the unix *rm* command for running tests you can
list ``allowlist_externals=rm`` or ``allowlist_externals=/usr/bin/rm``. If you want to allow all external
commands you can use ``allowlist_externals=*`` which will match all commands (not recommended).

.. conf::
:keys: labels
Expand Down Expand Up @@ -527,8 +529,8 @@ Python options

Leaving this unset will cause an error if the package under test has a different Python requires than tox itself
and tox is installed into a Python that's not supported by the package. For example, if your package requires
Python 3.9 or later, and you install tox in Python 3.8, when you run a tox environment that has left this
unspecified tox will use Python 3.8 to build and install your package which will fail given it requires 3.9.
Python 3.10 or later, and you install tox in Python 3.9, when you run a tox environment that has left this
unspecified tox will use Python 3.9 to build and install your package which will fail given it requires 3.10.

.. conf::
:keys: env_site_packages_dir, envsitepackagesdir
Expand All @@ -554,9 +556,25 @@ Python run
:keys: deps
:default: <empty list>

Name of the Python dependencies as specified by `PEP-440`_. Installed into the environment prior to project after
environment creation, but before package installation. All installer commands are executed using the :ref:`tox_root`
as the current working directory.
Name of the Python dependencies. Installed into the environment prior to project after environment creation, but
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Installed into the environment prior to project after environment creation

I do not understand this sentence. Maybe "after" should be removed? Or even "project after" should be removed?

We should rephrase this sentence.

Or does it mean...

"Installed into the environment prior to project creation, after environment creation,"

If so.. I'd prefer some repetition (the word creation) to make the sentence more clear.

before package installation. All installer commands are executed using the :ref:`tox_root` as the current working
directory. Each value must be one of:

- a Python dependency as specified by :pep:`440`,
- a `requirement file <https://pip.pypa.io/en/stable/user_guide/#requirements-files>`_ when the value starts with
``-r`` (followed by a file path),
- a `constraint file <https://pip.pypa.io/en/stable/user_guide/#constraints-files>`_ when the value starts with
``-c`` (followed by a file path).

For example:

.. code-block:: ini

[testenv]
deps =
pytest>=7,<8
-r requirements.txt
-c constraints.txt

.. conf::
:keys: use_develop, usedevelop
Expand Down Expand Up @@ -610,7 +628,7 @@ tox supports operating with externally built packages. External packages might b
:default: <empty list>
:ref_suffix: external

Name of the Python dependencies as specified by `PEP-440`_. Installed into the environment prior running the build
Name of the Python dependencies as specified by :pep:`440`. Installed into the environment prior running the build
commands. All installer commands are executed using the :ref:`tox_root` as the current working directory.

.. conf::
Expand Down Expand Up @@ -731,6 +749,3 @@ Pip installer
If ``true``, adds ``--pre`` to the ``opts`` passed to :ref:`install_command`. This will cause it to install the
latest available pre-release of any dependencies without a specified version. If ``false``, pip will only install
final releases of unpinned dependencies.

.. _`PEP-508`: https://www.python.org/dev/peps/pep-0508/
.. _`PEP-440`: https://www.python.org/dev/peps/pep-0440/
167 changes: 167 additions & 0 deletions docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,50 @@ FAQ

Here you'll find answers to some frequently asked questions.

Using a custom PyPI server
--------------------------

By default tox uses pip to install Python dependencies. Therefore to change the index server you should configure pip
directly. pip accepts environment variables as configuration flags, therefore the easiest way to do this is to set the
``PIP_INDEX_URL`` environment variable:

.. code-block:: ini

set_env =
PIP_INDEX_URL = https://tox.wiki/pypi/simple

It's considered a best practice to allow the user to change the index server rather than hard code it, allowing them
to use for example a local cache when they are offline. Therefore, a better form of this would be:

.. code-block:: ini

set_env =
PIP_INDEX_URL = {env:PIP_INDEX_URL:https://tox.wiki/pypi/simple}

Here we use an environment substitution to set the index URL if not set by the user, but otherwise default to our target
URI.
Comment on lines +26 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds a bit complicated... maybe something like: "We define a default index URL, but user can override the value" .. something like that...


Using two PyPI servers
----------------------

When you want to use two PyPI index servers because not all dependencies are found in either of them use the
``PIP_EXTRA_INDEX_URL`` environment variable:

.. code-block:: ini

set_env =
PIP_INDEX_URL = {env:PIP_INDEX_URL:https://tox.wiki/pypi/simple-first}
PIP_EXTRA_INDEX_URL = {env:PIP_EXTRA_INDEX_URL:https://tox.wiki/pypi/simple-second}

If the index server defined under ``PIP_INDEX_URL`` does not contain a package, pip will attempt to resolve it also from
the URI from ``PIP_EXTRA_INDEX_URL``.

.. warning::

Using an extra PyPI index for installing private packages may cause security issues. For example, if ``package1`` is
registered with the default PyPI index, pip will install ``package1`` from the default PyPI index, not from the extra
one.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure whether this is 100% true and will stay true. I heard quite some time that there is no guaranteed order for pip using index urls, and that the current order "default PyPI index first, then extra index" is an implementation detail and could change.

Maybe @pradyunsg could kindly clarify this?

That said... I am not sure whether we should put so much pip specific documentation into the tox documentation.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty much. There's no guarentees around which one pip would use the file from, if it sees two files with the same name from two package indexes.


Using constraint files
----------------------
`Constraint files <https://pip.pypa.io/en/stable/user_guide/#constraints-files>`_ are a type of artifact, supported by
Expand Down Expand Up @@ -75,3 +119,126 @@ and the following ``tox.ini`` content:
You can invoke ``tox`` in the directory where your ``tox.ini`` resides. ``tox`` creates two virtualenv environments
with the ``python3.10`` and ``python3.9`` interpreters, respectively, and will then run the specified command according
to platform you invoke ``tox`` at.

Ignoring the exit code of a given command
-----------------------------------------

When multiple commands are defined within the :ref:`commands` configuration field tox will run them sequentially until
one of them fails (by exiting with non zero exit code) or all of them are run. If you want to ignore the status code of
a given command add a ``-`` prefix to that line (similar syntax to how the GNU ``make`` handles this):

.. code-block:: ini


Comment on lines +131 to +132
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One empty line should be enough.

[testenv]
commands =
- python -c 'import sys; sys.exit(1)'
python --version

Customizing virtual environment creation
----------------------------------------

By default tox uses the :pypi:`virtualenv` to create Python virtual environments to run your tools in. To change how tox
creates virtual environments you can set environment variables to customize virtualenv. For example, to provision a given
pip version in the virtual environment you can set ``VIRTUALENV_PIP`` or to enable system site packages use the
``VIRTUALENV_SYSTEM_SITE_PACKAGES``:


Comment on lines +145 to +146
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One empty line should be enough.

.. code-block:: ini


Comment on lines +148 to +149
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One empty line should be enough.

[testenv]
setenv =
VIRTUALENV_PIP==22.1
VIRTUALENV_SYSTEM_SITE_PACKAGES=true

Consult the :pypi:`virtualenv` project for supported values (any CLI flag for virtualenv, in all upper case, prefixed
by the ``VIRTUALENV_`` key).

Building documentation with Sphinx
----------------------------------

It's possible to orchestrate the projects documentation with tox. The advantage of this is that now generating the
documentation can be part of the CI, and whenever any validations/checks/operations fail while generating the
documentation you'll catch it within tox.

We don't recommend using the Make and Batch file generated by Sphinx, as this makes your documentation generation
platform specific. A better solution is to use tox to setup a documentation build environment and invoke sphinx inside
it. This solution is cross platform.

For example if the sphinx file structure is under the ``docs`` folder the following configuration will generate
the documentation under ``.tox/docs_out/index.html`` and print out a link to the generated documentation:

.. code-block:: ini

[testenv:docs]
description = build documentation
basepython = python3.10
deps =
sphinx>=4
commands =
sphinx-build -d "{envtmpdir}{/}doctree" docs "{toxworkdir}{/}docs_out" --color -b html
python -c 'print(r"documentation available under file://{toxworkdir}{/}docs_out{/}index.html")'

Note here we also require Python 3.10, allowing us to use f-strings within the sphinx ``conf.py``.

Building documentation with mkdocs
----------------------------------

It's possible to orchestrate the projects documentation with tox. The advantage of this is that now generating the
documentation can be part of the CI, and whenever any validations/checks/operations fail while generating the
documentation you'll catch it within tox.

It's best to define one environment to write/generate the documentation, and another to deploy it. Use the config
substitution logic to avoid duplication:

.. code-block:: ini

[testenv:docs]
description = Run a development server for working on documentation
deps =
mkdocs>=1.3
mkdocs-material
commands =
mkdocs build --clean
python -c 'print("###### Starting local server. Press Control+C to stop server ######")'
mkdocs serve -a localhost:8080

[testenv:docs-deploy]
description = built fresh docs and deploy them
deps = {[testenv:docs]deps}
commands = mkdocs gh-deploy --clean

Understanding ``InvocationError`` exit codes
--------------------------------------------

When a command executed by tox fails, it always has a non-zero exit code and an ``InvocationError`` exception is
raised:

.. code-block:: shell

ERROR: InvocationError for command
'<command defined in tox.ini>' (exited with code 1)

Generally always check the documentation for the command executed to understand what the code means. For example for
:pypi:`pytest` you'd read `here <https://docs.pytest.org/en/latest/reference/exit-codes.html#exit-codes>`_. On unix
systems, there are some rather `common exit codes <http://www.faqs.org/docs/abs/HTML/exitcodes.html>`_. This is why for
exit codes larger than 128, if a signal with number equal to ``<exit code> - 128`` is found in the :py:mod:`signal`
module, an additional hint is given:

.. code-block:: shell

ERROR: InvocationError for command
'<command>' (exited with code 139)
Note: this might indicate a fatal error signal (139 - 128 = 11: SIGSEGV)


The signal numbers (e.g. 11 for a segmentation fault) can be found in the "Standard signals" section of the
`signal man page <https://man7.org/linux/man-pages/man7/signal.7.html>`_.
Their meaning is described in `POSIX signals <https://en.wikipedia.org/wiki/Signal_(IPC)#POSIX_signals>`_. Beware
that programs may issue custom exit codes with any value, so their documentation should be consulted.


Sometimes, no exit code is given at all. An example may be found in
:gh:`pytest-qt issue #170 <pytest-dev/pytest-qt/issues/170>`, where Qt was calling
`abort() <https://www.unix.org/version2/sample/abort.html>`_ instead of ``exit()``.
25 changes: 11 additions & 14 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Installation
via pipx
--------

:pypi:`tox` is a CLI tool that needs a Python interpreter (version 3.6 or higher) to run. We recommend :pypi:`pipx` to
:pypi:`tox` is a CLI tool that needs a Python interpreter (version 3.7 or higher) to run. We recommend :pypi:`pipx` to
install tox into an isolated environment. This has the added benefit that later you'll be able to upgrade tox without
affecting other parts of the system.

Expand All @@ -30,27 +30,24 @@ state. Note, if you go down this path you need to ensure pip is new enough per t
wheel
~~~~~
Installing tox via a wheel (default with pip) requires an installer that can understand the ``python-requires`` tag (see
`PEP-503 <https://www.python.org/dev/peps/pep-0503/>`_), with pip this is version ``9.0.0`` (released in November 2016).
Furthermore, in case you're not installing it via PyPI you need to use a mirror that correctly forwards the
``python-requires`` tag (notably the OpenStack mirrors don't do this, or older :gh_repo:`devpi/devpi` versions -
added with version ``4.7.0``).
:pep:`503`), with pip this is version ``9.0.0`` (released in November 2016). Furthermore, in case you're not installing
it via PyPI you need to use a mirror that correctly forwards the ``python-requires`` tag (notably the OpenStack mirrors
don't do this, or older :gh_repo:`devpi/devpi` versions - added with version ``4.7.0``).

.. _sdist:

sdist
~~~~~
When installing via a source distribution you need an installer that handles the
`PEP-517 <https://www.python.org/dev/peps/pep-0517/>`_ specification. In case of ``pip`` this is version ``18.0.0`` or
later (released in July 2018). If you cannot upgrade your pip to support this you need to ensure that the build
requirements from :gh:`pyproject.toml <tox-dev/tox/blob/rewrite/pyproject.toml#L2>` are satisfied before triggering the
installation.
When installing via a source distribution you need an installer that handles the :pep:`517` specification. In case of
``pip`` this is version ``18.0.0`` or later (released in July 2018). If you cannot upgrade your pip to support this you
need to ensure that the build requirements from :gh:`pyproject.toml <tox-dev/tox/blob/rewrite/pyproject.toml#L2>` are
satisfied before triggering the installation.

via ``setup.py``
----------------
We don't recommend and officially support this method. You should prefer using an installer that supports
`PEP-517 <https://www.python.org/dev/peps/pep-0517/>`_ interface, such as pip ``19.0.0`` or later. That being said you
might be able to still install a package via this method if you satisfy build dependencies before calling the
installation command (as described under :ref:`sdist`).
We don't recommend and officially support this method. You should prefer using an installer that supports :pep:`517`
interface, such as pip ``19.0.0`` or later. That being said you might be able to still install a package via this method
if you satisfy build dependencies before calling the installation command (as described under :ref:`sdist`).

latest unreleased
-----------------
Expand Down
Loading