Skip to content

Commit ae6b79c

Browse files
authored
Merge 60ae795 into f6977fe
2 parents f6977fe + 60ae795 commit ae6b79c

1 file changed

Lines changed: 20 additions & 15 deletions

File tree

source/addonHandler/__init__.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import inspect
1212
import itertools
1313
import collections
14-
import pkgutil
1514
import shutil
1615
from io import StringIO
1716
import pickle
@@ -29,7 +28,10 @@
2928
import addonAPIVersion
3029
from . import addonVersionCheck
3130
from .addonVersionCheck import isAddonCompatible
31+
import importlib
32+
from types import ModuleType
3233
import extensionPoints
34+
from keyword import iskeyword
3335

3436

3537
MANIFEST_FILENAME = "manifest.ini"
@@ -475,25 +477,28 @@ def _getPathForInclusionInPackage(self, package):
475477
extension_path = os.path.join(self.path, package.__name__)
476478
return extension_path
477479

478-
def loadModule(self, name):
480+
def loadModule(self, name: str) -> ModuleType:
479481
""" loads a python module from the addon directory
480482
@param name: the module name
481-
@type name: string
482-
@returns the python module with C{name}
483-
@rtype python module
484483
"""
485-
log.debug("Importing module %s from plugin %s", name, self.name)
486-
importer = pkgutil.ImpImporter(self.path)
487-
loader = importer.find_module(name)
488-
if not loader:
489-
return None
484+
splitName = name.split('.')
485+
moduleName = splitName[-1]
486+
path = os.path.join(self.path, *splitName[:-1])
487+
if any(n for n in splitName if not n.isidentifier() or iskeyword(n)):
488+
raise ValueError(f"{name} is an invalid python module name")
489+
log.debug(f"Importing module {name} from plugin {self!r}")
490490
# Create a qualified full name to avoid modules with the same name on sys.modules.
491-
fullname = "addons.%s.%s" % (self.name, name)
492-
try:
493-
return loader.load_module(fullname)
494-
except ImportError:
495-
# in this case return None, any other error throw to be handled elsewhere
491+
fullName = f"addons.{self.name}.{name}"
492+
if fullName in sys.modules:
493+
return importlib.import_module(fullName)
494+
spec = importlib.machinery.PathFinder.find_spec(fullName, [path])
495+
if not spec:
496496
return None
497+
mod = importlib.util.module_from_spec(spec)
498+
sys.modules[fullName] = mod
499+
if spec.loader:
500+
spec.loader.exec_module(mod)
501+
return mod
497502

498503
def getTranslationsInstance(self, domain='nvda'):
499504
""" Gets the gettext translation instance for this add-on.

0 commit comments

Comments
 (0)