def try_load_skill(self): if self.enable_intent_skill: intent_skill = create_intent_skill() intent_skill.bind(self.client) intent_skill.initialize() skill_descriptor = create_skill_descriptor(self.skill_directory) load_skill(skill_descriptor, self.client)
def try_load_skill(self): if self.enable_intent_skill: intent_skill = create_intent_skill() intent_skill.bind(self.ws) intent_skill.initialize() skill_descriptor = create_skill_descriptor(self.dir) load_skill(skill_descriptor, self.ws)
def watch_skills(): global ws, loaded_skills, last_modified_skill, skills_directories, \ id_counter, prioritary_skills # load prioritary skills first for p_skill in prioritary_skills: if p_skill not in loaded_skills: loaded_skills[p_skill] = {} skill = loaded_skills.get(p_skill) skill["path"] = os.path.join(os.path.dirname(__file__), p_skill) if not MainModule + ".py" in os.listdir(skill["path"]): logger.error(p_skill + " does not appear to be a skill") sys.exit(1) skill["loaded"] = True skill["instance"] = load_skill( create_skill_descriptor(skill["path"]), ws) while True: for dir in skills_directories: if exists(dir): list = sorted( filter(lambda x: os.path.isdir(os.path.join(dir, x)), os.listdir(dir))) for skill_folder in list: if skill_folder not in loaded_skills: loaded_skills[skill_folder] = {} skill = loaded_skills.get(skill_folder) skill["path"] = os.path.join(dir, skill_folder) if not MainModule + ".py" in os.listdir(skill["path"]): continue skill["last_modified"] = max( os.path.getmtime(root) for root, _, _ in os.walk(skill["path"])) modified = skill.get("last_modified", 0) if skill.get("loaded") and modified <= last_modified_skill: continue elif skill.get( "instance") and modified > last_modified_skill: if not skill["instance"].reload_skill: continue logger.debug("Reloading Skill: " + skill_folder) skill["instance"].shutdown() clear_skill_events(skill["instance"]) del skill["instance"] skill["loaded"] = True skill["instance"] = load_skill( create_skill_descriptor(skill["path"]), ws) last_modified_skill = max( map(lambda x: x.get("last_modified"), loaded_skills.values())) time.sleep(2)
def test_load_skill(self): """ Verify skill load function. """ e_path = join(dirname(__file__), 'test_skill') s = load_skill(create_skill_descriptor(e_path), MockEmitter(), 847) self.assertEquals(s._dir, e_path) self.assertEquals(s.skill_id, 847) self.assertEquals(s.name, 'LoadTestSkill')
def load_skills(emitter, skills_root): """Load all skills and set up emitter Args: emitter: The emmitter to use skills_root: Directory of the skills __init__.py Returns: tuple: (list of loaded skills, dict with logs for each skill) """ skill_list = [] log = {} for skill in get_skills(skills_root): path = skill["path"] skill_id = 'test-' + basename(path) # Catch the logs during skill loading from mycroft.skills.core import LOG as skills_log buf = StringIO() with temporary_handler(skills_log, StreamHandler(buf)): skill_list.append(load_skill(skill, emitter, skill_id)) log[path] = buf.getvalue() return skill_list, log
def load_skill_list(skills_to_load): """ load list of specific skills. Args: skills_to_load (list): list of skill directories to load """ if exists(SKILLS_DIR): # checking skills dir and getting all priority skills there skill_list = [folder for folder in filter( lambda x: os.path.isdir(os.path.join(SKILLS_DIR, x)), os.listdir(SKILLS_DIR)) if folder in skills_to_load] for skill_folder in skill_list: skill = {"id": hash(os.path.join(SKILLS_DIR, skill_folder))} skill["path"] = os.path.join(SKILLS_DIR, skill_folder) # checking if is a skill if not MainModule + ".py" in os.listdir(skill["path"]): continue # getting the newest modified date of skill last_mod = _get_last_modified_date(skill["path"]) skill["last_modified"] = last_mod # loading skill skill["loaded"] = True skill["instance"] = load_skill( create_skill_descriptor(skill["path"]), ws, skill["id"]) loaded_skills[skill_folder] = skill
def load_skills(emitter, skills_root): skill_list = [] skill_id = 0 for skill in get_skills(skills_root): skill_list.append(load_skill(skill, emitter, skill_id)) skill_id += 1 return skill_list
def _load_or_reload_skill(self, skill_folder): """ Check if unloaded skill or changed skill needs reloading and perform loading if necessary. """ if skill_folder not in self.loaded_skills: self.loaded_skills[skill_folder] = { "id": hash(os.path.join(SKILLS_DIR, skill_folder)) } skill = self.loaded_skills.get(skill_folder) skill["path"] = os.path.join(SKILLS_DIR, skill_folder) # check if folder is a skill (must have __init__.py) if not MainModule + ".py" in os.listdir(skill["path"]): return # getting the newest modified date of skill modified = _get_last_modified_date(skill["path"]) last_mod = skill.get("last_modified", 0) # checking if skill is loaded and hasn't been modified on disk if skill.get("loaded") and modified <= last_mod: return # Nothing to do! # check if skill was modified elif skill.get("instance") and modified > last_mod: # check if skill has been blocked from reloading if not skill["instance"].reload_skill: return LOG.debug("Reloading Skill: " + skill_folder) # removing listeners and stopping threads skill["instance"].shutdown() if DEBUG: gc.collect() # Collect garbage to remove false references # Remove two local references that are known refs = sys.getrefcount(skill["instance"]) - 2 if refs > 0: LOG.warning("After shutdown of {} there are still " "{} references remaining. The skill " "won't be cleaned from memory.".format( skill['instance'].name, refs)) del skill["instance"] # (Re)load the skill from disk with self.__msm_lock: # Make sure msm isn't running skill["loaded"] = True desc = create_skill_descriptor(skill["path"]) skill["instance"] = load_skill(desc, self.ws, skill["id"], BLACKLISTED_SKILLS) skill["last_modified"] = modified if skill and skill['instance']: ws.emit( Message('mycroft.skills.loaded', { 'id': skill['id'], 'name': skill['instance'].name }))
def _load_or_reload_skill(self, skill_folder): """ Check if unloaded skill or changed skill needs reloading and perform loading if necessary. """ if skill_folder not in self.loaded_skills: self.loaded_skills[skill_folder] = { "id": hash(os.path.join(SKILLS_DIR, skill_folder)) } skill = self.loaded_skills.get(skill_folder) skill["path"] = os.path.join(SKILLS_DIR, skill_folder) # check if folder is a skill (must have __init__.py) if not MainModule + ".py" in os.listdir(skill["path"]): return # getting the newest modified date of skill modified = _get_last_modified_date(skill["path"]) last_mod = skill.get("last_modified", 0) # checking if skill is loaded and wasn't modified if skill.get("loaded") and modified <= last_mod: return # check if skill was modified elif skill.get("instance") and modified > last_mod: # check if skill is allowed to reloaded if not skill["instance"].reload_skill: return LOG.debug("Reloading Skill: " + skill_folder) # removing listeners and stopping threads skill["instance"].shutdown() # Remove two local references that are known refs = sys.getrefcount(skill["instance"]) - 2 if refs > 0: LOG.warning( "After shutdown of {} there are still " "{} references remaining. The skill " "won't be cleaned from memory." .format(skill['instance'].name, refs)) del skill["instance"] # (Re)load the skill from disk with self.__msm_lock: # Make sure msm isn't running skill["loaded"] = True desc = create_skill_descriptor(skill["path"]) skill["instance"] = load_skill(desc, self.ws, skill["id"], BLACKLISTED_SKILLS) skill["last_modified"] = modified
def _watch_skills(): global ws, loaded_skills, last_modified_skill, \ id_counter # Scan the file folder that contains Skills. If a Skill is updated, # unload the existing version from memory and reload from the disk. while True: if exists(SKILLS_DIR): # checking skills dir and getting all skills there list = filter(lambda x: os.path.isdir( os.path.join(SKILLS_DIR, x)), os.listdir(SKILLS_DIR)) for skill_folder in list: if skill_folder not in loaded_skills: loaded_skills[skill_folder] = {} skill = loaded_skills.get(skill_folder) skill["path"] = os.path.join(SKILLS_DIR, skill_folder) # checking if is a skill if not MainModule + ".py" in os.listdir(skill["path"]): continue # getting the newest modified date of skill skill["last_modified"] = _get_last_modified_date(skill["path"]) modified = skill.get("last_modified", 0) # checking if skill is loaded and wasn't modified if skill.get( "loaded") and modified <= last_modified_skill: continue # checking if skill was modified elif skill.get( "instance") and modified > last_modified_skill: # checking if skill should be reloaded if not skill["instance"].reload_skill: continue logger.debug("Reloading Skill: " + skill_folder) # removing listeners and stopping threads skill["instance"].shutdown() del skill["instance"] skill["loaded"] = True skill["instance"] = load_skill( create_skill_descriptor(skill["path"]), ws) # get the last modified skill modified_dates = map(lambda x: x.get("last_modified"), loaded_skills.values()) if len(modified_dates) > 0: last_modified_skill = max(modified_dates) # Pause briefly before beginning next scan time.sleep(2)
def load_skills(emitter, skills_root): """Load all skills and set up emitter Args: emitter: The emmitter to use skills_root: Directory of the skills __init__.py Returns: list: a list of loaded skills """ skill_list = [] for skill in get_skills(skills_root): path = skill["path"] skill_id = 'test-' + basename(path) skill_list.append(load_skill(skill, emitter, skill_id)) return skill_list
def _load_or_reload_skill(self, skill_path): """ Check if unloaded skill or changed skill needs reloading and perform loading if necessary. Returns True if the skill was loaded/reloaded """ skill_path = skill_path.rstrip('/') skill = self.loaded_skills.setdefault(skill_path, {}) skill.update({"id": basename(skill_path), "path": skill_path}) # check if folder is a skill (must have __init__.py) if not MainModule + ".py" in os.listdir(skill_path): return False # getting the newest modified date of skill modified = _get_last_modified_date(skill_path) last_mod = skill.get("last_modified", 0) # checking if skill is loaded and hasn't been modified on disk if skill.get("loaded") and modified <= last_mod: return False # Nothing to do! # check if skill was modified elif skill.get("instance") and modified > last_mod: # check if skill has been blocked from reloading if not skill["instance"].reload_skill: return False LOG.debug("Reloading Skill: " + basename(skill_path)) # removing listeners and stopping threads try: skill["instance"]._shutdown() except Exception: LOG.exception("An error occured while shutting down {}".format( skill["instance"].name)) if DEBUG: gc.collect() # Collect garbage to remove false references # Remove two local references that are known refs = sys.getrefcount(skill["instance"]) - 2 if refs > 0: msg = ("After shutdown of {} there are still " "{} references remaining. The skill " "won't be cleaned from memory.") LOG.warning(msg.format(skill['instance'].name, refs)) del skill["instance"] self.ws.emit( Message("mycroft.skills.shutdown", { "path": skill_path, "id": skill["id"] })) skill["loaded"] = True desc = create_skill_descriptor(skill_path) skill["instance"] = load_skill(desc, self.ws, skill["id"], BLACKLISTED_SKILLS) skill["last_modified"] = modified if skill['instance'] is not None: self.ws.emit( Message( 'mycroft.skills.loaded', { 'path': skill_path, 'id': skill['id'], 'name': skill['instance'].name, 'modified': modified })) return True else: self.ws.emit( Message('mycroft.skills.loading_failure', { 'path': skill_path, 'id': skill['id'] })) return False
def load_skill(self): if self.enable_intent: IntentService(self.ws) skill_descriptor = create_skill_descriptor(self.dir) self.skill = load_skill(skill_descriptor, self.ws, hash(self.dir))
def _load_or_reload_skill(self, skill_folder): """ Check if unloaded skill or changed skill needs reloading and perform loading if necessary. """ if skill_folder not in self.loaded_skills: self.loaded_skills[skill_folder] = { "id": hash(os.path.join(SKILLS_DIR, skill_folder)) } skill = self.loaded_skills.get(skill_folder) skill["path"] = os.path.join(SKILLS_DIR, skill_folder) # check if folder is a skill (must have __init__.py) if not MainModule + ".py" in os.listdir(skill["path"]): return # getting the newest modified date of skill modified = _get_last_modified_date(skill["path"]) last_mod = skill.get("last_modified", 0) # checking if skill is loaded and hasn't been modified on disk if skill.get("loaded") and modified <= last_mod: return # Nothing to do! # check if skill was modified elif skill.get("instance") and modified > last_mod: # check if skill has been blocked from reloading if not skill["instance"].reload_skill: return LOG.debug("Reloading Skill: " + skill_folder) # removing listeners and stopping threads skill["instance"].shutdown() if DEBUG: gc.collect() # Collect garbage to remove false references # Remove two local references that are known refs = sys.getrefcount(skill["instance"]) - 2 if refs > 0: LOG.warning( "After shutdown of {} there are still " "{} references remaining. The skill " "won't be cleaned from memory." .format(skill['instance'].name, refs)) del skill["instance"] self.ws.emit(Message("mycroft.skills.shutdown", {"folder": skill_folder, "id": skill["id"]})) # (Re)load the skill from disk with self.__msm_lock: # Make sure msm isn't running skill["loaded"] = True desc = create_skill_descriptor(skill["path"]) skill["instance"] = load_skill(desc, self.ws, skill["id"], BLACKLISTED_SKILLS) skill["last_modified"] = modified if skill['instance'] is not None: self.ws.emit(Message('mycroft.skills.loaded', {'folder': skill_folder, 'id': skill['id'], 'name': skill['instance'].name, 'modified': modified})) else: self.ws.emit(Message('mycroft.skills.loading_failure', {'folder': skill_folder, 'id': skill['id']}))
def run(self): global ws, loaded_skills, last_modified_skill # Load priority skills first by order load_skill_list(PRIORITY_SKILLS) self._loaded_priority.set() # Scan the file folder that contains Skills. If a Skill is updated, # unload the existing version from memory and reload from the disk. while not self._stop_event.is_set(): if exists(SKILLS_DIR): # checking skills dir and getting all skills there list = filter(lambda x: os.path.isdir( os.path.join(SKILLS_DIR, x)), os.listdir(SKILLS_DIR)) for skill_folder in list: if skill_folder not in loaded_skills: loaded_skills[skill_folder] = { "id": hash(os.path.join(SKILLS_DIR, skill_folder)) } skill = loaded_skills.get(skill_folder) skill["path"] = os.path.join(SKILLS_DIR, skill_folder) # checking if is a skill if not MainModule + ".py" in os.listdir(skill["path"]): continue # getting the newest modified date of skill last_mod = _get_last_modified_date(skill["path"]) skill["last_modified"] = last_mod modified = skill.get("last_modified", 0) # checking if skill is loaded and wasn't modified if skill.get( "loaded") and modified <= last_modified_skill: continue # checking if skill was modified elif (skill.get("instance") and modified > last_modified_skill): # checking if skill should be reloaded if not skill["instance"].reload_skill: continue LOG.debug("Reloading Skill: " + skill_folder) # removing listeners and stopping threads skill["instance"].shutdown() # -2 since two local references that are known refs = sys.getrefcount(skill["instance"]) - 2 if refs > 0: LOG.warning( "After shutdown of {} there are still " "{} references remaining. The skill " "won't be cleaned from memory." .format(skill['instance'].name, refs)) del skill["instance"] skill["loaded"] = True skill["instance"] = load_skill( create_skill_descriptor(skill["path"]), ws, skill["id"], BLACKLISTED_SKILLS) # get the last modified skill modified_dates = map(lambda x: x.get("last_modified"), loaded_skills.values()) if len(modified_dates) > 0: last_modified_skill = max(modified_dates) if not self._loaded_once.is_set(): self._loaded_once.set() # Pause briefly before beginning next scan time.sleep(2)