Compare commits

..

11 Commits
rawhide ... f35

Author SHA1 Message Date
Charalampos Stratakis b7bcd2829e Disable certain rpminspect inspections not relevant to this package 2022-07-20 15:09:05 +00:00
Miro Hrončok d83a32823c Define and use %{_py3_shebang_s} in the shebang macros for easier opt-out
This is in-line with https://fedoraproject.org/wiki/Changes/PythonSafePath#Opting_out

Backported from https://src.fedoraproject.org/rpms/python-rpm-macros/pull-request/141
2022-07-19 16:59:49 +02:00
Miro Hrončok bb20c6908e Define %python3_cache_tag / %python_cache_tag, e.g. cpython-311
When reviewing https://src.fedoraproject.org/rpms/pyproject-rpm-macros/pull-request/291
we have discovered that there is no macronized way to get this part of some paths
and that packagers need to hardcode it as cpython-%{python3_version_nodots}.

This way, we have a standardized macro packagers (and other macros) can use.
2022-07-19 13:19:37 +02:00
Miro Hrončok cb6359bbdd Set $RPM_BUILD_ROOT in %{python3_...} macros, for alternate sysconfig install scheme
Our Pythons currently patches distutils to install packages to
/usr/lib(64)/pythonX.Y/site-packages when the $RPM_BUILD_ROOT environment
variable is set (and to /usr/local/lib(64)/pythonX.Y/site-packages otherwise).
With the deprecation of distutils [1] we want to change the patch to create
and use a different sysconfig install scheme [2].

However, we have realized that macros defined as %(%{__python3} ...) don't
"see" the environment variables set by rpmbuild because they are expanded earlier
and hence e.g. %{python3_sitelib} evaluates to
/usr/local/lib/python3.X/site-packages -- which is not desired.
To be able to reliably detect an RPM build environment by checking
the presence of the $RPM_BUILD_ROOT environment variable,
we manually set it in the macro definitions.

Since %{buildroot} in not fully populated
(e.g. it can expand literally to
/home/anna/rpmbuild/BUILDROOT/%{NAME}-%{VERSION}-%{RELEASE}.x86_64),
we don't use it here.
The variable simply needs to present in the environment.

See also the analysis of the build failures when this is not done [3].

[1] https://www.python.org/dev/peps/pep-0632/
[2] https://bugs.python.org/issue43976
[3] https://src.fedoraproject.org/rpms/python3.10/pull-request/63#comment-79042

------------------------------------------------------------------------------

Note about the backport: This is not required with the default %__python3 value,
but it is required when %__python3 is redefined to /usr/bin/python3.11 (or newer).
2022-02-07 11:35:11 +01:00
Miro Hrončok f0c6736d3b Move import_all_modules out of python-srpm-macros
There's no need for it in the default buildroot.
2021-11-03 07:53:54 +01:00
Miro Hrončok ff161e1059 %py(3)_check_import: Process .pth files in site(arch|lib)
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=2018551
2021-11-03 07:53:54 +01:00
Karolina Surma f836bce1c4 Fix %%py_shebang_flags handling within %%py_check_import
%%py{3}_check_import now respects the custom setting of %%py{3}_shebang_flags
and invokes Python with the respective values.
If %%py{3}_shebang_flags is undefined or set to no value,
there no flags are passed to Python on invoke.
Resolves: rhbz#2018615
2021-11-03 07:53:54 +01:00
Karolina Surma a3ce038993 Allow multiline arguments processing for %%py3_check_import
Fixes the regression introduced with the macro reimplementation.
Resolves: rhbz#2018809
2021-11-03 07:53:47 +01:00
Karolina Surma f6c1d3b3d1 Fix changelog entries 2021-10-27 16:01:47 +02:00
Karolina Surma 9ce6cb80da Add new options for %%py{3}_check_import: -f, -t, -e
-f: optionally read a file with module names to test
-t: bool flag - if set, filter only top-level modules
-e: optionally exclude module names matching the given glob (Unix
shell-style wildcards)
Importing all modules may cause bogus failures in some cases,
eg. when the imported code assumes there is an existing graphical window.
Such behaviour may be by design, hence for automatic processing it's
more convinient to - in some cases - check only for top-level modules
or filter out the troublemakers.
2021-10-27 16:01:42 +02:00
Tomas Orsava 68618631a9 Define a new macros %python_wheel_dir and %python_wheel_pkg_prefix 2021-10-20 13:58:51 +02:00
11 changed files with 164 additions and 434 deletions

View File

@ -15,6 +15,4 @@ if [ ! -x /usr/bin/marshalparser ]; then
exit 1
fi
# Set pipefail so if $path_to_fix does not exist, the build fails
set -o pipefail
find "$path_to_fix" -type f -name "*.pyc" | xargs /usr/bin/marshalparser --fix --overwrite

View File

