Skip to content
This repository has been archived by the owner on Jul 23, 2020. It is now read-only.

Leverage virtualenv to ensure pip and setuptools and wheel are recent #25

Closed
wants to merge 9 commits into from
Closed

Leverage virtualenv to ensure pip and setuptools and wheel are recent #25

wants to merge 9 commits into from

Conversation

jaraco
Copy link

@jaraco jaraco commented Sep 19, 2018

Fixes #24. Obviates #23. Fixes #17.

@jaraco
Copy link
Author

jaraco commented Sep 19, 2018

Try out this PR here: https://m.devpi.net/jaraco/dev/tox-venv/0.3.1+pr25

@jaraco
Copy link
Author

jaraco commented Sep 19, 2018

I'll be honest, I don't fully understand the test failures.

Some of them seem spurious to me, like the assertions are too tightly coupled to the implementation details.

Other ones may be more legitimate, revealing that in some cases 'python' doesn't exist. I'm not sure why that would be.

So I present this PR for your consideration. It works for me and it solves the issue in my environment. I don't do a lot of Python 3.5 work, but when I do, it's nice to have this functionality.

@asottile
Copy link

A few minor concerns, it's probably fine:

  • does this potentially downgrade packages? For instance say I'm running virtualenv 15.0.1 w/ python 3.7.0
    • 3.7.0 ships with pip 10.0.1, setuptools 39.0.1
    • virtualenv 15.0.1 ships with pip 8.1.1, setuptools 20.3 (and wheel and argparse)
  • does this work for debian's mangled pip / virtualenv packages? (probably ok to just not, but probably worth considering)

@jaraco
Copy link
Author

jaraco commented Sep 20, 2018

does this potentially downgrade packages?

I just installed virtualenv 15.0.1 and ran tox -r on a Python 3.7 environment (with this patched tox-venv installed), and pip 10.0.1 was still present in the new env. So it seems it does not downgrade packages.

does this work for debian's mangled pip / virtualenv packages?

Hard to say, but I'd imagine so, in part because it's leveraging the virtualenv code, but also because I just ran a test with this branch on ubuntu bionic... and it creates the environments just fine. Is there a test I could run that would reveal an anticipated failure?

Copy link

@asottile asottile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably sufficient then!

@jaraco
Copy link
Author

jaraco commented Sep 20, 2018

Thanks. In that case, I'll try to get the tests to pass.

@jaraco
Copy link
Author

jaraco commented Sep 21, 2018

I'm having difficulty running the tests. I can't get the tests on master to pass, nevermind the patch. I get 18 failures, most similar to those failing in Travis. Can someone help with ferreting out the issues with the tests failing - maybe give some advice how I might proceed?

@rpkilby
Copy link
Member

rpkilby commented Sep 21, 2018

Hi @jaraco. I haven't had time to look at this yet, but my immediate guess is that the test failures are due to the test suite being out of date. One maintenance annoyance is making sure the test suite is kept up to date, the reapplying the tox-venv related changes.

Try temporarily pinning tox==3.0.0, as that was the last test suite update.

I'll try to take a look at this soon.

@jaraco
Copy link
Author

jaraco commented Sep 21, 2018

Cool. I created the stable-deps branch, where tests are passing for me (and some pass in travis). I then rebased the work in this branch on there in the stable-deps+feature/update-env-installer branch, and many tests are failing, revealing apparent regressions. At least the concerns are separated now.

@jaraco
Copy link
Author

jaraco commented Sep 21, 2018

These errors match what I'm seeing locally. Probably the mocks need to be updated to mock out the virtualenv install_wheel call.

@jaraco
Copy link
Author

jaraco commented Sep 21, 2018

I've pushed 8b59f63, and I expect the tests to pass in Travis for that branch, but it doesn't prove much; it just disables the added functionality to prevent it from causing the tests to fail.
At this point, I need to defer to someone with more understanding of the mock technique to decide how's best to test (or not test) this functionality.

@jaraco
Copy link
Author

jaraco commented Sep 23, 2018

In pypa/setuptools#1500, I discovered a regression. It seems that when testing setuptools, including this functionality causes the develop-installed setuptools to be replaced by this vendored copy. I'll want to investigate why that is and why a virtualenv isn't affected.

(may be false alarm; tests now pass reliably and team member was unable to replicate even with this patch installed)

@jaraco
Copy link
Author

jaraco commented Dec 29, 2018

Today I found another regression elicited by the test suite on Python 3.5 (and probably Python 2.7). That's fixed in d988843. And as you can see in this build, if the dependencies are pinned to avoid unrelated issues in the dependencies, the tests pass on the same Pythons in which master passes with those some pins.

