Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tox v4.14.1 is no longer expanding {envtmpdir} (and potentially other variables) #3238

Open
Luthaf opened this issue Mar 7, 2024 · 20 comments · May be fixed by #3268
Open

Tox v4.14.1 is no longer expanding {envtmpdir} (and potentially other variables) #3238

Luthaf opened this issue Mar 7, 2024 · 20 comments · May be fixed by #3268
Assignees
Labels
bug:minor does not affect many people or has no big impact help:wanted Issues that have been acknowledged, a solution determined and a PR might likely be accepted. level:hard rought estimate that this might be quite hard to implement

Comments

@Luthaf
Copy link

Luthaf commented Mar 7, 2024

Issue

We are using package = external and package_env = build-metatensor-core in our tox setup, and build the wheels with pip wheel python/metatensor-core {[testenv]build_single_wheel_flags} --wheel-dir {envtmpdir}/dist

On tox 4.14.0, everything is fine, on 4.14.1 tox creates a directory literally named {envtmpdir}/dist (instead of expanding this to .tox/build-metatensor-core/tmp/dist.

$ ls \{envtmpdir\}/dist
metatensor_core-0.2.0.dev7-py3-none-macosx_14_0_arm64.whl

Environment

Provide at least:

  • OS: macOS 14.3.1
Output of pip list of the host Python, where tox is installed
$ pip list
Package                 Version
----------------------- --------
archspec                0.2.3
boltons                 23.1.1
Brotli                  1.1.0
build                   1.0.3
cachetools              5.3.3
certifi                 2024.2.2
cffi                    1.16.0
chardet                 5.2.0
charset-normalizer      3.3.2
colorama                0.4.6
conda                   24.1.2
conda-libmamba-solver   24.1.0
conda-package-handling  2.2.0
conda_package_streaming 0.9.0
distlib                 0.3.8
distro                  1.9.0
filelock                3.13.1
fsspec                  2024.2.0
idna                    3.6
importlib-metadata      7.0.1
Jinja2                  3.1.3
jsonpatch               1.33
jsonpointer             2.4
libmambapy              1.5.7
mamba                   1.5.7
MarkupSafe              2.1.5
menuinst                2.0.2
mpmath                  1.3.0
networkx                3.2.1
numpy                   1.26.4
packaging               23.2
pip                     24.0
platformdirs            4.2.0
pluggy                  1.4.0
pycosat                 0.6.6
pycparser               2.21
pyproject-api           1.6.1
pyproject_hooks         1.0.0
PySocks                 1.7.1
requests                2.31.0
ruamel.yaml             0.18.6
ruamel.yaml.clib        0.2.8
setuptools              69.1.1
sympy                   1.12
tomli                   2.0.1
torch                   2.2.1
tox                     4.14.1
tqdm                    4.66.2
truststore              0.8.0
typing_extensions       4.10.0
urllib3                 2.2.1
virtualenv              20.25.1
wheel                   0.42.0
zipp                    3.17.0
zstandard               0.22.0

Output of running tox

Output of tox -rvv
$ tox -rvv -e core-tests
build-metatensor-core: 111 W remove tox env folder /Users/guillaume/code/metatensor/.tox/build-metatensor-core [tox/tox_env/api.py:323]
build-metatensor-core_sdist_meta: 111 W remove tox env folder /Users/guillaume/code/metatensor/.tox/build-metatensor-core_sdist_meta [tox/tox_env/api.py:323]
core-tests: 115 I find interpreter for spec PythonSpec(path=/opt/miniforge3/bin/python3.11) [virtualenv/discovery/builtin.py:58]
core-tests: 115 I proposed PythonInfo(spec=CPython3.11.7.final.0-64, exe=/opt/miniforge3/bin/python3.11, platform=darwin, version='3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:38:07) [Clang 16.0.6 ]', encoding_fs_io=utf-8-utf-8) [virtualenv/discovery/builtin.py:65]
core-tests: 115 D accepted PythonInfo(spec=CPython3.11.7.final.0-64, exe=/opt/miniforge3/bin/python3.11, platform=darwin, version='3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:38:07) [Clang 16.0.6 ]', encoding_fs_io=utf-8-utf-8) [virtualenv/discovery/builtin.py:67]
core-tests: 116 D filesystem is not case-sensitive [virtualenv/info.py:25]
core-tests: 130 I create virtual environment via CPython3Posix(dest=/Users/guillaume/code/metatensor/.tox/core-tests, clear=False, no_vcs_ignore=False, global=False) [virtualenv/run/session.py:50]
core-tests: 130 D create folder /Users/guillaume/code/metatensor/.tox/core-tests/bin [virtualenv/util/path/_sync.py:12]
core-tests: 131 D create folder /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages [virtualenv/util/path/_sync.py:12]
core-tests: 131 D write /Users/guillaume/code/metatensor/.tox/core-tests/pyvenv.cfg [virtualenv/create/pyenv_cfg.py:33]
core-tests: 131 D 	home = /opt/miniforge3/bin [virtualenv/create/pyenv_cfg.py:38]
core-tests: 131 D 	implementation = CPython [virtualenv/create/pyenv_cfg.py:38]
core-tests: 131 D 	version_info = 3.11.7.final.0 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 131 D 	virtualenv = 20.25.1 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 131 D 	include-system-site-packages = false [virtualenv/create/pyenv_cfg.py:38]
core-tests: 131 D 	base-prefix = /opt/miniforge3 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 131 D 	base-exec-prefix = /opt/miniforge3 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 131 D 	base-executable = /opt/miniforge3/bin/python3.11 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 131 D symlink /opt/miniforge3/bin/python3.11 to /Users/guillaume/code/metatensor/.tox/core-tests/bin/python [virtualenv/util/path/_sync.py:32]
core-tests: 131 D create virtualenv import hook file /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/_virtualenv.pth [virtualenv/create/via_global_ref/api.py:91]
core-tests: 131 D create /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/_virtualenv.py [virtualenv/create/via_global_ref/api.py:94]
core-tests: 131 D ============================== target debug ============================== [virtualenv/run/session.py:52]
core-tests: 132 D debug via /Users/guillaume/code/metatensor/.tox/core-tests/bin/python /opt/miniforge3/lib/python3.11/site-packages/virtualenv/create/debug.py [virtualenv/create/creator.py:200]
core-tests: 131 D {
  "sys": {
    "executable": "/Users/guillaume/code/metatensor/.tox/core-tests/bin/python",
    "_base_executable": "/opt/miniforge3/bin/python3.11",
    "prefix": "/Users/guillaume/code/metatensor/.tox/core-tests",
    "base_prefix": "/opt/miniforge3",
    "real_prefix": null,
    "exec_prefix": "/Users/guillaume/code/metatensor/.tox/core-tests",
    "base_exec_prefix": "/opt/miniforge3",
    "path": [
      "/opt/miniforge3/lib/python311.zip",
      "/opt/miniforge3/lib/python3.11",
      "/opt/miniforge3/lib/python3.11/lib-dynload",
      "/Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages"
    ],
    "meta_path": [
      "<class '_virtualenv._Finder'>",
      "<class '_frozen_importlib.BuiltinImporter'>",
      "<class '_frozen_importlib.FrozenImporter'>",
      "<class '_frozen_importlib_external.PathFinder'>"
    ],
    "fs_encoding": "utf-8",
    "io_encoding": "utf-8"
  },
  "version": "3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:38:07) [Clang 16.0.6 ]",
  "makefile_filename": "/opt/miniforge3/lib/python3.11/config-3.11-darwin/Makefile",
  "os": "<module 'os' (frozen)>",
  "site": "<module 'site' (frozen)>",
  "datetime": "<module 'datetime' from '/opt/miniforge3/lib/python3.11/datetime.py'>",
  "math": "<module 'math' from '/opt/miniforge3/lib/python3.11/lib-dynload/math.cpython-311-darwin.so'>",
  "json": "<module 'json' from '/opt/miniforge3/lib/python3.11/json/__init__.py'>"
} [virtualenv/run/session.py:53]
core-tests: 151 I add seed packages via FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/guillaume/Library/Application Support/virtualenv) [virtualenv/run/session.py:57]
core-tests: 152 D got embed update of distribution %s from ('pip', PosixPath('/Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/embed/3/pip.json')) [virtualenv/app_data/via_disk_folder.py:131]
core-tests: 154 D install wheel from wheel /opt/miniforge3/lib/python3.11/site-packages/virtualenv/seed/wheels/embed/wheel-0.42.0-py3-none-any.whl via CopyPipInstall [virtualenv/seed/embed/via_app_data/via_app_data.py:49]
core-tests: 154 D install setuptools from wheel /opt/miniforge3/lib/python3.11/site-packages/virtualenv/seed/wheels/embed/setuptools-69.1.0-py3-none-any.whl via CopyPipInstall [virtualenv/seed/embed/via_app_data/via_app_data.py:49]
core-tests: 154 D install pip from wheel /opt/miniforge3/lib/python3.11/site-packages/virtualenv/seed/wheels/embed/pip-24.0-py3-none-any.whl via CopyPipInstall [virtualenv/seed/embed/via_app_data/via_app_data.py:49]
core-tests: 154 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/setuptools-69.1.0.dist-info to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/setuptools-69.1.0.dist-info [virtualenv/util/path/_sync.py:40]
core-tests: 155 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/wheel-0.42.0-py3-none-any/wheel-0.42.0.dist-info to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/wheel-0.42.0.dist-info [virtualenv/util/path/_sync.py:40]
core-tests: 155 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/pip-24.0-py3-none-any/pip-24.0.dist-info to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/pip-24.0.dist-info [virtualenv/util/path/_sync.py:40]
core-tests: 156 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/wheel-0.42.0-py3-none-any/wheel to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/wheel [virtualenv/util/path/_sync.py:40]
core-tests: 156 D copy /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/distutils-precedence.pth to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/distutils-precedence.pth [virtualenv/util/path/_sync.py:40]
core-tests: 157 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/pip-24.0-py3-none-any/pip to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/pip [virtualenv/util/path/_sync.py:40]
core-tests: 157 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/setuptools to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/setuptools [virtualenv/util/path/_sync.py:40]
core-tests: 162 D copy /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/wheel-0.42.0-py3-none-any/wheel-0.42.0.virtualenv to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/wheel-0.42.0.virtualenv [virtualenv/util/path/_sync.py:40]
core-tests: 163 D generated console scripts wheel wheel-3.11 wheel3 wheel3.11 [virtualenv/seed/embed/via_app_data/pip_install/base.py:43]
core-tests: 191 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/pkg_resources to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/pkg_resources [virtualenv/util/path/_sync.py:40]
core-tests: 200 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/_distutils_hack to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/_distutils_hack [virtualenv/util/path/_sync.py:40]
core-tests: 200 D copy /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/setuptools-69.1.0.virtualenv to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/setuptools-69.1.0.virtualenv [virtualenv/util/path/_sync.py:40]
core-tests: 201 D generated console scripts  [virtualenv/seed/embed/via_app_data/pip_install/base.py:43]
core-tests: 234 D copy /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/pip-24.0-py3-none-any/pip-24.0.virtualenv to /Users/guillaume/code/metatensor/.tox/core-tests/lib/python3.11/site-packages/pip-24.0.virtualenv [virtualenv/util/path/_sync.py:40]
core-tests: 234 D generated console scripts pip3 pip3.11 pip-3.11 pip [virtualenv/seed/embed/via_app_data/pip_install/base.py:43]
core-tests: 234 I add activators for Bash, CShell, Fish, Nushell, PowerShell, Python [virtualenv/run/session.py:63]
core-tests: 236 D write /Users/guillaume/code/metatensor/.tox/core-tests/pyvenv.cfg [virtualenv/create/pyenv_cfg.py:33]
core-tests: 236 D 	home = /opt/miniforge3/bin [virtualenv/create/pyenv_cfg.py:38]
core-tests: 236 D 	implementation = CPython [virtualenv/create/pyenv_cfg.py:38]
core-tests: 236 D 	version_info = 3.11.7.final.0 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 236 D 	virtualenv = 20.25.1 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 236 D 	include-system-site-packages = false [virtualenv/create/pyenv_cfg.py:38]
core-tests: 236 D 	base-prefix = /opt/miniforge3 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 236 D 	base-exec-prefix = /opt/miniforge3 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 236 D 	base-executable = /opt/miniforge3/bin/python3.11 [virtualenv/create/pyenv_cfg.py:38]
core-tests: 238 W install_deps> python -I -m pip install numpy pytest pytest-cov toml 'torch==2.2.*' [tox/tox_env/api.py:425]
Collecting numpy
  Using cached numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl.metadata (114 kB)
