implemented a stop-gap change to keep the skill API from breaking

pull/2287/head
Chris Veilleux 2019-09-04 13:11:45 -05:00 committed by Åke Forslund
parent 5c742d2ed0
commit b1a63638c1
3 changed files with 103 additions and 13 deletions

View File

@ -44,7 +44,7 @@ from mycroft.util.log import LOG
from .event_container import EventContainer, create_wrapper, get_handler_name
from ..event_scheduler import EventSchedulerInterface
from ..intent_service_interface import IntentServiceInterface
from ..settings import get_local_settings, save_settings
from ..settings import save_settings, Settings
from ..skill_data import (
load_vocabulary,
load_regex,
@ -129,7 +129,7 @@ class MycroftSkill:
# Get directory of skill
self.root_dir = dirname(abspath(sys.modules[self.__module__].__file__))
if use_settings:
self.settings = get_local_settings(self.root_dir, self.name)
self.settings = Settings(self)
else:
self.settings = None
self.settings_change_callback = None

View File

@ -74,14 +74,17 @@ ONE_MINUTE = 60
def get_local_settings(skill_dir, skill_name) -> dict:
"""Build a dictionary using the JSON string stored in settings.json."""
settings_path = Path(skill_dir).joinpath('settings.json')
with open(str(settings_path)) as settings_file:
try:
skill_settings = json.load(settings_file)
# TODO change to check for JSONDecodeError in 19.08
except Exception:
log_msg = 'Failed to load {} settings from settings.json'
LOG.exception(log_msg.format(skill_name))
skill_settings = {}
if settings_path.is_file():
with open(str(settings_path)) as settings_file:
try:
skill_settings = json.load(settings_file)
# TODO change to check for JSONDecodeError in 19.08
except Exception:
log_msg = 'Failed to load {} settings from settings.json'
LOG.exception(log_msg.format(skill_name))
skill_settings = {}
else:
skill_settings = {}
return skill_settings
@ -362,3 +365,36 @@ class SkillSettingsDownloader:
data={skill_gid: remote_settings}
)
self.bus.emit(message)
# TODO: remove in 20.02
class Settings:
def __init__(self, skill):
self._skill = skill
self._settings = get_local_settings(skill.root_dir, skill.name)
def __getattr__(self, attr):
if attr not in ['store', 'set_changed_callback']:
return getattr(self._settings, attr)
else:
return super().getattr(attr)
def __setitem__(self, key, val):
self._settings[key] = val
def __getitem__(self, key):
return self._settings[key]
def __iter__(self):
return iter(self._settings)
def __contains__(self, key):
return key in self._settings
def store(self, force=False):
LOG.warning('DEPRECATED - use mycroft.skills.settings.save_settings()')
save_settings(self._skill.root_dir, self._settings)
def set_changed_callback(self, callback):
LOG.warning('DEPRECATED - set the settings_changed_callback attribute')
self._skill.settings_change_callback = callback

View File

@ -13,13 +13,15 @@
# limitations under the License.
#
import json
from unittest.mock import call, Mock, patch
from os import remove
import tempfile
from pathlib import Path
from unittest import TestCase
from unittest.mock import call, Mock, patch
from mycroft.skills.settings import (
SkillSettingsDownloader,
SettingsMetaUploader
SettingsMetaUploader,
Settings
)
from ..base import MycroftUnitTestBase
@ -287,3 +289,55 @@ class TestSettingsDownloader(MycroftUnitTestBase):
[remote_skill_settings],
self.message_bus_mock.message_data
)
class TestSettings(TestCase):
def setUp(self) -> None:
temp_dir = tempfile.mkdtemp()
self.temp_dir = Path(temp_dir)
self.skill_mock = Mock()
self.skill_mock.root_dir = str(self.temp_dir)
self.skill_mock.name = 'test_skill'
def test_empty_settings(self):
settings = Settings(self.skill_mock)
self.assertDictEqual(settings._settings, {})
def test_settings_file_exists(self):
settings_path = self.temp_dir.joinpath('settings.json')
with open(settings_path, 'w') as settings_file:
settings_file.write('{"foo": "bar"}\n')
settings = Settings(self.skill_mock)
self.assertDictEqual(settings._settings, {'foo': 'bar'})
self.assertEqual(settings['foo'], 'bar')
self.assertNotIn('store', settings)
self.assertIn('foo', settings)
def test_change_settings(self):
settings = Settings(self.skill_mock)
settings['foo'] = 'bar'
self.assertDictEqual(settings._settings, {'foo': 'bar'})
self.assertIn('foo', settings)
def test_store_settings(self):
settings = Settings(self.skill_mock)
settings['foo'] = 'bar'
settings.store()
settings_path = self.temp_dir.joinpath('settings.json')
with open(settings_path) as settings_file:
file_contents = settings_file.read()
self.assertEqual(file_contents, '{"foo": "bar"}')
def test_set_changed_callback(self):
def test_callback():
pass
settings = Settings(self.skill_mock)
settings.set_changed_callback(test_callback)
self.assertEqual(
self.skill_mock.settings_change_callback,
test_callback
)