-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
When virtualenv-pyenv is not installed, and the pyenv entry point is therefore not available.
virtualenv, with cli parameter
Using cli parameter, the response is reasonable and helpful
$ virtualenv --discovery pyenv myenv
usage: virtualenv [--version] [--with-traceback] [-v | -q] [--read-only-app-data] [--app-data APP_DATA] [--reset-app-data] [--upgrade-embed-wheels] [--discovery {builtin}]
virtualenv: error: argument --discovery: invalid choice: 'pyenv' (choose from 'builtin')
SystemExit: 2
virtualenv, with env.var.
If using the environment variable, its less helpful:
$ VIRTUALENV_DISCOVERY=pyenv virtualenv myenv
KeyError: 'pyenv'
tox, with env.var.
# tox.ini
[tox]
envlist = py39
[testenv]
commands = pytest
setenv =
VIRTUALENV_DISCOVERY=pyenv
The result is both messy and unhelpful. And as a newbie, I thought it was probably a bug, but in fact I just needed to install virtualenv-pyenv.
$ tox
py39: internal error
Traceback (most recent call last):
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/api.py", line 282, in setup
self._setup_env()
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/runner.py", line 98, in _setup_env
super()._setup_env()
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/api.py", line 243, in _setup_env
self.ensure_python_env()
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/api.py", line 247, in ensure_python_env
conf = self.python_cache()
^^^^^^^^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/virtual_env/api.py", line 82, in python_cache
base = super().python_cache()
^^^^^^^^^^^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/api.py", line 284, in python_cache
"version_info": list(self.base_python.version_info),
^^^^^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/api.py", line 294, in base_python
self._base_python = self._get_python(base_pythons)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/virtual_env/api.py", line 139, in _get_python
interpreter = self.creator.interpreter
^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/virtual_env/api.py", line 131, in creator
return self.session.creator
^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/tox/tox_env/python/virtual_env/api.py", line 112, in session
self._virtualenv_session = session_via_cli(env_dir, options=None, setup_logging=False, env=env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/virtualenv/run/__init__.py", line 49, in session_via_cli
parser, elements = build_parser(args, options, setup_logging, env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/virtualenv/run/__init__.py", line 77, in build_parser
discover = get_discover(parser, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/velle/.virtualenvs/toxrunner/lib/python3.12/site-packages/virtualenv/run/plugin/discovery.py", line 27, in get_discover
discover_class = discover_types[options.discovery]
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
KeyError: 'pyenv'
py39: FAIL code 2 (0.01 seconds)
evaluation failed :( (0.07 seconds)
Solution, maybe...
I admit I don't understand virtualenv too well, so this is only my humble suggestion.
So first of all. In the case that VIRTUALENV_DISCOVERY holds a key that is not available as entry point, virtualenv needs to provide a more helpful reponse to the cli. Not just KeyError. Perhaps it could raise an exception like this
class DiscoverNotFoundException(Exception):
def __init__(self, key: str, discover_types: Mapping[str, type]):
self.key = key
self.discover_types = discover_types
def __str__(self):
msg = "No entrypoint in group 'virtualenv.discover' with config key '%s'. Available keys are:" % self.key
for key,typ in self.discover_types.items():
msg += "\n %-20s -> %s" % (key, typ)
return msg
with this check in get_discover
:
options, _ = parser.parse_known_args(args)
# ---- new code begin ----
if options.discovery not in discover_types:
raise DiscoverNotFoundException(options.discovery, discover_types)
# ---- new code end ----
discover_class = discover_types[options.discovery]
discover_class.add_parser_arguments(discovery_parser)
options, _ = parser.parse_known_args(args, namespace=options)
return discover_class(options)
It would look like this:
$ VIRTUALENV_DISCOVERY=discoverychannel virtualenv myenv
DiscoverNotFoundException: No entrypoint in group 'virtualenv.discover' with config key 'discoverychannel'. Available keys are:
pyenv -> <class '_virtualenv_pyenv.discovery.PyenvCompat'>
pyenv-compat -> <class '_virtualenv_pyenv.discovery.PyenvCompat'>
pyenv-fallback -> <class '_virtualenv_pyenv.discovery.PyenvFallback'>
pyenv-strict -> <class '_virtualenv_pyenv.discovery.PyenvStrict'>
builtin -> <class 'virtualenv.discovery.builtin.Builtin'>
That would make sure that the user always gets some helpful information, no matter how the tool is used.
And ideally, tox should catch this exception and print it without the stacktrace.
Environment
Ubuntu 24.04, bash, Python 3.12.3
(toxrunner) $ pip list
Package Version
------------- ---------
cachetools 6.1.0
chardet 5.2.0
colorama 0.4.6
dbf 0.99.11a1
distlib 0.3.9
filelock 3.18.0
packaging 25.0
pip 24.0
platformdirs 4.3.8
pluggy 1.6.0
pyenv-inspect 0.4.0
pyproject-api 1.9.1
tox 4.27.0
virtualenv 20.31.2