I'd like to propose merging this PR (and cutting an 0.4 release). I've used this technique for months with no issues other than the apparent regression I reported on Sep 23 that hasn't re-emerged, and I again today confirmed it's not happening in a typical environment.

@jaraco
Copy link
Author

jaraco commented Jan 1, 2019

Hmm. I may have run into a new issue with this code. This morning, I've created literally hundreds of virtualenvs using this tox-venv version. But now I'm trying it and it's failing with this traceback:

jaraco.financial master $ tox                                                                                                                                                            
python create: /Users/jaraco/code/main/jaraco.financial/.tox/python
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/bin/tox", line 11, in <module>
    sys.exit(cmdline())
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tox/session.py", line 42, in cmdline
    main(args)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tox/session.py", line 49, in main
    retcode = build_session(config).runcommand()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tox/session.py", line 457, in runcommand
    return self.subcommand_test()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tox/session.py", line 583, in subcommand_test
    if self.setupenv(venv):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tox/session.py", line 508, in setupenv
    status = venv.update(action=action)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tox/venv.py", line 217, in update
    self.hook.tox_testenv_create(action=action, venv=self)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pluggy/__init__.py", line 617, in __call__
    return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pluggy/__init__.py", line 222, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pluggy/__init__.py", line 216, in <lambda>
    firstresult=hook.spec_opts.get('firstresult'),
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pluggy/callers.py", line 201, in _multicall
    return outcome.get_result()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pluggy/callers.py", line 76, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pluggy/callers.py", line 180, in _multicall
    res = hook_impl.function(*args)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tox_venv/hooks.py", line 111, in tox_testenv_create
    py_executable=os.path.join(venv.path / exe_dir / 'python'),
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/virtualenv.py", line 904, in install_wheel
    call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=SCRIPT)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/virtualenv.py", line 796, in call_subprocess
    % (cmd_desc, proc.returncode))
OSError: Command /Users/jaraco/code/m...ox/python/bin/python - setuptools pip wheel failed with error code 2

Immediately I notice one deficiency - if an issue does occur when venv calls virtualenv to upgrade the packages, the output is unconditionally suppressed. Let's see if I can find a way to override that setting to see what the underlying error is.

@asottile
Copy link

asottile commented Jan 1, 2019

virtualenv 16.2 was released this morning, perhaps related?

@jaraco
Copy link
Author

jaraco commented Jan 1, 2019

Aha - so while trying to create a breakpoint in the stack trace above, I found it was failing earlier, and from there I was able to ascertain the underlying cause:

jaraco.financial master $ .tox/python/bin/python3 -Im ensurepip --upgrade --default-pip                                                                                                  
Looking in links: /var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/tmpqdilxrv1
Collecting setuptools
Collecting pip
Installing collected packages: setuptools, pip
Exception:
Traceback (most recent call last):
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/tmpqdilxrv1/pip-18.1-py2.py3-none-any.whl/pip/_internal/cli/base_command.py", line 143, in main
    status = self.run(options, args)
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/tmpqdilxrv1/pip-18.1-py2.py3-none-any.whl/pip/_internal/commands/install.py", line 366, in run
    use_user_site=options.use_user_site,
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/tmpqdilxrv1/pip-18.1-py2.py3-none-any.whl/pip/_internal/req/__init__.py", line 49, in install_given_reqs
    **kwargs
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/tmpqdilxrv1/pip-18.1-py2.py3-none-any.whl/pip/_internal/req/req_install.py", line 760, in install
    use_user_site=use_user_site, pycompile=pycompile,
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/tmpqdilxrv1/pip-18.1-py2.py3-none-any.whl/pip/_internal/req/req_install.py", line 382, in move_wheel_files
    warn_script_location=warn_script_location,
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/tmpqdilxrv1/pip-18.1-py2.py3-none-any.whl/pip/_internal/wheel.py", line 215, in move_wheel_files
    prefix=prefix,
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/tmpqdilxrv1/pip-18.1-py2.py3-none-any.whl/pip/_internal/locations.py", line 153, in distutils_scheme
    d.parse_config_files()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/distutils/dist.py", line 406, in parse_config_files
    parser.read(filename)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/configparser.py", line 696, in read
    self._read(fp, filename)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/configparser.py", line 1110, in _read
    raise e
configparser.ParsingError: Source contains parsing errors: 'setup.cfg'
        [line 57]: 'console_scripts\n'

