|
3 | 3 |
|
4 | 4 | Here you'll find answers to some frequently asked questions.
|
5 | 5 |
|
| 6 | +Using a custom PyPI server |
| 7 | +-------------------------- |
| 8 | + |
| 9 | +By default tox uses pip to install Python dependencies. Therefore to change the index server you should configure pip |
| 10 | +directly. pip accepts environment variables as configuration flags, therefore the easiest way to do this is to set the |
| 11 | +``PIP_INDEX_URL`` environment variable: |
| 12 | + |
| 13 | +.. code-block:: ini |
| 14 | +
|
| 15 | + set_env = |
| 16 | + PIP_INDEX_URL = https://tox.wiki/pypi/simple |
| 17 | +
|
| 18 | +It's considered a best practice to allow the user to change the index server rather than hard code it, allowing them |
| 19 | +to use for example a local cache when they are offline. Therefore, a better form of this would be: |
| 20 | + |
| 21 | +.. code-block:: ini |
| 22 | +
|
| 23 | + set_env = |
| 24 | + PIP_INDEX_URL = {env:PIP_INDEX_URL:https://tox.wiki/pypi/simple} |
| 25 | +
|
| 26 | +Here we use an environment substitution to set the index URL if not set by the user, but otherwise default to our target |
| 27 | +URI. |
| 28 | + |
| 29 | +Using two PyPI servers |
| 30 | +---------------------- |
| 31 | + |
| 32 | +When you want to use two PyPI index servers because not all dependencies are found in either of them use the |
| 33 | +``PIP_EXTRA_INDEX_URL`` environment variable: |
| 34 | + |
| 35 | +.. code-block:: ini |
| 36 | +
|
| 37 | + set_env = |
| 38 | + PIP_INDEX_URL = {env:PIP_INDEX_URL:https://tox.wiki/pypi/simple-first} |
| 39 | + PIP_EXTRA_INDEX_URL = {env:PIP_EXTRA_INDEX_URL:https://tox.wiki/pypi/simple-second} |
| 40 | +
|
| 41 | +If the index server defined under ``PIP_INDEX_URL`` does not contain a package, pip will attempt to resolve it also from |
| 42 | +the URI from ``PIP_EXTRA_INDEX_URL``. |
| 43 | + |
| 44 | +.. warning:: |
| 45 | + |
| 46 | + Using an extra PyPI index for installing private packages may cause security issues. For example, if ``package1`` is |
| 47 | + registered with the default PyPI index, pip will install ``package1`` from the default PyPI index, not from the extra |
| 48 | + one. |
| 49 | + |
6 | 50 | Using constraint files
|
7 | 51 | ----------------------
|
8 | 52 | `Constraint files <https://pip.pypa.io/en/stable/user_guide/#constraints-files>`_ are a type of artifact, supported by
|
@@ -75,3 +119,126 @@ and the following ``tox.ini`` content:
|
75 | 119 | You can invoke ``tox`` in the directory where your ``tox.ini`` resides. ``tox`` creates two virtualenv environments
|
76 | 120 | with the ``python3.10`` and ``python3.9`` interpreters, respectively, and will then run the specified command according
|
77 | 121 | to platform you invoke ``tox`` at.
|
| 122 | + |
| 123 | +Ignoring the exit code of a given command |
| 124 | +----------------------------------------- |
| 125 | + |
| 126 | +When multiple commands are defined within the :ref:`commands` configuration field tox will run them sequentially until |
| 127 | +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 |
| 128 | +a given command add a ``-`` prefix to that line (similar syntax to how the GNU ``make`` handles this): |
| 129 | + |
| 130 | +.. code-block:: ini |
| 131 | +
|
| 132 | +
|
| 133 | + [testenv] |
| 134 | + commands = |
| 135 | + - python -c 'import sys; sys.exit(1)' |
| 136 | + python --version |
| 137 | +
|
| 138 | +Customizing virtual environment creation |
| 139 | +---------------------------------------- |
| 140 | + |
| 141 | +By default tox uses the :pypi:`virtualenv` to create Python virtual environments to run your tools in. To change how tox |
| 142 | +creates virtual environments you can set environment variables to customize virtualenv. For example, to provision a given |
| 143 | +pip version in the virtual environment you can set ``VIRTUALENV_PIP`` or to enable system site packages use the |
| 144 | +``VIRTUALENV_SYSTEM_SITE_PACKAGES``: |
| 145 | + |
| 146 | + |
| 147 | +.. code-block:: ini |
| 148 | +
|
| 149 | +
|
| 150 | + [testenv] |
| 151 | + setenv = |
| 152 | + VIRTUALENV_PIP==22.1 |
| 153 | + VIRTUALENV_SYSTEM_SITE_PACKAGES=true |
| 154 | +
|
| 155 | +Consult the :pypi:`virtualenv` project for supported values (any CLI flag for virtualenv, in all upper case, prefixed |
| 156 | +by the ``VIRTUALENV_`` key). |
| 157 | + |
| 158 | +Building documentation with Sphinx |
| 159 | +---------------------------------- |
| 160 | + |
| 161 | +It's possible to orchestrate the projects documentation with tox. The advantage of this is that now generating the |
| 162 | +documentation can be part of the CI, and whenever any validations/checks/operations fail while generating the |
| 163 | +documentation you'll catch it within tox. |
| 164 | + |
| 165 | +We don't recommend using the Make and Batch file generated by Sphinx, as this makes your documentation generation |
| 166 | +platform specific. A better solution is to use tox to setup a documentation build environment and invoke sphinx inside |
| 167 | +it. This solution is cross platform. |
| 168 | + |
| 169 | +For example if the sphinx file structure is under the ``docs`` folder the following configuration will generate |
| 170 | +the documentation under ``.tox/docs_out/index.html`` and print out a link to the generated documentation: |
| 171 | + |
| 172 | +.. code-block:: ini |
| 173 | +
|
| 174 | + [testenv:docs] |
| 175 | + description = build documentation |
| 176 | + basepython = python3.10 |
| 177 | + deps = |
| 178 | + sphinx>=4 |
| 179 | + commands = |
| 180 | + sphinx-build -d "{envtmpdir}{/}doctree" docs "{toxworkdir}{/}docs_out" --color -b html |
| 181 | + python -c 'print(r"documentation available under file://{toxworkdir}{/}docs_out{/}index.html")' |
| 182 | +
|
| 183 | +Note here we also require Python 3.10, allowing us to use f-strings within the sphinx ``conf.py``. |
| 184 | + |
| 185 | +Building documentation with mkdocs |
| 186 | +---------------------------------- |
| 187 | + |
| 188 | +It's possible to orchestrate the projects documentation with tox. The advantage of this is that now generating the |
| 189 | +documentation can be part of the CI, and whenever any validations/checks/operations fail while generating the |
| 190 | +documentation you'll catch it within tox. |
| 191 | + |
| 192 | +It's best to define one environment to write/generate the documentation, and another to deploy it. Use the config |
| 193 | +substitution logic to avoid duplication: |
| 194 | + |
| 195 | +.. code-block:: ini |
| 196 | +
|
| 197 | + [testenv:docs] |
| 198 | + description = Run a development server for working on documentation |
| 199 | + deps = |
| 200 | + mkdocs>=1.3 |
| 201 | + mkdocs-material |
| 202 | + commands = |
| 203 | + mkdocs build --clean |
| 204 | + python -c 'print("###### Starting local server. Press Control+C to stop server ######")' |
| 205 | + mkdocs serve -a localhost:8080 |
| 206 | +
|
| 207 | + [testenv:docs-deploy] |
| 208 | + description = built fresh docs and deploy them |
| 209 | + deps = {[testenv:docs]deps} |
| 210 | + commands = mkdocs gh-deploy --clean |
| 211 | +
|
| 212 | +Understanding ``InvocationError`` exit codes |
| 213 | +-------------------------------------------- |
| 214 | + |
| 215 | +When a command executed by tox fails, it always has a non-zero exit code and an ``InvocationError`` exception is |
| 216 | +raised: |
| 217 | + |
| 218 | +.. code-block:: shell |
| 219 | +
|
| 220 | + ERROR: InvocationError for command |
| 221 | + '<command defined in tox.ini>' (exited with code 1) |
| 222 | +
|
| 223 | +Generally always check the documentation for the command executed to understand what the code means. For example for |
| 224 | +:pypi:`pytest` you'd read `here <https://docs.pytest.org/en/latest/reference/exit-codes.html#exit-codes>`_. On unix |
| 225 | +systems, there are some rather `common exit codes <http://www.faqs.org/docs/abs/HTML/exitcodes.html>`_. This is why for |
| 226 | +exit codes larger than 128, if a signal with number equal to ``<exit code> - 128`` is found in the :py:mod:`signal` |
| 227 | +module, an additional hint is given: |
| 228 | + |
| 229 | +.. code-block:: shell |
| 230 | +
|
| 231 | + ERROR: InvocationError for command |
| 232 | + '<command>' (exited with code 139) |
| 233 | + Note: this might indicate a fatal error signal (139 - 128 = 11: SIGSEGV) |
| 234 | +
|
| 235 | +
|
| 236 | +The signal numbers (e.g. 11 for a segmentation fault) can be found in the "Standard signals" section of the |
| 237 | +`signal man page <https://man7.org/linux/man-pages/man7/signal.7.html>`_. |
| 238 | +Their meaning is described in `POSIX signals <https://en.wikipedia.org/wiki/Signal_(IPC)#POSIX_signals>`_. Beware |
| 239 | +that programs may issue custom exit codes with any value, so their documentation should be consulted. |
| 240 | + |
| 241 | + |
| 242 | +Sometimes, no exit code is given at all. An example may be found in |
| 243 | +:gh:`pytest-qt issue #170 <pytest-dev/pytest-qt/issues/170>`, where Qt was calling |
| 244 | +`abort() <https://www.unix.org/version2/sample/abort.html>`_ instead of ``exit()``. |
0 commit comments