diff --git a/macros.python b/macros.python index f0c3f14..04c47c5 100644 --- a/macros.python +++ b/macros.python @@ -66,6 +66,19 @@ done } +# With $PATH and $PYTHONPATH set to the %%buildroot, +# try to import the given Python module(s). +# Useful as a smoke test in %%check when running tests is not feasible. +# Use spaces or commas as separators. +%py_check_import() %{expand:\\\ + (cd %{_topdir} &&\\\ + PATH="%{buildroot}%{_bindir}:$PATH"\\\ + PYTHONPATH="${PYTHONPATH:-%{buildroot}%{python_sitearch}:%{buildroot}%{python_sitelib}}"\\\ + PYTHONDONTWRITEBYTECODE=1\\\ + %{__python} -c "import %{lua:local m=rpm.expand('%{?*}'):gsub('[%s,]+', ', ');print(m)}" + ) +} + %python_provide() %{lua: local python = require "fedora.srpm.python" function string.starts(String,Start) diff --git a/macros.python3 b/macros.python3 index 6b19117..93b4199 100644 --- a/macros.python3 +++ b/macros.python3 @@ -64,6 +64,19 @@ done } +# With $PATH and $PYTHONPATH set to the %%buildroot, +# try to import the given Python 3 module(s). +# Useful as a smoke test in %%check when running tests is not feasible. +# Use spaces or commas as separators. +%py3_check_import() %{expand:\\\ + (cd %{_topdir} &&\\\ + PATH="%{buildroot}%{_bindir}:$PATH"\\\ + PYTHONPATH="${PYTHONPATH:-%{buildroot}%{python3_sitearch}:%{buildroot}%{python3_sitelib}}"\\\ + PYTHONDONTWRITEBYTECODE=1\\\ + %{__python3} -c "import %{lua:local m=rpm.expand('%{?*}'):gsub('[%s,]+', ', ');print(m)}" + ) +} + # This only supports Python 3.5+ and will never work with Python 2. # Hence, it has no Python version in the name. %pycached() %{lua: diff --git a/python-rpm-macros.spec b/python-rpm-macros.spec index 622a7a8..46e2d1b 100644 --- a/python-rpm-macros.spec +++ b/python-rpm-macros.spec @@ -39,7 +39,7 @@ elseif posix.stat('macros.python-srpm') then end } Version: %{__default_python3_version} -Release: 4%{?dist} +Release: 5%{?dist} BuildArch: noarch @@ -128,6 +128,9 @@ install -m 755 brp-* %{buildroot}%{_rpmconfigdir}/redhat/ %changelog +* Wed Jul 07 2021 Miro Hrončok - 3.10-5 +- Introduce %%py3_check_import + * Wed Jun 30 2021 Miro Hrončok - 3.10-4 - Include brp-python-hardlink in python-srpm-macros since it is no longer in RPM 4.17+ diff --git a/tests/test_evals.py b/tests/test_evals.py index 4a15091..631f234 100644 --- a/tests/test_evals.py +++ b/tests/test_evals.py @@ -1,6 +1,7 @@ import os import subprocess import platform +import re import sys import textwrap @@ -548,6 +549,7 @@ unversioned_macros = pytest.mark.parametrize('macro', [ '%py_install', '%py_install_egg', '%py_install_wheel', + '%py_check_import', ]) @@ -600,3 +602,46 @@ def test_python3_sitearch_value(lib): macro = '%python3_sitearch' assert rpm_eval(macro, __python3='/usr/bin/python3.6') == [f'/usr/{lib}/python3.6/site-packages'] assert rpm_eval(macro) == [f'/usr/{lib}/python{X_Y}/site-packages'] + + +@pytest.mark.parametrize( + 'args, imports', + [ + ('six', 'six'), + ('five six seven', 'five, six, seven'), + ('six,seven, eight', 'six, seven, eight'), + ('six.quarter six.half,, SIX', 'six.quarter, six.half, SIX'), + ] +) +@pytest.mark.parametrize('__python3', [None, f'/usr/bin/python{X_Y}', '/usr/bin/python3.6']) +def test_py3_check_import(args, imports, __python3, lib): + x_y = X_Y + macors = { + 'buildroot': 'BUILDROOT', + '_topdir': 'TOPDIR', + } + if __python3 is not None: + macors['__python3'] = __python3 + # If the __python3 command has version at the end, parse it and expect it. + # Note that the command is used to determine %python3_sitelib and %python3_sitearch, + # so we only test known CPython schemes here and not PyPy for simplicity. + # We also only test main Python + 3.6 because those are required by the CI config. + if (match := re.match(r'.+python(\d+\.\d+)$', __python3)): + x_y = match.group(1) + + lines = rpm_eval(f'%py3_check_import {args}', **macors) + + # An equality check is a bit inflexible here, + # every time we change the macro we need to change this test. + # However actually executing it and verifying the result is much harder :/ + # At least, let's make the lines saner to check: + lines = [line.rstrip('\\').strip() for line in lines] + expected = textwrap.dedent(fr""" + (cd TOPDIR && + PATH="BUILDROOT/usr/bin:$PATH" + PYTHONPATH="${{PYTHONPATH:-BUILDROOT/usr/{lib}/python{x_y}/site-packages:BUILDROOT/usr/lib/python{x_y}/site-packages}}" + PYTHONDONTWRITEBYTECODE=1 + {__python3 or '/usr/bin/python3'} -c "import {imports}" + ) + """) + assert lines == expected.splitlines()