Merge "allow project requirements to diverge at the lower bounds"
This commit is contained in:
commit
0b0b074524
@ -72,17 +72,37 @@ class RequirementsList(object):
|
|||||||
self.reqs_by_file[name] = self.extract_reqs(content, strict)
|
self.reqs_by_file[name] = self.extract_reqs(content, strict)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_exclusions(req):
|
||||||
|
return set(
|
||||||
|
spec
|
||||||
|
for spec in req.specifiers.split(',')
|
||||||
|
if '!=' in spec or '<' in spec
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _is_requirement_in_global_reqs(req, global_reqs):
|
def _is_requirement_in_global_reqs(req, global_reqs):
|
||||||
# Compare all fields except the extras field as the global
|
req_exclusions = _get_exclusions(req)
|
||||||
# requirements should not have any lines with the extras syntax
|
|
||||||
# example: oslo.db[xyz]<1.2.3
|
|
||||||
for req2 in global_reqs:
|
for req2 in global_reqs:
|
||||||
|
|
||||||
if (req.package == req2.package and
|
if (req.package == req2.package and
|
||||||
req.location == req2.location and
|
req.location == req2.location and
|
||||||
req.specifiers == req2.specifiers and
|
|
||||||
req.markers == req2.markers and
|
req.markers == req2.markers and
|
||||||
req.comment == req2.comment):
|
req.comment == req2.comment):
|
||||||
return True
|
# This matches the right package and other properties, so
|
||||||
|
# ensure that any exclusions are a subset of the global
|
||||||
|
# set.
|
||||||
|
global_exclusions = _get_exclusions(req2)
|
||||||
|
if req_exclusions.issubset(global_exclusions):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
"Requirement for package {} "
|
||||||
|
"has an exclusion not found in the "
|
||||||
|
"global list: {} vs. {}".format(
|
||||||
|
req.package, req_exclusions, global_exclusions)
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -103,7 +123,7 @@ def get_global_reqs(content):
|
|||||||
|
|
||||||
def _validate_one(name, reqs, branch_reqs, blacklist, global_reqs):
|
def _validate_one(name, reqs, branch_reqs, blacklist, global_reqs):
|
||||||
"Returns True if there is a failure."
|
"Returns True if there is a failure."
|
||||||
print(name, reqs, branch_reqs, blacklist, global_reqs)
|
print('_validate_one', name, reqs, branch_reqs, blacklist, global_reqs)
|
||||||
if (name in branch_reqs.reqs and
|
if (name in branch_reqs.reqs and
|
||||||
reqs == branch_reqs.reqs[name]):
|
reqs == branch_reqs.reqs[name]):
|
||||||
# Unchanged [or a change that preserves a current value]
|
# Unchanged [or a change that preserves a current value]
|
||||||
@ -117,8 +137,6 @@ def _validate_one(name, reqs, branch_reqs, blacklist, global_reqs):
|
|||||||
print("Requirement %s not in openstack/requirements" %
|
print("Requirement %s not in openstack/requirements" %
|
||||||
str(reqs))
|
str(reqs))
|
||||||
return True
|
return True
|
||||||
if reqs == global_reqs[name]:
|
|
||||||
return False
|
|
||||||
counts = {}
|
counts = {}
|
||||||
for req in reqs:
|
for req in reqs:
|
||||||
if req.extras:
|
if req.extras:
|
||||||
@ -141,6 +159,7 @@ def _validate_one(name, reqs, branch_reqs, blacklist, global_reqs):
|
|||||||
('[%s]' % extra) if extra else '',
|
('[%s]' % extra) if extra else '',
|
||||||
len(global_reqs[name])))
|
len(global_reqs[name])))
|
||||||
return True
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def validate(head_reqs, branch_reqs, blacklist, global_reqs):
|
def validate(head_reqs, branch_reqs, blacklist, global_reqs):
|
||||||
|
@ -66,7 +66,7 @@ class TestIsReqInGlobalReqs(testtools.TestCase):
|
|||||||
|
|
||||||
def test_min_mismatch(self):
|
def test_min_mismatch(self):
|
||||||
req = requirement.parse('name>=1.3,!=1.4')['name'][0][0]
|
req = requirement.parse('name>=1.3,!=1.4')['name'][0][0]
|
||||||
self.assertFalse(
|
self.assertTrue(
|
||||||
check._is_requirement_in_global_reqs(
|
check._is_requirement_in_global_reqs(
|
||||||
req,
|
req,
|
||||||
self.global_reqs['name'],
|
self.global_reqs['name'],
|
||||||
@ -84,7 +84,7 @@ class TestIsReqInGlobalReqs(testtools.TestCase):
|
|||||||
|
|
||||||
def test_missing_exclusion(self):
|
def test_missing_exclusion(self):
|
||||||
req = requirement.parse('name>=1.2')['name'][0][0]
|
req = requirement.parse('name>=1.2')['name'][0][0]
|
||||||
self.assertFalse(
|
self.assertTrue(
|
||||||
check._is_requirement_in_global_reqs(
|
check._is_requirement_in_global_reqs(
|
||||||
req,
|
req,
|
||||||
self.global_reqs['name'],
|
self.global_reqs['name'],
|
||||||
@ -92,6 +92,30 @@ class TestIsReqInGlobalReqs(testtools.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetExclusions(testtools.TestCase):
|
||||||
|
|
||||||
|
def test_none(self):
|
||||||
|
req = list(check.get_global_reqs('name>=1.2')['name'])[0]
|
||||||
|
self.assertEqual(
|
||||||
|
set(),
|
||||||
|
check._get_exclusions(req),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_one(self):
|
||||||
|
req = list(check.get_global_reqs('name>=1.2,!=1.4')['name'])[0]
|
||||||
|
self.assertEqual(
|
||||||
|
set(['!=1.4']),
|
||||||
|
check._get_exclusions(req),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_cap(self):
|
||||||
|
req = list(check.get_global_reqs('name>=1.2,!=1.4,<2.0')['name'])[0]
|
||||||
|
self.assertEqual(
|
||||||
|
set(['!=1.4', '<2.0']),
|
||||||
|
check._get_exclusions(req),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestValidateOne(testtools.TestCase):
|
class TestValidateOne(testtools.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -212,9 +236,32 @@ class TestValidateOne(testtools.TestCase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_new_item_mismatches_global_list(self):
|
def test_new_item_lower_min(self):
|
||||||
# If the new item does not match the global value, that is an
|
# If the new item has a lower minimum value than the global
|
||||||
# error.
|
# list, that is OK.
|
||||||
|
reqs = [
|
||||||
|
r
|
||||||
|
for r, line in requirement.parse('name>=1.1,!=1.4')['name']
|
||||||
|
]
|
||||||
|
branch_reqs = check.RequirementsList(
|
||||||
|
'testproj',
|
||||||
|
{'requirements': {'requirements.txt': ''}},
|
||||||
|
)
|
||||||
|
branch_reqs.process(False)
|
||||||
|
global_reqs = check.get_global_reqs('name>=1.2,!=1.4')
|
||||||
|
self.assertFalse(
|
||||||
|
check._validate_one(
|
||||||
|
'name',
|
||||||
|
reqs=reqs,
|
||||||
|
branch_reqs=branch_reqs,
|
||||||
|
blacklist=requirement.parse(''),
|
||||||
|
global_reqs=global_reqs,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_new_item_extra_exclusion(self):
|
||||||
|
# If the new item includes an exclusion that is not present in
|
||||||
|
# the global list that is not OK.
|
||||||
reqs = [
|
reqs = [
|
||||||
r
|
r
|
||||||
for r, line in requirement.parse('name>=1.2,!=1.4,!=1.5')['name']
|
for r, line in requirement.parse('name>=1.2,!=1.4,!=1.5')['name']
|
||||||
@ -235,6 +282,29 @@ class TestValidateOne(testtools.TestCase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_new_item_missing_exclusion(self):
|
||||||
|
# If the new item does not include an exclusion that is
|
||||||
|
# present in the global list that is OK.
|
||||||
|
reqs = [
|
||||||
|
r
|
||||||
|
for r, line in requirement.parse('name>=1.2')['name']
|
||||||
|
]
|
||||||
|
branch_reqs = check.RequirementsList(
|
||||||
|
'testproj',
|
||||||
|
{'requirements': {'requirements.txt': ''}},
|
||||||
|
)
|
||||||
|
branch_reqs.process(False)
|
||||||
|
global_reqs = check.get_global_reqs('name>=1.2,!=1.4')
|
||||||
|
self.assertFalse(
|
||||||
|
check._validate_one(
|
||||||
|
'name',
|
||||||
|
reqs=reqs,
|
||||||
|
branch_reqs=branch_reqs,
|
||||||
|
blacklist=requirement.parse(''),
|
||||||
|
global_reqs=global_reqs,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def test_new_item_matches_global_list_with_extra(self):
|
def test_new_item_matches_global_list_with_extra(self):
|
||||||
# If the global list has multiple entries for an item with
|
# If the global list has multiple entries for an item with
|
||||||
# different "extra" specifiers, the values must all be in the
|
# different "extra" specifiers, the values must all be in the
|
||||||
|
Loading…
Reference in New Issue
Block a user