add build-lower-constraints command
Add a command to merge lower constraints lists together, as a precursor to removing the global lower-constraints.txt list in this repository. Change-Id: Ia238607b9feb292842971d0fc161ae6294150e1f Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
parent
383a1f86bf
commit
9fa26daf57
20
README.rst
20
README.rst
@ -51,6 +51,26 @@ are normally constrained::
|
|||||||
|
|
||||||
edit-constraints oslo.db "-e file://opt/stack/oslo.db#egg=oslo.db"
|
edit-constraints oslo.db "-e file://opt/stack/oslo.db#egg=oslo.db"
|
||||||
|
|
||||||
|
build-lower-constraints
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Combine multiple lower-constraints.txt files to produce a list of the
|
||||||
|
highest version of each package mentioned in the files. This can be
|
||||||
|
used to produce the "highest minimum" for a global lower constraints
|
||||||
|
list (a.k.a., the "TJ Maxx").
|
||||||
|
|
||||||
|
To use the script, run::
|
||||||
|
|
||||||
|
$ tox -e venv -- build-lower-constraints input1.txt input2.txt
|
||||||
|
|
||||||
|
Where the input files are lower-constraints.txt or requirements.txt
|
||||||
|
files from one or more projects.
|
||||||
|
|
||||||
|
If the inputs are requirements files, a lower constraints list for the
|
||||||
|
requirements is produced. If the inputs are lower-constraints.txt, the
|
||||||
|
output includes the highest version of each package referenced in the
|
||||||
|
files.
|
||||||
|
|
||||||
Proposing changes
|
Proposing changes
|
||||||
=================
|
=================
|
||||||
|
|
||||||
|
72
openstack_requirements/cmds/build_lower_constraints.py
Normal file
72
openstack_requirements/cmds/build_lower_constraints.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""Merge multiple lower-constraints.txt files to find the highest values.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import collections
|
||||||
|
|
||||||
|
from openstack_requirements import requirement
|
||||||
|
|
||||||
|
import packaging.specifiers
|
||||||
|
import packaging.version
|
||||||
|
|
||||||
|
|
||||||
|
def read_requirements_file(filename):
|
||||||
|
with open(filename, 'rt') as f:
|
||||||
|
body = f.read()
|
||||||
|
return requirement.parse(body)
|
||||||
|
|
||||||
|
|
||||||
|
def get_requirements_version(req):
|
||||||
|
"""Find the version for a requirement.
|
||||||
|
|
||||||
|
Use the version attached to >=, ==, or ===, depending on the type
|
||||||
|
of input requirement.
|
||||||
|
|
||||||
|
"""
|
||||||
|
for specifier in packaging.specifiers.SpecifierSet(req.specifiers):
|
||||||
|
if '>=' in specifier.operator or '==' in specifier.operator:
|
||||||
|
return packaging.version.parse(specifier.version)
|
||||||
|
raise ValueError('could not find version for {}'.format(req))
|
||||||
|
|
||||||
|
|
||||||
|
def merge_constraints_sets(constraints_sets):
|
||||||
|
"Generator of Requirements with the maximum version for each constraint."
|
||||||
|
all_constraints = collections.defaultdict(list)
|
||||||
|
for constraints_set in constraints_sets:
|
||||||
|
for constraint_name, constraint in constraints_set.items():
|
||||||
|
all_constraints[constraint_name].extend(constraint)
|
||||||
|
for constraint_name, constraints in sorted(all_constraints.items()):
|
||||||
|
val = max((c[0] for c in constraints), key=get_requirements_version)
|
||||||
|
yield val.to_line()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
'lower_constraints',
|
||||||
|
nargs='+',
|
||||||
|
help='lower-constraints.txt files',
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
constraints_sets = [
|
||||||
|
read_requirements_file(filename)
|
||||||
|
for filename in args.lower_constraints
|
||||||
|
]
|
||||||
|
|
||||||
|
merged = list(merge_constraints_sets(constraints_sets))
|
||||||
|
print(''.join(merged))
|
57
openstack_requirements/tests/test_build_lower_constraints.py
Normal file
57
openstack_requirements/tests/test_build_lower_constraints.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import testtools
|
||||||
|
|
||||||
|
from openstack_requirements.cmds import build_lower_constraints
|
||||||
|
from openstack_requirements import requirement
|
||||||
|
|
||||||
|
|
||||||
|
class BuildLowerConstraintsTest(testtools.TestCase):
|
||||||
|
|
||||||
|
def test_one_input_file(self):
|
||||||
|
inputs = [
|
||||||
|
requirement.parse('package==1.2.3'),
|
||||||
|
]
|
||||||
|
expected = [
|
||||||
|
'package==1.2.3\n',
|
||||||
|
]
|
||||||
|
self.assertEqual(
|
||||||
|
expected,
|
||||||
|
list(build_lower_constraints.merge_constraints_sets(inputs))
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_two_input_file_same(self):
|
||||||
|
inputs = [
|
||||||
|
requirement.parse('package==1.2.3'),
|
||||||
|
requirement.parse('package==1.2.3'),
|
||||||
|
]
|
||||||
|
expected = [
|
||||||
|
'package==1.2.3\n',
|
||||||
|
]
|
||||||
|
self.assertEqual(
|
||||||
|
expected,
|
||||||
|
list(build_lower_constraints.merge_constraints_sets(inputs))
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_two_input_file_differ(self):
|
||||||
|
inputs = [
|
||||||
|
requirement.parse('package==1.2.3'),
|
||||||
|
requirement.parse('package==4.5.6'),
|
||||||
|
]
|
||||||
|
expected = [
|
||||||
|
'package==4.5.6\n',
|
||||||
|
]
|
||||||
|
self.assertEqual(
|
||||||
|
expected,
|
||||||
|
list(build_lower_constraints.merge_constraints_sets(inputs))
|
||||||
|
)
|
@ -41,3 +41,4 @@ console_scripts =
|
|||||||
normalize-requirements = openstack_requirements.cmds.normalize_requirements:main
|
normalize-requirements = openstack_requirements.cmds.normalize_requirements:main
|
||||||
check-python2-support = openstack_requirements.cmds.check_py2:main
|
check-python2-support = openstack_requirements.cmds.check_py2:main
|
||||||
check-constraints = openstack_requirements.cmds.check_exists:main
|
check-constraints = openstack_requirements.cmds.check_exists:main
|
||||||
|
build-lower-constraints = openstack_requirements.cmds.build_lower_constraints:main
|
||||||
|
Loading…
x
Reference in New Issue
Block a user