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

enhance Python easyblock: Add option to install pip with core Python, tweak defaults, create unversioned pip symlink #2388

Merged
merged 19 commits into from
May 13, 2021

Conversation

Flamefire
Copy link
Contributor

@Flamefire Flamefire commented Apr 14, 2021

Installing pip from the core Python allows easier installing of packages and avoids the fallback to using setup.py and egg files which can't be easily upgraded

I added an option install_pip for installing an initial pip+setuptools which may become the default in EB 5.0. However when that is used, then pip MUST be used to upgrade those 2 later in the EC or otherwise the initial version is not properly removed/updated but merely half-way patched (or with pip even kept and silently used)
Hence an additional check is added to catch this case.

This is a breaking change, however I see no viable alternative to fix the current bug. See #2388 (comment) for more details.
Current ECs are fixed in easybuilders/easybuild-easyconfigs#12650

The remaining changes are closely related:

  • When installing pip or checking for extensions the user site dir should be ignored
  • Creating the symlink pip to pip2/3 spares the ECs to do that in installopts
  • Set download_dep_fail by default. However it may fail in case we missed to install some deps in the EC which is the case for old ECs, hence I choose to only do it in recent Python 2 and in Python 3.
  • Set sanity_pip_check by default, if the installed pip is new enough. If pip check doesn't succeed for the core Python package something is wrong...
  • Disable '--ignore-installed` by default which is important as we update pip and setuptools. For the other packages it has no effect, as there can't be an installed package which we would want to ignore when installing Python itself.

The last one is critical as --ignore-installed does not properly update but only add new files, not changing existing files leads to a mix of versions and issues such as easybuilders/easybuild-easyconfigs#12757

@Flamefire Flamefire force-pushed the installPipIn2.7 branch 2 times, most recently from e01821a to e7b6ddd Compare April 14, 2021 15:24
@Flamefire Flamefire changed the title Also install bundled pip with Python 2 >= 2.7.9 Enhance Python EasyBlock: Install pip2 when available, tweak defaults, create unversioned pip symlink Apr 28, 2021
@boegel boegel changed the title Enhance Python EasyBlock: Install pip2 when available, tweak defaults, create unversioned pip symlink Enhance Python easyblock: install pip2 when available, tweak defaults, create unversioned pip symlink Apr 28, 2021
@boegel boegel added this to the next release (4.3.5?) milestone Apr 28, 2021
easybuild/easyblocks/p/python.py Outdated Show resolved Hide resolved
easybuild/easyblocks/p/python.py Outdated Show resolved Hide resolved
easybuild/easyblocks/p/python.py Outdated Show resolved Hide resolved
easybuild/easyblocks/p/python.py Outdated Show resolved Hide resolved
@boegel
Copy link
Member

boegel commented Apr 28, 2021

@Flamefire These changes seem to at least break Python-2.7.16-GCCcore-8.3.0.eb, perhaps more.

I also have a test report coming up from generoso with a reinstall of all installed Python modules we have there...

@boegel
Copy link
Member

boegel commented Apr 28, 2021

Test report by @boegel

Overview of tested easyconfigs (in order)

Build succeeded for 0 out of 1 (1 easyconfigs in total)
node3143.skitty.os - Linux centos linux 7.9.2009, x86_64, Intel(R) Xeon(R) Gold 6140 CPU @ 2.30GHz, Python 3.6.8
See https://gist.github.com/fb48f60089595c4639fac9a3db5701d6 for a full test report.

@Flamefire
Copy link
Contributor Author

Flamefire commented Apr 28, 2021

I may have an explanation here: That EasyConfig installs setuptools without pip. This may lead to the same issue as with pip itself: It will install the new setuptools without removing the old one and then the newer pip might use the older setuptools which leads to that issue.
Going to double-check.

Reading pypa/pip#6264 and your comments there suggests that indeed the older setuptools (installed by the bootstrap/ensurepip) are used

Not sure how this can be solved if the EC tries to install pip/setuptools without pip while Python has already a pip and setuptools.

