Compare commits
10 Commits
3a652b1c29
...
9b2577f91d
Author | SHA1 | Date |
---|---|---|
Miro Hrončok | 9b2577f91d | |
Tomas Orsava | 85209d6c46 | |
Tomas Orsava | a30059967b | |
Miro Hrončok | 32385d7b9e | |
Charalampos Stratakis | 785aef2702 | |
Tomas Orsava | 30da77e6af | |
Miro Hrončok | 04145e4cdd | |
Tomas Orsava | e22e5600bd | |
Karolina Surma | 25272d7d36 | |
Miro Hrončok | c7a9537dba |
|
@ -37,7 +37,7 @@
|
|||
|
||||
# use the underscored macros to redefine the behavior of %%python3_version etc.
|
||||
%__python2 /usr/bin/python2
|
||||
%__python3 /usr/bin/python3
|
||||
%__python3 /usr/bin/python%{python3_pkgversion}
|
||||
|
||||
# use the non-underscored macros to refer to Python in spec, etc.
|
||||
%python2 %__python2
|
||||
|
@ -163,6 +163,7 @@
|
|||
|
||||
%py_provides() %{lua:
|
||||
local python = require 'fedora.srpm.python'
|
||||
local rhel = rpm.expand('%{?rhel}')
|
||||
local name = rpm.expand('%1')
|
||||
if name == '%1' then
|
||||
rpm.expand('%{error:%%py_provides requires at least 1 argument, the name to provide}')
|
||||
|
@ -176,6 +177,21 @@
|
|||
for i, provide in ipairs(provides) do
|
||||
print('Provides: ' .. provide .. '\\n')
|
||||
end
|
||||
-- We only generate these Obsoletes on CentOS/RHEL to provide clean upgrade
|
||||
-- path, e.g. python3-foo obsoletes python39-foo from previous RHEL.
|
||||
-- In Fedora this is not needed as we don't ship ecosystem packages
|
||||
-- for alternative Python interpreters.
|
||||
if rhel ~= '' then
|
||||
-- Create Obsoletes only if the name does not end in a parenthesis,
|
||||
-- as Obsoletes can't include parentheses.
|
||||
-- This most commonly happens when the name contains an isa.
|
||||
if (string.sub(name, "-1") ~= ")") then
|
||||
local obsoletes = python.python_altobsoletes(name, evr)
|
||||
for i, obsolete in ipairs(obsoletes) do
|
||||
print('Obsoletes: ' .. obsolete .. '\\n')
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
%python_extras_subpkg(n:i:f:F) %{expand:%{lua:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Name: python-rpm-macros
|
||||
Version: 3.9
|
||||
Release: 46%{?dist}
|
||||
Release: 52%{?dist}
|
||||
Summary: The common Python RPM macros
|
||||
URL: https://src.fedoraproject.org/rpms/python-rpm-macros/
|
||||
|
||||
|
@ -30,6 +30,12 @@ BuildArch: noarch
|
|||
# For compileall2.py
|
||||
Requires: python-srpm-macros = %{version}-%{release}
|
||||
|
||||
# The packages are called python(3)-(s)rpm-macros
|
||||
# We never want python3-rpm-macros to provide python-rpm-macros
|
||||
# We opt out from all Python name-based automatic provides and obsoletes
|
||||
%undefine __pythonname_provides
|
||||
%undefine __pythonname_obsoletes
|
||||
|
||||
%description
|
||||
This package contains the unversioned Python RPM macros, that most
|
||||
implementations should rely on.
|
||||
|
@ -60,6 +66,15 @@ Requires: python-srpm-macros = %{version}-%{release}
|
|||
# For %%py_setup and import_all_modules.py
|
||||
Requires: python-rpm-macros = %{version}-%{release}
|
||||
|
||||
# We obsolete the old python39-rpm-macros for a smoother upgrade from RHEL8.
|
||||
# Since python39-rpm-macros are built from the python39 component in RHEL 8,
|
||||
# they're fully versioned (currently `0:3.9.7`), with the patch version likely
|
||||
# to increase in the future. RPM sorts this number as higher than `3.9`, which
|
||||
# is the version we have in RHEL 9. Therefore we're obsoleting with an Epoch 1
|
||||
# so that all versions from RHEL 8 are obsoleted (but we keep the possibility
|
||||
# of increasing the epoch in RHEL 8 to stop this).
|
||||
Obsoletes: python39-rpm-macros < 1:%{version}-%{release}
|
||||
|
||||
%description -n python3-rpm-macros
|
||||
RPM macros for building Python 3 packages.
|
||||
|
||||
|
@ -101,6 +116,30 @@ install -m 644 import_all_modules.py %{buildroot}%{_rpmconfigdir}/redhat/
|
|||
|
||||
|
||||
%changelog
|
||||
* Tue Feb 08 2022 Tomas Orsava <torsava@redhat.com> - 3.9-52
|
||||
- %%py_provides: Do not generate Obsoletes for names containing parentheses
|
||||
- Related: rhbz#1990421
|
||||
|
||||
* Tue Feb 08 2022 Tomas Orsava <torsava@redhat.com> - 3.9-51
|
||||
- Add Obsoletes tags with the python39- prefix for smoother upgrade from RHEL8
|
||||
- Related: rhbz#1990421
|
||||
|
||||
* Tue Feb 01 2022 Miro Hrončok <mhroncok@redhat.com> - 3.9-50
|
||||
- Explicitly opt-out from Python name-based provides and obsoletes generators
|
||||
|
||||
* Wed Jan 19 2022 Tomas Orsava <torsava@redhat.com> - 3.9-49
|
||||
- Add lua helper functions to make it possible to automatically generate
|
||||
Obsoletes tags
|
||||
- Modify the %%py_provides macro to also generate Obsoletes tags on CentOS/RHEL
|
||||
- Resolves: rhbz#1990421
|
||||
|
||||
* Tue Dec 21 2021 Karolina Surma <ksurma@redhat.com> - 3.9-48
|
||||
- Fix CI test configuration, so that pytest can import the package code
|
||||
|
||||
* Wed Dec 08 2021 Miro Hrončok <mhroncok@redhat.com> - 3.9-47
|
||||
- Set %%__python3 value according to %%python3_pkgversion
|
||||
I.e. when %%python3_pkgversion is 3.12, %%__python3 is /usr/bin/python3.12
|
||||
|
||||
* Mon Nov 01 2021 Karolina Surma <ksurma@redhat.com> - 3.9-46
|
||||
- Fix multiline arguments processing for %%py_check_import
|
||||
- Fix %%py_shebang_flags handling within %%py_check_import
|
||||
|
|
92
python.lua
92
python.lua
|
@ -2,22 +2,34 @@
|
|||
|
||||
-- Determine alternate names provided from the given name.
|
||||
-- Used in pythonname provides generator, python_provide and py_provides.
|
||||
-- There are 2 rules:
|
||||
-- If only_3_to_3_X is false/nil/unused there are 2 rules:
|
||||
-- python3-foo -> python-foo, python3.X-foo
|
||||
-- python3.X-foo -> python-foo, python3-foo
|
||||
-- If only_3_to_3_X is true there is only 1 rule:
|
||||
-- python3-foo -> python3X-foo
|
||||
-- There is no python-foo -> rule, python-foo packages are version agnostic.
|
||||
-- Returns a table/array with strings. Empty when no rule matched.
|
||||
local function python_altnames(name)
|
||||
local xy = rpm.expand('%{__default_python3_pkgversion}')
|
||||
local function python_altnames(name, only_3_to_3_X)
|
||||
local xy
|
||||
if only_3_to_3_X then
|
||||
-- Here we hardcode the xy prefix we want to obsolete to "39", because:
|
||||
-- 1. Python 3.9 will remain the main Python version in RHEL 9
|
||||
-- 2. python39 in RHEL 8 is still using the dotless naming (as opposed to
|
||||
-- python3.9)
|
||||
xy = "39"
|
||||
else
|
||||
xy = rpm.expand('%{__default_python3_pkgversion}')
|
||||
end
|
||||
local altnames = {}
|
||||
local replaced
|
||||
-- NB: dash needs to be escaped!
|
||||
if name:match('^python3%-') then
|
||||
for i, prefix in ipairs({'python-', 'python' .. xy .. '-'}) do
|
||||
local prefixes = only_3_to_3_X and {} or {'python-'}
|
||||
for i, prefix in ipairs({'python' .. xy .. '-', table.unpack(prefixes)}) do
|
||||
replaced = name:gsub('^python3%-', prefix)
|
||||
table.insert(altnames, replaced)
|
||||
end
|
||||
elseif name:match('^python' .. xy .. '%-') then
|
||||
elseif name:match('^python' .. xy .. '%-') and not only_3_to_3_X then
|
||||
for i, prefix in ipairs({'python-', 'python3-'}) do
|
||||
replaced = name:gsub('^python' .. xy .. '%-', prefix)
|
||||
table.insert(altnames, replaced)
|
||||
|
@ -27,42 +39,72 @@ local function python_altnames(name)
|
|||
end
|
||||
|
||||
|
||||
local function __python_alttags(name, evr, tag_type)
|
||||
-- for the "provides" tag_type we want also unversioned provides
|
||||
local only_3_to_3_X = tag_type ~= "provides"
|
||||
local operator = tag_type == "provides" and ' = ' or ' < '
|
||||
|
||||
-- global cache that tells what package NEVRs were already processed for the
|
||||
-- given tag type
|
||||
if __python_alttags_beenthere == nil then
|
||||
__python_alttags_beenthere = {}
|
||||
end
|
||||
if __python_alttags_beenthere[tag_type] == nil then
|
||||
__python_alttags_beenthere[tag_type] = {}
|
||||
end
|
||||
__python_alttags_beenthere[tag_type][name .. ' ' .. evr] = true
|
||||
local alttags = {}
|
||||
for i, altname in ipairs(python_altnames(name, only_3_to_3_X)) do
|
||||
table.insert(alttags, altname .. operator .. evr)
|
||||
end
|
||||
return alttags
|
||||
end
|
||||
|
||||
-- For any given name and epoch-version-release, return provides except self.
|
||||
-- Uses python_altnames under the hood
|
||||
-- Returns a table/array with strings.
|
||||
local function python_altprovides(name, evr)
|
||||
-- global cache that tells what provides were already processed
|
||||
if __python_altnames_provides_beenthere == nil then
|
||||
__python_altnames_provides_beenthere = {}
|
||||
end
|
||||
__python_altnames_provides_beenthere[name .. ' ' .. evr] = true
|
||||
local altprovides = {}
|
||||
for i, altname in ipairs(python_altnames(name)) do
|
||||
table.insert(altprovides, altname .. ' = ' .. evr)
|
||||
end
|
||||
return altprovides
|
||||
return __python_alttags(name, evr, "provides")
|
||||
end
|
||||
|
||||
-- For any given name and epoch-version-release, return versioned obsoletes except self.
|
||||
-- Uses python_altnames under the hood
|
||||
-- Returns a table/array with strings.
|
||||
local function python_altobsoletes(name, evr)
|
||||
return __python_alttags(name, evr, "obsoletes")
|
||||
end
|
||||
|
||||
|
||||
local function __python_alttags_once(name, evr, tag_type)
|
||||
-- global cache that tells what provides were already processed
|
||||
if __python_alttags_beenthere == nil
|
||||
or __python_alttags_beenthere[tag_type] == nil
|
||||
or __python_alttags_beenthere[tag_type][name .. ' ' .. evr] == nil then
|
||||
return __python_alttags(name, evr, tag_type)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Like python_altprovides but only return something once.
|
||||
-- For each argument can only be used once, returns nil otherwise.
|
||||
-- Previous usage of python_altprovides counts as well.
|
||||
local function python_altprovides_once(name, evr)
|
||||
-- global cache that tells what provides were already processed
|
||||
if __python_altnames_provides_beenthere == nil then
|
||||
__python_altnames_provides_beenthere = {}
|
||||
end
|
||||
if __python_altnames_provides_beenthere[name .. ' ' .. evr] == nil then
|
||||
__python_altnames_provides_beenthere[name .. ' ' .. evr] = true
|
||||
return python_altprovides(name, evr)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
return __python_alttags_once(name, evr, "provides")
|
||||
end
|
||||
|
||||
-- Like python_altobsoletes but only return something once.
|
||||
-- For each argument can only be used once, returns nil otherwise.
|
||||
-- Previous usage of python_altobsoletes counts as well.
|
||||
local function python_altobsoletes_once(name, evr)
|
||||
return __python_alttags_once(name, evr, "obsoletes")
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
python_altnames = python_altnames,
|
||||
python_altprovides = python_altprovides,
|
||||
python_altobsoletes = python_altobsoletes,
|
||||
python_altprovides_once = python_altprovides_once,
|
||||
python_altobsoletes_once = python_altobsoletes_once,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# completely disabled inspections:
|
||||
inspections:
|
||||
# there is no upstream and the files are changed from time to time
|
||||
addedfiles: off
|
||||
changedfiles: off
|
||||
filesize: off
|
||||
upstream: off
|
|
@ -83,6 +83,17 @@ def shell_stdout(script):
|
|||
shell=True).rstrip()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('macro', ['%__python3', '%python3'])
|
||||
def test_python3(macro):
|
||||
assert rpm_eval(macro) == ['/usr/bin/python3']
|
||||
|
||||
|
||||
@pytest.mark.parametrize('macro', ['%__python3', '%python3'])
|
||||
@pytest.mark.parametrize('pkgversion', ['3', '3.9', '3.12'])
|
||||
def test_python3_with_pkgversion(macro, pkgversion):
|
||||
assert rpm_eval(macro, python3_pkgversion=pkgversion) == [f'/usr/bin/python{pkgversion}']
|
||||
|
||||
|
||||
@pytest.mark.parametrize('argument, result', [
|
||||
('a', 'a'),
|
||||
('a-a', 'a-a'),
|
||||
|
@ -157,67 +168,102 @@ def test_python_provide_doubleuse():
|
|||
assert len(set(lines)) == 3
|
||||
|
||||
|
||||
def test_py_provides_python():
|
||||
lines = rpm_eval('%py_provides python-foo', version='6', release='1.fc66')
|
||||
@pytest.mark.parametrize('rhel', [None, 10])
|
||||
def test_py_provides_python(rhel):
|
||||
lines = rpm_eval('%py_provides python-foo', version='6', release='1.fc66', rhel=rhel)
|
||||
assert 'Provides: python-foo = 6-1.fc66' in lines
|
||||
assert len(lines) == 1
|
||||
|
||||
|
||||
def test_py_provides_whatever():
|
||||
lines = rpm_eval('%py_provides whatever', version='6', release='1.fc66')
|
||||
@pytest.mark.parametrize('rhel', [None, 12])
|
||||
def test_py_provides_whatever(rhel):
|
||||
lines = rpm_eval('%py_provides whatever', version='6', release='1.fc66', rhel=rhel)
|
||||
assert 'Provides: whatever = 6-1.fc66' in lines
|
||||
assert len(lines) == 1
|
||||
|
||||
|
||||
def test_py_provides_python3():
|
||||
lines = rpm_eval('%py_provides python3-foo', version='6', release='1.fc66')
|
||||
@pytest.mark.parametrize('rhel', [None, 9])
|
||||
def test_py_provides_python3(rhel):
|
||||
lines = rpm_eval('%py_provides python3-foo', version='6', release='1.fc66', rhel=rhel)
|
||||
assert 'Provides: python3-foo = 6-1.fc66' in lines
|
||||
assert 'Provides: python-foo = 6-1.fc66' in lines
|
||||
assert f'Provides: python{X_Y}-foo = 6-1.fc66' in lines
|
||||
if rhel:
|
||||
assert f'Obsoletes: python{XY}-foo < 6-1.fc66' in lines
|
||||
assert len(lines) == 4
|
||||
else:
|
||||
assert len(lines) == 3
|
||||
|
||||
|
||||
@pytest.mark.parametrize('rhel', [None, 9])
|
||||
def test_py_provides_python3_with_isa(rhel):
|
||||
lines = rpm_eval('%py_provides python3-foo(x86_64)', version='6', release='1.fc66', rhel=rhel)
|
||||
assert 'Provides: python3-foo(x86_64) = 6-1.fc66' in lines
|
||||
assert 'Provides: python-foo(x86_64) = 6-1.fc66' in lines
|
||||
assert f'Provides: python{X_Y}-foo(x86_64) = 6-1.fc66' in lines
|
||||
assert f'Obsoletes: python{X_Y}-foo(x86_64) < 6-1.fc66' not in lines
|
||||
assert len(lines) == 3
|
||||
|
||||
|
||||
def test_py_provides_python3_epoched():
|
||||
lines = rpm_eval('%py_provides python3-foo', epoch='1', version='6', release='1.fc66')
|
||||
@pytest.mark.parametrize('rhel', [None, 13])
|
||||
def test_py_provides_python3_epoched(rhel):
|
||||
lines = rpm_eval('%py_provides python3-foo', epoch='1', version='6', release='1.fc66', rhel=rhel)
|
||||
assert 'Provides: python3-foo = 1:6-1.fc66' in lines
|
||||
assert 'Provides: python-foo = 1:6-1.fc66' in lines
|
||||
assert f'Provides: python{X_Y}-foo = 1:6-1.fc66' in lines
|
||||
assert len(lines) == 3
|
||||
if rhel:
|
||||
assert f'Obsoletes: python{XY}-foo < 1:6-1.fc66' in lines
|
||||
assert len(lines) == 4
|
||||
else:
|
||||
assert len(lines) == 3
|
||||
|
||||
|
||||
def test_py_provides_python3X():
|
||||
lines = rpm_eval(f'%py_provides python{X_Y}-foo', version='6', release='1.fc66')
|
||||
@pytest.mark.parametrize('rhel', [None, 13])
|
||||
def test_py_provides_python3X(rhel):
|
||||
lines = rpm_eval(f'%py_provides python{X_Y}-foo', version='6', release='1.fc66', rhel=rhel)
|
||||
assert f'Provides: python{X_Y}-foo = 6-1.fc66' in lines
|
||||
assert 'Provides: python-foo = 6-1.fc66' in lines
|
||||
assert 'Provides: python3-foo = 6-1.fc66' in lines
|
||||
assert len(lines) == 3
|
||||
|
||||
|
||||
def test_py_provides_python3X_epoched():
|
||||
lines = rpm_eval(f'%py_provides python{X_Y}-foo', epoch='1', version='6', release='1.fc66')
|
||||
@pytest.mark.parametrize('rhel', [None, 27])
|
||||
def test_py_provides_python3X_epoched(rhel):
|
||||
lines = rpm_eval(f'%py_provides python{X_Y}-foo', epoch='1', version='6', release='1.fc66', rhel=rhel)
|
||||
assert f'Provides: python{X_Y}-foo = 1:6-1.fc66' in lines
|
||||
assert 'Provides: python-foo = 1:6-1.fc66' in lines
|
||||
assert 'Provides: python3-foo = 1:6-1.fc66' in lines
|
||||
assert len(lines) == 3
|
||||
|
||||
|
||||
def test_py_provides_doubleuse():
|
||||
@pytest.mark.parametrize('rhel', [None, 2])
|
||||
def test_py_provides_doubleuse(rhel):
|
||||
lines = rpm_eval('%{py_provides python3-foo}%{py_provides python3-foo}',
|
||||
version='6', release='1.fc66')
|
||||
version='6', release='1.fc66', rhel=rhel)
|
||||
assert 'Provides: python3-foo = 6-1.fc66' in lines
|
||||
assert 'Provides: python-foo = 6-1.fc66' in lines
|
||||
assert f'Provides: python{X_Y}-foo = 6-1.fc66' in lines
|
||||
assert len(lines) == 6
|
||||
assert len(set(lines)) == 3
|
||||
if rhel:
|
||||
assert f'Obsoletes: python{XY}-foo < 6-1.fc66' in lines
|
||||
assert len(lines) == 8
|
||||
assert len(set(lines)) == 4
|
||||
else:
|
||||
assert len(lines) == 6
|
||||
assert len(set(lines)) == 3
|
||||
|
||||
|
||||
def test_py_provides_with_evr():
|
||||
@pytest.mark.parametrize('rhel', [None, 2])
|
||||
def test_py_provides_with_evr(rhel):
|
||||
lines = rpm_eval('%py_provides python3-foo 123',
|
||||
version='6', release='1.fc66')
|
||||
version='6', release='1.fc66', rhel=rhel)
|
||||
assert 'Provides: python3-foo = 123' in lines
|
||||
assert 'Provides: python-foo = 123' in lines
|
||||
assert f'Provides: python{X_Y}-foo = 123' in lines
|
||||
assert len(lines) == 3
|
||||
if rhel:
|
||||
assert f'Obsoletes: python{XY}-foo < 123' in lines
|
||||
assert len(lines) == 4
|
||||
else:
|
||||
assert len(lines) == 3
|
||||
|
||||
|
||||
def test_pytest_passes_options_naturally():
|
||||
|
@ -629,7 +675,9 @@ def test_python3_sitelib_value_default():
|
|||
|
||||
def test_python3_sitelib_value_alternate_python(alt_x_y):
|
||||
macro = '%python3_sitelib'
|
||||
assert rpm_eval(macro, __python3=f'/usr/bin/python{alt_x_y}') == [f'/usr/lib/python{alt_x_y}/site-packages']
|
||||
assert (rpm_eval(macro, __python3=f'/usr/bin/python{alt_x_y}') ==
|
||||
rpm_eval(macro, python3_pkgversion=alt_x_y) ==
|
||||
[f'/usr/lib/python{alt_x_y}/site-packages'])
|
||||
|
||||
|
||||
def test_python_sitearch_value_python3(lib):
|
||||
|
@ -649,7 +697,9 @@ def test_python3_sitearch_value_default(lib):
|
|||
|
||||
def test_python3_sitearch_value_alternate_python(lib, alt_x_y):
|
||||
macro = '%python3_sitearch'
|
||||
assert rpm_eval(macro, __python3=f'/usr/bin/python{alt_x_y}') == [f'/usr/{lib}/python{alt_x_y}/site-packages']
|
||||
assert (rpm_eval(macro, __python3=f'/usr/bin/python{alt_x_y}') ==
|
||||
rpm_eval(macro, python3_pkgversion=alt_x_y) ==
|
||||
[f'/usr/{lib}/python{alt_x_y}/site-packages'])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
tests:
|
||||
- pytest:
|
||||
dir: .
|
||||
run: ALTERNATE_PYTHON_VERSION=SKIP pytest -v
|
||||
run: PYTHONPATH=/usr/lib/rpm/redhat ALTERNATE_PYTHON_VERSION=3.11 pytest -v
|
||||
- manual_byte_compilation:
|
||||
dir: .
|
||||
run: rpmbuild -ba pythontest.spec
|
||||
|
@ -25,4 +25,5 @@
|
|||
- python3-rpm-macros
|
||||
- python3-devel
|
||||
- python3-pytest
|
||||
- python3.11-devel
|
||||
|
||||
|
|
Loading…
Reference in New Issue