asv icon indicating copy to clipboard operation
asv copied to clipboard

Support venv on python>=3.3

Open anntzer opened this issue 8 years ago • 5 comments

I know that the docs state a dependency on

virtualenv, 1.10 or later (this is true even with Python 3.3, where virtualenv is included as venv, since venv is not compatible with other versions of Python).

but would it be possible to just replace

import virtualenv

by

try: import venv as virtualenv
except ImportError: import virtualenv

everywhere, so that virtualenv becomes unneeded on Python>=3.3?

(Basically, I don't know if the two have APIs compatible enough for asv.)

anntzer avatar Jun 24 '17 00:06 anntzer

Want to try if it works? Patches are welcome in principle. All relevant code is in asv/plugins/virtualenv.py

pv avatar Jun 24 '17 13:06 pv

Ah, I think that won't work because you want to be able to use the current python to create virtualenvs for other pythons, which venv doesn't support.

anntzer avatar Jun 24 '17 21:06 anntzer

I think that's probably not so crucial, it would probably also be fine to shell out to a subprocess for the env creation.

pv avatar Jun 24 '17 22:06 pv

The workaround to the nested virtualenv/venv case apparently requires finding the "real" Python executable: from https://github.com/berdario/pew/blob/c25f19e9bb0bc94f696407378fc104706b5dd3b5/pew/_venv.py#L68-L104

def find_real_python():
    # We need to run venv on the Python we want to use. sys.executable is not
    # enough because it might come from a venv itself. venv can be easily
    # confused if it is nested inside another venv.
    # https://bugs.python.org/issue30811
    python = ('python.exe' if windows else 'python')


    # If we're in a venv, excellent! The config file has this information.
    pyvenv_cfg = pathlib.Path(sys.prefix, 'pyvenv.cfg')
    if pyvenv_cfg.exists():
        return Cfg(pyvenv_cfg).bindir.joinpath(python)


    # Or we can try looking this up from the build configuration. This is
    # usually good enough, unless we're in a virtualenv (i.e. sys.real_prefix
    # is set), and sysconfig reports the wrong Python (i.e. in the virtualenv).
    import sysconfig
    bindir = sysconfig.get_config_var('BINDIR')
    try:
        real_prefix = sys.real_prefix
    except AttributeError:
        return pathlib.Path(bindir, python)
    if not os.path.realpath(bindir).startswith(real_prefix):
        return pathlib.Path(bindir, python)


    # OK, so we're in a virtualenv, and sysconfig lied. At this point there's
    # no definitive way to tell where the real Python is, so let's make an
    # educated guess. This works if the user isn't using a very exotic build.
    for rel in ['', os.path.relpath(str(bindir), real_prefix), env_bin_dir]:
        try:
            path = pathlib.Path(real_prefix, rel, python).resolve()
        except FileNotFoundError:
            continue
        if path.exists():   # On 3.6+ resolve() doesn't check for existence.
            return path


    # We've tried everything. Sorry.
    raise BrokenEnvironmentError

pv avatar Sep 01 '18 16:09 pv

It would be great to push this forward. venv is in the standard library since Python 3.3, and we support only version of python with a stable version of venv which is also the recommended way to use virtual environment.

pauloxnet avatar Nov 05 '24 09:11 pauloxnet