# HG changeset patch # User Mads Kiilerich # Date 2023-06-28 12:23:13 # Node ID 19108906abafd9ddd9c2b15919d577d0faa1b2f0 # Parent 847f703a4d136cb8000603766dc5c6247fb98529 extensions: imp module is removed in Python 3.12 - use importlib to load files imp has been deprecated for a long time, and has finally been removed in Python 3.12 . imp was only used for loading extensions that has been specified with direct .py path or path to a package directory. The same use cases can be achieved quite simple with importlib, , possiby with small changes in corner cases with undefined behaviour, such as extensions without .py source. There might also be corner cases and undefined behaviour around use of sys.modules and reloading. diff --git a/mercurial/extensions.py b/mercurial/extensions.py --- a/mercurial/extensions.py +++ b/mercurial/extensions.py @@ -9,9 +9,10 @@ import ast import collections import functools -import imp +import importlib import inspect import os +import sys from .i18n import ( _, @@ -89,20 +90,18 @@ def loadpath(path, module_name): path = pycompat.fsdecode(path) if os.path.isdir(path): # module/__init__.py style - d, f = os.path.split(path) - fd, fpath, desc = imp.find_module(f, [d]) - # When https://github.com/python/typeshed/issues/3466 is fixed - # and in a pytype release we can drop this disable. - return imp.load_module( - module_name, fd, fpath, desc # pytype: disable=wrong-arg-types - ) - else: - try: - return imp.load_source(module_name, path) - except IOError as exc: - if not exc.filename: - exc.filename = path # python does not fill this - raise + init_py_path = os.path.join(path, '__init__.py') + if not os.path.exists(init_py_path): + raise ImportError("No module named '%s'" % os.path.basename(path)) + path = init_py_path + + loader = importlib.machinery.SourceFileLoader(module_name, path) + spec = importlib.util.spec_from_file_location(module_name, loader=loader) + assert spec is not None # help Pytype + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + return module def _importh(name):