From 098e32d0b9d179992f76e6e6e0cb4c54f852de4d Mon Sep 17 00:00:00 2001 From: Michal Reznik Date: Sun, 7 Apr 2024 18:08:05 +0200 Subject: [PATCH 18/23] Replace deprecated FileFinder.find_module (Python 3.12) The find_module function has been deprecated for a long time and it has been removed in Python3.12. To keep the backward compatibility, we introduce compat.load_module() function that is compatible with Python2.7 -> Python3.12 now. Replacing all previous load of module in code by this function. Similar applies for the pkgutil.get_loader() Co-authored-by: Matej Matuska --- leapp/cli/__init__.py | 7 ++++++- leapp/compat.py | 19 +++++++++++++++++++ leapp/repository/__init__.py | 3 ++- leapp/repository/actor_definition.py | 3 ++- leapp/snactor/__init__.py | 3 ++- res/container-tests/Containerfile.ubi10 | 3 +++ 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/leapp/cli/__init__.py b/leapp/cli/__init__.py index ab16198..59192f9 100644 --- a/leapp/cli/__init__.py +++ b/leapp/cli/__init__.py @@ -1,3 +1,4 @@ +import importlib import os import pkgutil import socket @@ -24,7 +25,11 @@ def _load_commands(base_command): if os.path.isdir(entry_path) and os.path.isfile(os.path.join(entry_path, '__init__.py')): # We found a package - We will import it and get the `register` symbol and check if it is callable. package_name = 'leapp.cli.commands.{}'.format(entry) - package = pkgutil.get_loader(package_name).load_module(package_name) + if sys.version_info < (3, 12): + # get_loader and load_module are deprecated since 3.12 + package = pkgutil.get_loader(package_name).load_module(package_name) # noqa: E501, pylint: disable=deprecated-method + else: + package = importlib.import_module(package_name) register = getattr(package, 'register', None) if callable(register): register(base_command) diff --git a/leapp/compat.py b/leapp/compat.py index 2e340a2..a8c8bdf 100644 --- a/leapp/compat.py +++ b/leapp/compat.py @@ -1,4 +1,5 @@ import gettext # noqa: F401; pylint: disable=unused-import +import importlib import locale import sys @@ -66,3 +67,21 @@ else: :return: Nothing """ raise exc.with_traceback(tb) + + +def load_module(importer, name): + """ + Loads a module using the given importer and module name + + :param importer: A finder implementation (returned by e.g. pkgutils.iter_modules) + :param name: Module name + :return: The loaded module + """ + if sys.version_info < (3, 4): + return importer.find_module(name).load_module(name) + + spec = importer.find_spec(name) + module = importlib.util.module_from_spec(spec) + sys.modules[name] = module + spec.loader.exec_module(module) + return module diff --git a/leapp/repository/__init__.py b/leapp/repository/__init__.py index b47af3e..58b6d16 100644 --- a/leapp/repository/__init__.py +++ b/leapp/repository/__init__.py @@ -3,6 +3,7 @@ import os import pkgutil import sys +from leapp.compat import load_module from leapp.exceptions import RepoItemPathDoesNotExistError, UnsupportedDefinitionKindError from leapp.models import get_models, resolve_model_references import leapp.libraries.common # noqa # pylint: disable=unused-import @@ -166,7 +167,7 @@ class Repository(object): directories = [os.path.join(self._repo_dir, os.path.dirname(module)) for module in modules] prefix = prefix + '.' if not prefix.endswith('.') else prefix for importer, name, ispkg in pkgutil.iter_modules(directories, prefix=prefix): - importer.find_module(name).load_module(name) + load_module(importer, name) def serialize(self): """ diff --git a/leapp/repository/actor_definition.py b/leapp/repository/actor_definition.py index 2b5df1a..0e9cc0a 100644 --- a/leapp/repository/actor_definition.py +++ b/leapp/repository/actor_definition.py @@ -11,6 +11,7 @@ from multiprocessing import Process, Queue, Pipe import leapp.libraries.actor # noqa # pylint: disable=unused-import from leapp.actors import get_actor_metadata, get_actors +from leapp.compat import load_module from leapp.exceptions import (ActorInspectionFailedError, LeappRuntimeError, MultipleActorsError, UnsupportedDefinitionKindError) from leapp.repository.definition import DefinitionKind @@ -193,7 +194,7 @@ class ActorDefinition(object): path = os.path.abspath(os.path.join(self._repo_dir, self.directory)) for importer, name, is_pkg in pkgutil.iter_modules((path,)): if not is_pkg: - self._module = importer.find_module(name).load_module(name) + self._module = load_module(importer, name) break def discover(self): diff --git a/leapp/snactor/__init__.py b/leapp/snactor/__init__.py index 22ea993..3264a26 100644 --- a/leapp/snactor/__init__.py +++ b/leapp/snactor/__init__.py @@ -2,6 +2,7 @@ import os import pkgutil import socket +from leapp.compat import load_module from leapp.utils.i18n import _ # noqa; pylint: disable=redefined-builtin from leapp.snactor import commands from leapp.snactor.commands import workflow @@ -30,7 +31,7 @@ def _load_commands_from(path): for importer, name, is_pkg in pkgutil.iter_modules([pkg_path]): if is_pkg: continue - mod = importer.find_module(name).load_module(name) + mod = load_module(importer, name) if hasattr(mod.cli, 'command'): if not mod.cli.command.parent: cli.command.add_sub(mod.cli.command) diff --git a/res/container-tests/Containerfile.ubi10 b/res/container-tests/Containerfile.ubi10 index 22d5a8f..6d6507c 100644 --- a/res/container-tests/Containerfile.ubi10 +++ b/res/container-tests/Containerfile.ubi10 @@ -14,6 +14,9 @@ ENTRYPOINT virtualenv testenv -p "/usr/bin/$PYTHON_VENV" && \ pip install -U setuptools && \ pip install -U funcsigs && \ pip install -U -r requirements-tests.txt && \ + # NOTE(mmatuska): The pytest ver defined in requirements-tests is too old \ + # for Python 3.12 (missing imp module), there do an update here until we \ + # bump that. Similarly for six. \ pip install -U pytest && \ pip install -U six && \ pip install -U . && \ -- 2.42.0