diff --git a/README.md b/README.md index c1ba7be..92a7e65 100644 --- a/README.md +++ b/README.md @@ -269,6 +269,7 @@ If `%pyproject_save_files` is not used, calling `%pyproject_check_import` will f When `%pyproject_save_files` is invoked, it creates a list of all valid and public (i.e. not starting with `_`) importable module names found in the package. +Each top-level module name matches at least one of the globs provided as an argument to `%pyproject_save_files`. This list is then usable by `%pyproject_check_import` which performs an import check for each listed module. When a module fails to import, the build fails. diff --git a/pyproject-rpm-macros.spec b/pyproject-rpm-macros.spec index f35e222..ab1d985 100644 --- a/pyproject-rpm-macros.spec +++ b/pyproject-rpm-macros.spec @@ -127,9 +127,12 @@ export HOSTNAME="rpmbuild" # to speedup tox in network-less mock, see rhbz#1856 %license LICENSE %changelog -* Mon Sep 19 2022 Miro HronĨok - 1.4.0-1 +* Mon Sep 19 2022 Python Maint - 1.4.0-1 - %%pyproject_save_files: Support License-Files installed into the *Root License Directory* from PEP 369 - Fixes: rhbz#2127946 +- %%pyproject_check_import: Import only the modules whose top-level names + match any of the globs provided to %%pyproject_save_files +- Fixes: rhbz#2127958 * Tue Aug 30 2022 Otto Liljalaakso - 1.3.4-1 - Fix typo in internal function name diff --git a/pyproject_save_files.py b/pyproject_save_files.py index 880dd2b..fad28a5 100644 --- a/pyproject_save_files.py +++ b/pyproject_save_files.py @@ -536,6 +536,50 @@ def generate_file_list(paths_dict, module_globs, include_others=False): return sorted(files) +def generate_module_list(paths_dict, module_globs): + """ + This function takes the paths_dict created by the classify_paths() function and + reads the modules names from it. + It filters those whose top-level module names match any of the provided module_globs. + + Returns list with matching qualified module names. + + Examples: + + >>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'foo'}) + ['foo', 'foo.bar'] + + >>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'*foo'}) + ['foo', 'foo.bar'] + + >>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'foo', 'baz'}) + ['baz', 'foo', 'foo.bar'] + + >>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'*'}) + ['baz', 'foo', 'foo.bar'] + + >>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'bar'}) + [] + + Submodules aren't discovered: + + >>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'*bar'}) + [] + """ + + module_names = paths_dict['module_names'] + filtered_module_names = set() + + for glob in module_globs: + for name in module_names: + # Match the top-level part of the qualified name, eg. 'foo.bar.baz' -> 'foo' + top_level_name = name.split('.')[0] + if fnmatch.fnmatchcase(top_level_name, glob): + filtered_module_names.add(name) + + return sorted(filtered_module_names) + + def parse_varargs(varargs): """ Parse varargs from the %pyproject_save_files macro @@ -664,7 +708,7 @@ def pyproject_save_files_and_modules(buildroot, sitelib, sitearch, python_versio parsed_records = load_parsed_record(pyproject_record) final_file_list = [] - all_module_names = set() + final_module_list = [] for record_path, files in parsed_records.items(): metadata = dist_metadata(buildroot, record_path) @@ -675,12 +719,11 @@ def pyproject_save_files_and_modules(buildroot, sitelib, sitearch, python_versio final_file_list.extend( generate_file_list(paths_dict, globs, include_auto) ) - all_module_names.update(paths_dict["module_names"]) + final_module_list.extend( + generate_module_list(paths_dict, globs) + ) - # Sort values, so they are always checked in the same order - all_module_names = sorted(all_module_names) - - return final_file_list, all_module_names + return final_file_list, final_module_list def main(cli_args): diff --git a/pyproject_save_files_test_data.yaml b/pyproject_save_files_test_data.yaml index 44f368b..e9eb427 100644 --- a/pyproject_save_files_test_data.yaml +++ b/pyproject_save_files_test_data.yaml @@ -7755,7 +7755,6 @@ dumped: - ipykernel.tests.utils - ipykernel.trio_runner - ipykernel.zmqshell - - ipykernel_launcher - - zope - zope - - '%dir /usr/lib/python3.7/site-packages/zope' diff --git a/tests/python-ldap.spec b/tests/python-ldap.spec index b333070..db8274a 100644 --- a/tests/python-ldap.spec +++ b/tests/python-ldap.spec @@ -86,6 +86,12 @@ grep -F %{python3_sitearch}/__pycache__/ldif.cpython-%{python3_version_nodots}.p grep -F %{python3_sitearch}/__pycache__/ldif.cpython-%{python3_version_nodots}.opt-1.pyc %{pyproject_files} && exit 1 || true grep -F %{python3_sitearch}/slapdtest %{pyproject_files} && exit 1 || true +# Internal check: Unmatched modules are not supposed to be listed in %%{_pyproject_modules} +grep -F slapdtest %{_pyproject_modules} && exit 1 || true +grep -F ldif %{_pyproject_modules} && exit 1 || true +# Let's check that at least one module is listed in %%{_pyproject_modules} +grep -F ldapurl %{_pyproject_modules} + # Internal check: Top level __pycache__ is never owned grep -E '/site-packages/__pycache__$' %{pyproject_files} && exit 1 || true grep -E '/site-packages/__pycache__/$' %{pyproject_files} && exit 1 || true