-
Notifications
You must be signed in to change notification settings - Fork 11
/
tox.ini
316 lines (296 loc) · 17.9 KB
/
tox.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# --------------------( LICENSE )--------------------
# Copyright 2014-2025 by Alexis Pietak & Cecil Curry.
# See "LICENSE" for further details.
#
# --------------------( SYNOPSIS )--------------------
# Project-wide tox configuration, applied to all invocations of the tox test
# harness within this project.
#
# tox is a high-level Python-specific testing utility wrapping comparatively
# lower-level Python-specific testing frameworks (e.g., py.test, unittest2).
# Whereas the latter only exercise this project's codebase from the current
# working directory (CWD) without installing this project and hence exercising
# this project's installation, tox exercises both.
#
# Specifically, tox iteratively:
# 1. Creates a source-based tarball distribution of this project (e.g., via
# "python setup.py sdist").
# 2. Installs this tarball *AND* a system-agnostic Python interpreter into one
# isolated virtual environment for each testing configuration.
# 3. Tests this installation with the specified testing framework.
#
# --------------------( CAVEATS )--------------------
# *THIS CONFIGURATION IS INTOLERANT OF UNICODE CHARACTERS.* Note that setting
# "PYIOENCODING = UTF-8" under the "setenv" section below has no meaningful
# effect. For unknown reasons, "tox" is incapable of processing UTF-8 here.
# This is why nobody gets good things. If this file contains one or more
# UTF-8-encoded characters, "tox" fails with a non-human-readable traceback:
# Traceback (most recent call last):
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/runpy.py", line 194, in _run_module_as_main
# return _run_code(code, main_globals, None,
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/runpy.py", line 87, in _run_code
# exec(code, run_globals)
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/tox/__main__.py", line 4, in <module>
# tox.cmdline()
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/tox/session/__init__.py", line 44, in cmdline
# main(args)
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/tox/session/__init__.py", line 65, in main
# config = load_config(args)
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/tox/session/__init__.py", line 81, in load_config
# config = parseconfig(args)
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/tox/config/__init__.py", line 282, in parseconfig
# ParseIni(config, config_file, content)
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/tox/config/__init__.py", line 1145, in __init__
# self._cfg = py.iniconfig.IniConfig(config.toxinipath, ini_data)
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/py/_vendored_packages/iniconfig/__init__.py", line 54, in __init__
# tokens = self._parse(iter(f))
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/py/_vendored_packages/iniconfig/__init__.py", line 82, in _parse
# for lineno, line in enumerate(line_iter):
# File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/codecs.py", line 322, in decode
# (result, consumed) = self._buffer_decode(data, self.errors, final)
# UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd7 in position 3335: invalid continuation byte
# Error: Process completed with exit code 1.
#
# --------------------( VARIABLES )--------------------
# tox dynamically substitutes "{"- and "}"-delimited variable names with the
# strings to which those variables expand. Supported variable names include:
# * "{envtmpdir}", the absolute dirname of a temporary directory specific to
# the current virtual environment to which this project has been installed.
# * "{posargs}", the whitespace-delimited list of all command-line arguments
# passed to the current invocation of the "tox" command.
# * "{toxinidir}", the absolute dirname of the directory containing this file
# (e.g., the project root).
# ....................{ TOX }....................
# Metadata specific to tox itself.
[tox]
#FIXME: Disabled until required. Since "tox" currently behaves as expected,
#there's no incentive to break what's worky.
# # Comma- and newline-delimited string listing the names of all PyPI-hosted
# # projects required as mandatory dependencies to bootstrap "tox" -- typically
# # including some combination of "tox" itself, "virtualenv", and/or "pip".
# #
# # Note that all application-specific dependencies (e.g., "numpy", "scipy")
# # should be listed in the "deps" and/or "extras" settings under each
# # "[testenv]" section below.
# requires =
# # This "setuptools" dependency *MUST* be manially synchronized with the
# # "betse.metadeps" submodule here. "tox" requires this minimum version of
# # "setuptools" to create an sdist for this project *BEFORE* instantiating
# # the first venv. Ergo, the venv-specific "[testenv]" section below is of
# # no use to sdist generation. If omitted, "tox" fails at sdist generation
# # time with an exception resembling:
# #
# # GLOB sdist-make: /home/leycec/py/betse/setup.py
# # py36 inst-nodeps: /home/leycec/py/betse/.tox/.tmp/package/1/betse-1.1.1.zip
# # ERROR: invocation failed (exit code 1), logfile: /home/leycec/py/betse/.tox/py36/log/py36-3.log
# # =================================================== log start ===================================================
# # Processing ./.tox/.tmp/package/1/betse-1.1.1.zip
# # Complete output from command python setup.py egg_info:
# # Traceback (most recent call last):
# # File "<string>", line 1, in <module>
# # File "/tmp/pip-0j3y5x58-build/setup.py", line 158, in <module>
# # buputil.die_unless_setuptools_version_at_least(metadeps.SETUPTOOLS_VERSION_MIN)
# # File "/tmp/pip-0j3y5x58-build/betse_setup/buputil.py", line 74, in die_unless_setuptools_version_at_least
# # setuptools_version_min, setuptools.__version__))
# # Exception: setuptools >= 38.2.0 required by this application, but only setuptools 28.8.0 found.
# #
# # ----------------------------------------
# # Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-0j3y5x58-build/
# # You are using pip version 9.0.1, however version 19.3.1 is available.
# # You should consider upgrading via the 'pip install --upgrade pip' command.
# #
# # ==================================================== log end ====================================================
# setuptools >= 38.2.0
#
# # Install the most recent stable release of "virtualenv" as of this
# # writing. Note that this version dictates which versions of implicit
# # packages (e.g., "pip", "pkg_resources", "setuptools") come pre-installed
# # into each venv. If omitted, the obsolete version of "virtualenv" bundled
# # with "tox" is defaulted to; this induces non-trivial issues throughout
# # the installation toolchain, exemplified by the following "tox" warning:
# # py36 installed: You are using pip version 9.0.1, however version
# # 19.3.1 is available. You should consider upgrading via the 'pip
# # install --upgrade pip' command.
# # See also: https://github.com/tox-dev/tox/issues/765
# virtualenv >= 16.7.7
# ....................{ TOX ~ py }....................
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# WARNING: Changes to this setting *MUST* be manually synchronized with:
# * The "tox-env" setting in ".github/workflows/python_test.yml".
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Test matrix defined as a bash-interpolated string, where tox implicitly:
# * Expands "py" to "python".
# * Delimits the subsequent two digits with a dot to associate each resulting
# test configuration with the basename of an external command running an
# externally installed Python interpreter.
# * Expands "-"-delimited lists via the Cartesian set product A x B,
# effectively "multiplying" each environment on the left of each "-" against
# each environment on the right of that "-". Moreover, each such environment
# remains preserved and thus distinctly testable as that environment.
#
# For example, setting "envlist = py27,py38" produces a test matrix exercising
# the externally installed "python2.7" and "python3.8" commands. See also:
# https://tox.readthedocs.io/en/latest/config.html#generating-environments-conditional-settings
envlist = py{311,312}-coverage
# Ignore Python environments unavailable on the current system. By default,
# "tox" fails on the first unavailable Python environment. While sensible for
# continuous integration (CI), this default fails to generalize for local
# developers lacking one or more Python environments.
#
# Note that our CI configuration explicitly falsifies this setting back to its
# CI-friendly default via the "--skip-missing-interpreters=false" CLI option,
# forcing CI failures for unavailable Python environments. See also:
# https://github.com/tox-dev/tox/issues/903
skip_missing_interpreters = true
# ....................{ ENV }....................
# Job run for each test environment, exercising this project under that
# environment.
[testenv]
# Human-readable string synopsizing the current test configuration.
description = Exercise "{toxinidir}" with "{basepython} -m pytest".
# ....................{ ENV ~ shell }....................
# Absolute dirname of the directory to change to for the current test
# configuration, required to avoid accidental import collisions with
# uninstalled packages of the same name residing in "{toxinidir}". See also the
# following pertinent blog post, "Testing your python package as installed":
# https://blog.ganssle.io/articles/2019/08/test-as-installed.html
changedir = {envtmpdir}
# Newline-delimited string listing all environment variables to be temporarily
# set in each shell subprocess running tests.
setenv =
# Permit the "pip" installation commands internally invoked under each
# "tox" venv to optionally install wheels from an external third-party PyPI
# repository explicitly supporting PyPy. If this is *NOT* done,
# PyPy-specific "tox" venvs typically fail to install one or more Python
# packages in the standard scientific stack.
#
# Note that this repository resides at:
# https://github.com/antocuni/pypy-wheels
PIP_EXTRA_INDEX_URL=https://antocuni.github.io/pypy-wheels/manylinux2010
# Enable the Python Development Mode (PDM), which:
# "Introduces additional runtime checks that are too expensive to be
# enabled by default. It should not be more verbose than the default if
# the code is correct; new warnings are only emitted when an issue is
# detected."
# Specifically, the PDM enables:
# * "-W default", emitting warnings ignored by default. Yes, Python
# insanely ignores various categories of warnings by default -- including
# deprecating warnings, which *ABSOLUTELY* should be emitted by default,
# but aren't. We can't resolve that for end users but we can resolve that
# for ourselves.
# * "PYTHONMALLOC=debug", registering memory allocators hooks detecting
# unsafe call stack, memory, and GIL violations.
# * "PYTHONFAULTHANDLER=1", registering fault handlers emitting Python
# tracebacks on segmentation faults.
# * "PYTHONASYNCIODEBUG=1", enabling asyncio debug mode logging unawaited
# coroutines.
# * Detections for unsafe string encoding and decoding operations.
# * Logging io.IOBase.close() exceptions on object finalization.
# * Enabling the "dev_mode" attribute of "sys.flags".
# See also:
# https://docs.python.org/3/library/devmode.html
PYTHONDEVMODE = 1
# Prevent Python from buffering and hence failing to log output in the
# unlikely (but feasible) event of catastrophic failure from either the
# active Python process or OS kernel.
PYTHONUNBUFFERED = 1
#FIXME: Temporarily disabled until required. While "tox" is indeed *NOT*
#reliably detectable, "virtualenv" leveraged by "tox" is... Good enough!
# Explicitly notify our py.test-based test suite that it is currently
# running under tox. On startup, this test suite detects the existence of
# this codebase-specific variable and behaves accordingly (e.g., by
# stripping all non-tox directories from "sys.path").
#
# Note that tox itself provides *NO* reliable means of detecting itself,
# excluding the obvious (albeit highly non-trivial) approach of testing
# whether the basename of the command invoking the parent process is "tox".
# Although that approach does technically work, all sane implementations
# (e.g., the betse.util.test.tsttest.is_tox() tester) require importing
# from the BETSE codebase, which itself requires that all non-tox
# directories have been stripped from "sys.path". Chicken-and-egg insanity!
#
# Note also that tox itself generates a custom "site.py" file for all
# temporary virtual environments fundamentally preventing use
#BETSE_TOX_ENV_DIR={envdir}
# Command fragment measuring coverage while running tests, defined *ONLY*
# when the caller explicitly concatenated the current environment name by
# "-coverage" (e.g., "py310-coverage").
#
# Note that we intentionally do *NOT* leverage the "pytest-cov" plugin,
# which lacks sufficient configurability and friendly maintainership to
# warrant yet another fragile dependency.
coverage: _COVERAGE_COMMAND = coverage run -m
# Newline-delimited string listing all environment variables to be passed from
# the current shell process to each shell subprocess running tests.
# Dismantled, this is:
# * "CI" and "GITHUB_ACTIONS", enabling our test suite to programatically
# detect execution by a remote continuous integration (CI) host.
passenv =
CI
GITHUB_ACTIONS
PIP_CACHE_DIR
# ....................{ ENV ~ dependencies }....................
# Comma- and newline-delimited string listing the names of all "setup.py"-based
# "extras" required as mandatory or optional dependencies when testing this
# project.
extras =
# Install all mandatory test-specific dependencies. This is the official
# solution supported by "tox" developers for eliminating redundancy between
# testing dependencies listed within this file and the top-level "setup.py"
# script. While non-intuitive, we have little recourse. See also:
# https://stackoverflow.com/questions/29870629/pip-install-test-dependencies-for-tox-from-setup-py
# https://stackoverflow.com/questions/39922650/tox-tests-use-setup-py-extra-require-as-tox-deps-source
# https://github.com/tox-dev/tox/issues/13#issuecomment-247788280
# Note that this also requires ".[test-tox]" to be listed as a dependency.
test-tox
# If the caller explicitly concatenated the current environment name by
# "-coverage" (e.g., "py310-coverage"), install all mandatory
# coverage-specific dependencies as well.
coverage: test-tox-coverage
# Comma- and newline-delimited string listing the names of all mandatory
# dependencies (i.e., third-party packages) required to test this project.
#
# Note that this also requires "test-tox" to be listed as an extra above.
deps = .[test-tox]
# ....................{ ENV ~ commands }....................
# Shell command with which to install project dependencies.
#
# This command extends the default "install_command" with support for an
# optional "${_TOX_PIP_INSTALL_OPTIONS}" environment variable defaulting to the
# empty string. This variable is typically defined by the higher-level
# ".github/workflows/python_test.yml" continuous integration (CI) configuration
# file on a platform-specific basis (e.g., "--force-reinstall" under macOS).
install_command =
python -m pip install {env:_TOX_PIP_INSTALL_OPTIONS:} {opts} {packages}
# Newline-delimited string listing all shell commands required to test this
# project under this environment.
#
# Note that:
# * For disambiguity, avoid running any Python-based commands *EXCEPT* those
# explicitly prefixed by "{envpython}" (i.e., the absolute filename of the
# venv-specific Python interpreter).
# * For portability between POSIX-compliant platforms (e.g., Linux, macOS) and
# POSIX-noncompliant platforms (e.g., Windows), the current platform and
# shell should *NOT* assumed. Ergo, commands should be confined to those
# explicitly prefixed by "{envpython}".
commands =
# Print metadata on the current versions of Python and pytest (in order).
{envpython} --version
{envpython} -m pytest --version
{envpython} -m betse --headless --version
{envpython} -m betse --headless info
# Run our entire pytest-based test suite. Dismantled, this is:
# * "{env:_COVERAGE_COMMAND:}", expanding to either:
# * If measuring coverage, the value of the "${_COVERAGE_COMMAND}"
# environment variable defined above.
# * Else, the empty string.
# * "--maxfail={n}", halting testing on the {n}th failure.
{envpython} \
-m {env:_COVERAGE_COMMAND:} \
pytest --maxfail=1 {posargs} "{toxinidir}"
# {envpython} -m {env:_COVERAGE_COMMAND:} pytest --maxfail=1 -vvvv {posargs} "{toxinidir}"
# {envpython} -m {env:_COVERAGE_COMMAND:} pytest --maxfail=1 -k test_pep563_closure_nested {posargs} "{toxinidir}"
# If measuring coverage, additionally generate a coverage report in the
# specific format expected by Codecov *AFTER* running our test suite and
# thus collecting coverage statistics.
coverage: {envpython} -m coverage xml -o "{toxinidir}/coverage.xml"