Mercurial > hg
comparison mercurial/extensions.py @ 50757:19108906abaf stable
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.
author | Mads Kiilerich <mads@kiilerich.com> |
---|---|
date | Wed, 28 Jun 2023 14:23:13 +0200 |
parents | b9eb65a1ec14 |
children | 3ccef7902070 |
comparison
equal
deleted
inserted
replaced
50756:847f703a4d13 | 50757:19108906abaf |
---|---|
7 | 7 |
8 | 8 |
9 import ast | 9 import ast |
10 import collections | 10 import collections |
11 import functools | 11 import functools |
12 import imp | 12 import importlib |
13 import inspect | 13 import inspect |
14 import os | 14 import os |
15 import sys | |
15 | 16 |
16 from .i18n import ( | 17 from .i18n import ( |
17 _, | 18 _, |
18 gettext, | 19 gettext, |
19 ) | 20 ) |
87 path = util.normpath(util.expandpath(path)) | 88 path = util.normpath(util.expandpath(path)) |
88 module_name = pycompat.fsdecode(module_name) | 89 module_name = pycompat.fsdecode(module_name) |
89 path = pycompat.fsdecode(path) | 90 path = pycompat.fsdecode(path) |
90 if os.path.isdir(path): | 91 if os.path.isdir(path): |
91 # module/__init__.py style | 92 # module/__init__.py style |
92 d, f = os.path.split(path) | 93 init_py_path = os.path.join(path, '__init__.py') |
93 fd, fpath, desc = imp.find_module(f, [d]) | 94 if not os.path.exists(init_py_path): |
94 # When https://github.com/python/typeshed/issues/3466 is fixed | 95 raise ImportError("No module named '%s'" % os.path.basename(path)) |
95 # and in a pytype release we can drop this disable. | 96 path = init_py_path |
96 return imp.load_module( | 97 |
97 module_name, fd, fpath, desc # pytype: disable=wrong-arg-types | 98 loader = importlib.machinery.SourceFileLoader(module_name, path) |
98 ) | 99 spec = importlib.util.spec_from_file_location(module_name, loader=loader) |
99 else: | 100 assert spec is not None # help Pytype |
100 try: | 101 module = importlib.util.module_from_spec(spec) |
101 return imp.load_source(module_name, path) | 102 sys.modules[module_name] = module |
102 except IOError as exc: | 103 spec.loader.exec_module(module) |
103 if not exc.filename: | 104 return module |
104 exc.filename = path # python does not fill this | |
105 raise | |
106 | 105 |
107 | 106 |
108 def _importh(name): | 107 def _importh(name): |
109 """import and return the <name> module""" | 108 """import and return the <name> module""" |
110 mod = __import__(pycompat.sysstr(name)) | 109 mod = __import__(pycompat.sysstr(name)) |