def process(self, p: Package): if not p.action: return locale_dir = self.rt.paths.skill_locale(skill_name=p.skill, lang=p.lang) file_base = join(locale_dir, p.action) speech = file_base + '.speech' dialog = file_base + '.dialog' text = file_base + '.text' line_id = -1 if not p.speech: if isfile(speech): line_id, p.speech = self.render_file(speech, p, Format.speech, line_id) elif isfile(dialog): line_id, p.speech = self.render_file(dialog, p, Format.speech, line_id) else: p.speech = p.text if not p.text: if isfile(text): line_id, p.text = self.render_file(text, p, Format.text, line_id) elif isfile(dialog): line_id, p.text = self.render_file(dialog, p, Format.text, line_id) else: p.text = p.speech if not p.speech and not p.text: log.warning('No dialog at:', dialog)
def download_extract_tar(tar_url, folder, check_md5=False, subdir='', on_update: Callable = None, on_complete: Callable = None) -> bool: """Warning! If check_md5 is True, it will delete <folder>/<subdir> when remote md5 updates""" data_file = join(folder, basename(tar_url)) if not isdir(join(folder, subdir)): makedirs(folder, exist_ok=True) download(tar_url, data_file) import tarfile tar = tarfile.open(data_file) tar.extractall(path=folder) tar.close() return True elif check_md5: md5_url = tar_url + '.md5' try: remote_md5 = download(md5_url, debug=False, timeout=1).decode('ascii').split(' ')[0] except (RequestException, URLError) as e: log.warning('Failed to download md5 at url:', md5_url) return False if remote_md5 != calc_md5(data_file): on_update and on_update() rmtree(join(folder, subdir)) download_extract_tar(tar_url, folder, subdir=subdir) on_complete and on_complete() return True return False
def __init__(self, rt): ServicePlugin.__init__(self, rt) sys.path.append(self.rt.paths.skills) def inject_rt(cls): cls.rt = rt log.info('Loading skills...') GroupPlugin.__init__(self, gp_alter_class=inject_rt, gp_blacklist=self.config['blacklist'], gp_timeout=10.0, gp_daemon=True) for name, thread in self._init_threads.items(): if thread.is_alive(): log.warning('Skill init method taking too long for:', name) log.info('Finished loading skills.') # The watch manager stores the watches and provides operations on watches wm = pyinotify.WatchManager() mask = pyinotify.IN_MODIFY | pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MOVED_TO skills_dir = self.rt.paths.skills handler = EventHandler(self, skills_dir) notifier = pyinotify.ThreadedNotifier(wm, handler) notifier.daemon = True wm.add_watch(skills_dir, mask, rec=True, auto_add=True) notifier.start() self.git_repo = self.create_git_repo()
def __register_intents(self): intents = [] entities = [] for name in dir(self): item = getattr(self, name) if callable(item): intent_calls = getattr(item, 'intent_calls', None) if intent_calls: for params in intent_calls: func, intent, intent_engine, handler_type = params if not intent: log.warning('Skipping empty intent from skill:', self.skill_name) continue intents.append(intent) self.register_intent(func, intent, intent_engine, handler_type) entity_calls = getattr(item, 'entity_calls', None) if entity_calls: for params in entity_calls: entity, intent_engine = params entities.append(entity) self.register_entity(entity, intent_engine) log.debug('Intents for', self.skill_name + ':', intents) if entities: log.debug('Entities for', self.skill_name + ':', entities)
def format(self, obj, fmt=Format.speech): handler = self.formatters.get(type(obj)) if not handler: log.warning('No formatter for', type(obj)) return str(obj) if isclass(handler) or len(signature(handler).parameters) == 1: return handler(obj) else: return handler(obj, fmt)
def __getattr__(self, item) -> Any: if item.startswith('_'): raise AttributeError(item) if '_plugins' not in self.__dict__: raise AttributeError(item) if item not in self._plugins: log.warning(item, 'plugin does not exist.', stack_offset=1) self._plugins[item] = Empty() return self._plugins[item]
def run(self): Thread(target=self._run_serial, daemon=True).start() while self.rt.main_thread: line = self.serial.readline().decode() if 'volume.up' in line: self.rt.skills.volume.increase_volume() elif 'volume.down' in line: self.rt.skills.volume.decrease_volume() elif 'Command: ' in line: pass # Reply from Arduino elif len(line.strip()) > 0: log.warning('Could not handle message: ' + line)
def __init__(self, rt): # type: (Root) -> None self.rt = rt if self._package_struct: if 'package' not in self.rt: log.warning('Package struct for module loaded before package:', self._plugin_path) else: self.rt.package.add_struct(self._package_struct) if not self._plugin_path and self._config: print('PLUGIN_PATH:', self._plugin_path, self._attr_name, self._config, self) raise RuntimeError( 'Cannot set _config for non-dynamically loaded class {}'. format(self.__class__.__name__)) if 'config' in rt and self._plugin_path: if self._root_config: rt.config.inject(self._root_config) if self._config: rt.config.inject(self._config, self._plugin_path) self.config = {} rt.config.on_change(self._plugin_path, self.on_config_change) self.on_config_change(rt.config.get_path(self._plugin_path)) else: self.config = {} if 'config' in rt and self._required_attributes: for required_attribute in self._required_attributes: if required_attribute not in self.rt.config['platform'][ 'attributes']: raise NotImplementedError('Missing attribute: ' + required_attribute) if 'plugin_versions' in rt: old_version = rt.plugin_versions.get(self._plugin_path) if old_version != self.__version__: if self.setup.__func__ is not BasePlugin.setup: log.info( 'Running {}.setup() to upgrade from {} to {}'.format( self.__class__.__name__, old_version, self.__version__)) self.setup() rt.plugin_versions[self._plugin_path] = self.__version__
def __init__(self, timeout=2.0, blacklist=None): GroupPlugin.__init__(self, self, gp_order=[ 'config', 'package', 'scheduler', 'paths', 'filesystem', 'plugin_versions', 'identity', 'device_info', 'remote_key', 'query', 'transformers', 'interfaces', 'intent', '*', 'skills', 'main_thread' ], gp_timeout=timeout, gp_daemon=True, gp_blacklist=blacklist) for name, thread in self._init_threads.items(): if thread.is_alive(): log.warning('Service init method taking too long for:', name)
def run_ordered_parallel(items, get_function, args, kwargs, order=None, daemon=False, label='', warn=False, custom_exception=None, custom_handler=None, timeout=None) \ -> Union[List[Any], Dict[str, Thread]]: order = order or [] if '*' not in order: order.append('*') if daemon and timeout is None: timeout = 0.0 return_vals = [] def run_item(item, name): return_val = safe_run(get_function(item), args=args, kwargs=kwargs, label=label + ' ' + name, warn=warn, custom_exception=custom_exception, custom_handler=custom_handler) return_vals.append(return_val) threads = {} for name in set(items) - set(order): threads[name] = Thread(target=run_item, args=(items[name], name), daemon=daemon) for name in order: if name == '*': for i in threads.values(): i.start() try: join_threads(threads.values(), timeout) except KeyboardInterrupt: log.error( 'KeyboardInterrupt joining threads:', [name for name, t in threads.items() if t.is_alive()]) raise elif name in items: run_item(items[name], name) else: log.warning('Plugin from runner load order not found:', name) if not daemon: return return_vals return threads
def warn_once(key, message, stack_offset=0): if key not in warned_keys: warned_keys.add(key) log.warning(message, stack_offset=stack_offset + 1)
def _log_exception(label, e, warn, stack_offset): if warn: log.warning(label, '--', e.__class__.__name__ + ':', e, stack_offset=stack_offset + 1) else: log.exception(label, stack_offset=stack_offset + 1)