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

platforms: rewrite mechanism which parses version into EVR #10038

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 7 additions & 84 deletions ssg/requirement_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,91 +11,14 @@
pkg_resources.safe_extra = lambda extra: re.sub('[^A-Za-z0-9.-]+', '_', extra).lower()


def _add_version_element(elements, el):
elements.append(str(int(el)))


def _add_version_elements_to_evr_component(evr, elements, component):
evr[component] = '.'.join(elements if elements else ['0'])
elements.clear()


def _select_next_component(el):
if el.endswith('final-'):
return 'release'
if el.endswith('final'):
return None


def _evr_from_tuple_for_sure(version_tuple):
# TODO: We do not support `epoch` at this moment, it is always None
evr = {'epoch': None, 'version': None, 'release': None}
component = 'version'
elements = []
for el in version_tuple:
if el.startswith('*'):
_add_version_elements_to_evr_component(evr, elements, component)
component = _select_next_component(el)
if component is None:
break
continue
_add_version_element(elements, el)
return evr


def _evr_from_tuple(version_tuple):
# This is a version tuple from setuptools 0.9.8
# 1.22.33-444 -> ('00000011', '00000022', '00000033', '*final-', '00000444', '*final')
if isinstance(version_tuple, tuple):
return _evr_from_tuple_for_sure(version_tuple)
raise ValueError('Invalid object: %s, '
'expected: tuple' % repr(version_tuple))


def _evr_from_version_object_for_sure(version_object):
# TODO: We do not support `epoch` at this moment, it is always None
if hasattr(version_object, 'post'):
post = version_object.post
elif hasattr(version_object, '_version') and hasattr(version_object._version, 'post'):
# There was a range of versions around 40.8 of setuptools
# where `post` hasn't been a public property of the Version class.
# In _version it has structure of ('post', 12) for version 1.2.3-12.
post = version_object._version.post[1] if version_object._version.post else None
else:
raise ValueError('Invalid pkg_resources.packaging.version.Version object: '
'no Version.post or Version._version.post attributes.'
'Current version of setuptools is not supported.')
return {'epoch': None,
'version': version_object.base_version,
'release': str(post) if post else None}


def _evr_from_version_object(version_object):
if isinstance(version_object, pkg_resources.packaging.version.Version):
return _evr_from_version_object_for_sure(version_object)
raise ValueError('Invalid version object: %s, '
'expected: pkg_resources.packaging.version.Version' % repr(version_object))


def _get_evr(version_something):
# Function should be redefined in accordance with setuptools behaviour. See below.
raise Exception("No EVR parser defined!")


try:
from pkg_resources import packaging
# We are using modern setuptools, packaging.version.Version is available
# and is used as the result of parse_version() function.
_get_evr = _evr_from_version_object
except ImportError:
# We are using old setuptools (Python 2.7 / 0.9.8) the parse_version() function
# returns a tuple object.
_get_evr = _evr_from_tuple


def _parse_version_into_evr(version):
ver = pkg_resources.parse_version(version)
return _get_evr(ver)
evr = {"epoch": None, "version": None, "release": None}
match_version = re.match(r'^(\d[\d\.]*)(?:-(\d*))?$', version)
if not match_version:
raise ValueError("Invalid version specifier {0}".format(version))
evr["version"] = match_version.groups()[0]
evr["release"] = match_version.groups()[1]
return evr


def _spec_to_version_specifier(spec):
Expand Down
31 changes: 17 additions & 14 deletions tests/unit/ssg-module/test_requirement_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,6 @@
from ssg import requirement_specs


def test_evr_from_tuple():
v = requirement_specs._evr_from_tuple(
('00000001', '00000022', '00000333', '*final-', '00004444', '*final'))
assert v == {'epoch': None, 'version': '1.22.333', 'release': '4444'}

v = requirement_specs._evr_from_tuple(
('*final',))
assert v == {'epoch': None, 'version': '0', 'release': None}

v = requirement_specs._evr_from_tuple(
('*final-', '00000001', '*final'))
assert v == {'epoch': None, 'version': '0', 'release': '1'}


def test_parse_version_into_evr():
v = requirement_specs._parse_version_into_evr('1.22.333-4444')
assert v == {'epoch': None, 'version': '1.22.333', 'release': '4444'}
Expand All @@ -34,3 +20,20 @@ def test_parse_version_into_evr():
# We do not support epoch at this moment, this version string is invalid.
with pytest.raises(ValueError):
v = requirement_specs._parse_version_into_evr('1:1.0.0')

# we do not support letters anywhere for now

with pytest.raises(ValueError):
v = requirement_specs._parse_version_into_evr('1.0.0-r2')
with pytest.raises(ValueError):
v = requirement_specs._parse_version_into_evr('b1')

# some more tests to ensure that the regex is correct
with pytest.raises(ValueError):
v = requirement_specs._parse_version_into_evr('0:')
with pytest.raises(ValueError):
v = requirement_specs._parse_version_into_evr('-1')
with pytest.raises(ValueError):
v = requirement_specs._parse_version_into_evr(':')
with pytest.raises(ValueError):
v = requirement_specs._parse_version_into_evr('-')