Add option to skip certain python version

This can be used on CentOS to default to skipping the py3 expansion
as well as, if set to py2, generate python3-only spec files from
the same singlespec input.

Change-Id: I94926258ebd50a478e79717d4b0ad6fa1736d1c2
This commit is contained in:
Dirk Mueller 2017-09-27 16:56:20 +02:00
parent f646eea279
commit 2d0afbf1cf
6 changed files with 89 additions and 34 deletions

View File

@ -23,6 +23,18 @@ be done with::
renderspec --spec-style suse example.spec.j2
Different pyver variants
************************
For singlespec variant spec.j2 templates (i.e. templates that can build for
multiple python flavors in parallel) it might be undesirable to expand requirements
for a particular python flavor. In that case the option `--skip-pyversion` can
be used to skip expansion for those dependencies:
renderspec --skip-pyversion py3 example.spec.j2
For CentOS 7.x hosts :program:`renderspec` defaults to skipping the py3 expansion.
Different template formats
**************************
The only supported input template format is currently called `spec.j2` (which is

View File

@ -31,19 +31,20 @@ from renderspec import versions
from renderspec import contextfuncs
def generate_spec(spec_style, epochs, requirements, input_template_format,
input_template_path, output_path):
def generate_spec(spec_style, epochs, requirements, skip_pyversion,
input_template_format, input_template_path, output_path):
"""generate a spec file with the given style and input template"""
if input_template_format == 'spec.j2':
return _renderer_input_template_format_spec(
spec_style, epochs, requirements, input_template_path,
output_path)
spec_style, epochs, requirements, skip_pyversion,
input_template_path, output_path)
else:
raise Exception('Unknown input-template-format "%s"' %
input_template_format)
def _renderer_input_template_format_spec(spec_style, epochs, requirements,
skip_pyversion,
input_template_path, output_path):
"""render a 'traditional' .spec.j2 template into a .spec file"""
env = Environment(loader=RenderspecLoader(
@ -64,6 +65,7 @@ def _renderer_input_template_format_spec(spec_style, epochs, requirements,
output_dir = None
return template.render(spec_style=spec_style, epochs=epochs,
requirements=requirements,
skip_pyversion=skip_pyversion,
input_template_dir=input_template_dir,
output_dir=output_dir)
@ -102,6 +104,15 @@ def _get_default_distro():
return "unknown"
def _get_default_pyskips(distro):
# py3 building is all complicated on CentOS 7.x
if distro == 'fedora':
distname, distver, _ = platform.linux_distribution()
if 'CentOS' in distname and distver.startswith('7'):
return 'py3'
return None
def _get_default_template():
fns = [f for f in os.listdir('.')
if os.path.isfile(f) and f.endswith('.spec.j2')]
@ -145,6 +156,10 @@ def process_args():
parser.add_argument("--spec-style", help="distro style you want to use. "
"default: %s" % (distro), default=distro,
choices=['suse', 'fedora'])
parser.add_argument("--skip-pyversion",
help='Skip requirements for this pyversion',
default=_get_default_pyskips(distro),
choices=['py2', 'py3'])
parser.add_argument("--epochs", help="yaml file with epochs listed.")
parser.add_argument("input-template", nargs='?',
help="specfile jinja2 template to render. "
@ -191,8 +206,9 @@ def main():
output_path = None
spec = generate_spec(args['spec_style'], epochs, requirements,
args['input_template_format'], input_template,
output_path)
args['skip_pyversion'],
args['input_template_format'],
input_template, output_path)
if output_path:
print("Rendering: %s -> %s" % (input_template, output_path))
with open(output_path, "w") as o:

View File

@ -147,12 +147,16 @@ def _context_epoch(context, pkg_name):
return context['epochs'].get(pkg_name, 0)
def _pymod2pkg_translate(pkg_name, spec_style, py_versions):
def _pymod2pkg_translate(pkg_name, context, py_versions):
"""translate a given package name for a single or multiple py versions"""
if py_versions and not isinstance(py_versions, (list, tuple)):
py_versions = [py_versions]
kwargs = {'py_vers': py_versions} if py_versions else {}
translations = pymod2pkg.module2package(pkg_name, spec_style, **kwargs)
kwargs = {}
if py_versions:
kwargs['py_vers'] = list(set(py_versions) -
set((context['skip_pyversion'],)))
translations = pymod2pkg.module2package(
pkg_name, context['spec_style'], **kwargs)
# we want always return a list but module2package() might return a string
if not isinstance(translations, (list, tuple)):
translations = [translations]
@ -175,14 +179,12 @@ def _context_py2name(context, pkg_name=None, pkg_version=None,
'py2name')
pkg_name = context.vars[CONTEXT_VAR_PYPI_NAME]
# return always a string to be backwards compat
return ' '.join(_pymod2pkg_translate(
pkg_name, context['spec_style'], py_versions))
return ' '.join(_pymod2pkg_translate(pkg_name, context, py_versions))
def _context_py2pkg(context, pkg_name, pkg_version=None, py_versions=None):
"""generate a distro specific package name with optional version tuple."""
name_list = _pymod2pkg_translate(pkg_name, context['spec_style'],
py_versions)
name_list = _pymod2pkg_translate(pkg_name, context, py_versions)
# if no pkg_version is given, look in the requirements and set one
if not pkg_version:

View File

@ -1,3 +1,9 @@
%if 0%{?rhel} || 0%{?fedora}
%global rdo 1
%endif
%if 0%{?rhel} == 7
%global skip_python3 1
%endif
{% extends ".spec" %}
{% block build_requires %}
BuildRequires: {{ py2pkg('setuptools') }}

View File

@ -1,3 +1,4 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
{% extends ".spec" %}
{% block build_requires %}
BuildRequires: openstack-macros

View File

@ -62,57 +62,73 @@ class RenderspecContextFunctionTests(unittest.TestCase):
'oslo.config', None, ('py', 'py3'),
'python-oslo.config python3-oslo.config'),
# with version
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
({'epochs': {}, 'requirements': {}},
'oslo.config', ('>=', '1.2.3'), None, 'python-oslo.config >= 1.2.3'),
({'spec_style': 'fedora', 'epochs': {}, 'requirements': {}},
'oslo.config', ('==', '1.2.3~a0'), None,
'python-oslo-config == 1.2.3~a0'),
# with version, with epoch
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
({'epochs': {'oslo.config': 4},
'requirements': {}},
'oslo.config', ('>=', '1.2.3'), None,
'python-oslo.config >= 4:1.2.3'),
# without version, with epoch
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
({'epochs': {'oslo.config': 4},
'requirements': {}},
'oslo.config', None, None, 'python-oslo.config'),
# with version, with requirements
({'spec_style': 'suse', 'epochs': {},
({'epochs': {},
'requirements': {'oslo.config' '1.2.3'}},
'oslo.config', ('>=', '4.5.6'), None, 'python-oslo.config >= 4.5.6'),
# without version, with requirements
({'spec_style': 'suse', 'epochs': {},
({'epochs': {},
'requirements': {'oslo.config': '1.2.3'}},
'oslo.config', None, None, 'python-oslo.config >= 1.2.3'),
# without version, with requirements, with epoch
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
({'epochs': {'oslo.config': 4},
'requirements': {'oslo.config': '1.2.3'}},
'oslo.config', None, None, 'python-oslo.config >= 4:1.2.3'),
# with version, with requirements, with epoch
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
({'epochs': {'oslo.config': 4},
'requirements': {'oslo.config' '1.2.3'}},
'oslo.config', ('>=', '4.5.6'), None,
'python-oslo.config >= 4:4.5.6'),
# with version, with requirements, with epoch, python2
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
({'epochs': {'oslo.config': 4},
'requirements': {'oslo.config' '1.2.3'}},
'oslo.config', ('>=', '4.5.6'), 'py2',
'python2-oslo.config >= 4:4.5.6'),
# with version, with requirements, with epoch, python3
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
({'epochs': {'oslo.config': 4},
'requirements': {'oslo.config' '1.2.3'}},
'oslo.config', ('>=', '4.5.6'), 'py3',
'python3-oslo.config >= 4:4.5.6'),
# with version, with requirements, python3, skip python3
({'epochs': {}, 'skip_pyversion': 'py3',
'requirements': {'oslo.config' '1.2.3'}},
'oslo.config', ('>=', '4.5.6'), 'py3',
''),
# with version, with requirements, with epoch, python2 and python3
({'spec_style': 'suse', 'epochs': {'oslo.config': 4},
({'epochs': {'oslo.config': 4},
'requirements': {'oslo.config' '1.2.3'}},
'oslo.config', ('>=', '4.5.6'), ['py2', 'py3'],
'python2-oslo.config >= 4:4.5.6 python3-oslo.config >= 4:4.5.6'),
# with version, with requirements, python2 and python3, skip python3
({'epochs': {'oslo.config': 4}, 'skip_pyversion': 'py3',
'requirements': {'oslo.config' '1.2.3'}},
'oslo.config', ('>=', '4.5.6'), ['py2', 'py3'],
'python2-oslo.config >= 4:4.5.6'),
# with version, with requirements, python2 and python3, skip python2
({'epochs': {'oslo.config': 4}, 'skip_pyversion': 'py2',
'requirements': {'oslo.config' '1.2.3'}},
'oslo.config', ('>=', '4.5.6'), ['py2', 'py3'],
'python3-oslo.config >= 4:4.5.6'),
)
@unpack
def test_context_py2pkg(self, context, pkg_name, pkg_version,
py_versions, expected_result):
context.setdefault('skip_pyversion', ())
context.setdefault('spec_style', 'suse')
self.assertEqual(
renderspec.contextfuncs._context_py2pkg(
context, pkg_name, pkg_version, py_versions),
@ -180,32 +196,32 @@ class RenderspecTemplateFunctionTests(unittest.TestCase):
@data(
# plain
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
({'epochs': {}, 'requirements': {}},
"{{ py2pkg('requests') }}", "python-requests"),
# plain, with multiple py_versions
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
({'epochs': {}, 'requirements': {}},
"{{ py2pkg('requests', py_versions=['py2', 'py3']) }}",
"python2-requests python3-requests"),
# with version
({'spec_style': 'suse', 'epochs': {}, 'requirements': {}},
({'epochs': {}, 'requirements': {}},
"{{ py2pkg('requests', ('>=', '2.8.1')) }}",
"python-requests >= 2.8.1"),
# with version, with epoch
({'spec_style': 'suse', 'epochs': {'requests': 4}, 'requirements': {}},
({'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},
({'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},
({'epochs': {'requests': 4},
'requirements': {'requests': '1.2.3'}},
"{{ py2pkg('requests') }}",
"python-requests >= 4:1.2.3"),
# without version, with epoch, with requirements, with py_versions
({'spec_style': 'suse', 'epochs': {'requests': 4},
({'epochs': {'requests': 4},
'requirements': {'requests': '1.2.3'}},
"{{ py2pkg('requests', py_versions=['py2']) }}",
"python2-requests >= 4:1.2.3"),
@ -213,6 +229,8 @@ class RenderspecTemplateFunctionTests(unittest.TestCase):
@unpack
def test_render_func_py2pkg(self, context, string, expected_result):
template = self.env.from_string(string)
context.setdefault('skip_pyversion', ())
context.setdefault('spec_style', 'suse')
self.assertEqual(
template.render(**context),
expected_result)
@ -421,8 +439,8 @@ class RenderspecCommonTests(unittest.TestCase):
with open(f1, 'w+') as f:
f.write(template)
rendered = renderspec.generate_spec(
style, epochs, requirements, 'spec.j2', f1, None)
self.assertEqual(rendered, expected_result)
style, epochs, requirements, (), 'spec.j2', f1, None)
self.assertTrue(rendered.endswith(expected_result))
finally:
shutil.rmtree(tmpdir)
@ -484,7 +502,7 @@ class RenderspecDistTeamplatesTests(unittest.TestCase):
# mock this to use testing dist-tempaltes folder
mock_dt_path.return_value = dt_dir
out = renderspec.generate_spec('loldistro', {}, {}, 'spec.j2',
out = renderspec.generate_spec('loldistro', {}, {}, (), 'spec.j2',
base_path, None)
self.assertEqual(out, expected_out)
finally: