Skip to content

Commit dabfc73

Browse files
committed
refactor/mutable_config (#13)
makes self.config_core a property, ensures we always get the latest mycroft.conf Configuration is a singleton, keeps an internal cache and reacts to bus events. This does not repeatedly read from disk
1 parent 72dfcab commit dabfc73

File tree

13 files changed

+168
-64
lines changed

13 files changed

+168
-64
lines changed

mycroft/api/__init__.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,22 @@ class Api:
4545

4646
def __init__(self, path):
4747
self.path = path
48+
self.identity = IdentityManager.get()
49+
self.disabled = is_backend_disabled()
4850

51+
@property
52+
def url(self):
4953
# Load the config, skipping the remote config since we are
5054
# getting the info needed to get to it!
51-
config = Configuration.get(cache=False, remote=False)
52-
config_server = config.get("server")
53-
self.url = config_server.get("url")
54-
self.version = config_server.get("version")
55-
self.identity = IdentityManager.get()
56-
self.disabled = is_backend_disabled()
55+
config = Configuration.get(cache=False, remote=False).get("server", {})
56+
return config.get("url")
57+
58+
@property
59+
def version(self):
60+
# Load the config, skipping the remote config since we are
61+
# getting the info needed to get to it!
62+
config = Configuration.get(cache=False, remote=False).get("server", {})
63+
return config.get("version")
5764

5865
def request(self, params):
5966
self.check_token()

mycroft/audio/audioservice.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ def __init__(self, bus):
201201
bus: Mycroft messagebus
202202
"""
203203
self.bus = bus
204-
self.config = Configuration.get().get("Audio")
205204
self.service_lock = Lock()
206205

207206
self.default = None
@@ -213,6 +212,10 @@ def __init__(self, bus):
213212
self._loaded = MonotonicEvent()
214213
self.load_services()
215214

215+
@property
216+
def config(self):
217+
return Configuration.get().get("Audio")
218+
216219
def load_services(self):
217220
"""Method for loading services.
218221

mycroft/client/enclosure/base.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,21 @@
3030

3131
class Enclosure:
3232
def __init__(self):
33-
# Load full config
34-
config = Configuration.get()
35-
self.lang = config['lang']
36-
self.config = config.get("enclosure")
37-
self.global_config = config
38-
3933
# Create Message Bus Client
4034
self.bus = MessageBusClient()
4135

36+
@property
37+
def lang(self):
38+
return self.global_config.get("lang", "en-us")
39+
40+
@property
41+
def config(self):
42+
return self.global_config.get("enclosure") or {}
43+
44+
@property
45+
def global_config(self):
46+
return Configuration.get()
47+
4248
def run(self):
4349
"""Start the Enclosure after it has been constructed."""
4450
# Allow exceptions to be raised to the Enclosure Service

mycroft/client/speech/listener.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,22 @@ def __init__(self, bus, watchdog=None, stt=None):
258258
def bind(self, stt):
259259
self.stt = stt
260260

261+
@property
262+
def config_core(self):
263+
return Configuration.get()
264+
265+
@property
266+
def config(self):
267+
self._config_hash = recognizer_conf_hash(self.config_core)
268+
return self.config_core.get('listener')
269+
270+
@property
271+
def lang(self):
272+
return self.config_core.get('lang', "en-us")
273+
261274
def _load_config(self):
262275
"""Load configuration parameters from configuration."""
263-
config = Configuration.get()
264-
self.config_core = config
265-
self._config_hash = recognizer_conf_hash(config)
266-
self.lang = config.get('lang')
267-
self.config = config.get('listener')
268276
rate = self.config.get('sample_rate')
269-
270277
device_index = self.config.get('device_index')
271278
device_name = self.config.get('device_name')
272279
if not device_index and device_name:

mycroft/client/speech/mic.py

Lines changed: 88 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -332,30 +332,9 @@ class ResponsiveRecognizer(speech_recognition.Recognizer):
332332
def __init__(self, loop, watchdog=None):
333333
self.loop = loop
334334
self._watchdog = watchdog or (lambda: None) # Default to dummy func
335-
self.config = Configuration.get()
336-
listener_config = self.config.get('listener')
337-
self.instant_listen = listener_config.get("instant_listen", False)
338-
self.upload_url = listener_config['wake_word_upload']['url']
339-
self.upload_disabled = listener_config['wake_word_upload']['disable']
340-
341-
self.overflow_exc = listener_config.get('overflow_exception', False)
342335

343336
super().__init__()
344337
self.audio = pyaudio.PyAudio()
345-
self.multiplier = listener_config.get('multiplier')
346-
self.energy_ratio = listener_config.get('energy_ratio')
347-
348-
# Check the config for the flag to save wake words, utterances
349-
# and for a path under which to save them
350-
self.save_utterances = listener_config.get('save_utterances', False)
351-
self.save_wake_words = listener_config.get('record_wake_words', False)
352-
self.save_path = listener_config.get('save_path', gettempdir())
353-
self.saved_wake_words_dir = join(self.save_path, 'mycroft_wake_words')
354-
if self.save_wake_words:
355-
os.makedirs(self.saved_wake_words_dir, exist_ok=True)
356-
self.saved_utterances_dir = join(self.save_path, 'mycroft_utterances')
357-
if self.save_utterances:
358-
os.makedirs(self.saved_utterances_dir, exist_ok=True)
359338

360339
# Signal statuses
361340
self._stop_signaled = False
@@ -366,22 +345,103 @@ def __init__(self, loop, watchdog=None):
366345
# identifier used when uploading wakewords to selene
367346
self._account_id = None
368347

348+
@property
349+
def config(self):
350+
return Configuration.get()
351+
352+
@property
353+
def instant_listen(self):
354+
listener_config = self.config.get('listener') or {}
355+
return listener_config.get("instant_listen", False)
356+
357+
@property
358+
def overflow_exc(self):
359+
listener_config = self.config.get('listener') or {}
360+
return listener_config.get('overflow_exception', False)
361+
362+
@property
363+
def upload_url(self):
364+
listener_config = self.config.get('listener') or {}
365+
return listener_config['wake_word_upload']['url']
366+
367+
@property
368+
def upload_disabled(self):
369+
listener_config = self.config.get('listener') or {}
370+
return listener_config['wake_word_upload']['disable']
371+
372+
@property
373+
def multiplier(self):
374+
listener_config = self.config.get('listener') or {}
375+
return listener_config.get('multiplier')
376+
377+
@property
378+
def energy_ratio(self):
379+
listener_config = self.config.get('listener') or {}
380+
return listener_config.get('energy_ratio')
381+
382+
@property
383+
def save_utterances(self):
384+
listener_config = self.config.get('listener') or {}
385+
return listener_config.get('save_utterances', False)
386+
387+
@property
388+
def save_wake_words(self):
389+
listener_config = self.config.get('listener') or {}
390+
return listener_config.get('record_wake_words', False)
391+
392+
@property
393+
def save_path(self):
394+
listener_config = self.config.get('listener') or {}
395+
return listener_config.get('save_path', gettempdir())
396+
397+
@property
398+
def saved_wake_words_dir(self):
399+
path = join(self.save_path, 'mycroft_wake_words')
400+
if self.save_wake_words:
401+
os.makedirs(path, exist_ok=True)
402+
return path
403+
404+
@property
405+
def saved_utterances_dir(self):
406+
path = join(self.save_path, 'mycroft_utterances')
407+
if self.save_wake_words:
408+
os.makedirs(path, exist_ok=True)
409+
return path
410+
411+
@property
412+
def recording_timeout(self):
369413
# The maximum seconds a phrase can be recorded,
370414
# provided there is noise the entire time
371-
self.recording_timeout = listener_config.get('recording_timeout', 10.0)
415+
listener_config = self.config.get('listener') or {}
416+
return listener_config.get('recording_timeout', 10.0)
417+
418+
@property
419+
def recording_timeout_with_silence(self):
372420
# The maximum time it will continue to record silence
373421
# when not enough noise has been detected
374-
self.recording_timeout_with_silence = listener_config.get('recording_timeout_with_silence', 3.0)
375-
# mic meter settings, will write mic level to ipc, used by debug_cli
376-
# NOTE: this writes a lot to disk, it can be problematic in a sd card if you don't use a tmpfs for ipc
422+
listener_config = self.config.get('listener') or {}
423+
return listener_config.get('recording_timeout_with_silence', 3.0)
424+
425+
@property
426+
def mic_level_file(self):
377427
ipc = get_ipc_directory()
378428
os.makedirs(ipc, exist_ok=True)
379-
self.mic_level_file = os.path.join(ipc, "mic_level")
380-
self.mic_meter_ipc_enabled = listener_config.get("mic_meter_ipc", True)
429+
return os.path.join(ipc, "mic_level")
381430

431+
@property
432+
def mic_meter_ipc_enabled(self):
433+
# mic meter settings, will write mic level to ipc, used by debug_cli
434+
# NOTE: this writes a lot to disk
435+
# can be problematic in a sd card if you don't use a tmpfs for ipc
436+
listener_config = self.config.get('listener') or {}
437+
return listener_config.get("mic_meter_ipc", True)
438+
439+
@property
440+
def test_ww_sec(self):
382441
# The maximum audio in seconds to keep for transcribing a phrase
383442
# The wake word must fit in this time
384-
self.test_ww_sec = listener_config.get("test_ww_sec", 3)
443+
listener_config = self.config.get('listener') or {}
444+
return listener_config.get("test_ww_sec", 3)
385445

386446
@property
387447
def account_id(self):

mycroft/client/speech/service.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ def __init__(self, on_ready=on_ready, on_error=on_error,
5151
self.status = ProcessStatus('speech', callback_map=callbacks)
5252
self.status.set_started()
5353

54-
self.config = Configuration.get()
5554
self.bus = start_message_bus_client("VOICE")
5655
self.connect_bus_events()
5756
self.status.bind(self.bus)
@@ -60,6 +59,10 @@ def __init__(self, on_ready=on_ready, on_error=on_error,
6059
self.loop = RecognizerLoop(self.bus, watchdog)
6160
self.connect_loop_events()
6261

62+
@property
63+
def config(self):
64+
return Configuration.get()
65+
6366
# loop events
6467
def handle_record_begin(self):
6568
"""Forward internal bus message to external bus."""
@@ -188,7 +191,7 @@ def handle_stop(self, event):
188191
def handle_open(self):
189192
# TODO: Move this into the Enclosure (not speech client)
190193
# Reset the UI to indicate ready for speech processing
191-
EnclosureAPI(bus).reset()
194+
EnclosureAPI(self.bus).reset()
192195

193196
def connect_loop_events(self):
194197
self.loop.on('recognizer_loop:utterance', self.handle_utterance)
@@ -229,7 +232,3 @@ def run(self):
229232
except Exception as e:
230233
self.status.set_error(e)
231234
self.status.set_stopping()
232-
233-
234-
if __name__ == "__main__":
235-
main()

mycroft/gui/service.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
class GUIService:
2727
def __init__(self):
28-
self.global_config = Configuration.get()
2928
# Create Message Bus Client
3029
self.bus = MessageBusClient()
3130

@@ -64,6 +63,10 @@ def __init__(self):
6463
self.bus.on("gui.event.send", self.on_gui_send_event)
6564
self.bus.on("gui.status.request", self.handle_gui_status_request)
6665

66+
@property
67+
def global_config(self):
68+
return Configuration.get()
69+
6770
def create_gui_socket(self):
6871
import tornado.options
6972
LOG.info('Starting message bus for GUI...')

mycroft/skills/intent_services/adapt_service.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,21 +175,24 @@ class AdaptService:
175175
def __init__(self, config):
176176
self.config = config
177177

178-
self.lang = Configuration.get().get("lang", "en-us")
179178
langs = Configuration.get().get('secondary_langs') or []
180179
if self.lang not in langs:
181180
langs.append(self.lang)
182181

183182
self.engines = {lang: IntentDeterminationEngine()
184183
for lang in langs}
185-
# Context related intializations
184+
# Context related initializations
186185
self.context_keywords = self.config.get('keywords', [])
187186
self.context_max_frames = self.config.get('max_frames', 3)
188187
self.context_timeout = self.config.get('timeout', 2)
189188
self.context_greedy = self.config.get('greedy', False)
190189
self.context_manager = ContextManager(self.context_timeout)
191190
self.lock = Lock()
192191

192+
@property
193+
def lang(self):
194+
return Configuration.get().get("lang", "en-us")
195+
193196
def update_context(self, intent):
194197
"""Updates context with keyword from the intent.
195198

mycroft/skills/intent_services/padatious_service.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ def __init__(self, bus, config):
116116
intent_cache = expanduser(self.padatious_config['intent_cache'])
117117
self._padaos = self.padatious_config.get("padaos_only", False)
118118

119-
self.lang = Configuration.get().get("lang", "en-us")
120119
langs = Configuration.get().get('secondary_langs') or []
121120
if self.lang not in langs:
122121
langs.append(self.lang)
@@ -157,6 +156,10 @@ def __init__(self, bus, config):
157156
self.registered_intents = []
158157
self.registered_entities = []
159158

159+
@property
160+
def lang(self):
161+
return Configuration.get().get("lang", "en-us")
162+
160163
def train(self, message=None):
161164
"""Perform padatious training.
162165

mycroft/skills/mycroft_skill/mycroft_skill.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,6 @@ def __init__(self, name=None, bus=None, use_settings=True, skill_id=""):
139139
self._bus = None
140140
self._enclosure = EnclosureAPI(bus)
141141

142-
#: Mycroft global configuration. (dict)
143-
self.config_core = Configuration.get()
144-
145142
self.settings = {}
146143
self._initial_settings = {}
147144
self.settings_write_path = None
@@ -183,6 +180,13 @@ def __init__(self, name=None, bus=None, use_settings=True, skill_id=""):
183180
if bus and skill_id:
184181
self._startup(bus, skill_id)
185182

183+
@property
184+
def config_core(self):
185+
""" reads mycroft.conf
186+
contains and internal cache and integrates with the bus
187+
"""
188+
return Configuration.get()
189+
186190
@property
187191
def is_fully_initialized(self):
188192
return self._init_event.is_set()
@@ -366,7 +370,7 @@ def _core_lang(self):
366370
NOTE: this should be public, but since if a skill uses this it wont
367371
work in regular mycroft-core it was made private! Equivalent PRs in
368372
mycroft-core have been rejected/abandoned"""
369-
return Configuration.get().get("lang", "en-us").lower()
373+
return self.config_core.get("lang", "en-us").lower()
370374

371375
@property
372376
def _secondary_langs(self):

0 commit comments

Comments
 (0)