def _move_config_sections(user_config, local_config): """ Temporary method to handle one-time migration of user_config params to local_config Args: user_config (NGIConfig): user configuration object local_config (NGIConfig): local configuration object """ depreciated_user_configs = ("interface", "listener", "skills", "session", "tts", "stt", "logs", "device") if any([d in user_config.content for d in depreciated_user_configs]): LOG.warning( "Depreciated keys found in user config! Adding them to local config" ) if "wake_words_enabled" in user_config.content.get( "interface", dict()): user_config["interface"]["wake_word_enabled"] = user_config[ "interface"].pop("wake_words_enabled") config_to_move = { "interface": user_config.content.pop("interface", {}), "listener": user_config.content.pop("listener", {}), "skills": user_config.content.pop("skills", {}), "session": user_config.content.pop("session", {}), "tts": user_config.content.pop("tts", {}), "stt": user_config.content.pop("stt", {}), "logs": user_config.content.pop("logs", {}), "device": user_config.content.pop("device", {}) } local_config.update_keys(config_to_move)
def get_config_dir(): """ Get a default directory in which to find configuration files Returns: Path to configuration or else default """ site = sysconfig.get_paths()['platlib'] if exists(join(site, 'NGI')): return join(site, "NGI") for p in [path for path in sys.path if path != ""]: if exists(join(p, "NGI")): return join(p, "NGI") if re.match(".*/lib/python.*/site-packages", p): clean_path = "/".join(p.split("/")[0:-4]) if exists(join(clean_path, "NGI")): LOG.warning( f"Depreciated core structure found at {clean_path}") return join(clean_path, "NGI") elif exists(join(clean_path, "neon_core")): # Dev Environment return clean_path elif exists(join(clean_path, "mycroft")): LOG.info(f"Mycroft core structure found at {clean_path}") return clean_path elif exists(join(clean_path, ".venv")): # Localized Production Environment (Servers) return clean_path default_path = expanduser("~/.local/share/neon") # LOG.info(f"System packaged core found! Using default configuration at {default_path}") return default_path
def get_neon_lang_config() -> dict: """ Get a language config for language utilities Returns: dict of config params used by Language Detector and Translator modules """ core_config = get_neon_local_config() language_config = deepcopy(get_neon_user_config().content.get( "speech", {})) language_config["internal"] = language_config.get( "internal", "en-us") # TODO: This is core, not user DM language_config["user"] = language_config.get("stt_language", "en-us") language_config["boost"] = False language_config["detection_module"] = core_config.get( "stt", {}).get("detection_module") language_config["translation_module"] = core_config.get( "stt", {}).get("translation_module") merged_language = { **_safe_mycroft_config().get("language", {}), **language_config } if merged_language.keys() != language_config.keys(): LOG.warning(f"Keys missing from Neon config! {merged_language.keys()}") return merged_language
def get_neon_skills_config() -> dict: """ Get a configuration dict for the skills module. Merge any values from Mycroft config if missing from Neon. Returns: dict of config params used for the Mycroft Skills module """ core_config = get_neon_local_config() mycroft_config = _safe_mycroft_config() neon_skills = deepcopy(core_config.get("skills", {})) neon_skills["directory"] = os.path.expanduser(core_config["dirVars"].get("skillsDir")) neon_skills["disable_osm"] = neon_skills["skill_manager"] != "osm" if not isinstance(neon_skills["auto_update_interval"], float): try: neon_skills["auto_update_interval"] = float(neon_skills["auto_update_interval"]) except Exception as e: LOG.error(e) neon_skills["auto_update_interval"] = 24.0 if not isinstance(neon_skills["appstore_sync_interval"], float): try: neon_skills["appstore_sync_interval"] = float(neon_skills["appstore_sync_interval"]) except Exception as e: LOG.error(e) neon_skills["appstore_sync_interval"] = 6.0 neon_skills["update_interval"] = neon_skills["auto_update_interval"] # Backwards Compat. if not neon_skills["neon_token"]: try: neon_skills["neon_token"] = find_neon_git_token() # TODO: GetPrivateKeys populate_github_token_config(neon_skills["neon_token"]) except FileNotFoundError: LOG.warning(f"No Github token found; skills may fail to install!") skills_config = {**mycroft_config.get("skills", {}), **neon_skills} return skills_config
def dict_make_equal_keys(dct_to_change: MutableMapping, keys_dct: MutableMapping, max_depth: int = 1, cur_depth: int = 0) -> MutableMapping: """ Adds and removes keys from dct_to_change such that it has the same keys as keys_dct. Values from dct_to_change are preserved with any added keys using default values from keys_dct. Args: dct_to_change: Dict of user preferences to modify and return keys_dct: Dict containing all keys and default values max_depth: Int depth to recurse (0-indexed) cur_depth: Current depth relative to top-level config (0-indexed) Returns: dct_to_change with any keys not in keys_dct removed and any new keys added with default values """ if not isinstance(dct_to_change, MutableMapping) or not isinstance(keys_dct, MutableMapping): raise AttributeError("merge_recursive_dicts expects two dict objects as args") for key in list(dct_to_change.keys()): if isinstance(keys_dct.get(key), dict) and isinstance(dct_to_change[key], MutableMapping): if max_depth > cur_depth and key not in ("tts", "stt"): dct_to_change[key] = dict_make_equal_keys(dct_to_change[key], keys_dct[key], max_depth, cur_depth + 1) elif key not in keys_dct.keys(): dct_to_change.pop(key) LOG.warning(f"Removing '{key}' from dict!") # del dct_to_change[key] for key, value in keys_dct.items(): if key not in dct_to_change.keys(): dct_to_change[key] = value return dct_to_change
def get_neon_client_config() -> dict: core_config = get_neon_local_config() server_addr = core_config.get("remoteVars", {}).get("remoteHost", "167.172.112.7") if server_addr == "64.34.186.92": LOG.warning(f"Depreciated call to host: {server_addr}") server_addr = "167.172.112.7" return {"server_addr": server_addr, "devVars": core_config["devVars"], "remoteVars": core_config["remoteVars"]}
def populate(self, content, check_existing=False): if not check_existing: self.__add__(content) return old_content = deepcopy(self._content) self._content = dict_merge(content, self._content) # to_change, one_with_all_keys if old_content == self._content: LOG.warning(f"Update called with no change: {self.file_path}") return self._write_yaml_file()
def get_neon_bus_config() -> dict: """ Get a configuration dict for the messagebus. Merge any values from Mycroft config if missing from Neon. Returns: dict of config params used for a messagebus client """ mycroft = _safe_mycroft_config().get("websocket", {}) neon = get_neon_local_config().get("websocket", {}) merged = {**mycroft, **neon} if merged.keys() != neon.keys(): LOG.warning(f"Keys missing from Neon config! {merged.keys()}") return merged
def get_neon_api_config() -> dict: """ Get a configuration dict for the api module. Merge any values from Mycroft config if missing from Neon. Returns: dict of config params used for the Mycroft API module """ core_config = get_neon_local_config() api_config = deepcopy(core_config.get("api")) api_config["metrics"] = core_config["prefFlags"].get("metrics", False) mycroft = _safe_mycroft_config().get("server", {}) merged = {**mycroft, **api_config} if merged.keys() != api_config.keys(): LOG.warning(f"Keys missing from Neon config! {merged.keys()}") return merged
def update_keys(self, other): """ Adds keys to this config such that it has all keys in 'other'. Configuration values are preserved with any added keys using default values from 'other'. Args: other: dict of keys and default values this should be added to this configuration """ old_content = deepcopy(self._content) self._content = dict_update_keys(self._content, other) # to_change, one_with_all_keys if old_content == self._content: LOG.warning(f"Update called with no change: {self.file_path}") return self._write_yaml_file()
def get_neon_audio_config() -> dict: """ Get a configuration dict for the audio module. Merge any values from Mycroft config if missing from Neon. Returns: dict of config params used for the Audio module """ mycroft = _safe_mycroft_config() local_config = get_neon_local_config() neon_audio = local_config.get("audioService", {}) merged_audio = {**mycroft.get("Audio", {}), **neon_audio} if merged_audio.keys() != neon_audio.keys(): LOG.warning(f"Keys missing from Neon config! {merged_audio.keys()}") return {"Audio": merged_audio, "tts": get_neon_tts_config(), "language": get_neon_lang_config()}
def create(config=None, results_event: Event = None): if config and not config.get( "module" ): # No module, try getting stt config from passed config config = config.get("stt") if not config: # No config, go get it config = get_neon_speech_config().get("stt", {}) LOG.info(f"Create STT with config: {config}") clazz = OVOSSTTFactory.get_class(config) if not clazz: LOG.warning("plugin not found, falling back to Chromium STT") config["module"] = "google" # TODO configurable fallback plugin clazz = OVOSSTTFactory.get_class(config) if not clazz: raise ValueError("fallback plugin not found") return WrappedSTT(clazz, config=config, results_event=results_event)
def get_neon_speech_config() -> dict: """ Get a configuration dict for listener. Merge any values from Mycroft config if missing from Neon. Returns: dict of config params used for listener in neon_speech """ mycroft = _safe_mycroft_config() local_config = get_neon_local_config() neon_listener_config = deepcopy(local_config.get("listener", {})) neon_listener_config["wake_word_enabled"] = local_config["interface"].get("wake_word_enabled", True) neon_listener_config["save_utterances"] = local_config["prefFlags"].get("saveAudio", False) neon_listener_config["confirm_listening"] = local_config["interface"].get("confirm_listening", True) neon_listener_config["record_utterances"] = neon_listener_config["save_utterances"] neon_listener_config["record_wake_words"] = neon_listener_config["save_utterances"] merged_listener = {**mycroft.get("listener", {}), **neon_listener_config} if merged_listener.keys() != neon_listener_config.keys(): LOG.warning(f"Keys missing from Neon config! {merged_listener.keys()}") lang = mycroft.get("language", {}).get("internal", "en-us") # core_lang neon_stt_config = local_config.get("stt", {}) merged_stt_config = {**mycroft.get("stt", {}), **neon_stt_config} if merged_stt_config.keys() != neon_stt_config.keys(): LOG.warning(f"Keys missing from Neon config! {merged_stt_config.keys()}") hotword_config = local_config.get("hotwords") or mycroft.get("hotwords") if hotword_config != local_config.get("hotwords"): LOG.warning(f"Neon hotword config missing! {hotword_config}") neon_audio_parser_config = local_config.get("audio_parsers", {}) merged_audio_parser_config = {**mycroft.get("audio_parsers", {}), **neon_audio_parser_config} if merged_audio_parser_config.keys() != neon_audio_parser_config.keys(): LOG.warning(f"Keys missing from Neon config! {merged_audio_parser_config.keys()}") return {"listener": merged_listener, "hotwords": hotword_config, "audio_parsers": merged_audio_parser_config, "lang": lang, "stt": merged_stt_config, "metric_upload": local_config["prefFlags"].get("metrics", False), "remote_server": local_config.get("remoteVars", {}).get("remoteHost", "64.34.186.120"), "data_dir": os.path.expanduser(local_config.get("dirVars", {}).get("rootDir") or "~/.local/share/neon"), "keys": {} # TODO: Read from somewhere DM }