Merge "Add new context functions for version handling"
This commit is contained in:
commit
abc85adaa3
@ -76,6 +76,57 @@ package name. Using multiple files looks like this::
|
||||
.. _PEP0508: https://www.python.org/dev/peps/pep-0508/
|
||||
.. _global-requirements.txt: https://git.openstack.org/cgit/openstack/requirements/tree/global-requirements.txt
|
||||
|
||||
Handling the package version
|
||||
****************************
|
||||
|
||||
Distributions handle versions, especially pre-release versions differently.
|
||||
SUSE for example allows using RPM's tilde ('~) while Fedora doesn't allow that
|
||||
and uses a combination of RPM `Version` and `Release` tag to express pre-releases.
|
||||
To support both styles with renderspec, the upstream version and a release
|
||||
must be available in the context::
|
||||
|
||||
{% set upstream_version = '1.2.3.0rc1' %}
|
||||
{% set rpm_release = '1' %}
|
||||
|
||||
This should be done on the first lines in the spec.j2 template. The `rpm_release` is
|
||||
only used in the fedora style.
|
||||
Then for the RPM version and release, use::
|
||||
|
||||
Version: {{ py2rpmversion() }}
|
||||
Release: {{ py2rpmrelease() }}
|
||||
|
||||
For suse-style, this renders to::
|
||||
|
||||
Version: 1.2.3.0~rc1
|
||||
Release: 0
|
||||
|
||||
For fedora-style, this renders to::
|
||||
|
||||
Version: 1.2.3
|
||||
Release: 0.1.0rc1%{?dist}
|
||||
|
||||
Note that in case of pre-releases you may need to adjust the version that is used
|
||||
in the `Source` tag and the `%prep` sections `%setup`. So use e.g. ::
|
||||
|
||||
{% set upstream_version = '1.2.3.0rc1' %}
|
||||
{% set rpm_release = '1' %}
|
||||
%name oslo.config
|
||||
Version: {{ py2rpmversion() }}
|
||||
Release: {{ py2rpmrelease() }}
|
||||
Source0: https://pypi.io/packages/source/o/%{sname}/%{sname}-{{ upstream_version }}.tar.gz
|
||||
%prep
|
||||
%setup -q -n %{sname}-{{upstream_version}}
|
||||
|
||||
which would render (with suse-style) to::
|
||||
|
||||
%name oslo.config
|
||||
Version: 1.2.3.0~rc1
|
||||
Release: 0
|
||||
Source0: https://pypi.io/packages/source/o/%{sname}/%{sname}-1.2.3rc1.tar.gz
|
||||
%prep
|
||||
%setup -q -n %{sname}-1.2.3.0rc1
|
||||
|
||||
|
||||
Template features
|
||||
=================
|
||||
|
||||
@ -164,6 +215,47 @@ With the `suse` spec-style::
|
||||
License: Apache-2.0
|
||||
|
||||
|
||||
context function `py2rpmversion`
|
||||
********************************
|
||||
Python has a semantic version schema (see `PEP0440`_) and converting Python versions
|
||||
to RPM compatible versions is needed in some cases. For example, in the Python world
|
||||
the version "1.1.0a3" is lower than "1.1.0" but for RPM the version is higher.
|
||||
To transform a Python version to a RPM compatible version, use::
|
||||
|
||||
{% set upstream_version = '1.1.0a3' %}
|
||||
{% set rpm_release = '1' %}
|
||||
|
||||
Version: {{ py2rpmversion() }}
|
||||
|
||||
With the `suse` spec-style it will be translated to::
|
||||
|
||||
Version: 1.1.0~xalpha3
|
||||
|
||||
Note that you need to set 2 context variables (`upstream_version` and `rpm_release`)
|
||||
to be able to use the `py2rpmversion()` function.
|
||||
|
||||
|
||||
context function `py2rpmrelease`
|
||||
********************************
|
||||
Fedora doesn't allow the usage of `~` (tilde) in the `Version` tag. So for pre-releases
|
||||
the `Release` tag is used (see `Fedora Packaging Versioning`_)
|
||||
For the fedora-style::
|
||||
|
||||
{% set upstream_version = '1.1.0a3' %}
|
||||
{% set rpm_release = '1' %}
|
||||
|
||||
Version: {{ py2rpmversion() }}
|
||||
Release: {{ py2rpmrelease() }}
|
||||
|
||||
this would render to::
|
||||
|
||||
Version: 1.1.0
|
||||
Release: 0.1a3%{?dist}
|
||||
|
||||
Note that you need to set 2 context variables (`upstream_version` and `rpm_release`)
|
||||
to be able to use the `py2rpmrelease()` function.
|
||||
|
||||
|
||||
distribution specific blocks & child templates
|
||||
**********************************************
|
||||
|
||||
@ -199,3 +291,5 @@ For more information, see current `renderspec/dist-templates` and usage in
|
||||
.. _pymod2pkg: https://git.openstack.org/cgit/openstack/pymod2pkg
|
||||
.. _pypi.python.org: https://pypi.python.org/pypi
|
||||
.. _SPDX: https://spdx.org/licenses/
|
||||
.. _PEP0440: https://www.python.org/dev/peps/pep-0440/
|
||||
.. _Fedora Packaging Versioning: https://fedoraproject.org/wiki/Packaging:Versioning#Pre-Release_packages
|
||||
|
@ -24,6 +24,8 @@ import sys
|
||||
from jinja2 import contextfilter
|
||||
from jinja2 import contextfunction
|
||||
from jinja2 import Environment
|
||||
from jinja2.exceptions import TemplateRuntimeError
|
||||
from packaging.version import parse
|
||||
import pymod2pkg
|
||||
|
||||
import yaml
|
||||
@ -32,6 +34,66 @@ from renderspec.distloader import RenderspecLoader
|
||||
from renderspec import versions
|
||||
|
||||
|
||||
# a variable that needs to be set for some functions in the context
|
||||
CONTEXT_VAR_UPSTREAM_VERSION = "upstream_version"
|
||||
CONTEXT_VAR_RPM_RELEASE = "rpm_release"
|
||||
|
||||
|
||||
def _context_check_variable(context, var_name, needed_by):
|
||||
"""check that the context has a given variable"""
|
||||
if var_name not in context.vars:
|
||||
raise TemplateRuntimeError("Variable '%s' not available in context but"
|
||||
" needed for '%s'" % (var_name, needed_by))
|
||||
|
||||
|
||||
def _context_py2rpmversion(context):
|
||||
"""get a python PEP0440 compatible version and translate it to an RPM
|
||||
version"""
|
||||
# the context needs a variable set via {% set upstream_version = 'ver' %}
|
||||
_context_check_variable(context, CONTEXT_VAR_UPSTREAM_VERSION,
|
||||
'py2rpmversion')
|
||||
version = context.vars[CONTEXT_VAR_UPSTREAM_VERSION]
|
||||
v_python = parse(version)
|
||||
# fedora does not allow '~' in versions but uses a combination of Version
|
||||
# and Release
|
||||
# https://fedoraproject.org/wiki/Packaging:Versioning\#Pre-Release_packages
|
||||
if context['spec_style'] == 'fedora':
|
||||
return v_python.base_version
|
||||
else:
|
||||
v_rpm = v_python.public
|
||||
if v_python.is_prerelease:
|
||||
# we need to add the 'x' in front of alpha/beta releases because
|
||||
# in the python world, "1.1a10" > "1.1.dev10"
|
||||
# but in the rpm world, "1.1~a10" < "1.1~dev10"
|
||||
v_rpm = v_rpm.replace('a', '~xalpha')
|
||||
v_rpm = v_rpm.replace('b', '~xbeta')
|
||||
v_rpm = v_rpm.replace('rc', '~rc')
|
||||
v_rpm = v_rpm.replace('.dev', '~dev')
|
||||
return v_rpm
|
||||
|
||||
|
||||
def _context_py2rpmrelease(context):
|
||||
if context['spec_style'] == 'fedora':
|
||||
# the context needs a var set via {% set upstream_version = 'ver' %}
|
||||
_context_check_variable(context, CONTEXT_VAR_UPSTREAM_VERSION,
|
||||
'py2rpmrelease')
|
||||
# the context needs a var set via {% set rpm_release = 'ver' %}
|
||||
_context_check_variable(context, CONTEXT_VAR_RPM_RELEASE,
|
||||
'py2rpmrelease')
|
||||
upstream_version = context.vars[CONTEXT_VAR_UPSTREAM_VERSION]
|
||||
rpm_release = context.vars[CONTEXT_VAR_RPM_RELEASE]
|
||||
v_python = parse(upstream_version)
|
||||
if v_python.is_prerelease:
|
||||
_, alphatag = v_python.public.split(v_python.base_version)
|
||||
return '0.{}.{}%{{?dist}}'.format(rpm_release,
|
||||
alphatag.lstrip('.'))
|
||||
else:
|
||||
return '{}%{{?dist}}'.format(rpm_release)
|
||||
else:
|
||||
# SUSE uses just '0'. The OpenBuildService handles the Release tag
|
||||
return '0'
|
||||
|
||||
|
||||
def _context_epoch(context, pkg_name):
|
||||
"""get the epoch (or 0 if unknown) for the given pkg name"""
|
||||
return context['epochs'].get(pkg_name, 0)
|
||||
@ -115,6 +177,16 @@ def _globals_py2pkg(context, pkg_name, pkg_version=None):
|
||||
return _context_py2pkg(context, pkg_name, pkg_version)
|
||||
|
||||
|
||||
@contextfunction
|
||||
def _globals_py2rpmversion(context):
|
||||
return _context_py2rpmversion(context)
|
||||
|
||||
|
||||
@contextfunction
|
||||
def _globals_py2rpmrelease(context):
|
||||
return _context_py2rpmrelease(context)
|
||||
|
||||
|
||||
@contextfunction
|
||||
def _globals_epoch(context, value):
|
||||
return _context_epoch(context, value)
|
||||
@ -133,6 +205,8 @@ def _globals_py2name(context, value):
|
||||
def _env_register_filters_and_globals(env):
|
||||
"""register all the jinja2 filters we want in the environment"""
|
||||
env.filters['epoch'] = _filter_epoch
|
||||
env.globals['py2rpmversion'] = _globals_py2rpmversion
|
||||
env.globals['py2rpmrelease'] = _globals_py2rpmrelease
|
||||
env.globals['py2pkg'] = _globals_py2pkg
|
||||
env.globals['py2name'] = _globals_py2name
|
||||
env.globals['epoch'] = _globals_epoch
|
||||
|
50
tests.py
50
tests.py
@ -185,6 +185,56 @@ class RenderspecTemplateFunctionTests(unittest.TestCase):
|
||||
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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user