I had a malformed setup.cfg... and that's almost certainly what's tripping up the invocation. Probably it would be best if the invocation of virtualenv.install_wheel happened in a temporary directory so as to avoid any influence of a setup.cfg in the current working directory.

@jaraco
Copy link
Author

jaraco commented Jan 1, 2019

virtualenv 16.2 was released this morning, perhaps related?

I was thinking the same thing, but I'm still running the older version.

@asottile
Copy link

asottile commented Jan 1, 2019

ahah, yeah I've hit that in the past too -- pre-commit works around this by invoking in /: https://github.com/pre-commit/pre-commit/blob/b31cb22d8b3fc2beb24ab451f5e1ac0121c95ee1/pre_commit/languages/python.py#L153

GitHub
A framework for managing and maintaining multi-language pre-commit hooks. - pre-commit/pre-commit

@jaraco
Copy link
Author

jaraco commented Jan 3, 2019

I've confirmed that the setup.cfg issue is a known issue in virtualenv, so not something that can or should be solved here. Ideally the tests should be passing, but I'm fairly confident the failures are outside the scope of this effort. I'm hoping the PR can be merged as-is or that someone can address the test failures. Thanks all for the feedback.

@rpkilby
Copy link
Member

rpkilby commented Mar 29, 2019

Hi @jaraco. I've fixed a few issues with the test suite and updated it to reflect tox 3.8.1
Do you think you could take a second look at this, based on the latests changes.

@jaraco
Copy link
Author

jaraco commented Apr 22, 2019

@rpkilby I'm hoping you'll have a chance to review/accept this and cut a release with it.

CHANGELOG.rst Outdated Show resolved Hide resolved
@jayvdb
Copy link

jayvdb commented Jun 12, 2019

I expect this is going to break a lot of people's use of tox-venv, as they expect that with this plugin the new venv is raw from Python, which is very stable except that the builtin Python venv already upgrades pip.

I dont understand why people would want to use tox-venv if this gets merged, as it seems easier to just use the standard tox without tox-venv which will do all this.

@jaraco
Copy link
Author

jaraco commented Jun 12, 2019

the builtin Python venv already upgrades pip.

That's not my experience:

$ python -m venv test                                                                                                   
$ test/bin/python -m pip --version                                                                                      
pip 19.0.3 from /Users/jaraco/code/public/pypa/twine/test/lib/python3.7/site-packages/pip (python 3.7)

Note that pip 19.1.1 is the latest pip at this time of writing.

I dont understand why people would want to use tox-venv if this gets merged, as it seems easier to just use the standard tox without tox-venv which will do all this.

There are many reasons.

  • venv addresses issues inherent in the design of virtualenv that make it better behaved and have fewer bugs (I don't have a reference handy, but the references in the original post may illustrate some).
  • venv is newer than virtualenv and intends to supersede virtualenv for later Pythons; it's the future, so early adopters should be able to opt-in
  • venv is more robust against changes to the interpreter
  • venv is built-in, so has no variability in versions and is thus more predictable
  • venv is lighter weight, having no dependencies

All of these reasons are why I use tox-venv (in roughly descending order of importance). My understanding also is that tox intends to adopt this functionality by default, not as a plugin, so having it operate at parity with the existing virtualenv implementation is an important step in that transition.

@jayvdb
Copy link

jayvdb commented Jun 12, 2019

Builtin venv has option with_pip which can be used to upgrade pip, if that is the main goal of this PR, without using virtualenv. It would be great if tox-venv exposed that venv options as tox configuration, enabled by default.

As noted elsewhere, mandatory installation and upgrading of wheel is weird and should be not copied.

That only leaves the problem of auto upgrading setuptools, which is a simple problem to solve without virtualenv if venv has already upgraded pip.

@asottile
Copy link

Builtin venv has option with_pip which can be used to upgrade pip, if that is the main goal of this PR, without using virtualenv. It would be great if tox-venv exposed that venv options as tox configuration, enabled by default.

I only see --without-pip which prevents installation of pip into the resulting virtualenv (and I'm not sure why that option would eve be used) -- as far as I can tell with_pip (from the python api) only ensures that ensurepip is called on the final virtualenv

@asottile
Copy link

and ensurepip uses the wheels bundled with the interpreter -- it does not upgrade from pypi

@jayvdb
Copy link

jayvdb commented Jun 12, 2019

https://github.com/python/cpython/blob/master/Lib/venv/__init__.py#L269 - it uses --upgrade

https://github.com/python/cpython/blob/master/Lib/ensurepip/__init__.py#L110 passes upgrade to pip

GitHub
The Python programming language. Contribute to python/cpython development by creating an account on GitHub.
GitHub
The Python programming language. Contribute to python/cpython development by creating an account on GitHub.

@asottile
Copy link

asottile commented Jun 12, 2019

@jayvdb
Copy link

jayvdb commented Jun 12, 2019

Bugger! I guess they also decided to choose stability over dephell of constantly updating pip/setuptools/etc., a reason I used tox-venv. As we can disregard 2.7, 3.4, etc now all EOL or close to EOL, most people are using venv bundles from py36, pip-18.1 and setuptools-40.6.2 .

https://github.com/python/cpython/tree/3.6/Lib/ensurepip/_bundled

And they are being updated fairly frequently

https://github.com/python/cpython/commits/master/Lib/ensurepip/_bundled

We're not in the days of distros providing pip 0.3-ish, which couldnt even read 90% of requirements files in the wild.

For people needing more recent versions, another approach is tox-pip-version , which does provide upgrading, as this is also a feature requested of tox - tox-dev/tox#791 . The beauty of plugins where each does one thing.

GitHub
The Python programming language. Contribute to python/cpython development by creating an account on GitHub.
GitHub
The Python programming language. Contribute to python/cpython development by creating an account on GitHub.

@rpkilby
Copy link
Member

rpkilby commented Jun 12, 2019

Leaving this functionality to tox-pip-version seems sensible to me. @jaraco any reason this wouldn't work?

@jaraco
Copy link
Author

jaraco commented Jun 13, 2019

any reason this wouldn't work?

I have no reason to expect that tox-pip-version can't be used to specify a pip version... and other features could be used to specify setuptools/wheel versions.

I still think you want this change to get parity between virtualenv and env envs (even for just between py2/3 when tox-venv is present). Another way to achieve parity would be to instead use ensurepip in virtualenv envs.

@jaraco
Copy link
Author

jaraco commented Sep 30, 2019

II agree it seems nicer to separate the concerns of pip version requirements and virtualenv management. I'll give tox-pip-version a try and stop fighting this battle.

@jaraco jaraco closed this Sep 30, 2019
@rpkilby
Copy link
Member

rpkilby commented Sep 30, 2019

Apologies - never meant for this to be difficult. I'm just stretched on time. Currently, I'm waiting on the tox 4 to see if this is even necessary. But for now, using tox-pip-version is the way to go.

@Aricg
Copy link

Aricg commented Oct 25, 2019

tox-pip-version does not seem to work with tox-venv
one uses virtualenv and one uses python -m venv
am I missing something?

How can I at the same time not use virtualenv with tox and also have a reasonable version of pip?

@Aricg
Copy link

Aricg commented Oct 25, 2019

I take it back! it works!

16:27:55 coala run-test: commands[0] | python check-pip-version.py 18.1 16:27:56 PASS: version '18.1' is in set '==18.1'

@Aricg
Copy link

Aricg commented Oct 25, 2019

Thanks for making this package. tox-venv and tox-pip-version have combined to saved me from the Fifth Circle of python hell.

[testenv:coala]
basepython = python3
pip_version = pip==18.1
deps =
    coala
    coala-bears
    pygments~=2.3.1
    requests~=2.21.0
    nodeenv
    numpy~=1.16.4
commands =
    python check-pip-version.py 18.1
    nodeenv -p
    npm install --global remark-cli remark-lint write-good
    coala --non-interactive

@jaraco
Copy link
Author

jaraco commented Feb 15, 2020

Unfortunately, it seems that tox-pip-version is not suitable for the case of a bootstrap environment (.tox/.tox). See pypa/setuptools#2000.

@rpkilby rpkilby reopened this Feb 16, 2020
@rpkilby
Copy link
Member

rpkilby commented Feb 16, 2020

Hi @gaborbernat. Given the changes to virtualenv 20, is there a "recommended" but unofficial way of installing the bundled wheels? Right now, it looks like we'd need to do something like:

from virtualenv.run import session_via_cli

session = session_via_cli(['path/to/venv', '--seeder', 'pip'])
session.seeder.run(session.creator)

@gaborbernat
Copy link
Member

Out of box it installs bundled wheels.

@jaraco
Copy link
Author

jaraco commented Apr 27, 2020

venv is dead. long live virtualenv.

@jaraco jaraco closed this Apr 27, 2020
@jaraco jaraco deleted the feature/update-env-installer branch April 27, 2020 22:57
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Broken on macOS with Python 3.6 and below upgrade pip/setuptools and install wheel in venv?
8 participants