1
0
Fork 0
mirror of https://gitlab.alpinelinux.org/alpine/aports.git synced 2025-07-23 19:25:25 +03:00
aports/testing/mycroft-core/0002-follow-xdg-for-skill-settings.patch
2020-05-09 17:24:24 +00:00

204 lines
8.4 KiB
Diff

Upstream pull-request: https://github.com/MycroftAI/mycroft-core/pull/2559
diff --git a/mycroft/skills/mycroft_skill/mycroft_skill.py b/mycroft/skills/mycroft_skill/mycroft_skill.py
index 4f3b6d9da6..d60a3279d0 100644
--- a/mycroft/skills/mycroft_skill/mycroft_skill.py
+++ b/mycroft/skills/mycroft_skill/mycroft_skill.py
@@ -21,8 +21,11 @@ import traceback
from itertools import chain
from os import walk
from os.path import join, abspath, dirname, basename, exists
+from pathlib import Path
from threading import Event, Timer
+from xdg import BaseDirectory
+
from adapt.intent import Intent, IntentBuilder
from mycroft import dialog
@@ -113,6 +116,7 @@ class MycroftSkill:
bus (MycroftWebsocketClient): Optional bus connection
use_settings (bool): Set to false to not use skill settings at all
"""
+
def __init__(self, name=None, bus=None, use_settings=True):
self.name = name or self.__class__.__name__
self.resting_name = None
@@ -123,16 +127,6 @@ class MycroftSkill:
#: Member variable containing the absolute path of the skill's root
#: directory. E.g. /opt/mycroft/skills/my-skill.me/
self.root_dir = dirname(abspath(sys.modules[self.__module__].__file__))
- if use_settings:
- self.settings = get_local_settings(self.root_dir, self.name)
- self._initial_settings = deepcopy(self.settings)
- else:
- self.settings = None
-
- #: Set to register a callback method that will be called every time
- #: the skills settings are updated. The referenced method should
- #: include any logic needed to handle the updated settings.
- self.settings_change_callback = None
self.gui = SkillGUI(self)
@@ -141,6 +135,19 @@ class MycroftSkill:
self.bind(bus)
#: Mycroft global configuration. (dict)
self.config_core = Configuration.get()
+
+ self.settings = None
+ self.settings_write_path = None
+ self.settings_read_path = None
+
+ if use_settings:
+ self._init_settings()
+
+ #: Set to register a callback method that will be called every time
+ #: the skills settings are updated. The referenced method should
+ #: include any logic needed to handle the updated settings.
+ self.settings_change_callback = None
+
self.dialog_renderer = None
#: Filesystem access to skill specific folder.
@@ -157,6 +164,42 @@ class MycroftSkill:
self.event_scheduler = EventSchedulerInterface(self.name)
self.intent_service = IntentServiceInterface()
+ def _init_settings(self):
+ """Setup skill settings."""
+
+ # To not break existing setups,
+ # save to skill directory if the file exists already
+ self.settings_write_path = Path(self.root_dir)
+
+ # Otherwise save to XDG_CONFIG_DIR
+ if not self.settings_write_path.joinpath('settings.json').exists():
+ self.settings_write_path = Path(BaseDirectory.save_config_path(
+ 'mycroft', 'skills', basename(self.root_dir)))
+
+ # To not break existing setups,
+ # read from skill directory if the settings file exists there
+ self.settings_read_path = Path(self.root_dir)
+
+ # Then, check XDG_CONFIG_DIR
+ if not self.settings_read_path.joinpath('settings.json').exists():
+ for dir in BaseDirectory.load_config_paths('mycroft',
+ 'skills',
+ basename(
+ self.root_dir)):
+ path = Path(dir)
+ #: If there is a settings file here, use it
+ if path.joinpath('settings.json').exists():
+ self.settings_read_path = path
+ break
+
+ # Lastly, check /etc/mycroft
+ if not self.settings_read_path.joinpath('settings.json').exists():
+ self.settings_read_path = Path(
+ '/etc/mycroft/skills/').joinpath(basename(self.root_dir))
+
+ self.settings = get_local_settings(self.settings_read_path, self.name)
+ self._initial_settings = deepcopy(self.settings)
+
@property
def enclosure(self):
if self._enclosure:
@@ -271,7 +314,7 @@ class MycroftSkill:
if remote_settings is not None:
LOG.info('Updating settings for skill ' + self.name)
self.settings.update(**remote_settings)
- save_settings(self.root_dir, self.settings)
+ save_settings(self.settings_write_path, self.settings)
if self.settings_change_callback is not None:
self.settings_change_callback()
@@ -544,7 +587,7 @@ class MycroftSkill:
if not voc or not exists(voc):
raise FileNotFoundError(
- 'Could not find {}.voc file'.format(voc_filename))
+ 'Could not find {}.voc file'.format(voc_filename))
# load vocab and flatten into a simple list
vocab = read_vocab_file(voc)
self.voc_match_cache[cache_key] = list(chain(*vocab))
@@ -811,7 +854,7 @@ class MycroftSkill:
"""Store settings and indicate that the skill handler has completed
"""
if self.settings != self._initial_settings:
- save_settings(self.root_dir, self.settings)
+ save_settings(self.settings_write_path, self.settings)
self._initial_settings = self.settings
if handler_info:
msg_type = handler_info + '.complete'
@@ -1233,7 +1276,7 @@ class MycroftSkill:
# Store settings
if self.settings != self._initial_settings:
- save_settings(self.root_dir, self.settings)
+ save_settings(self.settings_write_path, self.settings)
if self.settings_meta:
self.settings_meta.stop()
diff --git a/mycroft/skills/settings.py b/mycroft/skills/settings.py
index c210625f5b..f576b34c9e 100644
--- a/mycroft/skills/settings.py
+++ b/mycroft/skills/settings.py
@@ -93,18 +93,22 @@ def get_local_settings(skill_dir, skill_name) -> dict:
def save_settings(skill_dir, skill_settings):
"""Save skill settings to file."""
settings_path = Path(skill_dir).joinpath('settings.json')
- if Path(skill_dir).exists():
- with open(str(settings_path), 'w') as settings_file:
- try:
- json.dump(skill_settings, settings_file)
- except Exception:
- LOG.exception('error saving skill settings to '
- '{}'.format(settings_path))
- else:
- LOG.info('Skill settings successfully saved to '
- '{}' .format(settings_path))
- else:
- LOG.info('Skill folder no longer exists, can\'t save settings.')
+
+ # Either the file already exists in /opt, or we are writing
+ # to XDG_CONFIG_DIR and always have the permission to make
+ # sure the file always exists
+ if not Path(settings_path).exists():
+ settings_path.touch(mode=0o644)
+
+ with open(str(settings_path), 'w') as settings_file:
+ try:
+ json.dump(skill_settings, settings_file)
+ except Exception:
+ LOG.exception('error saving skill settings to '
+ '{}'.format(settings_path))
+ else:
+ LOG.info('Skill settings successfully saved to '
+ '{}' .format(settings_path))
def get_display_name(skill_name: str):
diff --git a/mycroft/skills/skill_loader.py b/mycroft/skills/skill_loader.py
index 2402740188..b7e8186967 100644
--- a/mycroft/skills/skill_loader.py
+++ b/mycroft/skills/skill_loader.py
@@ -259,7 +259,8 @@ class SkillLoader:
if first_run:
LOG.info("First run of " + self.skill_id)
self.instance.settings["__mycroft_skill_firstrun"] = False
- save_settings(self.skill_directory, self.instance.settings)
+ save_settings(self.instance.settings_write_path,
+ self.instance.settings)
intro = self.instance.get_intro_message()
if intro:
self.instance.speak(intro)
diff --git a/requirements.txt b/requirements.txt
index 509436fb89..c9358db687 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -30,3 +30,4 @@ fann2==1.0.7
padaos==0.1.9
precise-runner==0.2.1
petact==0.1.2
+pyxdg==0.26