Collecting pytest
  Using cached pytest-8.0.2-py3-none-any.whl.metadata (7.7 kB)
Collecting pytest-cov
  Using cached pytest_cov-4.1.0-py3-none-any.whl.metadata (26 kB)
Collecting toml
  Using cached toml-0.10.2-py2.py3-none-any.whl.metadata (7.1 kB)
Collecting torch==2.2.*
  Using cached torch-2.2.1-cp311-none-macosx_11_0_arm64.whl.metadata (25 kB)
Collecting filelock (from torch==2.2.*)
  Using cached filelock-3.13.1-py3-none-any.whl.metadata (2.8 kB)
Collecting typing-extensions>=4.8.0 (from torch==2.2.*)
  Using cached typing_extensions-4.10.0-py3-none-any.whl.metadata (3.0 kB)
Collecting sympy (from torch==2.2.*)
  Using cached sympy-1.12-py3-none-any.whl.metadata (12 kB)
Collecting networkx (from torch==2.2.*)
  Using cached networkx-3.2.1-py3-none-any.whl.metadata (5.2 kB)
Collecting jinja2 (from torch==2.2.*)
  Using cached Jinja2-3.1.3-py3-none-any.whl.metadata (3.3 kB)
Collecting fsspec (from torch==2.2.*)
  Using cached fsspec-2024.2.0-py3-none-any.whl.metadata (6.8 kB)
