fix: 'load_module()' deprecated in Python 3.12
[babeltrace.git] / src / bindings / python / bt2 / bt2 / py_plugin.py
index b845030863ce224582406af5698e840a3d70465c..50bfe91ab7f44c5e184b88dbb3046a31134346e1 100644 (file)
 # THE SOFTWARE.
 
 from bt2 import utils
-import bt2.component
+from bt2 import component as bt2_component
+import sys
+
+
+# Python plugin path to `_PluginInfo` (cache)
+_plugin_infos = {}
 
 
 def plugin_component_class(component_class):
-    if not issubclass(component_class, bt2.component._UserComponent):
+    if not issubclass(component_class, bt2_component._UserComponent):
         raise TypeError('component class is not a subclass of a user component class')
 
     component_class._bt_plugin_component_class = None
     return component_class
 
 
-def register_plugin(module_name, name, description=None, author=None,
-                    license=None, version=None):
-    import sys
-
+def register_plugin(
+    module_name, name, description=None, author=None, license=None, version=None
+):
     if module_name not in sys.modules:
-        raise RuntimeError("cannot find module '{}' in loaded modules".format(module_name))
+        raise RuntimeError(
+            "cannot find module '{}' in loaded modules".format(module_name)
+        )
 
     utils._check_str(name)
 
@@ -52,11 +58,13 @@ def register_plugin(module_name, name, description=None, author=None,
 
     if version is not None:
         if not _validate_version(version):
-            raise ValueError('wrong version: expecting a tuple: (major, minor, patch) or (major, minor, patch, extra)')
+            raise ValueError(
+                'wrong version: expecting a tuple: (major, minor, patch) or (major, minor, patch, extra)'
+            )
 
-    sys.modules[module_name]._bt_plugin_info = _PluginInfo(name, description,
-                                                           author, license,
-                                                           version)
+    sys.modules[module_name]._bt_plugin_info = _PluginInfo(
+        name, description, author, license, version
+    )
 
 
 def _validate_version(version):
@@ -97,6 +105,10 @@ class _PluginInfo:
 
 # called by the BT plugin system
 def _try_load_plugin_module(path):
+    if path in _plugin_infos:
+        # do not load module and create plugin info twice for this path
+        return _plugin_infos[path]
+
     import importlib.machinery
     import inspect
     import hashlib
@@ -110,9 +122,19 @@ def _try_load_plugin_module(path):
     h = hashlib.sha256()
     h.update(path.encode())
     module_name = 'bt_plugin_{}'.format(h.hexdigest())
+    assert module_name not in sys.modules
 
     # try loading the module: any raised exception is catched by the caller
-    mod = importlib.machinery.SourceFileLoader(module_name, path).load_module()
+    if sys.version_info < (3, 5):
+        mod = importlib.machinery.SourceFileLoader(module_name, path).load_module()
+    else:
+        import importlib.util
+
+        loader = importlib.machinery.SourceFileLoader(module_name, path)
+        spec = importlib.util.spec_from_file_location(module_name, path, loader=loader)
+        mod = importlib.util.module_from_spec(spec)
+        sys.modules[mod.__name__] = mod
+        loader.exec_module(mod)
 
     # we have the module: look for its plugin info first
     if not hasattr(mod, '_bt_plugin_info'):
@@ -132,4 +154,5 @@ def _try_load_plugin_module(path):
 
     comp_class_entries = inspect.getmembers(mod, is_user_comp_class)
     plugin_info.comp_class_addrs = [entry[1].addr for entry in comp_class_entries]
+    _plugin_infos[path] = plugin_info
     return plugin_info
This page took 0.02538 seconds and 4 git commands to generate.