Merge "Remove requirements overlap check"
This commit is contained in:
commit
6c340e5e69
@ -1,105 +0,0 @@
|
|||||||
# Copyright 2014 IBM Corp.
|
|
||||||
#
|
|
||||||
# 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 pkg_resources
|
|
||||||
import testtools
|
|
||||||
from testtools import matchers
|
|
||||||
|
|
||||||
import versions_overlap_parent as vop
|
|
||||||
|
|
||||||
|
|
||||||
class TestVersionsOverlapParent(testtools.TestCase):
|
|
||||||
def test_increase_version(self):
|
|
||||||
self.assertThat(vop.increase_version('1.0'), matchers.Equals('1.1'))
|
|
||||||
|
|
||||||
def test_decrease_version(self):
|
|
||||||
self.assertThat(vop.decrease_version('1.0'), matchers.Equals('1.9'))
|
|
||||||
|
|
||||||
def _test_get_version_required(self, start_version, op, exp_version):
|
|
||||||
req = pkg_resources.Requirement.parse('pkg%s%s' % (op, start_version))
|
|
||||||
self.assertThat(vop.get_version_required(req.specs[0]),
|
|
||||||
matchers.Equals(exp_version))
|
|
||||||
|
|
||||||
def test_get_version_required_eq(self):
|
|
||||||
self._test_get_version_required('1.0', '==', '1.0')
|
|
||||||
|
|
||||||
def test_get_version_required_gt(self):
|
|
||||||
self._test_get_version_required('1.0', '>', '1.1')
|
|
||||||
|
|
||||||
def test_get_version_required_ge(self):
|
|
||||||
self._test_get_version_required('1.0', '>=', '1.0')
|
|
||||||
|
|
||||||
def test_get_version_required_lt(self):
|
|
||||||
self._test_get_version_required('1.0', '<', '1.9')
|
|
||||||
|
|
||||||
def test_get_version_required_le(self):
|
|
||||||
self._test_get_version_required('1.0', '<=', '1.0')
|
|
||||||
|
|
||||||
def test_get_version_required_ne(self):
|
|
||||||
self._test_get_version_required('1.0', '!=', '1.0')
|
|
||||||
|
|
||||||
def test_RequirementsList_read_requirements_empty_line(self):
|
|
||||||
rl = vop.RequirementsList('something')
|
|
||||||
rl.read_requirements([''])
|
|
||||||
self.assertThat(rl.reqs, matchers.Equals({}))
|
|
||||||
|
|
||||||
def test_RequirementsList_read_requirements_comment_line(self):
|
|
||||||
rl = vop.RequirementsList('something')
|
|
||||||
rl.read_requirements(['# comment'])
|
|
||||||
self.assertThat(rl.reqs, matchers.Equals({}))
|
|
||||||
|
|
||||||
def test_RequirementsList_read_requirements_skips(self):
|
|
||||||
# Lines starting with certain strings are skipped.
|
|
||||||
rl = vop.RequirementsList('something')
|
|
||||||
rl.read_requirements(['http://tarballs.openstack.org/something',
|
|
||||||
'-esomething',
|
|
||||||
'-fsomething'])
|
|
||||||
self.assertThat(rl.reqs, matchers.Equals({}))
|
|
||||||
|
|
||||||
def test_RequirementsList_read_requirements_parse(self):
|
|
||||||
rl = vop.RequirementsList('something')
|
|
||||||
rl.read_requirements(['extras',
|
|
||||||
'sphinx>=1.1.2,!=1.2.0,<1.3 # BSD', ])
|
|
||||||
self.assertThat(rl.reqs['extras'].specs,
|
|
||||||
matchers.Equals([]))
|
|
||||||
exp_sphinx_specs = [('>=', '1.1.2'), ('!=', '1.2.0'), ('<', '1.3')]
|
|
||||||
self.assertThat(rl.reqs['sphinx'].specs,
|
|
||||||
matchers.Equals(exp_sphinx_specs))
|
|
||||||
|
|
||||||
def _compare(self, head_reqs, parent_reqs):
|
|
||||||
vop_obj = vop.VersionsOverlapParent()
|
|
||||||
vop_obj.set_head_requirements(head_reqs)
|
|
||||||
vop_obj.set_parent_requirements(parent_reqs)
|
|
||||||
vop_obj.compare_reqs()
|
|
||||||
|
|
||||||
def test_VersionsOverlapParent_same(self):
|
|
||||||
# No problem if the requirements list is the same.
|
|
||||||
self._compare(['extras'], ['extras'])
|
|
||||||
|
|
||||||
def test_VersionsOverlapParent_add(self):
|
|
||||||
# No problem if a new requirement is added
|
|
||||||
self._compare(['extras'], ['extras', 'new_requirement>=1.0'])
|
|
||||||
|
|
||||||
def test_VersionsOverlapParent_remove(self):
|
|
||||||
# No problem if a requirement is removed.
|
|
||||||
self._compare(['extras', 'old_requirement>=1.0'], ['extras'])
|
|
||||||
|
|
||||||
def test_VersionsOverlapParent_update_overlap(self):
|
|
||||||
# No problem if a requirement is updated and it overlaps
|
|
||||||
self._compare(['package>=1.0'], ['package>=1.0,<2.0'])
|
|
||||||
|
|
||||||
def test_VersionsOverlapParent_update_nooverlap_fails(self):
|
|
||||||
# Fails if versions don't overlap.
|
|
||||||
cmp_fn = lambda: self._compare(['package>=1.0,<2.0'], ['package>=2.0'])
|
|
||||||
self.assertThat(cmp_fn, matchers.raises(Exception))
|
|
4
tox.ini
4
tox.ini
@ -19,10 +19,6 @@ deps = setuptools>3.4
|
|||||||
[testenv:pep8]
|
[testenv:pep8]
|
||||||
commands = flake8
|
commands = flake8
|
||||||
|
|
||||||
[testenv:versions-overlap-parent]
|
|
||||||
commands =
|
|
||||||
python versions_overlap_parent.py
|
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
ignore = H803
|
ignore = H803
|
||||||
exclude = .venv,.git,.tox,dist,doc,*egg,build
|
exclude = .venv,.git,.tox,dist,doc,*egg,build
|
||||||
|
@ -1,149 +0,0 @@
|
|||||||
#! /usr/bin/env python
|
|
||||||
# Copyright (C) 2011 OpenStack, LLC.
|
|
||||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
# Copyright (c) 2013 OpenStack Foundation
|
|
||||||
# Copyright 2014 IBM Corp.
|
|
||||||
#
|
|
||||||
# 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 subprocess
|
|
||||||
|
|
||||||
import pkg_resources
|
|
||||||
|
|
||||||
|
|
||||||
def increase_version(version_string):
|
|
||||||
"""Returns simple increased version string."""
|
|
||||||
items = version_string.split('.')
|
|
||||||
for i in range(len(items) - 1, 0, -1):
|
|
||||||
current_item = items[i]
|
|
||||||
if current_item.isdigit():
|
|
||||||
current_item = int(current_item) + 1
|
|
||||||
items[i] = str(current_item)
|
|
||||||
break
|
|
||||||
final = '.'.join(items)
|
|
||||||
return final
|
|
||||||
|
|
||||||
|
|
||||||
def decrease_version(version_string):
|
|
||||||
"""Returns simple decreased version string."""
|
|
||||||
items = version_string.split('.')
|
|
||||||
for i in range(len(items) - 1, 0, -1):
|
|
||||||
current_item = items[i]
|
|
||||||
if current_item.isdigit():
|
|
||||||
current_item = int(current_item) - 1
|
|
||||||
if current_item >= 0:
|
|
||||||
items[i] = str(current_item)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# continue to parent
|
|
||||||
items[i] = '9'
|
|
||||||
|
|
||||||
final = '.'.join(items)
|
|
||||||
return final
|
|
||||||
|
|
||||||
|
|
||||||
def get_version_required(req):
|
|
||||||
"""Returns required version string depending on reqs."""
|
|
||||||
operator = req[0]
|
|
||||||
version = req[1]
|
|
||||||
if operator == '>':
|
|
||||||
version = increase_version(version)
|
|
||||||
elif operator == '<':
|
|
||||||
version = decrease_version(version)
|
|
||||||
return version
|
|
||||||
|
|
||||||
|
|
||||||
class RequirementsList(object):
|
|
||||||
def __init__(self, name):
|
|
||||||
self.name = name
|
|
||||||
self.reqs = {}
|
|
||||||
|
|
||||||
def read_requirements(self, req_lines):
|
|
||||||
"""Read requirements."""
|
|
||||||
for line in req_lines:
|
|
||||||
if '#' in line:
|
|
||||||
line = line[:line.find('#')]
|
|
||||||
line = line.strip()
|
|
||||||
if (not line or
|
|
||||||
line.startswith('http://tarballs.openstack.org/') or
|
|
||||||
line.startswith('-e') or
|
|
||||||
line.startswith('-f')):
|
|
||||||
continue
|
|
||||||
req = pkg_resources.Requirement.parse(line)
|
|
||||||
self.reqs[req.project_name.lower()] = req
|
|
||||||
|
|
||||||
|
|
||||||
def compare_reqs(parent_reqs, head_reqs):
|
|
||||||
failed = False
|
|
||||||
for req in head_reqs.reqs.values():
|
|
||||||
name = req.project_name.lower()
|
|
||||||
parent_req = parent_reqs.reqs.get(name)
|
|
||||||
if not parent_req:
|
|
||||||
# head req didn't exist in parent reqs.
|
|
||||||
continue
|
|
||||||
|
|
||||||
if req == parent_req:
|
|
||||||
# Requirement is the same, nothing to do.
|
|
||||||
continue
|
|
||||||
|
|
||||||
# check if overlaps
|
|
||||||
for spec in req.specs:
|
|
||||||
version = get_version_required(spec)
|
|
||||||
if not parent_req.__contains__(version):
|
|
||||||
failed = True
|
|
||||||
print("Requirement %s does not overlap with parent " %
|
|
||||||
str(req))
|
|
||||||
|
|
||||||
if failed:
|
|
||||||
raise Exception("Problem with requirements, check previous output.")
|
|
||||||
|
|
||||||
|
|
||||||
class VersionsOverlapParent(object):
|
|
||||||
GLOBAL_REQUIREMENTS_FILENAME = 'global-requirements.txt'
|
|
||||||
|
|
||||||
def set_head_requirements(self, head_requirements):
|
|
||||||
head_reqs = RequirementsList(name='HEAD')
|
|
||||||
head_reqs.read_requirements(head_requirements)
|
|
||||||
self._head_reqs = head_reqs
|
|
||||||
|
|
||||||
def set_parent_requirements(self, parent_requirements):
|
|
||||||
parent_reqs = RequirementsList(name='parent')
|
|
||||||
parent_reqs.read_requirements(parent_requirements)
|
|
||||||
self._parent_reqs = parent_reqs
|
|
||||||
|
|
||||||
def compare_reqs(self):
|
|
||||||
compare_reqs(self._parent_reqs, self._head_reqs)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
# Parse current commit requirements list.
|
|
||||||
with open(self.GLOBAL_REQUIREMENTS_FILENAME) as global_reqs:
|
|
||||||
self.set_head_requirements(global_reqs)
|
|
||||||
|
|
||||||
# Read the global requirements file from the parent commit.
|
|
||||||
parent_global_reqs = subprocess.check_output(
|
|
||||||
['git', 'show', 'HEAD~1:%s' % self.GLOBAL_REQUIREMENTS_FILENAME])
|
|
||||||
|
|
||||||
# Store parent commit requirements list.
|
|
||||||
self.set_parent_requirements(parent_global_reqs.splitlines())
|
|
||||||
|
|
||||||
self.compare_reqs()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
versions_overlap_parent = VersionsOverlapParent()
|
|
||||||
versions_overlap_parent.run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
main()
|
|
Loading…
Reference in New Issue
Block a user