@ -16,62 +16,74 @@ if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then
exit 0
fi
# Figure out how deep we need to descend. We could pick an insanely high
# number and hope it's enough, but somewhere, somebody's sure to run into it.
depth=`(find "$RPM_BUILD_ROOT" -type f -name "*.py" -print0 ; echo /) | \
xargs -0 -n 1 dirname | sed 's,[^/],,g' | sort -u | tail -n 1 | wc -c`
if [ -z "$depth" -o "$depth" -le "1" ]; then
exit 0
fi
# This function now implements Python byte-compilation in three different ways:
# Python >= 3.4 and < 3.9 uses a new module compileall2 - https://github.com/fedora-python/compileall2
# In Python >= 3.9, compileall2 was merged back to standard library (compileall) so we can use it directly again.
# Python < 3.4 (inc. Python 2) uses compileall module from stdlib with some hacks
# When we drop support for Python 2, we'd be able to use all compileall2 features like:
# - -s and -p options to manipulate with a path baked into pyc files instead of $real_libdir
# - -o 0 -o 1 to produce multiple files in one run - each with a different optimization level - instead of $options
# - removed useless $depth - both compileall and compileall2 are limited by sys.getrecursionlimit()
# These changes will make this script much simpler
# In Python >= 3.9, compileall2 was merged back to standard library (compileall) so we can use it directly again.
function python_bytecompile()
{
local options=$1
local python_binary=$2
local exclude=$3
local python_libdir="$4"
local depth=$5 # Not used for Python >= 3.4
local real_libdir=$6 # Not used for Python >= 3.4
python_version=$($python_binary -c "import sys; sys.stdout.write('{0.major}{0.minor}'.format(sys.version_info))")
python_version=$($python_binary -c "import sys; sys.stdout.write('{0.major}{0.minor}'.format(sys.version_info))")
#
# Python 3.4 and higher
#
if [ "$python_version" -ge 34 ]; then
#
# Python 3.9 and higher
#
if [ "$python_version" -ge 39 ]; then
# We compile all opt levels in one go: only when $options is empty.
if [ -n "$options" ]; then
return
fi
[ ! -z $exclude ] && exclude="-x '$exclude'"
# -q disables verbose output
# -f forces the process to overwrite existing compiled files
# -x excludes paths defined by regex
# -e excludes symbolic links pointing outside the build root
# -x and -e together implements the same functionality as the Filter class below
# -s strips $RPM_BUILD_ROOT from the path
# -p prepends the leading slash to the path to make it absolute
$python_binary -B $options -m compileall -q -f $exclude -s "$RPM_BUILD_ROOT" -p / -e "$RPM_BUILD_ROOT" "$python_libdir"
if [ "$python_version" -ge 39 ]; then
# For Pyhon 3.9+, use the standard library
compileall_module=compileall
else
# For older Pythons, use compileall2
compileall_module=compileall2
fi
#
# Python 3.4 and higher
#
elif [ "$python_version" -ge 34 ]; then
[ ! -z $exclude ] && exclude="-x '$exclude'"
# PYTHONPATH is needed for compileall2, but doesn't hurt for the stdlib
# -o 0 -o 1 are the optimization levels
# -q disables verbose output
# -f forces the process to overwrite existing compiled files
# -x excludes paths defined by regex
# -e excludes symbolic links pointing outside the build root
# -x and -e together implements the same functionality as the Filter class below
# -s strips $RPM_BUILD_ROOT from the path
# -p prepends the leading slash to the path to make it absolute
PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary -B -m $compileall_module -o 0 -o 1 -q -f $exclude -s "$RPM_BUILD_ROOT" -p / --hardlink-dupes -e "$RPM_BUILD_ROOT" "$python_libdir"
else
[ ! -z $exclude ] && exclude="-x '$exclude'"
# /usr/lib/rpm/redhat/ contains compileall2 Python module
# -q disables verbose output
# -f forces the process to overwrite existing compiled files
# -x excludes paths defined by regex
# -e excludes symbolic links pointing outside the build root
# -x and -e together implements the same functionality as the Filter class below
# -s strips $RPM_BUILD_ROOT from the path
# -p prepends the leading slash to the path to make it absolute
PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary -B $options -m compileall2 -q -f $exclude -s "$RPM_BUILD_ROOT" -p / -e "$RPM_BUILD_ROOT" "$python_libdir"
else
#
# Python 3.3 and lower (incl. Python 2)
#
local real_libdir=${python_libdir/$RPM_BUILD_ROOT/}
cat << EOF | $python_binary $options
import compileall, sys, os, re
python_libdir = "$python_libdir"
depth = sys.getrecursionlimit()
depth = $depth
real_libdir = "$real_libdir"
build_root = "$RPM_BUILD_ROOT"
exclude = r"$exclude"
@ -104,25 +116,24 @@ fi
# Disable Python hash seed randomization
# This should help with byte-compilation reproducibility: https://bugzilla.redhat.com/show_bug.cgi?id=1686078
# Python 3.11+ no longer needs this: https://github.com/python/cpython/pull/27926 (but we support older Pythons as well)
export PYTHONHASHSEED=0
shopt -s nullglob
find "$RPM_BUILD_ROOT" -type d -print0|grep -z -E "/(usr|app)/lib(64)?/python[0-9]\.[0-9]+$" | while read -d "" python_libdir;
do
python_binary=$(basename "$python_libdir")
real_libdir=${python_libdir/$RPM_BUILD_ROOT/}
echo "Bytecompiling .py files below $python_libdir using $python_binary"
# Generate normal (.pyc) byte-compiled files.
python_bytecompile "" "$python_binary" "" "$python_libdir"
python_bytecompile "" "$python_binary" "" "$python_libdir" "$depth" "$real_libdir"
if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then
# One or more of the files had a syntax error
exit 1
fi
# Generate optimized (.pyo) byte-compiled files.
# N.B. For Python 3.4+, this call does nothing
python_bytecompile "-O" "$python_binary" "" "$python_libdir"
python_bytecompile "-O" "$python_binary" "" "$python_libdir" "$depth" "$real_libdir"
if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then
# One or more of the files had a syntax error
exit 1

View File

@ -14,7 +14,6 @@
# Setting PYTHONHASHSEED=0 disables Python hash seed randomization
# This should help with byte-compilation reproducibility: https://bugzilla.redhat.com/show_bug.cgi?id=1686078
# Python 3.11+ no longer needs this: https://github.com/python/cpython/pull/27926 (but we support older Pythons as well)
%py_byte_compile()\
py2_byte_compile () {\
@ -29,13 +28,13 @@ py2_byte_compile () {\
py3_byte_compile () {\
python_binary="env PYTHONHASHSEED=0 %1"\
bytecode_compilation_path="%2"\
PYTHONPATH="%{_rpmconfigdir}/redhat" $python_binary -s -B -m compileall2 -o 0 -o 1 -s $RPM_BUILD_ROOT -p / --hardlink-dupes $bytecode_compilation_path \
PYTHONPATH="%{_rpmconfigdir}/redhat" $python_binary -s -B -m compileall2 -o 0 -o 1 -s $RPM_BUILD_ROOT -p / $bytecode_compilation_path \
}\
\
py39_byte_compile () {\
python_binary="env PYTHONHASHSEED=0 %1"\
bytecode_compilation_path="%2"\
$python_binary -s -B -m compileall -o 0 -o 1 -s $RPM_BUILD_ROOT -p / --hardlink-dupes $bytecode_compilation_path \
$python_binary -s -B -m compileall -o 0 -o 1 -s $RPM_BUILD_ROOT -p / $bytecode_compilation_path \
}\
\
# Path to intepreter should not contain any arguments \

View File

@ -2,9 +2,8 @@
# __python is defined to error by default in the srpm macros
# nb: $RPM_BUILD_ROOT is not set when the macros are expanded (at spec parse time)
# so we set it manually (to empty string), making our Python prefer the correct install scheme location
# platbase/base is explicitly set to %%{_prefix} to support custom values, such as /app for flatpaks
%python_sitelib %(RPM_BUILD_ROOT= %{__python} -Esc "import sysconfig; print(sysconfig.get_path('purelib', vars={'platbase': '%{_prefix}', 'base': '%{_prefix}'}))")
%python_sitearch %(RPM_BUILD_ROOT= %{__python} -Esc "import sysconfig; print(sysconfig.get_path('platlib', vars={'platbase': '%{_prefix}', 'base': '%{_prefix}'}))")
%python_sitelib %(RPM_BUILD_ROOT= %{__python} -Esc "import sysconfig; print(sysconfig.get_path('purelib'))")
%python_sitearch %(RPM_BUILD_ROOT= %{__python} -Esc "import sysconfig; print(sysconfig.get_path('platlib'))")
%python_version %(RPM_BUILD_ROOT= %{__python} -Esc "import sys; sys.stdout.write('{0.major}.{0.minor}'.format(sys.version_info))")
%python_version_nodots %(RPM_BUILD_ROOT= %{__python} -Esc "import sys; sys.stdout.write('{0.major}{0.minor}'.format(sys.version_info))")
%python_platform %(RPM_BUILD_ROOT= %{__python} -Esc "import sysconfig; print(sysconfig.get_platform())")
@ -14,8 +13,7 @@
%py_setup setup.py
%_py_shebang_s s
%_py_shebang_P %(RPM_BUILD_ROOT= %{__python} -Esc "import sys; print('P' if hasattr(sys.flags, 'safe_path') else '')")
%py_shbang_opts -%{?_py_shebang_s}%{?_py_shebang_P}
%py_shbang_opts -%{?_py_shebang_s}
%py_shbang_opts_nodash %(opts=%{py_shbang_opts}; echo ${opts#-})
%py_shebang_flags %(opts=%{py_shbang_opts}; echo ${opts#-})
%py_shebang_fix %{expand:\\\
@ -51,7 +49,7 @@
%py_install() %{expand:\\\
CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}"\\\
%{__python} %{py_setup} %{?py_setup_args} install -O1 --skip-build --root %{buildroot} --prefix %{_prefix} %{?*}
%{__python} %{py_setup} %{?py_setup_args} install -O1 --skip-build --root %{buildroot} %{?*}
rm -rfv %{buildroot}%{_bindir}/__pycache__
}
@ -62,7 +60,7 @@
}
%py_install_wheel() %{expand:\\\
%{__python} -m pip install -I dist/%{1} --root %{buildroot} --prefix %{_prefix} --no-deps --no-index --no-warn-script-location
%{__python} -m pip install -I dist/%{1} --root %{buildroot} --no-deps --no-index --no-warn-script-location
rm -rfv %{buildroot}%{_bindir}/__pycache__
for distinfo in %{buildroot}%{python_sitelib}/*.dist-info %{buildroot}%{python_sitearch}/*.dist-info; do
if [ -f ${distinfo}/direct_url.json ]; then

View File

@ -1,3 +1,22 @@
# Define the Python interpreter paths in the SRPM macros so that
# - they can be used in Build/Requires
# - they can be used in non-Python packages where requiring pythonX-devel would
# be an overkill
# use the underscored macros to redefine the behavior of %%python3_version etc.
%__python2 /usr/bin/python2
%__python3 /usr/bin/python3
# use the non-underscored macros to refer to Python in spec, etc.
%python2 %__python2
%python3 %__python3
# See https://fedoraproject.org/wiki/Changes/PythonMacroError
%__python %{error:attempt to use unversioned python, define %%__python to %{__python2} or %{__python3} explicitly}
# Users can use %%python only if they redefined %%__python (e.g. to %%__python3)
%python %__python
# There are multiple Python 3 versions packaged, but only one can be the "main" version
# That means that it owns the "python3" namespace:
# - python3 package name
@ -17,7 +36,7 @@
# There are two macros:
#
# This always contains the major.minor version (with dots), default for %%python3_version.
%__default_python3_version 3.11
%__default_python3_version 3.10
#
# The pkgname version that determines the alternative provide name (e.g. python3.9-foo),
# set to the same as above, but historically hasn't included the dot.
@ -30,25 +49,6 @@
# Alternatively, it can be overridden in spec (e.g. to "3.8") when building for alternate Python stacks.
%python3_pkgversion 3
# Define the Python interpreter paths in the SRPM macros so that
# - they can be used in Build/Requires
# - they can be used in non-Python packages where requiring pythonX-devel would
# be an overkill
# use the underscored macros to redefine the behavior of %%python3_version etc.
%__python2 /usr/bin/python2
%__python3 /usr/bin/python%{python3_pkgversion}
# use the non-underscored macros to refer to Python in spec, etc.
%python2 %__python2
%python3 %__python3
# See https://fedoraproject.org/wiki/Changes/PythonMacroError
%__python %{error:attempt to use unversioned python, define %%__python to %{__python2} or %{__python3} explicitly}
# Users can use %%python only if they redefined %%__python (e.g. to %%__python3)
%python %__python
# Define where Python wheels will be stored and the prefix of -wheel packages
# - In Fedora we want wheel subpackages named e.g. `python-pip-wheel` that
# install packages into `/usr/share/python-wheels`. Both names are not
@ -191,7 +191,6 @@
%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}')
@ -205,21 +204,6 @@
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 python3.9-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:

View File

@ -1,8 +1,7 @@
# nb: $RPM_BUILD_ROOT is not set when the macros are expanded (at spec parse time)
# so we set it manually (to empty string), making our Python prefer the correct install scheme location
# platbase/base is explicitly set to %%{_prefix} to support custom values, such as /app for flatpaks
%python3_sitelib %(RPM_BUILD_ROOT= %{__python3} -Ic "import sysconfig; print(sysconfig.get_path('purelib', vars={'platbase': '%{_prefix}', 'base': '%{_prefix}'}))")
%python3_sitearch %(RPM_BUILD_ROOT= %{__python3} -Ic "import sysconfig; print(sysconfig.get_path('platlib', vars={'platbase': '%{_prefix}', 'base': '%{_prefix}'}))")
%python3_sitelib %(RPM_BUILD_ROOT= %{__python3} -Ic "import sysconfig; print(sysconfig.get_path('purelib'))")
%python3_sitearch %(RPM_BUILD_ROOT= %{__python3} -Ic "import sysconfig; print(sysconfig.get_path('platlib'))")
%python3_version %(RPM_BUILD_ROOT= %{__python3} -Ic "import sys; sys.stdout.write('{0.major}.{0.minor}'.format(sys.version_info))")
%python3_version_nodots %(RPM_BUILD_ROOT= %{__python3} -Ic "import sys; sys.stdout.write('{0.major}{0.minor}'.format(sys.version_info))")
%python3_platform %(RPM_BUILD_ROOT= %{__python3} -Ic "import sysconfig; print(sysconfig.get_platform())")
@ -12,8 +11,7 @@
%py3dir %{_builddir}/python3-%{name}-%{version}-%{release}
%_py3_shebang_s s
%_py3_shebang_P %(RPM_BUILD_ROOT= %{__python3} -Ic "import sys; print('P' if hasattr(sys.flags, 'safe_path') else '')")
%py3_shbang_opts -%{?_py3_shebang_s}%{?_py3_shebang_P}
%py3_shbang_opts -%{?_py3_shebang_s}
%py3_shbang_opts_nodash %(opts=%{py3_shbang_opts}; echo ${opts#-})
%py3_shebang_flags %(opts=%{py3_shbang_opts}; echo ${opts#-})
%py3_shebang_fix %{expand:\\\
@ -49,7 +47,7 @@
%py3_install() %{expand:\\\
CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}"\\\
%{__python3} %{py_setup} %{?py_setup_args} install -O1 --skip-build --root %{buildroot} --prefix %{_prefix} %{?*}
%{__python3} %{py_setup} %{?py_setup_args} install -O1 --skip-build --root %{buildroot} %{?*}
rm -rfv %{buildroot}%{_bindir}/__pycache__
}
@ -60,7 +58,7 @@
}
%py3_install_wheel() %{expand:\\\
%{__python3} -m pip install -I dist/%{1} --root %{buildroot} --prefix %{_prefix} --no-deps --no-index --no-warn-script-location
%{__python3} -m pip install -I dist/%{1} --root %{buildroot} --no-deps --no-index --no-warn-script-location
rm -rfv %{buildroot}%{_bindir}/__pycache__
for distinfo in %{buildroot}%{python3_sitelib}/*.dist-info %{buildroot}%{python3_sitearch}/*.dist-info; do
if [ -f ${distinfo}/direct_url.json ]; then

View File

@ -49,7 +49,8 @@ elseif posix.stat('macros.python-srpm') then
end
}
Version: %{__default_python3_version}
Release: 4%{?dist}
Release: 12%{?dist}
BuildArch: noarch
@ -58,12 +59,6 @@ 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.
@ -130,7 +125,7 @@ install -m 755 brp-* %{buildroot}%{_rpmconfigdir}/redhat/
%check
# no macros in comments
grep -E '^#[^%%]*%%[^%%]' %{buildroot}%{rpmmacrodir}/macros.* && exit 1 || true
! grep -E '^#[^%%]*%%[^%%]' %{buildroot}%{rpmmacrodir}/macros.*
%files
@ -151,40 +146,15 @@ grep -E '^#[^%%]*%%[^%%]' %{buildroot}%{rpmmacrodir}/macros.* && exit 1 || true
%changelog
* Fri Jul 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 3.10-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Tue Jul 19 2022 Miro Hrončok <mhroncok@redhat.com> - 3.11-3
- Add "P" to %%py3_shbang_opts, %%py3_shbang_opts_nodash, %%py3_shebang_flags
and to %%py_shbang_opts, %%py_shbang_opts_nodash, %%py_shebang_flags
- https://fedoraproject.org/wiki/Changes/PythonSafePath
* Mon Jun 20 2022 Miro Hrončok <mhroncok@redhat.com> - 3.11-2
* Tue Jul 19 2022 Miro Hrončok <mhroncok@redhat.com> - 3.10-12
- Define %%python3_cache_tag / %%python_cache_tag, e.g. cpython-311
- Define and use %%{_py3_shebang_s} in the shebang macros for easier opt-out
* Mon Jun 13 2022 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.11-1
- Update main Python to Python 3.11
- https://fedoraproject.org/wiki/Changes/Python3.11
* Mon Feb 07 2022 Miro Hrončok <mhroncok@redhat.com> - 3.10-11
- Set $RPM_BUILD_ROOT in %%{python3_...} macros
to allow selecting alternate sysconfig install scheme based on that variable
* Thu May 26 2022 Owen Taylor <otaylor@redhat.com> - 3.10-18
- Support installing to %%{_prefix} other than /usr
* Tue Feb 08 2022 Tomas Orsava <torsava@redhat.com> - 3.10-17
- %%py_provides: Do not generate Obsoletes for names containing parentheses
* Mon Jan 31 2022 Miro Hrončok <mhroncok@redhat.com> - 3.10-16
- Explicitly opt-out from Python name-based provides and obsoletes generators
* Tue Dec 21 2021 Tomas Orsava <torsava@redhat.com> - 3.10-15
- 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
* Wed Dec 08 2021 Miro Hrončok <mhroncok@redhat.com> - 3.10-14
- 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.10-13
* Mon Nov 01 2021 Karolina Surma <ksurma@redhat.com> - 3.10-10
- Fix multiline arguments processing for %%py_check_import
Resolves: rhbz#2018809
- Fix %%py_shebang_flags handling within %%py_check_import
@ -193,28 +163,15 @@ Resolves: rhbz#2018615
Resolves: rhbz#2018551
- Move import_all_modules.py from python-srpm-macros to python-rpm-macros
* Mon Oct 25 2021 Karolina Surma <ksurma@redhat.com> - 3.10-12
* Mon Oct 25 2021 Karolina Surma <ksurma@redhat.com> - 3.10-9
- Introduce -f (read from file) option to %%py{3}_check_import
- Introduce -t (filter top-level modules) option to %%py{3}_check_import
- Introduce -e (exclude module globs) option to %%py{3}_check_import
* Wed Oct 20 2021 Tomas Orsava <torsava@redhat.com> - 3.10-11
* Wed Sep 29 2021 Tomas Orsava <torsava@redhat.com> - 3.10-8
- Define a new macros %%python_wheel_dir and %%python_wheel_pkg_prefix
* Tue Oct 12 2021 Lumír Balhar <lbalhar@redhat.com> - 3.10-10
- Non-existing path in py_reproducible_pyc_path causes build to fail
Resolves: rhbz#2011056
* Thu Sep 09 2021 Miro Hrončok <mhroncok@redhat.com> - 3.10-9
- Set $RPM_BUILD_ROOT in %%{python3_...} macros
to allow selecting alternate sysconfig install scheme based on that variable
* Thu Sep 09 2021 Petr Viktorin <pviktori@redhat.com> - 3.10-8
- Use --hardlink-dupes in %%py_byte_compile and brp-python-bytecompile
(for Python 3)
- Resolves: rhbz#1977895
* Fri Jul 23 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.9-7
* Fri Jul 23 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.10-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Wed Jul 07 2021 Miro Hrončok <mhroncok@redhat.com> - 3.10-6

View File

@ -2,25 +2,22 @@
-- Determine alternate names provided from the given name.
-- Used in pythonname provides generator, python_provide and py_provides.
-- If only_3_to_3_X is false/nil/unused there are 2 rules:
-- 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 -> python3.X-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, only_3_to_3_X)
local function python_altnames(name)
local xy = rpm.expand('%{__default_python3_pkgversion}')
local altnames = {}
local replaced
-- NB: dash needs to be escaped!
if name:match('^python3%-') then
local prefixes = only_3_to_3_X and {} or {'python-'}
for i, prefix in ipairs({'python' .. xy .. '-', table.unpack(prefixes)}) do
for i, prefix in ipairs({'python-', 'python' .. xy .. '-'}) do
replaced = name:gsub('^python3%-', prefix)
table.insert(altnames, replaced)
end
elseif name:match('^python' .. xy .. '%-') and not only_3_to_3_X then
elseif name:match('^python' .. xy .. '%-') then
for i, prefix in ipairs({'python-', 'python3-'}) do
replaced = name:gsub('^python' .. xy .. '%-', prefix)
table.insert(altnames, replaced)
@ -30,72 +27,42 @@ local function python_altnames(name, only_3_to_3_X)
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)
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
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
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)
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")
-- 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
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,
}

View File

@ -1,18 +1,11 @@
%global basedir /opt/test/byte_compilation
# We have 3 different ways of bytecompiling: for 3.9+, 3.4-3.8, and 2.7
# Test with a representative of each.
%global python36_sitelib /usr/lib/python3.6/site-packages
%global python27_sitelib /usr/lib/python2.7/site-packages
Name: pythontest
Version: 0
Release: 0
Summary: ...
License: MIT
BuildRequires: python3-devel
BuildRequires: python3.6
BuildRequires: python2.7
%description
...
@ -26,48 +19,15 @@ echo "print()" > %{buildroot}%{basedir}/directory/to/test/recursion/file_in_dir.
%py_byte_compile %{python3} %{buildroot}%{basedir}/file.py
%py_byte_compile %{python3} %{buildroot}%{basedir}/directory
# Files in sitelib are compiled automatically by brp-python-bytecompile
mkdir -p %{buildroot}%{python3_sitelib}/directory/
echo "print()" > %{buildroot}%{python3_sitelib}/directory/file.py
mkdir -p %{buildroot}%{python36_sitelib}/directory/
echo "print()" > %{buildroot}%{python36_sitelib}/directory/file.py
mkdir -p %{buildroot}%{python27_sitelib}/directory/
echo "print()" > %{buildroot}%{python27_sitelib}/directory/file.py
%check
LOCATIONS="
%{buildroot}%{basedir}
%{buildroot}%{python3_sitelib}/directory/
%{buildroot}%{python36_sitelib}/directory/
%{buildroot}%{python27_sitelib}/directory/
"
# Count .py and .pyc files
PY=$(find $LOCATIONS -name "*.py" | wc -l)
PYC=$(find $LOCATIONS -name "*.py[co]" | wc -l)
# We should have 5 .py files (3 for python3, one each for 3.6 & 2.7)
test $PY -eq 5
PY=$(find %{buildroot}%{basedir} -name "*.py" | wc -l)
PYC=$(find %{buildroot}%{basedir} -name "*.pyc" | wc -l)
# Every .py file should be byte-compiled to two .pyc files (optimization level 0 and 1)
# so we should have two times more .pyc files than .py files
test $(expr $PY \* 2) -eq $PYC
# In this case the .pyc files should be identical across omtimization levels
# (they don't use docstrings and assert staements)
# So they should be hardlinked; the number of distinct inodes should match the
# number of source files. (Or be smaller, if the dupe detection is done
# across all files.)
INODES=$(stat --format %i $(find $LOCATIONS -name "*.py[co]") | sort -u | wc -l)
test $PY -ge $INODES
%files
%pycached %{basedir}/file.py
%pycached %{basedir}/directory/to/test/recursion/file_in_dir.py
%pycached %{python3_sitelib}/directory/file.py
%pycached %{python36_sitelib}/directory/file.py
%{python27_sitelib}/directory/file.py*

View File

@ -51,45 +51,6 @@ def lib():
return lib_eval
def get_alt_x_y():
"""
Some tests require alternate Python version to be installed.
In order to allow any Python version (or none at all),
this function/fixture exists.
You can control the behavior by setting the $ALTERNATE_PYTHON_VERSION
environment variable to X.Y (e.g. 3.6) or SKIP.
The environment variable must be set.
"""
env_name = "ALTERNATE_PYTHON_VERSION"
alternate_python_version = os.getenv(env_name, "")
if alternate_python_version.upper() == "SKIP":
pytest.skip(f"${env_name} set to SKIP")
if not alternate_python_version:
raise ValueError(f"${env_name} must be set, "
f"set it to SKIP if you want to skip tests that "
f"require alternate Python version.")
if not re.match(r"^\d+\.\d+$", alternate_python_version):
raise ValueError(f"${env_name} must be X.Y")
return alternate_python_version
def get_alt_xy():
"""
Same as get_alt_x_y() but without a dot
"""
return get_alt_x_y().replace(".", "")
# We don't use decorators, to be able to call the functions directly
alt_x_y = pytest.fixture(scope="session")(get_alt_x_y)
alt_xy = pytest.fixture(scope="session")(get_alt_xy)
# https://fedoraproject.org/wiki/Changes/PythonSafePath
def safe_path_flag(x_y):
return 'P' if tuple(int(i) for i in x_y.split('.')) >= (3, 11) else ''
def shell_stdout(script):
return subprocess.check_output(script,
env={**os.environ, 'LANG': 'C.utf-8'},
@ -97,17 +58,6 @@ 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'),
@ -132,8 +82,8 @@ def test_py3_dist():
assert rpm_eval(f'%py3_dist Aha[Boom] a') == ['python3dist(aha[boom]) python3dist(a)']
def test_py3_dist_with_python3_pkgversion_redefined(alt_x_y):
assert rpm_eval(f'%py3_dist Aha[Boom] a', python3_pkgversion=alt_x_y) == [f'python{alt_x_y}dist(aha[boom]) python{alt_x_y}dist(a)']
def test_py3_dist_with_python3_pkgversion_redefined():
assert rpm_eval(f'%py3_dist Aha[Boom] a', python3_pkgversion="3.6") == ['python3.6dist(aha[boom]) python3.6dist(a)']
def test_python_provide_python():
@ -182,102 +132,67 @@ def test_python_provide_doubleuse():
assert len(set(lines)) == 3
@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)
def test_py_provides_python():
lines = rpm_eval('%py_provides python-foo', version='6', release='1.fc66')
assert 'Provides: python-foo = 6-1.fc66' in lines
assert len(lines) == 1
@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)
def test_py_provides_whatever():
lines = rpm_eval('%py_provides whatever', version='6', release='1.fc66')
assert 'Provides: whatever = 6-1.fc66' in lines
assert len(lines) == 1
@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)
def test_py_provides_python3():
lines = rpm_eval('%py_provides python3-foo', version='6', release='1.fc66')
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{X_Y}-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
@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)
def test_py_provides_python3_epoched():
lines = rpm_eval('%py_provides python3-foo', epoch='1', version='6', release='1.fc66')
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
if rhel:
assert f'Obsoletes: python{X_Y}-foo < 1:6-1.fc66' in lines
assert len(lines) == 4
else:
assert len(lines) == 3
assert len(lines) == 3
@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)
def test_py_provides_python3X():
lines = rpm_eval(f'%py_provides python{X_Y}-foo', version='6', release='1.fc66')
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
@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)
def test_py_provides_python3X_epoched():
lines = rpm_eval(f'%py_provides python{X_Y}-foo', epoch='1', version='6', release='1.fc66')
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
@pytest.mark.parametrize('rhel', [None, 2])
def test_py_provides_doubleuse(rhel):
def test_py_provides_doubleuse():
lines = rpm_eval('%{py_provides python3-foo}%{py_provides python3-foo}',
version='6', release='1.fc66', rhel=rhel)
version='6', release='1.fc66')
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{X_Y}-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
assert len(lines) == 6
assert len(set(lines)) == 3
@pytest.mark.parametrize('rhel', [None, 2])
def test_py_provides_with_evr(rhel):
def test_py_provides_with_evr():
lines = rpm_eval('%py_provides python3-foo 123',
version='6', release='1.fc66', rhel=rhel)
version='6', release='1.fc66')
assert 'Provides: python3-foo = 123' in lines
assert 'Provides: python-foo = 123' in lines
assert f'Provides: python{X_Y}-foo = 123' in lines
if rhel:
assert f'Obsoletes: python{X_Y}-foo < 123' in lines
assert len(lines) == 4
else:
assert len(lines) == 3
assert len(lines) == 3
def test_python_wheel_pkg_prefix():
@ -311,12 +226,8 @@ def test_pytest_different_command():
def test_pytest_command_suffix():
lines = rpm_eval('%pytest -v')
assert '/usr/bin/pytest -v' in lines[-1]
# this test does not require alternate Pythons to be installed
@pytest.mark.parametrize('version', ['3.6', '3.7', '3.12'])
def test_pytest_command_suffix_alternate_pkgversion(version):
lines = rpm_eval('%pytest -v', python3_pkgversion=version, python3_version=version)
assert f'/usr/bin/pytest-{version} -v' in lines[-1]
lines = rpm_eval('%pytest -v', python3_pkgversion="3.6", python3_version="3.6")
assert '/usr/bin/pytest-3.6 -v' in lines[-1]
def test_pytest_undefined_addopts_are_not_set():
@ -414,7 +325,7 @@ def test_py3_shebang_fix():
def test_py3_shebang_fix_default_shebang_flags():
lines = rpm_eval('%py3_shebang_fix arg1 arg2')
lines[-1] = 'echo $shebang_flags'
assert shell_stdout('\n'.join(lines)) == f'-kas{safe_path_flag(X_Y)}'
assert shell_stdout('\n'.join(lines)) == '-kas'
def test_py3_shebang_fix_custom_shebang_flags():
@ -427,24 +338,6 @@ def test_py3_shebang_fix_custom_shebang_flags():
def test_py3_shebang_fix_undefined_py3_shebang_s(_py3_shebang_s):
lines = rpm_eval('%py3_shebang_fix arg1 arg2', _py3_shebang_s=_py3_shebang_s)
lines[-1] = 'echo $shebang_flags'
expected = f'-ka{safe_path_flag(X_Y)}' if safe_path_flag(X_Y) else '-k'
assert shell_stdout('\n'.join(lines)) == expected
@pytest.mark.parametrize('_py3_shebang_P', [None, '%{nil}'])
def test_py3_shebang_fix_undefined_py3_shebang_P(_py3_shebang_P):
lines = rpm_eval('%py3_shebang_fix arg1 arg2', _py3_shebang_P=_py3_shebang_P)
lines[-1] = 'echo $shebang_flags'
assert shell_stdout('\n'.join(lines)) == '-kas'
@pytest.mark.parametrize('_py3_shebang_s', [None, '%{nil}'])
@pytest.mark.parametrize('_py3_shebang_P', [None, '%{nil}'])
def test_py3_shebang_fix_undefined_py3_shebang_sP(_py3_shebang_s, _py3_shebang_P):
lines = rpm_eval('%py3_shebang_fix arg1 arg2',
_py3_shebang_s=_py3_shebang_s,
_py3_shebang_P=_py3_shebang_P)
lines[-1] = 'echo $shebang_flags'
assert shell_stdout('\n'.join(lines)) == '-k'
@ -476,14 +369,11 @@ def test_pycached_in_sitearch(lib):
]
# this test does not require alternate Pythons to be installed
@pytest.mark.parametrize('version', ['3.6', '3.7', '3.12'])
def test_pycached_with_alternate_version(version):
version_nodot = version.replace('.', '')
lines = rpm_eval(f'%pycached /usr/lib/python{version}/site-packages/foo*.py')
def test_pycached_in_36():
lines = rpm_eval('%pycached /usr/lib/python3.6/site-packages/foo*.py')
assert lines == [
f'/usr/lib/python{version}/site-packages/foo*.py',
f'/usr/lib/python{version}/site-packages/__pycache__/foo*.cpython-{version_nodot}{{,.opt-?}}.pyc'
'/usr/lib/python3.6/site-packages/foo*.py',
'/usr/lib/python3.6/site-packages/__pycache__/foo*.cpython-36{,.opt-?}.pyc'
]
@ -720,68 +610,38 @@ def test_cache_tag():
assert rpm_eval("%python3_cache_tag") == [f"cpython-{XY}"]
def test_cache_tag_alternate_python(alt_x_y, alt_xy):
assert rpm_eval("%python_cache_tag", __python=f"/usr/bin/python{alt_x_y}") == [f"cpython-{alt_xy}"]
def test_cache_tag_alternate_python():
assert rpm_eval("%python_cache_tag", __python=f"/usr/bin/python3.6") == [f"cpython-36"]
def test_cache_tag_alternate_python3(alt_x_y, alt_xy):
assert rpm_eval("%python3_cache_tag", __python3=f"/usr/bin/python{alt_x_y}") == [f"cpython-{alt_xy}"]
def test_cache_tag_alternate_python3():
assert rpm_eval("%python3_cache_tag", __python3=f"/usr/bin/python3.6") == [f"cpython-36"]
def test_python_sitelib_value_python3():
def test_python_sitelib_value():
macro = '%python_sitelib'
assert rpm_eval(macro, __python='/usr/bin/python3.6') == [f'/usr/lib/python3.6/site-packages']
assert rpm_eval(macro, __python='%__python3') == [f'/usr/lib/python{X_Y}/site-packages']
def test_python_sitelib_value_alternate_python(alt_x_y):
macro = '%python_sitelib'
assert rpm_eval(macro, __python=f'/usr/bin/python{alt_x_y}') == [f'/usr/lib/python{alt_x_y}/site-packages']
def test_python3_sitelib_value_default():
def test_python3_sitelib_value():
macro = '%python3_sitelib'
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']
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}') ==
rpm_eval(macro, python3_pkgversion=alt_x_y) ==
[f'/usr/lib/python{alt_x_y}/site-packages'])
def test_python3_sitelib_value_alternate_prefix():
macro = '%python3_sitelib'
assert rpm_eval(macro, _prefix='/app') == [f'/app/lib/python{X_Y}/site-packages']
def test_python_sitearch_value_python3(lib):
def test_python_sitearch_value(lib):
macro = '%python_sitearch'
assert rpm_eval(macro, __python='/usr/bin/python3.6') == [f'/usr/{lib}/python3.6/site-packages']
assert rpm_eval(macro, __python='%__python3') == [f'/usr/{lib}/python{X_Y}/site-packages']
def test_python_sitearch_value_alternate_python(lib, alt_x_y):
macro = '%python_sitearch'
assert rpm_eval(macro, __python=f'/usr/bin/python{alt_x_y}') == [f'/usr/{lib}/python{alt_x_y}/site-packages']
def test_python3_sitearch_value_default(lib):
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']
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}') ==
rpm_eval(macro, python3_pkgversion=alt_x_y) ==
[f'/usr/{lib}/python{alt_x_y}/site-packages'])
def test_python3_sitearch_value_alternate_prefix(lib):
macro = '%python3_sitearch'
assert rpm_eval(macro, _prefix='/app') == [f'/app/{lib}/python{X_Y}/site-packages']
@pytest.mark.parametrize(
'args, expected_args',
[
@ -797,20 +657,20 @@ def test_python3_sitearch_value_alternate_prefix(lib):
@pytest.mark.parametrize('__python3',
[None,
f'/usr/bin/python{X_Y}',
'/usr/bin/pythonX.Y'])
'/usr/bin/python3.6'])
def test_py3_check_import(args, expected_args, __python3, lib):
x_y = X_Y
macros = {
'buildroot': 'BUILDROOT',
'_rpmconfigdir': 'RPMCONFIGDIR',
'py3_shebang_flags': 's',
}
if __python3 is not None:
if 'X.Y' in __python3:
__python3 = __python3.replace('X.Y', get_alt_x_y())
macros['__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)
@ -827,7 +687,7 @@ def test_py3_check_import(args, expected_args, __python3, lib):
PYTHONPATH="${{PYTHONPATH:-BUILDROOT/usr/{lib}/python{x_y}/site-packages:BUILDROOT/usr/lib/python{x_y}/site-packages}}"
_PYTHONSITE="BUILDROOT/usr/{lib}/python{x_y}/site-packages:BUILDROOT/usr/lib/python{x_y}/site-packages"
PYTHONDONTWRITEBYTECODE=1
{__python3 or '/usr/bin/python3'} -s{safe_path_flag(x_y)} RPMCONFIGDIR/redhat/import_all_modules.py {expected_args}
{__python3 or '/usr/bin/python3'} -s RPMCONFIGDIR/redhat/import_all_modules.py {expected_args}
""")
assert lines == expected.splitlines()
@ -835,7 +695,6 @@ def test_py3_check_import(args, expected_args, __python3, lib):
@pytest.mark.parametrize(
'shebang_flags_value, expected_shebang_flags',
[
('sP', '-sP'),
('s', '-s'),
('%{nil}', ''),
(None, ''),

View File

@ -15,7 +15,7 @@
tests:
- pytest:
dir: .
run: PYTHONPATH=/usr/lib/rpm/redhat ALTERNATE_PYTHON_VERSION=3.6 pytest -v
run: PYTHONPATH=/usr/lib/rpm/redhat pytest -v
- manual_byte_compilation:
dir: .
run: rpmbuild -ba pythontest.spec
@ -26,5 +26,4 @@
- python3-devel
- python3-pytest
- python3.6
- python2.7