I'm running out of ideas how to fix the issues AND have it backward compat. E.g. current ECs install pip without pip but use pip for setuptools: https://github.com/easybuilders/easybuild-easyconfigs/blob/91e0e3809cc56ae6e95db8cef902093d2f806be0/easybuild/easyconfigs/p/Python/Python-3.8.2-GCCcore-9.3.0.eb#L53
This breaks pip in a similar way as it breaks setuptools now (your issue) as it may use the older pip, not the newer one.

So either we use ensurepip in Python base and use pip to install/upgrade BOTH setuptools and pip, or don't use ensurepip and install setuptools/pip via setup.py. Everything else is trouble... And we can't have that without breaking something

Idea: Force using pip for the pip/setuptools extensions. In a quick test the only thing that might be required is installing wheel before pip as newer versions of pip might require that

@easybuilders easybuilders deleted a comment from boegelbot Apr 28, 2021
@boegelbot
Copy link

Test report by @boegelbot

Overview of tested easyconfigs (in order)

  • SUCCESS Python-2.7.15-GCCcore-7.3.0-bare.eb
  • FAIL (build issue) Python-2.7.15-GCCcore-8.2.0.eb (partial log available at https://gist.github.com/4cf26cce5af507434cc117909de9c38a)
  • SUCCESS Python-2.7.15-foss-2018b.eb
  • SUCCESS Python-2.7.15-fosscuda-2018b.eb
  • FAIL (build issue) Python-2.7.16-GCCcore-8.3.0.eb (partial log available at https://gist.github.com/4ee958a61d244849d0dc6b82eee86503)
  • SUCCESS Python-2.7.18-GCCcore-10.2.0.eb
  • SUCCESS Python-2.7.18-GCCcore-9.3.0.eb
  • SUCCESS Python-3.6.6-foss-2018b.eb
  • SUCCESS Python-3.6.6-fosscuda-2018b.eb
  • SUCCESS Python-3.7.2-GCCcore-8.2.0.eb
  • SUCCESS Python-3.7.4-GCCcore-8.3.0.eb
  • SUCCESS Python-3.8.2-GCCcore-9.3.0.eb
  • SUCCESS Python-3.8.6-GCCcore-10.2.0.eb

Build succeeded for 11 out of 13 (13 easyconfigs in total)
generoso - Linux centos linux 8.2.2004, x86_64, Intel(R) Xeon(R) CPU E5-2667 v3 @ 3.20GHz (haswell), Python 3.6.8
See https://gist.github.com/f37735711e7d4990f2ee2db311079c13 for a full test report.

@boegel
Copy link
Member

boegel commented Apr 29, 2021

@Flamefire We're fixing bugs here, which means things don't have to be fully backwards-compatible. If some of the existing easyconfigs we have centrally need changes in combination with the changes being made here to ensure they still work, then so be it.

@Flamefire
Copy link
Contributor Author

Ok then my suggestion would be:

  • Add an option to install pip (via ensurepip) which is enabled by default for Python 3.4+, i.e. not for Python 2 to avoid having to change countless ECs. While not using pip there to install pip may be suboptimal it seemingly works
  • When that option is enabled, check that use_pip for pip and setuptools extensions is set to true, if not either force set it or error out
  • Additionally move the "wheel" package to the front

This means for older pythons (e.g. Python 2) setuptools&pip will still be installed as eggs, which has worked so far. Real issues occur only when we want to update those 2 which was not (AFAIK) the case, until we used ensurepip. We can update recentish Python 2 ECs to set this option

Installing/upgrading setuptools via pip was likely never a problem (checked some versions, and if we used ensurepip of course), but installing pip via pip requires wheel for newer versions of pip (I think 20+ according to some quick experiments)
My guess is (assuming sane Python devs), that wheel can always be installed with any version of setuptools and pip, hence we can do that first.
Newer versions of pip use a new feature of setuptools, e.g. the __legacy__ thing.
Hence I think it makes sense to either enforce (i.e. error out) or ensure (i.e. reorder exts) to install: wheels, setuptools, pip, in this order, when we have used ensurepip.

The error option would mean we need to fix a lot of ECs.

So maybe add that option but make it off by default. Then we only need to fix ECs which we have changed to rely on pip being there, which are far less, and maybe backport that for a few older ones (2019a+ I'd say)

--> Add option use_ensurepip (better name idea?), off by default, and if set check if use_pip=True is used for pip&setuptools and error out if not the case

I'll be back for further discussion via slack on Monday if required.

@Flamefire Flamefire marked this pull request as draft May 3, 2021 08:32
@Flamefire Flamefire marked this pull request as ready for review May 3, 2021 12:33
@Flamefire Flamefire requested a review from boegel May 3, 2021 12:33
@Flamefire
Copy link
Contributor Author

Enabling the default sanity_pip_check can only be done if we also install a recent pip (i.e. >= 9). I added 6c7a190 for that.

@Flamefire
Copy link
Contributor Author

Enabling the download_dep_fail option by default does make sense to me but it shows "bugs" in older ECs, e.g. Python-2.7.13-foss-2017a.eb does not include ipaddress but that is a dependency for cryptography. Due to enabling the "disconnected" option of pip if "download_dep_fail" is set, with this change it will NOT download ipaddress from PyPi anymore and fail to install the EC.

@boegel I can PR the fix to the EC and keep the download_dep_fail = True default here. Or shall we wait with changing this default until EB 5?

@Flamefire
Copy link
Contributor Author

Looks like fixing the EC(s) is more work and likely some more are also affected. I choose to not set download_dep_fail for "old" Python versions. The remaining ones should already set that in the EC so it's safe there, I guess. Could still remove this and wait for EB 5.x with that change

@Flamefire
Copy link
Contributor Author

Test report by @Flamefire

Overview of tested easyconfigs (in order)

  • SUCCESS Python-2.7.11-foss-2016a.eb
  • SUCCESS Python-2.7.14-foss-2018a.eb
  • SUCCESS Python-2.7.15-GCCcore-8.2.0.eb
  • SUCCESS Python-2.7.18-GCCcore-10.2.0.eb
  • SUCCESS Python-3.6.4-foss-2018a.eb
  • SUCCESS Python-3.7.2-GCCcore-8.2.0.eb
  • SUCCESS bzip2-1.0.6-GCCcore-6.3.0.eb
  • SUCCESS XZ-5.2.2-GCCcore-4.9.3.eb
  • SUCCESS Python-3.5.1-foss-2016a.eb
  • SUCCESS libreadline-7.0-GCCcore-6.3.0.eb
  • SUCCESS GMP-6.1.2-GCCcore-6.3.0.eb
  • SUCCESS Tcl-8.6.6-GCCcore-6.3.0.eb
  • SUCCESS SQLite-3.17.0-GCCcore-6.3.0.eb
  • SUCCESS libffi-3.2.1-GCCcore-6.3.0.eb
  • SUCCESS XZ-5.2.3-GCCcore-6.3.0.eb
  • FAIL (build issue) Python-2.7.13-foss-2017a.eb (partial log available at https://gist.github.com/6f8088abebdf19c6077156e61873ec8f)
  • FAIL (build issue) Python-3.6.1-foss-2017a.eb (partial log available at https://gist.github.com/e6df4900f4d4929bf3241740a3e37cd2)

Build succeeded for 15 out of 17 (9 easyconfigs in total)
taurusi6216.taurus.hrsk.tu-dresden.de - Linux RHEL 7.9, x86_64, Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz (haswell), Python 2.7.5
See https://gist.github.com/d0a47e552f431e5185a2c426cca74961 for a full test report.

@Flamefire
Copy link
Contributor Author

Ok, it seems the old ECs can no longer be installed. I tested the failing 2 Python ECs without this patch and e.g. Python/3.6.1-foss-2017a/ does fail too with:

Processing dependencies for cffi==1.11.5
Searching for pycparser
Reading https://pypi.python.org/simple/pycparser/
Couldn't find index page for 'pycparser' (maybe misspelled?)
Scanning index of all packages (this may take a while)
Reading https://pypi.python.org/simple/
No local packages or working download links found for pycparser
error: Could not find suitable distribution for Requirement.parse('pycparser')

So it seems we missed a required package and PyPi has changed something so old pips can't use it anymore.
That would be a reason to enable download_dep_fail by default unconditionally to "weed out" such ECs and fix them if anyone still uses them.

But I'd also be fine with leaving this as-is and get this in rather sooner than later

@boegel
Copy link
Member

boegel commented May 5, 2021

@Flamefire That failure is not related to the changes made in #2390, right?

@Flamefire
Copy link
Contributor Author

@boegel Yes they are not related. The failing command:

== 2021-05-04 17:11:09,106 easyblock.py:3427 WARNING build failed (first 300 chars): cmd " /tmp/ebinstall/software/Python/3.6.1-foss-2017a/bin/python setup.py install --prefix=/tmp/ebinstall/software/Python/3.6.1-foss-2017a " exited with exit code 1 and output:

I.e. it is using setup.py not pip, hence this is unaffected by the change in #2390 which only affects pip

# Since Python 2.7.14 (and all Python 3 versions) we usually enable download_dep_fail in the ECs
# already so this should not lead to failures
if LooseVersion(self.version) >= LooseVersion('2.7.14'):
ext_defaults['download_dep_fail'] = True
Copy link
Member

Choose a reason for hiding this comment

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

@Flamefire I don't think we should automatically enable this at this point, that's a rather intrusive change in the default behavior, which we should only make in EasyBuild v5.0 (cfr. #2127).

I fully agree with you that we should do this, which is why the easyconfig test suite has been requiring this for a while now, and I'm looking forward to not having to worry about this anymore and enabling it by default, but we shouldn't for the time being.

We're not enabling download_dep_fail in the oldest Python 3 easyconfigs (and it's not worth spending time in trying to enable that there). Those easyconfigs are old enough that they'll be archived in EasyBuild v5.0, so they won't block enabling download_dep_fail by default.

If I understand correctly, just removing this part won't affect the rest of this PR, correct me if I'm wrong...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Postponed to EB 5.x where this will be the default in the PythonPackage EasyBlock

Comment on lines 139 to 140
# Python installations must be clean. Requires pip >= 9
'sanity_pip_check': LooseVersion(self._get_pip_ext_version() or '0') >= LooseVersion('9'),
Copy link
Member

Choose a reason for hiding this comment

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

This comment should be clarified a bit I think, and I would use 9.0 rather than 9 (just for clarity sake):

Suggested change
# Python installations must be clean. Requires pip >= 9
'sanity_pip_check': LooseVersion(self._get_pip_ext_version() or '0') >= LooseVersion('9'),
# enable "pip check" in sanity check by default, to ensure that Python installations are clean;
# requires pip v9.0 or newer
'sanity_pip_check': LooseVersion(self._get_pip_ext_version() or '0') >= LooseVersion('9.0'),

That said, I don't think we should be enabling sanity_pip_check by default just yet. It'll result in broken Python easyconfigs that worked just fine up until now, and changes that break backwards compability should only be made in the next major EasyBuild release (v5.0), cfr. #2127

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Removed and will open a follow-up PR for this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Follow-up: #2423

easybuild/easyblocks/p/python.py Show resolved Hide resolved
easybuild/easyblocks/p/python.py Outdated Show resolved Hide resolved
easybuild/easyblocks/p/python.py Outdated Show resolved Hide resolved
@Flamefire
Copy link
Contributor Author

Test report by @Flamefire

Overview of tested easyconfigs (in order)

  • SUCCESS Python-2.7.14-foss-2018a.eb
  • SUCCESS Python-2.7.15-GCCcore-8.2.0.eb
  • SUCCESS Python-2.7.18-GCCcore-10.2.0.eb
  • SUCCESS Python-3.6.4-foss-2018a.eb
  • SUCCESS Python-3.7.2-GCCcore-8.2.0.eb
  • SUCCESS flex-2.5.39.eb
  • SUCCESS binutils-2.25.eb
  • SUCCESS GCCcore-4.9.3.eb
  • SUCCESS M4-1.4.17-GCCcore-4.9.3.eb
  • SUCCESS flex-2.5.39-GCCcore-4.9.3.eb
  • SUCCESS zlib-1.2.8-GCCcore-4.9.3.eb
  • SUCCESS Bison-3.0.4-GCCcore-4.9.3.eb
  • SUCCESS binutils-2.25-GCCcore-4.9.3.eb
  • SUCCESS ncurses-6.0-GCCcore-4.9.3.eb
  • SUCCESS bzip2-1.0.6-GCCcore-4.9.3.eb
  • SUCCESS libreadline-6.3-GCCcore-4.9.3.eb
  • SUCCESS GCC-4.9.3-2.25.eb
  • SUCCESS Tcl-8.6.4-GCC-4.9.3-2.25.eb
  • SUCCESS SQLite-3.9.2-GCC-4.9.3-2.25.eb
  • SUCCESS Tk-8.6.4-GCC-4.9.3-2.25-no-X11.eb
  • SUCCESS Autoconf-2.69-GCCcore-4.9.3.eb
  • FAIL (build issue) OpenBLAS-0.2.15-GCC-4.9.3-2.25-LAPACK-3.6.0.eb (partial log available at https://gist.github.com/394d14291f728a16a47eb05830049b77)
  • SUCCESS Automake-1.15-GCCcore-4.9.3.eb
  • SUCCESS libtool-2.4.6-GCCcore-4.9.3.eb
  • SUCCESS Autotools-20150215-GCCcore-4.9.3.eb
  • SUCCESS numactl-2.0.11-GCCcore-4.9.3.eb
  • SUCCESS GMP-6.1.0-GCC-4.9.3-2.25.eb
  • SUCCESS XZ-5.2.2-GCCcore-4.9.3.eb
  • SUCCESS hwloc-1.11.2-GCC-4.9.3-2.25.eb
  • SUCCESS OpenMPI-1.10.2-GCC-4.9.3-2.25.eb
  • SUCCESS gompi-2016a.eb
  • SUCCESS FFTW-3.3.4-gompi-2016a.eb
  • FAIL (build issue) ScaLAPACK-2.0.2-gompi-2016a-OpenBLAS-0.2.15-LAPACK-3.6.0.eb (partial log available at https://gist.github.com/8f283b1911af6c6e3baa8754a89132e5)
  • FAIL (build issue) foss-2016a.eb (partial log available at https://gist.github.com/4d13943ac2f9c27844700217e46765fa)
  • FAIL (build issue) Python-2.7.11-foss-2016a.eb (partial log available at https://gist.github.com/170a6a446265257423f9fde3a475aefb)
  • FAIL (build issue) Python-3.5.1-foss-2016a.eb (partial log available at https://gist.github.com/2ff707319358a7f916b8a7b8263ecde3)

Build succeeded for 31 out of 36 (7 easyconfigs in total)
taurusi8009 - Linux centos linux 7.9.2009, x86_64, AMD EPYC 7352 24-Core Processor (zen2), Python 2.7.5
See https://gist.github.com/be3b7708f67321dd7a739e9b2d0d49f8 for a full test report.

@boegel
Copy link
Member

boegel commented May 13, 2021

Test report by @boegel

Overview of tested easyconfigs (in order)

  • SUCCESS Python-2.7.10-GCC-4.9.3-2.25-bare.eb
  • SUCCESS Python-2.7.10-GNU-4.9.3-2.25-bare.eb
  • SUCCESS Python-2.7.11-foss-2016a.eb
  • SUCCESS Python-2.7.11-GCC-4.9.3-2.25-bare.eb
  • SUCCESS Python-2.7.11-intel-2016.02-GCC-4.9.eb
  • SUCCESS Python-2.7.11-intel-2016a.eb
  • SUCCESS Python-2.7.12-GCC-5.4.0-2.26-bare.eb
  • SUCCESS Python-2.7.12-GCCcore-4.9.3-bare.eb
  • SUCCESS Python-2.7.13-GCCcore-6.3.0-bare.eb
  • SUCCESS Python-2.7.14-foss-2017b.eb
  • SUCCESS Python-2.7.14-foss-2018a.eb
  • SUCCESS Python-2.7.14-fosscuda-2017b.eb
  • SUCCESS Python-2.7.14-fosscuda-2018a.eb
  • SUCCESS Python-2.7.14-GCCcore-6.4.0-bare.eb
  • SUCCESS Python-2.7.15-foss-2018b.eb
  • SUCCESS Python-2.7.15-fosscuda-2018b.eb
  • SUCCESS Python-2.7.15-GCCcore-7.2.0-bare.eb
  • SUCCESS Python-2.7.15-GCCcore-7.3.0-bare.eb
  • SUCCESS Python-2.7.15-GCCcore-8.2.0.eb
  • SUCCESS Python-2.7.15-intel-2018b.eb
  • SUCCESS Python-2.7.15-iomkl-2018b.eb
  • SUCCESS Python-2.7.16-GCCcore-8.3.0.eb
  • SUCCESS Python-2.7.18-GCCcore-10.2.0.eb
  • SUCCESS Python-2.7.18-GCCcore-9.3.0.eb
  • SUCCESS Python-2.7.9-GCC-4.8.4-bare.eb
  • SUCCESS Python-2.7.9-GCC-4.9.2-bare.eb
  • SUCCESS Python-3.5.1-foss-2016a.eb
  • FAIL (build issue) Python-3.5.1-intel-2016a.eb (partial log available at https://gist.github.com/b69cdc5ac6cccbb46b1d0069faab2aee)
  • SUCCESS Python-3.6.2-foss-2017b.eb
  • FAIL (build issue) Python-3.6.3-foss-2017b.eb (partial log available at https://gist.github.com/58b19faa19690eda3e9838561f8e9902)
  • SUCCESS Python-3.6.4-foss-2017a.eb
  • SUCCESS Python-3.6.4-foss-2018a.eb
  • SUCCESS Python-3.6.4-fosscuda-2018a.eb
  • SUCCESS Python-3.6.4-golf-2018a.eb
  • SUCCESS Python-3.6.4-iomkl-2018.02.eb
  • SUCCESS Python-3.6.6-foss-2018b.eb
  • SUCCESS Python-3.6.6-fosscuda-2018b.eb
  • SUCCESS Python-3.6.6-intel-2018b.eb
  • SUCCESS Python-3.6.6-iomkl-2018b.eb
  • SUCCESS Python-3.7.0-foss-2018b.eb
  • SUCCESS Python-3.7.0-intel-2018b.eb
  • SUCCESS Python-3.7.0-iomkl-2018b.eb
  • SUCCESS Python-3.7.2-GCCcore-8.2.0.eb
  • SUCCESS Python-3.7.4-GCCcore-8.3.0.eb
  • SUCCESS Python-3.8.2-GCCcore-9.3.0.eb
  • SUCCESS Python-3.8.6-GCCcore-10.2.0.eb

Build succeeded for 44 out of 46 (46 easyconfigs in total)
node2648.swalot.os - Linux centos linux 7.9.2009, x86_64, Intel(R) Xeon(R) CPU E5-2660 v3 @ 2.60GHz (haswell), Python 3.6.8
See https://gist.github.com/ec0738dcc52efe09bf0cea050f846a84 for a full test report.

Copy link
Member

@boegel boegel left a comment

Choose a reason for hiding this comment

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

The Python easyconfigs that didn't work are due to problems not related to the changes in this PR (they're broken in the same way with the current Python easyblock), so I'll go ahead and merge this and follow up on those specific easyconfigs in a separate (easyconfigs) PR (with low priority though, since they're ancient...).

Thanks for your efforts on this @Flamefire!

@boegel boegel merged commit fa51c6c into easybuilders:develop May 13, 2021
@Flamefire Flamefire deleted the installPipIn2.7 branch May 15, 2021 08:21
@boegel boegel changed the title Enhance Python easyblock: install pip2 when available, tweak defaults, create unversioned pip symlink enhance Python easyblock: install pip2 when available, tweak defaults, create unversioned pip symlink May 26, 2021
@Flamefire Flamefire changed the title enhance Python easyblock: install pip2 when available, tweak defaults, create unversioned pip symlink enhance Python easyblock: Add option to install pip with core Python, tweak defaults, create unversioned pip symlink May 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants