%py(3)_check_import: Process .pth files in site(arch|lib)

Fixes https://bugzilla.redhat.com/show_bug.cgi?id=2018551
This commit is contained in:
Miro Hrončok 2021-11-01 15:53:43 +01:00
parent b0302c7fe2
commit 08bc049da9
5 changed files with 51 additions and 0 deletions

View File

@ -3,7 +3,9 @@
import argparse import argparse
import importlib import importlib
import fnmatch import fnmatch
import os
import re import re
import site
import sys import sys
from contextlib import contextmanager from contextlib import contextmanager
@ -135,6 +137,18 @@ def remove_unwanteds_from_sys_path():
sys.path = old_sys_path sys.path = old_sys_path
def addsitedirs_from_environ():
'''Load directories from the _PYTHONSITE environment variable (separated by :)
and load the ones already present in sys.path via site.addsitedir()
to handle .pth files in them.
This is needed to properly import old-style namespace packages with nspkg.pth files.
See https://bugzilla.redhat.com/2018551 for a more detailed rationale.'''
for path in os.getenv('_PYTHONSITE', '').split(':'):
if path in sys.path:
site.addsitedir(path)
def main(argv=None): def main(argv=None):
cli_args = argparser().parse_args(argv) cli_args = argparser().parse_args(argv)
@ -145,6 +159,7 @@ def main(argv=None):
modules = read_modules_from_all_args(cli_args) modules = read_modules_from_all_args(cli_args)
with remove_unwanteds_from_sys_path(): with remove_unwanteds_from_sys_path():
addsitedirs_from_environ()
import_modules(modules) import_modules(modules)

View File

@ -78,6 +78,7 @@
%py_check_import(e:tf:) %{expand:\\\ %py_check_import(e:tf:) %{expand:\\\
PATH="%{buildroot}%{_bindir}:$PATH"\\\ PATH="%{buildroot}%{_bindir}:$PATH"\\\
PYTHONPATH="${PYTHONPATH:-%{buildroot}%{python_sitearch}:%{buildroot}%{python_sitelib}}"\\\ PYTHONPATH="${PYTHONPATH:-%{buildroot}%{python_sitearch}:%{buildroot}%{python_sitelib}}"\\\
_PYTHONSITE="%{buildroot}%{python_sitearch}:%{buildroot}%{python_sitelib}"\\\
PYTHONDONTWRITEBYTECODE=1\\\ PYTHONDONTWRITEBYTECODE=1\\\
%{__python} -%{py_shebang_flags} %{_rpmconfigdir}/redhat/import_all_modules.py %{?**} %{__python} -%{py_shebang_flags} %{_rpmconfigdir}/redhat/import_all_modules.py %{?**}
} }

View File

@ -76,6 +76,7 @@
%py3_check_import(e:tf:) %{expand:\\\ %py3_check_import(e:tf:) %{expand:\\\
PATH="%{buildroot}%{_bindir}:$PATH"\\\ PATH="%{buildroot}%{_bindir}:$PATH"\\\
PYTHONPATH="${PYTHONPATH:-%{buildroot}%{python3_sitearch}:%{buildroot}%{python3_sitelib}}"\\\ PYTHONPATH="${PYTHONPATH:-%{buildroot}%{python3_sitearch}:%{buildroot}%{python3_sitelib}}"\\\
_PYTHONSITE="%{buildroot}%{python3_sitearch}:%{buildroot}%{python3_sitelib}"\\\
PYTHONDONTWRITEBYTECODE=1\\\ PYTHONDONTWRITEBYTECODE=1\\\
%{__python3} -%{py3_shebang_flags} %{_rpmconfigdir}/redhat/import_all_modules.py %{?**} %{__python3} -%{py3_shebang_flags} %{_rpmconfigdir}/redhat/import_all_modules.py %{?**}
} }

View File

@ -710,6 +710,7 @@ def test_py3_check_import(args, __python3, lib):
expected = textwrap.dedent(fr""" expected = textwrap.dedent(fr"""
PATH="BUILDROOT/usr/bin:$PATH" PATH="BUILDROOT/usr/bin:$PATH"
PYTHONPATH="${{PYTHONPATH:-BUILDROOT/usr/{lib}/python{x_y}/site-packages:BUILDROOT/usr/lib/python{x_y}/site-packages}}" 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 PYTHONDONTWRITEBYTECODE=1
{__python3 or '/usr/bin/python3'} -s RPMCONFIGDIR/redhat/import_all_modules.py {args} {__python3 or '/usr/bin/python3'} -s RPMCONFIGDIR/redhat/import_all_modules.py {args}
""") """)

View File

@ -390,3 +390,36 @@ def test_module_list_from_relative_path(tmp_path, monkeypatch):
]) ])
assert 'wave' in sys.modules assert 'wave' in sys.modules
@pytest.mark.parametrize('arch_in_path', [True, False])
def test_pth_files_are_read_from__PYTHONSITE(arch_in_path, tmp_path, monkeypatch, capsys):
sitearch = tmp_path / 'lib64'
sitearch.mkdir()
sitelib = tmp_path / 'lib'
sitelib.mkdir()
for where, word in (sitearch, "ARCH"), (sitelib, "LIB"), (sitelib, "MOD"):
module = where / f'print{word}.py'
module.write_text(f'print("{word}")')
pth_sitearch = sitearch / 'ARCH.pth'
pth_sitearch.write_text('import printARCH\n')
pth_sitelib = sitelib / 'LIB.pth'
pth_sitelib.write_text('import printLIB\n')
if arch_in_path:
sys.path.append(str(sitearch))
sys.path.append(str(sitelib))
# we always add sitearch to _PYTHONSITE
# but when not in sys.path, it should not be processed for .pth files
monkeypatch.setenv('_PYTHONSITE', f'{sitearch}:{sitelib}')
modules_main(['printMOD'])
out, err = capsys.readouterr()
if arch_in_path:
assert out == 'ARCH\nLIB\nMOD\n'
else:
assert out == 'LIB\nMOD\n'