From 88867be49936c4275fa188a8fee3adcc114d9c57 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Wed, 4 Mar 2020 22:42:14 +0100 Subject: [PATCH 1/2] Let buildout run a script to create a constraints file. This replaces the buildout.requirements extension. Good points for this extension: - It is a proper buildout extension. Bad points for this extension: - It cannot be run standalone: it only gathers information while buildout is running. - It ignores version pins for packages that buildout does not use in this run: if you run `bin/buildout install part1`, then version pins for other parts are ignored. - On Jenkins node 4 with Python 3.6 the package is broken. https://github.com/plone/buildout.coredev/issues/642 Good points for the new script: - It can be run as a standalone script. You just need any Python with any zc.buildout version. - It is fast: it takes maybe two seconds. - It reports *all* version pins, not just the ones that got installed. Bad points for the new script: - It is not a proper buildout extension. We want to run it from buildout, so we need a separate section/part for it, using plone.recipe.command (which is even older than buildout.requirements, though it works fine on Python 3). But it should be fairly easy to turn this into an extension (or recipe). - It is hardcoded to read `buildout.cfg`, including its extends. Should be easy enough to make this configurable with argparse/optparse/whatever. Script adapted from: https://gist.github.com/mauritsvanrees/c47e974e418c707a626200cb6561405b See also https://community.plone.org/t/creating-constraints-and-requirements-from-buildout-config/10296 We cannot use configparser, because buildout configs contain 'duplicate' options: $ grep -i chameleon versions.cfg Chameleon = 3.6.2 chameleon = 3.6.2 So we use the buildout configparser. Bonus: we automatically use the section expressions, like `[versions:python27]`. So the end result of running this script can be different per Python version. That is something to remember. --- core.cfg | 12 +++++++----- create-constraints.py | 27 +++++++++++++++++++++++++++ tests.cfg | 1 + 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 create-constraints.py diff --git a/core.cfg b/core.cfg index cf2716e975..5d0d563db9 100644 --- a/core.cfg +++ b/core.cfg @@ -19,15 +19,10 @@ allow-hosts = find-links += http://dist.plone.org/thirdparty/ extensions = - buildout.requirements # Keep mr.developer as last one, because some jenkins scripts look for # this and add a git-clone-depth after it. mr.developer -# write a constraints file -dump-requirements-file = ${buildout:directory}/constraints.txt -overwrite-requirements-file = true - # require picked versions show-picked-versions = true allow-picked-versions = false @@ -53,6 +48,7 @@ plone-user = [buildout:python27] parts = + constraints instance instance-archetypes zopepy @@ -67,6 +63,7 @@ extensions += [buildout:python3] parts = + constraints instance zopepy ploneversioncheck @@ -158,3 +155,8 @@ recipe = zc.recipe.egg eggs = zodbupdate ${instance:eggs} + +[constraints] +recipe = plone.recipe.command +command = bin/python create-constraints.py +update-command = ${:command} diff --git a/create-constraints.py b/create-constraints.py new file mode 100644 index 0000000000..f3feaf1760 --- /dev/null +++ b/create-constraints.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +""" +Parse versions from buildout.cfg and write them into constraints.txt. +This script is automatically called by buildout. + +Manual usage: bin/python create-constraints.py +zc.buildout needs to be importable in that python. +""" +from zc.buildout import buildout + + +# We could read a buildout config filename from the command line arguments, +# but for now it is fine to hardcode it: +configfile = "buildout.cfg" +config = buildout.Buildout(configfile, []) + +# Get the constraints from the version pins. +# Nice: the versions get set directly on the config. +# Note: this works like a dictionary, but is a class 'zc.buildout.buildout.Options'. +versions = config.versions +constraints_file = "constraints.txt" +with open(constraints_file, "w") as cfile: + cfile.write("# File created by {}\n".format(__file__)) + cfile.write("# Constraints parsed from {}\n".format(configfile)) + for package, version in sorted(versions.items()): + cfile.write("{}=={}\n".format(package, version)) +print("Wrote all versions as constraints to {}.".format(constraints_file)) diff --git a/tests.cfg b/tests.cfg index 8d1897f716..06a23785c0 100644 --- a/tests.cfg +++ b/tests.cfg @@ -173,6 +173,7 @@ oauthlib = 3.1.0 pathtools = 0.1.2 pdbpp = 0.10.2 pkginfo = 1.5.0.1 +plone.recipe.command = 1.1 progress = 1.5 prompt-toolkit = 1.0.18 pycparser = 2.19 From 53f6b41dbcf0e2b9f50efa03405c3a9ff0178af7 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Wed, 4 Mar 2020 23:45:39 +0100 Subject: [PATCH 2/2] Fixed constraints command in buildout. bin/python was not found on Jenkins. --- core.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core.cfg b/core.cfg index 5d0d563db9..0da4bce6ca 100644 --- a/core.cfg +++ b/core.cfg @@ -158,5 +158,5 @@ eggs = [constraints] recipe = plone.recipe.command -command = bin/python create-constraints.py +command = ${buildout:executable} create-constraints.py update-command = ${:command}