
When packaging pre-releases (alpha, beta, RC), the version from the Python sdist tarball needs to be converted into something usable in the RPM world. "py2rpmversion" and "py2rpmrelease" can be used for that. Change-Id: I5990fa4883b381147cefda88d58d40a6e8fe508a
388 lines
15 KiB
Python
388 lines
15 KiB
Python
#!/usr/bin/python
|
|
# Copyright (c) 2016 SUSE Linux GmbH
|
|
#
|
|
# 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.
|
|
|
|
|
|
try:
|
|
import unittest2 as unittest
|
|
except ImportError:
|
|
import unittest
|
|
|
|
from ddt import data, ddt, unpack
|
|
|
|
from jinja2 import Environment
|
|
|
|
from mock import Mock, patch
|
|
import os
|
|
import renderspec
|
|
import renderspec.versions
|
|
import shutil
|
|
import tempfile
|
|
|
|
|
|
@ddt
|
|
class RenderspecContextFunctionTests(unittest.TestCase):
|
|
"""test functions which do some calculation based on the context"""
|
|
def test_context_license_spdx(self):
|
|
self.assertEqual(
|
|
renderspec._context_license_spdx(
|
|
{'spec_style': 'suse'}, 'Apache-2.0'),
|
|
'Apache-2.0'
|
|
)
|
|
self.assertEqual(
|
|
renderspec._context_license_spdx(
|
|
{'spec_style': 'fedora'}, 'Apache-2.0'),
|
|
'ASL 2.0'
|
|
)
|
|
|
|
@data(
|
|
# without version
|
|
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
|
|
'oslo.config', None, 'python-oslo.config'),
|
|
({'spec_style': 'fedora', 'epochs': {}, 'requirements': {}},
|
|
'oslo.config', None, 'python-oslo-config'),
|
|
# with version
|
|
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
|
|
'oslo.config', ('>=', '1.2.3'), 'python-oslo.config >= 1.2.3'),
|
|
({'spec_style': 'fedora', 'epochs': {}, 'requirements': {}},
|
|
'oslo.config', ('==', '1.2.3~a0'), 'python-oslo-config == 1.2.3~a0'),
|
|
# with version, with epoch
|
|
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
|
|
'requirements': {}},
|
|
'oslo.config', ('>=', '1.2.3'), 'python-oslo.config >= 4:1.2.3'),
|
|
# without version, with epoch
|
|
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
|
|
'requirements': {}},
|
|
'oslo.config', None, 'python-oslo.config'),
|
|
# with version, with requirements
|
|
({'spec_style': 'suse', 'epochs': {},
|
|
'requirements': {'oslo.config' '1.2.3'}},
|
|
'oslo.config', ('>=', '4.5.6'), 'python-oslo.config >= 4.5.6'),
|
|
# without version, with requirements
|
|
({'spec_style': 'suse', 'epochs': {},
|
|
'requirements': {'oslo.config': '1.2.3'}},
|
|
'oslo.config', None, 'python-oslo.config >= 1.2.3'),
|
|
# without version, with requirements, with epoch
|
|
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
|
|
'requirements': {'oslo.config': '1.2.3'}},
|
|
'oslo.config', None, 'python-oslo.config >= 4:1.2.3'),
|
|
# with version, with requirements, with epoch
|
|
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
|
|
'requirements': {'oslo.config' '1.2.3'}},
|
|
'oslo.config', ('>=', '4.5.6'), 'python-oslo.config >= 4:4.5.6'),
|
|
)
|
|
@unpack
|
|
def test_context_py2pkg(self, context, pkg_name, pkg_version,
|
|
expected_result):
|
|
self.assertEqual(
|
|
renderspec._context_py2pkg(context, pkg_name, pkg_version),
|
|
expected_result)
|
|
|
|
def test_context_epoch_without_epochs(self):
|
|
self.assertEqual(
|
|
renderspec._context_epoch(
|
|
{'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
|
|
'oslo.config'), 0)
|
|
|
|
def test_context_epoch_with_epochs(self):
|
|
self.assertEqual(
|
|
renderspec._context_epoch(
|
|
{'spec_style': 'suse', 'epochs': {'oslo.config': 4},
|
|
'requirements': {}}, 'oslo.config'), 4)
|
|
|
|
|
|
@ddt
|
|
class RenderspecTemplateFunctionTests(unittest.TestCase):
|
|
def setUp(self):
|
|
"""create a Jinja2 environment and register the standard filters"""
|
|
self.env = Environment()
|
|
renderspec._env_register_filters_and_globals(self.env)
|
|
|
|
def test_render_func_license_spdx(self):
|
|
template = self.env.from_string(
|
|
"{{ license('Apache-2.0') }}")
|
|
self.assertEqual(
|
|
template.render(spec_style='fedora', epochs={}, requirements={}),
|
|
'ASL 2.0')
|
|
|
|
@data(
|
|
# plain
|
|
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
|
|
"{{ py2pkg('requests') }}", "python-requests"),
|
|
# with version
|
|
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
|
|
"{{ py2pkg('requests', ('>=', '2.8.1')) }}",
|
|
"python-requests >= 2.8.1"),
|
|
# with version, with epoch
|
|
({'spec_style': 'suse', 'epochs': {'requests': 4}, 'requirements': {}},
|
|
"{{ py2pkg('requests', ('>=', '2.8.1')) }}",
|
|
"python-requests >= 4:2.8.1"),
|
|
# with version, with epoch, with requirements
|
|
({'spec_style': 'suse', 'epochs': {'requests': 4},
|
|
'requirements': {'requests': '1.2.3'}},
|
|
"{{ py2pkg('requests', ('>=', '2.8.1')) }}",
|
|
"python-requests >= 4:2.8.1"),
|
|
# without version, with epoch, with requirements
|
|
({'spec_style': 'suse', 'epochs': {'requests': 4},
|
|
'requirements': {'requests': '1.2.3'}},
|
|
"{{ py2pkg('requests') }}",
|
|
"python-requests >= 4:1.2.3"),
|
|
)
|
|
@unpack
|
|
def test_render_func_py2pkg(self, context, string, expected_result):
|
|
template = self.env.from_string(string)
|
|
self.assertEqual(
|
|
template.render(**context),
|
|
expected_result)
|
|
|
|
def test_render_func_epoch_without_epochs(self):
|
|
template = self.env.from_string(
|
|
"Epoch: {{ epoch('requests') }}")
|
|
self.assertEqual(
|
|
template.render(spec_style='suse', epochs={}, requirements={}),
|
|
'Epoch: 0')
|
|
|
|
def test_render_func_epoch_with_epochs(self):
|
|
template = self.env.from_string(
|
|
"Epoch: {{ epoch('requests') }}")
|
|
self.assertEqual(
|
|
template.render(spec_style='suse', epochs={'requests': 1},
|
|
requirements={}),
|
|
'Epoch: 1')
|
|
|
|
@data(
|
|
# plain name
|
|
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
|
|
"{{ py2name('requests') }}",
|
|
"python-requests"),
|
|
# name with epoch
|
|
({'spec_style': 'suse', 'epochs': {'requests': 4}, 'requirements': {}},
|
|
"{{ py2name('requests') }}",
|
|
"python-requests"),
|
|
# name with epoch, with requirements
|
|
({'spec_style': 'suse', 'epochs': {'requests': 4},
|
|
'requirements': {'requests': '1.4.0'}},
|
|
"{{ py2name('requests') }}",
|
|
"python-requests"),
|
|
)
|
|
@unpack
|
|
def test_render_func_py2name(self, context, string, expected_result):
|
|
"""test the template context function called 'py2name()'"""
|
|
template = self.env.from_string(string)
|
|
self.assertEqual(
|
|
template.render(**context),
|
|
expected_result)
|
|
|
|
@data(
|
|
('suse', '1.1.0', '1.1.0'),
|
|
('suse', '1.1.0.post2', '1.1.0.post2'),
|
|
('suse', '1.1.0dev10', '1.1.0~dev10'),
|
|
('suse', '1.1.0a10', '1.1.0~xalpha10'),
|
|
('suse', '1.1.0a10dev5', '1.1.0~xalpha10~dev5'),
|
|
('suse', '1.1.0b10', '1.1.0~xbeta10'),
|
|
('suse', '1.1.0rc2', '1.1.0~rc2'),
|
|
('suse', '1.1.0rc2dev2', '1.1.0~rc2~dev2'),
|
|
('fedora', '1.1.0', '1.1.0'),
|
|
('fedora', '1.1.0b10', '1.1.0'),
|
|
('fedora', '1.1.0rc2dev2', '1.1.0'),
|
|
)
|
|
@unpack
|
|
def test_render_func_py2rpmversion(self, style, py_ver, rpm_ver):
|
|
context = {'spec_style': style, 'epochs': {}, 'requirements': {}}
|
|
# need to escape '{' and '}' here
|
|
s = "{{% set upstream_version = '{}' %}}{{{{ py2rpmversion() }}}}"\
|
|
.format(py_ver)
|
|
template = self.env.from_string(s)
|
|
self.assertEqual(
|
|
template.render(**context),
|
|
rpm_ver)
|
|
|
|
@data(
|
|
('suse', '1.1.0', '1', '0'),
|
|
('suse', '1.1.0.post2', '1', '0'),
|
|
('suse', '1.1.0dev10', '2', '0'),
|
|
('fedora', '1.1.0', '1', '1%{?dist}'),
|
|
# ('fedora', '1.1.0.post2', '1', 'FIXME'),
|
|
('fedora', '1.1.0dev10', '1', '0.1.dev10%{?dist}'),
|
|
('fedora', '1.1.0a10', '1', '0.1.a10%{?dist}'),
|
|
('fedora', '1.1.0a10dev5', '1', '0.1.a10.dev5%{?dist}'),
|
|
('fedora', '1.1.0b10', '1', '0.1.b10%{?dist}'),
|
|
('fedora', '1.1.0rc2', '5', '0.5.rc2%{?dist}'),
|
|
('fedora', '1.1.0rc2dev2', '1', '0.1.rc2.dev2%{?dist}'),
|
|
)
|
|
@unpack
|
|
def test_render_func_py2rpmrelease(self, style, upstream_ver, rpm_release,
|
|
rpm_release_expected):
|
|
context = {'spec_style': style, 'epochs': {}, 'requirements': {}}
|
|
# need to escape '{' and '}' here
|
|
s = "{{% set upstream_version = '{}' %}}" \
|
|
"{{% set rpm_release = '{}' %}}" \
|
|
"{{{{ py2rpmrelease() }}}}".format(upstream_ver, rpm_release)
|
|
template = self.env.from_string(s)
|
|
self.assertEqual(
|
|
template.render(**context),
|
|
rpm_release_expected)
|
|
|
|
|
|
class RenderspecVersionsTests(unittest.TestCase):
|
|
def test_without_version(self):
|
|
requires = renderspec.versions.get_requirements(
|
|
['# a comment', '', ' ', 'pyasn1 # BSD', 'Paste'])
|
|
self.assertEqual(requires, {})
|
|
|
|
def test_with_single_version(self):
|
|
requires = renderspec.versions.get_requirements(
|
|
['paramiko>=1.16.0 # LGPL'])
|
|
self.assertEqual(requires, {'paramiko': '1.16.0'})
|
|
|
|
def test_with_multiple_versions(self):
|
|
requires = renderspec.versions.get_requirements(
|
|
['sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3 # BSD'])
|
|
self.assertEqual(requires, {'sphinx': '1.1.2'})
|
|
|
|
def test_with_multiple_versions_and_invalid_lowest(self):
|
|
requires = renderspec.versions.get_requirements(
|
|
['sphinx>=1.1.2,!=1.1.0,!=1.3b1,<1.3 # BSD'])
|
|
self.assertEqual(requires, {'sphinx': '1.1.2'})
|
|
|
|
def test_with_single_marker(self):
|
|
requires = renderspec.versions.get_requirements(
|
|
["pywin32>=1.0;sys_platform=='win32' # PSF"])
|
|
self.assertEqual(requires, {})
|
|
|
|
def test_with_multiple_markers(self):
|
|
requires = renderspec.versions.get_requirements(
|
|
["""pyinotify>=0.9.6;sys_platform!='win32' and \
|
|
sys_platform!='darwin' and sys_platform!='sunos5' # MIT"""])
|
|
self.assertEqual(requires, {'pyinotify': '0.9.6'})
|
|
|
|
|
|
@ddt
|
|
class RenderspecCommonTests(unittest.TestCase):
|
|
def test__get_requirements_single_file(self):
|
|
tmpdir = tempfile.mkdtemp(prefix='renderspec-test_')
|
|
try:
|
|
f1 = os.path.join(tmpdir, 'f1')
|
|
with open(f1, 'w+') as f:
|
|
f.write('paramiko>=1.16.0\n'
|
|
'pyinotify>=0.9.6')
|
|
self.assertDictEqual(
|
|
renderspec._get_requirements([f1]),
|
|
{'paramiko': '1.16.0', 'pyinotify': '0.9.6'})
|
|
finally:
|
|
shutil.rmtree(tmpdir)
|
|
|
|
def test__get_requirements_multiple_files(self):
|
|
tmpdir = tempfile.mkdtemp(prefix='renderspec-test_')
|
|
try:
|
|
f1 = os.path.join(tmpdir, 'f1')
|
|
f2 = os.path.join(tmpdir, 'f2')
|
|
with open(f1, 'w+') as f:
|
|
f.write('paramiko>=1.17.0 # LGPL')
|
|
with open(f2, 'w+') as f:
|
|
f.write('paramiko>=1.16.0 # LGPL')
|
|
# we expect the second file was used (because mentioned last)
|
|
self.assertEqual(renderspec._get_requirements([f1, f2]),
|
|
{'paramiko': '1.16.0'})
|
|
finally:
|
|
shutil.rmtree(tmpdir)
|
|
|
|
@data(
|
|
("{{ py2pkg('requests') }}", "suse", {}, {}, "python-requests"),
|
|
("{{ py2pkg('requests') }}", "fedora", {}, {}, "python-requests"),
|
|
("{{ py2pkg('requests') }}", "suse", {}, {"requests": '1.1.0'},
|
|
"python-requests >= 1.1.0"),
|
|
)
|
|
@unpack
|
|
def test_generate_spec(self, template, style, epochs, requirements,
|
|
expected_result):
|
|
tmpdir = tempfile.mkdtemp(prefix='renderspec-test_')
|
|
try:
|
|
f1 = os.path.join(tmpdir, 'test.spec')
|
|
with open(f1, 'w+') as f:
|
|
f.write(template)
|
|
rendered = renderspec.generate_spec(
|
|
style, epochs, requirements, f1)
|
|
self.assertEqual(rendered, expected_result)
|
|
finally:
|
|
shutil.rmtree(tmpdir)
|
|
|
|
|
|
class RenderspecDistroDetection(unittest.TestCase):
|
|
def test_is_fedora(self):
|
|
self.assertTrue(renderspec._is_fedora("CentOS Linux"))
|
|
self.assertTrue(renderspec._is_fedora("Fedora"))
|
|
self.assertTrue(renderspec._is_fedora("Red Hat Enterprise Linux 7.2"))
|
|
self.assertFalse(renderspec._is_fedora("SUSE Linux Enterprise Server"))
|
|
|
|
def test_get_default_distro(self):
|
|
import platform
|
|
platform.linux_distribution = Mock(
|
|
return_value=('SUSE Linux Enterprise Server ', '12', 'x86_64'))
|
|
self.assertEqual(renderspec._get_default_distro(),
|
|
"suse")
|
|
platform.linux_distribution = Mock(
|
|
return_value=('Fedora', '24', 'x86_64'))
|
|
self.assertEqual(renderspec._get_default_distro(), "fedora")
|
|
platform.linux_distribution = Mock(
|
|
return_value=('Red Hat Enterprise Linux Server', '7.3', 'x86_64'))
|
|
self.assertEqual(renderspec._get_default_distro(), "fedora")
|
|
platform.linux_distribution = Mock(
|
|
return_value=('CentOS Linux', '7.3', 'x86_64'))
|
|
self.assertEqual(renderspec._get_default_distro(), "fedora")
|
|
platform.linux_distribution = Mock(
|
|
return_value=('debian', '7.0', 'x86_64'))
|
|
self.assertEqual(renderspec._get_default_distro(), "unknown")
|
|
|
|
|
|
class RenderspecDistTeamplatesTests(unittest.TestCase):
|
|
@patch('renderspec.distloader.get_dist_templates_path')
|
|
def test_dist_templates(self, mock_dt_path):
|
|
base_txt = ('Line before block\n'
|
|
'{% block footest %}{% endblock %}\n'
|
|
'Line after block\n')
|
|
dt_txt = ('{% extends ".spec" %}'
|
|
'{% block footest %}'
|
|
'foo block\n'
|
|
'macro: {{ py2pkg("test") }}\n'
|
|
'{% endblock %}')
|
|
expected_out = ('Line before block\n'
|
|
'foo block\n'
|
|
'macro: python-test\n'
|
|
'Line after block')
|
|
tmpdir = tempfile.mkdtemp(prefix='renderspec-test_')
|
|
try:
|
|
# create .spec template
|
|
base_path = os.path.join(tmpdir, 'foo.spec.j2')
|
|
with open(base_path, 'w+') as f:
|
|
f.write(base_txt)
|
|
# create custom dist template
|
|
dt_dir = os.path.join(tmpdir, 'dist-templates')
|
|
os.mkdir(dt_dir)
|
|
dt_path = os.path.join(dt_dir, 'loldistro.spec.j2')
|
|
with open(dt_path, 'w+') as f:
|
|
f.write(dt_txt)
|
|
# mock this to use testing dist-tempaltes folder
|
|
mock_dt_path.return_value = dt_dir
|
|
|
|
out = renderspec.generate_spec('loldistro', {}, {}, base_path)
|
|
self.assertEqual(out, expected_out)
|
|
finally:
|
|
shutil.rmtree(tmpdir)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|