|
44 | 44 | from __future__ import generator_stop |
45 | 45 |
|
46 | 46 | import abc |
47 | | -import imp |
48 | 47 | import importlib |
49 | 48 | import inspect |
50 | 49 | import itertools |
|
53 | 52 | from sopel import loader |
54 | 53 | from . import exceptions |
55 | 54 |
|
56 | | -try: |
57 | | - reload = importlib.reload |
58 | | -except AttributeError: |
59 | | - # py2: no reload function |
60 | | - # TODO: imp is deprecated, to be removed when py2 support is dropped |
61 | | - reload = imp.reload |
62 | | - |
63 | 55 |
|
64 | 56 | class AbstractPluginHandler(abc.ABC): |
65 | 57 | """Base class for plugin handlers. |
@@ -303,7 +295,7 @@ def reload(self): |
303 | 295 |
|
304 | 296 | This method assumes the plugin is already loaded. |
305 | 297 | """ |
306 | | - self._module = reload(self._module) |
| 298 | + self._module = importlib.reload(self._module) |
307 | 299 |
|
308 | 300 | def is_loaded(self): |
309 | 301 | return self._module is not None |
@@ -404,45 +396,25 @@ def __init__(self, filename): |
404 | 396 |
|
405 | 397 | if good_file: |
406 | 398 | name = os.path.basename(filename)[:-3] |
407 | | - module_type = imp.PY_SOURCE |
| 399 | + self.path = filename |
| 400 | + self.filename = filename |
408 | 401 | elif good_dir: |
409 | 402 | name = os.path.basename(filename) |
410 | | - module_type = imp.PKG_DIRECTORY |
| 403 | + self.path = filename |
| 404 | + self.filename = os.path.join(filename, '__init__.py') |
411 | 405 | else: |
412 | 406 | raise exceptions.PluginError('Invalid Sopel plugin: %s' % filename) |
413 | 407 |
|
414 | | - self.filename = filename |
415 | | - self.path = filename |
416 | | - self.module_type = module_type |
417 | | - |
418 | 408 | super().__init__(name) |
419 | 409 |
|
420 | 410 | def _load(self): |
421 | | - # The current implementation uses `imp.load_module` to perform the |
422 | | - # load action, which also reloads the module. However, `imp` is |
423 | | - # deprecated in Python 3, so that might need to be changed when the |
424 | | - # support for Python 2 is dropped. |
425 | | - # |
426 | | - # However, the solution for Python 3 is non-trivial, since the |
427 | | - # `importlib` built-in module does not have a similar function, |
428 | | - # therefore requires to dive into its public internals |
429 | | - # (``importlib.machinery`` and ``importlib.util``). |
430 | | - # |
431 | | - # All of that is doable, but represents a lot of work. As long as |
432 | | - # Python 2 is supported, we can keep it for now. |
433 | | - # |
434 | | - # TODO: switch to ``importlib`` when Python2 support is dropped. |
435 | | - if self.module_type == imp.PY_SOURCE: |
436 | | - with open(self.path) as mod: |
437 | | - description = ('.py', 'U', self.module_type) |
438 | | - mod = imp.load_module(self.name, mod, self.path, description) |
439 | | - elif self.module_type == imp.PKG_DIRECTORY: |
440 | | - description = ('', '', self.module_type) |
441 | | - mod = imp.load_module(self.name, None, self.path, description) |
442 | | - else: |
443 | | - raise TypeError('Unsupported module type') |
| 411 | + # basically the example code from |
| 412 | + # https://docs.python.org/3.7/library/importlib.html#importing-a-source-file-directly |
| 413 | + spec = importlib.util.spec_from_file_location(self.name, self.filename) |
| 414 | + module = importlib.util.module_from_spec(spec) |
| 415 | + spec.loader.exec_module(module) |
444 | 416 |
|
445 | | - return mod |
| 417 | + return module |
446 | 418 |
|
447 | 419 | def get_meta_description(self): |
448 | 420 | """Retrieve a meta description for the plugin. |
|
0 commit comments