Switch from the deprecated imp to importlib
Separate python 3.4 and 3.5+ implementation
#
"""Periodically run by skill manager to load skills into memory."""
import gc
-import imp
import os
import sys
from time import time
@@ -29,6 +28,32 @@ from .settings import SettingsMetaUploader
SKILL_MAIN_MODULE = '__init__.py'
+def load_skill_module(path, skill_id):
+ """Load a skill module
+
+ This function handles the differences between python 3.4 and 3.5+ as well
+ as makes sure the module is inserted into the sys.modules dict.
+
+ Arguments:
+ path: Path to the skill main file (__init__.py)
+ skill_id: skill_id used as skill identifier in the module list
+ """
+ module_name = skill_id.replace('.', '_')
+ if sys.version_info >= (3, 5):
+ import importlib.util
+ spec = importlib.util.spec_from_file_location(module_name, path)
+ mod = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(mod)
+ else:
+ from importlib.machinery import SourceFileLoader
+ mod = SourceFileLoader(module_name, path).load_module()
+ if mod:
+ sys.modules[module_name] = mod
+ return mod
+ else:
+ return None
+
+
def _get_last_modified_time(path):
"""Get the last modified date of the most recently updated file in a path.
@@ -139,7 +164,7 @@ class SkillLoader:
"""Call the shutdown method of the skill being reloaded."""
try:
self.instance.default_shutdown()
- except Exception as e:
+ except Exception:
log_msg = 'An error occurred while shutting down {}'
LOG.exception(log_msg.format(self.instance.name))
else:
@@ -196,20 +221,13 @@ class SkillLoader:
def _load_skill_source(self):
"""Use Python's import library to load a skill's source code."""
- # TODO: Replace the deprecated "imp" library with the newer "importlib"
- module_name = self.skill_id.replace('.', '_')
main_file_path = os.path.join(self.skill_directory, SKILL_MAIN_MODULE)
- try:
- with open(main_file_path, 'rb') as main_file:
- skill_module = imp.load_module(
- module_name,
- main_file,
- main_file_path,
- ('.py', 'rb', imp.PY_SOURCE)
- )
- except FileNotFoundError as f:
+ if not os.path.exists(main_file_path):
error_msg = 'Failed to load {} due to a missing file.'
- LOG.exception(error_msg.format(self.skill_id))
+ LOG.error(error_msg.format(self.skill_id))
+ else:
+ try:
+ skill_module = load_skill_module(main_file_path, self.skill_id)
except Exception as e:
LOG.exception('Failed to load skill: '
'{} ({})'.format(self.skill_id, repr(e)))
