about summary refs log tree commit diff
path: root/pkgs/development/python-modules/sopel/python311-support.patch
blob: dfa0283409acd71d9cbf78cd10f61a0edc310db3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
diff --git a/sopel/plugins/handlers.py b/sopel/plugins/handlers.py
index 76902aa0..05f0279d 100644
--- a/sopel/plugins/handlers.py
+++ b/sopel/plugins/handlers.py
@@ -46,20 +46,15 @@ from __future__ import absolute_import, division, print_function, unicode_litera
 
 import imp
 import importlib
+import importlib.util
 import inspect
 import itertools
 import os
+import sys
 
 from sopel import loader
 from . import exceptions
 
-try:
-    reload = importlib.reload
-except AttributeError:
-    # py2: no reload function
-    # TODO: imp is deprecated, to be removed when py2 support is dropped
-    reload = imp.reload
-
 
 class AbstractPluginHandler(object):
     """Base class for plugin handlers.
@@ -301,7 +296,7 @@ class PyModulePlugin(AbstractPluginHandler):
 
         This method assumes the plugin is already loaded.
         """
-        self._module = reload(self._module)
+        self._module = importlib.reload(self._module)
 
     def is_loaded(self):
         return self._module is not None
@@ -402,45 +397,31 @@ class PyFilePlugin(PyModulePlugin):
 
         if good_file:
             name = os.path.basename(filename)[:-3]
-            module_type = imp.PY_SOURCE
+            spec = importlib.util.spec_from_file_location(
+                name,
+                filename,
+            )
         elif good_dir:
             name = os.path.basename(filename)
-            module_type = imp.PKG_DIRECTORY
+            spec = importlib.util.spec_from_file_location(
+                name,
+                os.path.join(filename, '__init__.py'),
+                submodule_search_locations=filename,
+            )
         else:
             raise exceptions.PluginError('Invalid Sopel plugin: %s' % filename)
 
         self.filename = filename
         self.path = filename
-        self.module_type = module_type
+        self.module_spec = spec
 
         super(PyFilePlugin, self).__init__(name)
 
     def _load(self):
-        # The current implementation uses `imp.load_module` to perform the
-        # load action, which also reloads the module. However, `imp` is
-        # deprecated in Python 3, so that might need to be changed when the
-        # support for Python 2 is dropped.
-        #
-        # However, the solution for Python 3 is non-trivial, since the
-        # `importlib` built-in module does not have a similar function,
-        # therefore requires to dive into its public internals
-        # (``importlib.machinery`` and ``importlib.util``).
-        #
-        # All of that is doable, but represents a lot of work. As long as
-        # Python 2 is supported, we can keep it for now.
-        #
-        # TODO: switch to ``importlib`` when Python2 support is dropped.
-        if self.module_type == imp.PY_SOURCE:
-            with open(self.path) as mod:
-                description = ('.py', 'U', self.module_type)
-                mod = imp.load_module(self.name, mod, self.path, description)
-        elif self.module_type == imp.PKG_DIRECTORY:
-            description = ('', '', self.module_type)
-            mod = imp.load_module(self.name, None, self.path, description)
-        else:
-            raise TypeError('Unsupported module type')
-
-        return mod
+        module = importlib.util.module_from_spec(self.module_spec)
+        sys.modules[self.name] = module
+        self.module_spec.loader.exec_module(module)
+        return module
 
     def get_meta_description(self):
         """Retrieve a meta description for the plugin.