Skip to content
This repository has been archived by the owner on Sep 8, 2024. It is now read-only.

Commit

Permalink
Handle reloading of relative imports
Browse files Browse the repository at this point in the history
Submodule reload is enforced by removing sys.modules reference. This
will make imports do the full uncached importing
  • Loading branch information
forslund committed Jun 29, 2020
1 parent b968b06 commit a8b1888
Showing 1 changed file with 36 additions and 13 deletions.
49 changes: 36 additions & 13 deletions mycroft/skills/skill_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@
#
"""Periodically run by skill manager to load skills into memory."""
import gc
import importlib
from importlib import reload
from importlib.machinery import SourceFileLoader
from modulefinder import ModuleFinder
import os
from os.path import dirname
import sys
from time import time
from types import ModuleType

from mycroft.configuration import Configuration
from mycroft.messagebus import Message
Expand All @@ -28,6 +34,28 @@
SKILL_MAIN_MODULE = '__init__.py'


def remove_submodule_refs(module_name):
"""Ensure submodules being reloaded by removing the refs from sys.modules.
Python import system puts a reference for each module in the sys.modules
dictionary to bypass loading if a module is already in memory. To make
sure skills are completely reloaded these references are deleted.
Arguments:
module_name: name of skill module.
"""
submodules = []
LOG.info('Skill module'.format(module_name))
# Collect found submodules
for m in sys.modules:
if m.startswith(module_name + '.'):
submodules.append(m)
# Remove all references to in sys.modules
for m in submodules:
LOG.debug('Removing sys.modules ref for {}'.format(m))
del(sys.modules[m])


def load_skill_module(path, skill_id):
"""Load a skill module
Expand All @@ -39,19 +67,14 @@ def load_skill_module(path, skill_id):
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

remove_submodule_refs(module_name)

spec = importlib.util.spec_from_file_location(module_name, path)
mod = importlib.util.module_from_spec(spec)
sys.modules[module_name] = mod
spec.loader.exec_module(mod)
return mod


def _get_last_modified_time(path):
Expand Down

0 comments on commit a8b1888

Please sign in to comment.