Collecting iniconfig (from pytest)
  Using cached iniconfig-2.0.0-py3-none-any.whl.metadata (2.6 kB)
Collecting packaging (from pytest)
  Using cached packaging-23.2-py3-none-any.whl.metadata (3.2 kB)
Collecting pluggy<2.0,>=1.3.0 (from pytest)
  Using cached pluggy-1.4.0-py3-none-any.whl.metadata (4.3 kB)
Collecting coverage>=5.2.1 (from coverage[toml]>=5.2.1->pytest-cov)
  Using cached coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl.metadata (8.2 kB)
Collecting MarkupSafe>=2.0 (from jinja2->torch==2.2.*)
  Using cached MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl.metadata (3.0 kB)
Collecting mpmath>=0.19 (from sympy->torch==2.2.*)
  Using cached mpmath-1.3.0-py3-none-any.whl.metadata (8.6 kB)
Using cached torch-2.2.1-cp311-none-macosx_11_0_arm64.whl (59.7 MB)
Using cached numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl (14.0 MB)
Using cached pytest-8.0.2-py3-none-any.whl (333 kB)
Using cached pytest_cov-4.1.0-py3-none-any.whl (21 kB)
Using cached toml-0.10.2-py2.py3-none-any.whl (16 kB)
Using cached coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl (207 kB)
Using cached pluggy-1.4.0-py3-none-any.whl (20 kB)
Using cached typing_extensions-4.10.0-py3-none-any.whl (33 kB)
Using cached filelock-3.13.1-py3-none-any.whl (11 kB)
Using cached fsspec-2024.2.0-py3-none-any.whl (170 kB)
Using cached iniconfig-2.0.0-py3-none-any.whl (5.9 kB)
Using cached Jinja2-3.1.3-py3-none-any.whl (133 kB)
Using cached networkx-3.2.1-py3-none-any.whl (1.6 MB)
Using cached packaging-23.2-py3-none-any.whl (53 kB)
Using cached sympy-1.12-py3-none-any.whl (5.7 MB)
Using cached MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl (18 kB)
Using cached mpmath-1.3.0-py3-none-any.whl (536 kB)
Installing collected packages: mpmath, typing-extensions, toml, sympy, pluggy, packaging, numpy, networkx, MarkupSafe, iniconfig, fsspec, filelock, coverage, pytest, jinja2, torch, pytest-cov
Successfully installed MarkupSafe-2.1.5 coverage-7.4.3 filelock-3.13.1 fsspec-2024.2.0 iniconfig-2.0.0 jinja2-3.1.3 mpmath-1.3.0 networkx-3.2.1 numpy-1.26.4 packaging-23.2 pluggy-1.4.0 pytest-8.0.2 pytest-cov-4.1.0 sympy-1.12 toml-0.10.2 torch-2.2.1 typing-extensions-4.10.0
core-tests: 11493 I exit 0 (11.25 seconds) /Users/guillaume/code/metatensor> python -I -m pip install numpy pytest pytest-cov toml 'torch==2.2.*' pid=44644 [tox/execute/api.py:280]
build-metatensor-core: 11495 I find interpreter for spec PythonSpec(path=/opt/miniforge3/bin/python3.11) [virtualenv/discovery/builtin.py:58]
build-metatensor-core: 11495 I proposed PythonInfo(spec=CPython3.11.7.final.0-64, exe=/opt/miniforge3/bin/python3.11, platform=darwin, version='3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:38:07) [Clang 16.0.6 ]', encoding_fs_io=utf-8-utf-8) [virtualenv/discovery/builtin.py:65]
build-metatensor-core: 11495 D accepted PythonInfo(spec=CPython3.11.7.final.0-64, exe=/opt/miniforge3/bin/python3.11, platform=darwin, version='3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:38:07) [Clang 16.0.6 ]', encoding_fs_io=utf-8-utf-8) [virtualenv/discovery/builtin.py:67]
build-metatensor-core: 11496 I create virtual environment via CPython3Posix(dest=/Users/guillaume/code/metatensor/.tox/build-metatensor-core, clear=False, no_vcs_ignore=False, global=False) [virtualenv/run/session.py:50]
build-metatensor-core: 11496 D create folder /Users/guillaume/code/metatensor/.tox/build-metatensor-core/bin [virtualenv/util/path/_sync.py:12]
build-metatensor-core: 11496 D create folder /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages [virtualenv/util/path/_sync.py:12]
build-metatensor-core: 11496 D write /Users/guillaume/code/metatensor/.tox/build-metatensor-core/pyvenv.cfg [virtualenv/create/pyenv_cfg.py:33]
build-metatensor-core: 11496 D 	home = /opt/miniforge3/bin [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11496 D 	implementation = CPython [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11496 D 	version_info = 3.11.7.final.0 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11496 D 	virtualenv = 20.25.1 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11496 D 	include-system-site-packages = false [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11496 D 	base-prefix = /opt/miniforge3 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11496 D 	base-exec-prefix = /opt/miniforge3 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11496 D 	base-executable = /opt/miniforge3/bin/python3.11 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11497 D symlink /opt/miniforge3/bin/python3.11 to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/bin/python [virtualenv/util/path/_sync.py:32]
build-metatensor-core: 11497 D create virtualenv import hook file /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/_virtualenv.pth [virtualenv/create/via_global_ref/api.py:91]
build-metatensor-core: 11497 D create /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/_virtualenv.py [virtualenv/create/via_global_ref/api.py:94]
build-metatensor-core: 11497 D ============================== target debug ============================== [virtualenv/run/session.py:52]
build-metatensor-core: 11497 D debug via /Users/guillaume/code/metatensor/.tox/build-metatensor-core/bin/python /opt/miniforge3/lib/python3.11/site-packages/virtualenv/create/debug.py [virtualenv/create/creator.py:200]
build-metatensor-core: 11497 D {
  "sys": {
    "executable": "/Users/guillaume/code/metatensor/.tox/build-metatensor-core/bin/python",
    "_base_executable": "/opt/miniforge3/bin/python3.11",
    "prefix": "/Users/guillaume/code/metatensor/.tox/build-metatensor-core",
    "base_prefix": "/opt/miniforge3",
    "real_prefix": null,
    "exec_prefix": "/Users/guillaume/code/metatensor/.tox/build-metatensor-core",
    "base_exec_prefix": "/opt/miniforge3",
    "path": [
      "/opt/miniforge3/lib/python311.zip",
      "/opt/miniforge3/lib/python3.11",
      "/opt/miniforge3/lib/python3.11/lib-dynload",
      "/Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages"
    ],
    "meta_path": [
      "<class '_virtualenv._Finder'>",
      "<class '_frozen_importlib.BuiltinImporter'>",
      "<class '_frozen_importlib.FrozenImporter'>",
      "<class '_frozen_importlib_external.PathFinder'>"
    ],
    "fs_encoding": "utf-8",
    "io_encoding": "utf-8"
  },
  "version": "3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:38:07) [Clang 16.0.6 ]",
  "makefile_filename": "/opt/miniforge3/lib/python3.11/config-3.11-darwin/Makefile",
  "os": "<module 'os' (frozen)>",
  "site": "<module 'site' (frozen)>",
  "datetime": "<module 'datetime' from '/opt/miniforge3/lib/python3.11/datetime.py'>",
  "math": "<module 'math' from '/opt/miniforge3/lib/python3.11/lib-dynload/math.cpython-311-darwin.so'>",
  "json": "<module 'json' from '/opt/miniforge3/lib/python3.11/json/__init__.py'>"
} [virtualenv/run/session.py:53]
build-metatensor-core: 11517 I add seed packages via FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/guillaume/Library/Application Support/virtualenv) [virtualenv/run/session.py:57]
build-metatensor-core: 11518 D got embed update of distribution %s from ('pip', PosixPath('/Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/embed/3/pip.json')) [virtualenv/app_data/via_disk_folder.py:131]
build-metatensor-core: 11518 D install setuptools from wheel /opt/miniforge3/lib/python3.11/site-packages/virtualenv/seed/wheels/embed/setuptools-69.1.0-py3-none-any.whl via CopyPipInstall [virtualenv/seed/embed/via_app_data/via_app_data.py:49]
build-metatensor-core: 11518 D install wheel from wheel /opt/miniforge3/lib/python3.11/site-packages/virtualenv/seed/wheels/embed/wheel-0.42.0-py3-none-any.whl via CopyPipInstall [virtualenv/seed/embed/via_app_data/via_app_data.py:49]
build-metatensor-core: 11518 D install pip from wheel /opt/miniforge3/lib/python3.11/site-packages/virtualenv/seed/wheels/embed/pip-24.0-py3-none-any.whl via CopyPipInstall [virtualenv/seed/embed/via_app_data/via_app_data.py:49]
build-metatensor-core: 11519 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/pip-24.0-py3-none-any/pip-24.0.dist-info to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/pip-24.0.dist-info [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11519 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/setuptools-69.1.0.dist-info to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/setuptools-69.1.0.dist-info [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11519 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/wheel-0.42.0-py3-none-any/wheel-0.42.0.dist-info to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/wheel-0.42.0.dist-info [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11521 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/wheel-0.42.0-py3-none-any/wheel to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/wheel [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11521 D copy /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/distutils-precedence.pth to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/distutils-precedence.pth [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11522 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/setuptools to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/setuptools [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11522 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/pip-24.0-py3-none-any/pip to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/pip [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11528 D copy /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/wheel-0.42.0-py3-none-any/wheel-0.42.0.virtualenv to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/wheel-0.42.0.virtualenv [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11529 D generated console scripts wheel wheel3 wheel-3.11 wheel3.11 [virtualenv/seed/embed/via_app_data/pip_install/base.py:43]
build-metatensor-core: 11558 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/pkg_resources to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/pkg_resources [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11567 D copy directory /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/_distutils_hack to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/_distutils_hack [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11568 D copy /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/setuptools-69.1.0-py3-none-any/setuptools-69.1.0.virtualenv to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/setuptools-69.1.0.virtualenv [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11568 D generated console scripts  [virtualenv/seed/embed/via_app_data/pip_install/base.py:43]
build-metatensor-core: 11604 D copy /Users/guillaume/Library/Application Support/virtualenv/wheel/3.11/image/1/CopyPipInstall/pip-24.0-py3-none-any/pip-24.0.virtualenv to /Users/guillaume/code/metatensor/.tox/build-metatensor-core/lib/python3.11/site-packages/pip-24.0.virtualenv [virtualenv/util/path/_sync.py:40]
build-metatensor-core: 11604 D generated console scripts pip3 pip3.11 pip-3.11 pip [virtualenv/seed/embed/via_app_data/pip_install/base.py:43]
build-metatensor-core: 11604 I add activators for Bash, CShell, Fish, Nushell, PowerShell, Python [virtualenv/run/session.py:63]
build-metatensor-core: 11605 D write /Users/guillaume/code/metatensor/.tox/build-metatensor-core/pyvenv.cfg [virtualenv/create/pyenv_cfg.py:33]
build-metatensor-core: 11605 D 	home = /opt/miniforge3/bin [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11605 D 	implementation = CPython [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11605 D 	version_info = 3.11.7.final.0 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11605 D 	virtualenv = 20.25.1 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11605 D 	include-system-site-packages = false [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11605 D 	base-prefix = /opt/miniforge3 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11605 D 	base-exec-prefix = /opt/miniforge3 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11606 D 	base-executable = /opt/miniforge3/bin/python3.11 [virtualenv/create/pyenv_cfg.py:38]
build-metatensor-core: 11607 W install_requires> python -I -m pip install cmake packaging setuptools wheel [tox/tox_env/api.py:425]
Collecting cmake
  Using cached cmake-3.28.3-py2.py3-none-macosx_10_10_universal2.macosx_10_10_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl.metadata (6.3 kB)
Collecting packaging
  Using cached packaging-23.2-py3-none-any.whl.metadata (3.2 kB)
Requirement already satisfied: setuptools in ./.tox/build-metatensor-core/lib/python3.11/site-packages (69.1.0)
Requirement already satisfied: wheel in ./.tox/build-metatensor-core/lib/python3.11/site-packages (0.42.0)
Using cached cmake-3.28.3-py2.py3-none-macosx_10_10_universal2.macosx_10_10_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl (48.5 MB)
Using cached packaging-23.2-py3-none-any.whl (53 kB)
Installing collected packages: cmake, packaging
Successfully installed cmake-3.28.3 packaging-23.2
build-metatensor-core: 13373 I exit 0 (1.77 seconds) /Users/guillaume/code/metatensor> python -I -m pip install cmake packaging setuptools wheel pid=44648 [tox/execute/api.py:280]
build-metatensor-core: 13374 W install_deps> python -I -m pip install cmake packaging setuptools wheel [tox/tox_env/api.py:425]
Requirement already satisfied: cmake in ./.tox/build-metatensor-core/lib/python3.11/site-packages (3.28.3)
Requirement already satisfied: packaging in ./.tox/build-metatensor-core/lib/python3.11/site-packages (23.2)
Requirement already satisfied: setuptools in ./.tox/build-metatensor-core/lib/python3.11/site-packages (69.1.0)
Requirement already satisfied: wheel in ./.tox/build-metatensor-core/lib/python3.11/site-packages (0.42.0)
build-metatensor-core: 13647 I exit 0 (0.27 seconds) /Users/guillaume/code/metatensor> python -I -m pip install cmake packaging setuptools wheel pid=44650 [tox/execute/api.py:280]
build-metatensor-core: 13648 W commands[0]> pip wheel python/metatensor-core --no-deps --no-build-isolation --check-build-dependencies --wheel-dir '{env_tmp_dir}/dist' [tox/tox_env/api.py:425]
Processing ./python/metatensor-core
  Preparing metadata (pyproject.toml) ... done
Building wheels for collected packages: metatensor-core
  Building wheel for metatensor-core (pyproject.toml) ... done
  Created wheel for metatensor-core: filename=metatensor_core-0.2.0.dev7-py3-none-macosx_14_0_arm64.whl size=393337 sha256=3ef52bf49aeeab3cb26abb2f37e70fa66a4e087d0bea399fe5138888d440b34f
  Stored in directory: /Users/guillaume/Library/Caches/pip/wheels/51/2c/1e/776d763cc8f4fe85ef01b2aa554b8f88005d759914ef385ec8
Successfully built metatensor-core
build-metatensor-core: 14924 I exit 0 (1.28 seconds) /Users/guillaume/code/metatensor> pip wheel python/metatensor-core --no-deps --no-build-isolation --check-build-dependencies --wheel-dir '{env_tmp_dir}/dist' pid=44652 [tox/execute/api.py:280]
core-tests: 14925 E failed with no package found in /Users/guillaume/code/metatensor/.tox/build-metatensor-core/tmp/dist/* [tox/session/cmd/run/single.py:57]
  core-tests: FAIL code 1 (14.82 seconds)
  evaluation failed :( (14.85 seconds)

Ping @gaborbernat, this seems to be a fallout of #3237

@gaborbernat
Copy link
Member

No need to ping ☹️ that's a bit aggressive. You could have put in a PR with the fix instead...

@Luthaf
Copy link
Author

Luthaf commented Mar 7, 2024

Sorry if the ping was seen as aggressive, that was not the intent! I assumed you would be well placed to understand what's going on here, and interested in knowing about this.

Regarding the PR, I have no idea how tox works internally so I'll have to leave that to another contributor! Thank you for your work on tox, it is working very well for us 😃 (I just realized you are the main author of the whole package, and not just the PR mentioned above)

@gaborbernat
Copy link
Member

I maintain this project, I already get notified of new issues. That being said, I maintain the project, that doesn't mean I do all the development. We don't have today any active developers, so realistically, unless you put in a PR, this might take a while... this is an open-source project kept alive by its community, we have no paid staff to troubleshoot and resolve new issues.

@gaborbernat gaborbernat added bug:minor does not affect many people or has no big impact help:wanted Issues that have been acknowledged, a solution determined and a PR might likely be accepted. labels Mar 7, 2024
@gaborbernat
Copy link
Member

Furthermore, creating a repository that I can clone to reproduce would significantly increase the chances of getting traction. Thanks!

@Luthaf
Copy link
Author

Luthaf commented Mar 7, 2024

Here is a minimal reproduction repository: https://github.com/Luthaf/tox-variables

I had to add a separate tests environment to reproduce the error, so maybe there is something more going on here.

@gaborbernat
Copy link
Member

Thanks for that 🙏

@felixscherz
Copy link

Hi, I ran some tests and it seem if I change this line

key = section.key, for_env or "", "-".join(base or [])
back to how it was in v4.14.0
key = section.key, for_env or ""

the example in the reproduction repository runs fine:)
I haven't had the time to figure out how to fix the issue however.

mkoeppe added a commit to mkoeppe/sage that referenced this issue Apr 6, 2024
mkoeppe added a commit to mkoeppe/sage that referenced this issue Apr 8, 2024
@bennyrowland
Copy link

I have done a bit of further digging based off @felixscherz very helpful information. As he points out, with the change to 4.14.1 ConfigSet objects are cached based on the section.key, for_env and base values, with base being the new addition. However, when we look at where this is called:

tox/src/tox/config/main.py

Lines 163 to 169 in 08223fc

return self.get_section_config(
section,
base=base_pkg if package else base_test,
of_type=EnvConfigSet,
for_env=item,
loaders=loaders,
)

the base is determined from the package argument, which is only ever true during env creation:

pkg_conf = self._state.conf.get_env(name, package=True)

When the packaging environment is actually run, the config is accessed with package=False (the default value) and this causes it to create a new Config object, rather than reusing the original one, which means that everything that happens in
pkg_env.register_config()

doesn't get included in the Config made available during the commands on the packaging environment.

@gaborbernat why was there a need to include the base in the Config cache keys? I thought that any given environment had to either be a run or package environment, so surely the section.key is enough to uniquely identify an environment and retrieve the correct config? I am happy to work on a PR to resolve this, but will need some guidance on what the desired resolution is, if it is more complicated than just following @felixscherz change to remove base from the key.

@gaborbernat
Copy link
Member

gaborbernat commented Apr 9, 2024

Package and run environments have different base environment. Base environments are important when determining the fallback env. For run env this is testenv and for package env this is testenv:.pkg. Base environment will be used to get the fallback value if a config is not set, before going to hard-coded fallback.

@bennyrowland
Copy link

bennyrowland commented Apr 9, 2024

Yes, but the issue here is that a packaging environment like testenv:.pkg is being created as a package environment (with a base of pkgenv) but when the packaging commands are being run the config for testenv:.pkg is being accessed via get_env("testenv:.pkg", package=False) and so the retrieved config is not the config that was created when the env was being built (which has things like the env_tmp_dir set on it), but is instead a second copy of the config which is created at the point of retrieval and only accesses the section values from tox.ini. I get that get_env() needs a package argument at creation time, but surely afterwards you always want to retrieve the previously created config for the environment, rather than create a second Config with a different base for the same Env?

@gaborbernat
Copy link
Member

You're correct. Not entirely sure how to encode that in the interface, suggestions?

@gaborbernat
Copy link
Member

being accessed via get_env("testenv:.pkg", package=False) and

Is this the bug, should we pass in package=True instead? Can we do that?

@bennyrowland
Copy link

I think there are a few options available here (with a choice on size of change vs overall quality of fix) - passing package=True would work, but I am not sure that that information is readily available at the point where get_env() is being called (package=False is merely the default value, it is not being passed in deliberately here):

def _config_value_sources(
env: str | None,
section: str | None,
current_env: str | None,
conf: Config,
loader: IniLoader,
) -> Iterator[SectionProxy | ConfigSet]:
# if we have an env name specified take only from there
if env is not None and env in conf:
yield conf.get_env(env)
if section is None:
# if no section specified perhaps it's an unregistered config:
# 1. try first from core conf
yield conf.core
# 2. and then fallback to our own environment
if current_env is not None:
yield conf.get_env(current_env)
return

It also seems unnecessary to have to try and retrieve whether package is true over and over when it shouldn't change.

I think the simplest fix is that suggested by @felixscherz - just don't use base in the key for accessing the config. base will still be pkgenv the first time that the function is called for packaging envs and testenv when it is called for run envs but will be ignored at all subsequent calls for a specific env (as the cache will be used before it is looked at) and therefore it doesn't matter that it is not being passed correctly for later calls.

Probably a better fix would be to store and retrieve the config directly from the environment that is being run, rather than looking it up in the global cache. I think the env already has access to this conf, but I don't know enough detail on the data flow to figure out where in the chain of calls that leads to calling get_env() we would want to redirect it to the environment instead. That would probably be a somewhat bigger change so more likely to have unforeseen side effects. If you think it is the right way to go then I can investigate this but don't want to break something else important fiddling about with that.

@gaborbernat
Copy link
Member

gaborbernat commented Apr 9, 2024

I think there are a few options available here (with a choice on size of change vs overall quality of fix) - passing package=True would work, but I am not sure that that information is readily available at the point where get_env() is being called (package=False is merely the default value, it is not being passed in deliberately here):

I believe this would be the actual solution, and we need to check how we can pass this information down from the callers side rather than using that default. 🤔

I think the simplest fix is that suggested by @felixscherz - just don't use base in the key for accessing the config. base will still be pkgenv the first time that the function is called for packaging envs and testenv when it is called for run envs but will be ignored at all subsequent calls for a specific env (as the cache will be used before it is looked at) and therefore it doesn't matter that it is not being passed correctly for later calls.

I do not like this approach in general, ignoring argument is not desirable.

Probably a better fix would be to store and retrieve the config directly from the environment that is being run, rather than looking it up in the global cache. I think the env already has access to this conf, but I don't know enough detail on the data flow to figure out where in the chain of calls that leads to calling get_env() we would want to redirect it to the environment instead. That would probably be a somewhat bigger change so more likely to have unforeseen side effects. If you think it is the right way to go then I can investigate this but don't want to break something else important fiddling about with that.

Some configuration can be expensive to calculate. That is why we have the cash so that we don't do redundant work unless we must.

@bennyrowland
Copy link

I do not like this approach in general, ignoring argument is not desirable.

The point is that the argument is only relevant when creating the config for an environment, and at no point afterwards. conf.get_env(".pkg") should not need to be replaced by conf.get_env(".pkg", package=True) because the environment .pkg implies package=True (I don't mean based on the name, but the fact that once an environment is created its packaging/run status is not going to change, so you shouldn't need to track both pieces of information separately).

At the moment the actual env config is created here:

pkg_conf = self._state.conf.get_env(name, package=True)

which is paired with the matching line here for creating a run env config:
env_conf = self._state.conf.get_env(name, package=False)

Could we split the current get_env() function into a create_env() and get_env() pair, where create_env() is called in the two places above, and accepts a package argument (or even just a base argument directly) and everywhere else uses get_env() which drops package altogether and raises a KeyError if asked for an env which does not yet exist, rather than creating it on demand? As far as I can tell that would better describe the current logic as there don't appear to be any cases where calling the current get_env() should sometimes create and sometimes retrieve the result, it is always the case that it is first called from tox/session/env_select.py first to create it, and then from config/loader/ini/replace.py to retrieve it.

Some configuration can be expensive to calculate. That is why we have the cash so that we don't do redundant work unless we must.

But the ToxEnv class member variable conf is the same data that we retrieve via e.g. conf.get_env(".pkg") so if we could retrieve the ToxEnv (is/could there be a singleton dictionary of ToxEnvs that could be accessed by name, for example?) then we could do something like `envs[".pkg"].conf instead. This would be a much bigger change to the code, though, so I am less keen to take that on.

@bennyrowland
Copy link

I do not like this approach in general, ignoring argument is not desirable.

I should also point out that in the relevant function:

tox/src/tox/config/main.py

Lines 126 to 146 in 08223fc

def get_section_config( # noqa: PLR0913
self,
section: Section,
base: list[str] | None,
of_type: type[T],
for_env: str | None,
loaders: Sequence[Loader[Any]] | None = None,
) -> T:
key = section.key, for_env or "", "-".join(base or [])
try:
return self._key_to_conf_set[key] # type: ignore[return-value] # expected T but found ConfigSet
except KeyError:
conf_set = of_type(self, section, for_env)
self._key_to_conf_set[key] = conf_set
if for_env is not None:
conf_set.loaders.extend(self.memory_seed_loaders.get(for_env, []))
for loader in self._src.get_loaders(section, base, self._overrides, conf_set):
conf_set.loaders.append(loader)
if loaders is not None:
conf_set.loaders.extend(loaders)
return conf_set

The loaders argument is already being ignored when retrieving from the cache, it is only used to build it the first time, and the base argument was previously being ignored except for the first time, so it is not like this is without precedent ;-)

@gaborbernat
Copy link
Member

I do not like this approach in general, ignoring argument is not desirable.

The point is that the argument is only relevant when creating the config for an environment, and at no point afterwards. conf.get_env(".pkg") should not need to be replaced by conf.get_env(".pkg", package=True) because the environment .pkg implies package=True (I don't mean based on the name, but the fact that once an environment is created its packaging/run status is not going to change, so you shouldn't need to track both pieces of information separately).

This is not true. If you look deeper into the code you will realize that we are actually doing a two-phase environment creation. If we first discover an environment we assume it's going to be running environment and then if at the later point running environment marks that as a packaging we will convert it to a packaging environment.

@gaborbernat
Copy link
Member

Could we split the current get_env() function into a create_env() and get_env() pair, where create_env() is called in the two places above, and accepts a package argument (or even just a base argument directly) and everywhere else uses get_env() which drops package altogether and raises a KeyError if asked for an env which does not yet exist, rather than creating it on demand?

That could work.

@bennyrowland
Copy link

This is not true. If you look deeper into the code you will realize that we are actually doing a two-phase environment creation. If we first discover an environment we assume it's going to be running environment and then if at the later point running environment marks that as a packaging we will convert it to a packaging environment.

I may have missed something in the depths of the code, but on all my tests the get_env() calls from env_select.py only happen once for each environment, with the correct package=True|False call depending on which they are. I understand that prior to this there is a process that works out which is which, but by the stage of creating the envs I think this has been determined.

Could we split the current get_env() function into a create_env() and get_env() pair, where create_env() is called in the two places above, and accepts a package argument (or even just a base argument directly) and everywhere else uses get_env() which drops package altogether and raises a KeyError if asked for an env which does not yet exist, rather than creating it on demand?

That could work.

Going through the code to make changes, this is unfortunately not enough by itself - the current get_env() call passes on most of the responsibility to get_section_config() (that is where the base parameter is actually used). The change that produced this issue was including base in the key for looking up section config in Config._key_to_conf_set, so we still need to know the correct base to pass in there, which splitting up into create_env() and get_env() would not give us. Therefore we have three possible routes to solving this problem:

  1. Make sure we pass in a consistent base of testenv or pkgenv every time we want to get the conf for an env. As discussed above, this is hard to do at the moment as we only have the envname as a string at the point of calling these functions. We could make it possible to look up actual ToxEnv objects by name from somewhere to access whether they are packaging type or run type, but at that point we could just access the conf directly from the env instead.
  2. We could allow Config to have a second dictionary to store ToxEnv configs, indexed presumably only by name. In create_env() we would call get_section_config() to retrieve the ini file config (where we do have the correct value for the base parameter via the package argument that is passed on those calls) and store the resultant object in the second dict e.g. _key_to_env_set or similar. Then get_env() would simply look up from that dictionary instead of deferring back to get_section_config() again. This is the simplest option without changing any other behaviour, and probably what I would propose.
  3. We could revert to not including base on the get_section_config() key option (as proposed by @felixscherz above). This would have the result that you couldn't call get_section_config() twice with different base values as you would get the first base value back the second time you called it. This is not ideal in principle, but I don't know whether in practice it is ever done, or indeed permissible, to get_section_config() with the same section but different bases.

I think option 2 is the simplest and cleanest and I will put together a PR to implement that, unless anyone has a counter-proposal? It would be very helpful to get some advice on how to run a suitable test and where to put it within the test folder structure. It could go into config but because it needs to actually run an env (I think) and check the environment variables passed in, it might be better in tox_env?

@gaborbernat
Copy link
Member

I'd be ok to see a 2 proposals implementation, but also 1. I'm against 3.

@gaborbernat gaborbernat added the level:hard rought estimate that this might be quite hard to implement label Apr 12, 2024
mkoeppe added a commit to mkoeppe/sage that referenced this issue Apr 12, 2024
@bennyrowland bennyrowland linked a pull request Apr 18, 2024 that will close this issue
5 tasks
mkoeppe added a commit to mkoeppe/sage that referenced this issue Apr 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug:minor does not affect many people or has no big impact help:wanted Issues that have been acknowledged, a solution determined and a PR might likely be accepted. level:hard rought estimate that this might be quite hard to implement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants