SettingLoader.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. import logging
  2. from YAMLLoader import YAMLLoader
  3. from core.FileManager import FileManager
  4. from core.Models import Singleton
  5. from core.Models.RestAPI import RestAPI
  6. from core.Models.Settings import Settings
  7. from core.Models.Stt import Stt
  8. from core.Models.Trigger import Trigger
  9. from core.Models.Tts import Tts
  10. FILE_NAME = "settings.yml"
  11. logging.basicConfig()
  12. logger = logging.getLogger("kalliope")
  13. class SettingInvalidException(Exception):
  14. """
  15. Some data must match the expected value/type
  16. .. seealso:: Settings
  17. """
  18. pass
  19. class NullSettingException(Exception):
  20. """
  21. Some Attributes can not be Null
  22. .. seealso:: Settings
  23. """
  24. pass
  25. class SettingNotFound(Exception):
  26. """
  27. Some Attributes are missing
  28. .. seealso:: Settings
  29. """
  30. pass
  31. @Singleton
  32. class SettingLoader(object):
  33. """
  34. This Class is used to get the Settings YAML and the Settings as an object
  35. """
  36. def __init__(self, file_path=None):
  37. logger.debug("Loading settings with file path: %s" % file_path)
  38. self.file_path = file_path
  39. if self.file_path is None:
  40. # use default file if not provided
  41. self.file_path = FILE_NAME
  42. self.yaml_config = self._get_yaml_config()
  43. self.settings = self._get_settings()
  44. def _get_yaml_config(self):
  45. """
  46. Class Methods which loads default or the provided YAML file and return it as a String
  47. :return: The loaded settings YAML
  48. :rtype: dict
  49. :Example:
  50. settings_yaml = SettingLoader.get_yaml_config(/var/tmp/settings.yml)
  51. .. warnings:: Class Method
  52. """
  53. return YAMLLoader.get_config(self.file_path)
  54. def _get_settings(self):
  55. """
  56. Class Methods which loads default or the provided YAML file and return a Settings Object
  57. :return: The loaded Settings
  58. :rtype: Settings
  59. :Example:
  60. settings = SettingLoader.get_settings(file_path="/var/tmp/settings.yml")
  61. .. seealso:: Settings
  62. .. warnings:: Class Method
  63. """
  64. # create a new setting
  65. setting_object = Settings()
  66. # Get the setting parameters
  67. settings = self._get_yaml_config()
  68. default_stt_name = self._get_default_speech_to_text(settings)
  69. default_tts_name = self._get_default_text_to_speech(settings)
  70. default_trigger_name = self._get_default_trigger(settings)
  71. stts = self._get_stts(settings)
  72. ttss = self._get_ttss(settings)
  73. triggers = self._get_triggers(settings)
  74. random_wake_up_answers = self._get_random_wake_up_answers(settings)
  75. random_wake_up_sounds = self._get_random_wake_up_sounds(settings)
  76. rest_api = self._get_rest_api(settings)
  77. cache_path = self._get_cache_path(settings)
  78. # Load the setting singleton with the parameters
  79. setting_object.default_tts_name = default_tts_name
  80. setting_object.default_stt_name = default_stt_name
  81. setting_object.default_trigger_name = default_trigger_name
  82. setting_object.stts = stts
  83. setting_object.ttss = ttss
  84. setting_object.triggers = triggers
  85. setting_object.random_wake_up_answers = random_wake_up_answers
  86. setting_object.random_wake_up_sounds = random_wake_up_sounds
  87. setting_object.rest_api = rest_api
  88. setting_object.cache_path = cache_path
  89. return setting_object
  90. @staticmethod
  91. def _get_default_speech_to_text(settings):
  92. """
  93. Get the default speech to text defined in the settings.yml file
  94. :param settings: The YAML settings file
  95. :type settings: dict
  96. :return: the default speech to text
  97. :rtype: str
  98. :Example:
  99. default_stt_name = cls._get_default_speech_to_text(settings)
  100. .. seealso:: Stt
  101. .. raises:: NullSettingException, SettingNotFound
  102. .. warnings:: Static and Private
  103. """
  104. try:
  105. default_speech_to_text = settings["default_speech_to_text"]
  106. if default_speech_to_text is None:
  107. raise NullSettingException("Attribute default_speech_to_text is null")
  108. logger.debug("Default STT: %s" % default_speech_to_text)
  109. return default_speech_to_text
  110. except KeyError, e:
  111. raise SettingNotFound("%s setting not found" % e)
  112. @staticmethod
  113. def _get_default_text_to_speech(settings):
  114. """
  115. Get the default text to speech defined in the settings.yml file
  116. :param settings: The YAML settings file
  117. :type settings: dict
  118. :return: the default text to speech
  119. :rtype: str
  120. :Example:
  121. default_tts_name = cls._get_default_text_to_speech(settings)
  122. .. seealso:: Tts
  123. .. raises:: NullSettingException, SettingNotFound
  124. .. warnings:: Static and Private
  125. """
  126. try:
  127. default_text_to_speech = settings["default_text_to_speech"]
  128. if default_text_to_speech is None:
  129. raise NullSettingException("Attribute default_text_to_speech is null")
  130. logger.debug("Default TTS: %s" % default_text_to_speech)
  131. return default_text_to_speech
  132. except KeyError, e:
  133. raise SettingNotFound("%s setting not found" % e)
  134. @staticmethod
  135. def _get_default_trigger(settings):
  136. """
  137. Get the default trigger defined in the settings.yml file
  138. :param settings: The YAML settings file
  139. :type settings: dict
  140. :return: the default trigger
  141. :rtype: str
  142. :Example:
  143. default_trigger_name = cls._get_default_trigger(settings)
  144. .. seealso:: Trigger
  145. .. raises:: NullSettingException, SettingNotFound
  146. .. warnings:: Static and Private
  147. """
  148. try:
  149. default_trigger = settings["default_trigger"]
  150. if default_trigger is None:
  151. raise NullSettingException("Attribute default_trigger is null")
  152. logger.debug("Default Trigger name: %s" % default_trigger)
  153. return default_trigger
  154. except KeyError, e:
  155. raise SettingNotFound("%s setting not found" % e)
  156. @staticmethod
  157. def _get_stts(settings):
  158. """
  159. Return a list of stt object
  160. :param settings: The YAML settings file
  161. :type settings: dict
  162. :return: List of Stt
  163. :rtype: list
  164. :Example:
  165. stts = cls._get_stts(settings)
  166. .. seealso:: Stt
  167. .. raises:: SettingNotFound
  168. .. warnings:: Class Method and Private
  169. """
  170. try:
  171. speechs_to_text_list = settings["speech_to_text"]
  172. except KeyError:
  173. raise SettingNotFound("speech_to_text settings not found")
  174. stts = list()
  175. for speechs_to_text_el in speechs_to_text_list:
  176. if isinstance(speechs_to_text_el, dict):
  177. # print "Neurons dict ok"
  178. for stt_name in speechs_to_text_el:
  179. name = stt_name
  180. parameters = speechs_to_text_el[name]
  181. new_stt = Stt(name=name, parameters=parameters)
  182. stts.append(new_stt)
  183. else:
  184. # the neuron does not have parameter
  185. new_stt = Stt(name=speechs_to_text_el)
  186. stts.append(new_stt)
  187. return stts
  188. @staticmethod
  189. def _get_ttss(settings):
  190. """
  191. Return a list of stt object
  192. :param settings: The YAML settings file
  193. :type settings: dict
  194. :return: List of Ttss
  195. :rtype: list
  196. :Example:
  197. ttss = cls._get_ttss(settings)
  198. .. seealso:: Tts
  199. .. raises:: SettingNotFound
  200. .. warnings:: Class Method and Private
  201. """
  202. try:
  203. text_to_speech_list = settings["text_to_speech"]
  204. except KeyError, e:
  205. raise SettingNotFound("%s setting not found" % e)
  206. ttss = list()
  207. for text_to_speech_el in text_to_speech_list:
  208. if isinstance(text_to_speech_el, dict):
  209. # print "Neurons dict ok"
  210. for tts_name in text_to_speech_el:
  211. name = tts_name
  212. parameters = text_to_speech_el[name]
  213. new_tts = Tts(name=name, parameters=parameters)
  214. ttss.append(new_tts)
  215. else:
  216. # the neuron does not have parameter
  217. new_tts = Tts(name=text_to_speech_el)
  218. ttss.append(new_tts)
  219. return ttss
  220. @staticmethod
  221. def _get_triggers(settings):
  222. """
  223. Return a list of Trigger object
  224. :param settings: The YAML settings file
  225. :type settings: dict
  226. :return: List of Trigger
  227. :rtype: list
  228. :Example:
  229. triggers = cls._get_triggers(settings)
  230. .. seealso:: Trigger
  231. .. raises:: SettingNotFound
  232. .. warnings:: Class Method and Private
  233. """
  234. try:
  235. triggers_list = settings["triggers"]
  236. except KeyError, e:
  237. raise SettingNotFound("%s setting not found" % e)
  238. triggers = list()
  239. for trigger_el in triggers_list:
  240. if isinstance(trigger_el, dict):
  241. # print "Neurons dict ok"
  242. for trigger_name in trigger_el:
  243. name = trigger_name
  244. parameters = trigger_el[name]
  245. new_trigger = Trigger(name=name, parameters=parameters)
  246. triggers.append(new_trigger)
  247. else:
  248. # the neuron does not have parameter
  249. new_trigger = Trigger(name=trigger_el)
  250. triggers.append(new_trigger)
  251. return triggers
  252. @staticmethod
  253. def _get_random_wake_up_answers(settings):
  254. """
  255. Return a list of the wake up answers set up on the settings.yml file
  256. :param settings: The YAML settings file
  257. :type settings: dict
  258. :return: List of wake up answers
  259. :rtype: list of str
  260. :Example:
  261. wakeup = cls._get_random_wake_up_answers(settings)
  262. .. seealso::
  263. .. raises:: NullSettingException
  264. .. warnings:: Class Method and Private
  265. """
  266. try:
  267. random_wake_up_answers_list = settings["random_wake_up_answers"]
  268. except KeyError:
  269. # User does not provide this settings
  270. return None
  271. # The list cannot be empty
  272. if random_wake_up_answers_list is None:
  273. raise NullSettingException("random_wake_up_answers settings is null")
  274. return random_wake_up_answers_list
  275. @staticmethod
  276. def _get_random_wake_up_sounds(settings):
  277. """
  278. Return a list of the wake up sounds set up on the settings.yml file
  279. :param settings: The YAML settings file
  280. :type settings: dict
  281. :return: list of wake up sounds
  282. :rtype: list of str
  283. :Example:
  284. wakeup_sounds = cls._get_random_wake_up_sounds(settings)
  285. .. seealso::
  286. .. raises:: NullSettingException
  287. .. warnings:: Class Method and Private
  288. """
  289. try:
  290. random_wake_up_sounds_list = settings["random_wake_up_sounds"]
  291. except KeyError:
  292. # User does not provide this settings
  293. return None
  294. # The the setting is present, the list cannot be empty
  295. if random_wake_up_sounds_list is None:
  296. raise NullSettingException("random_wake_up_sounds settings is empty")
  297. return random_wake_up_sounds_list
  298. @staticmethod
  299. def _get_rest_api(settings):
  300. """
  301. Return the settings of the RestApi
  302. :param settings: The YAML settings file
  303. :type settings: dict
  304. :return: the RestApi object
  305. :rtype: RestApi
  306. :Example:
  307. rest_api = cls._get_rest_api(settings)
  308. .. seealso:: RestApi
  309. .. raises:: SettingNotFound, NullSettingException, SettingInvalidException
  310. .. warnings:: Class Method and Private
  311. """
  312. try:
  313. rest_api = settings["rest_api"]
  314. except KeyError, e:
  315. raise SettingNotFound("%s setting not found" % e)
  316. if rest_api is not None:
  317. try:
  318. password_protected = rest_api["password_protected"]
  319. if password_protected is None:
  320. raise NullSettingException("password_protected setting cannot be null")
  321. login = rest_api["login"]
  322. password = rest_api["password"]
  323. if password_protected:
  324. if login is None:
  325. raise NullSettingException("login setting cannot be null if password_protected is True")
  326. if login is None:
  327. raise NullSettingException("password setting cannot be null if password_protected is True")
  328. active = rest_api["active"]
  329. if active is None:
  330. raise NullSettingException("active setting cannot be null")
  331. port = rest_api["port"]
  332. if port is None:
  333. raise NullSettingException("port setting cannot be null")
  334. # check that the port in an integer
  335. try:
  336. port = int(port)
  337. except ValueError:
  338. raise SettingInvalidException("port must be an integer")
  339. # check the port is a valid port number
  340. if not 1024 <= port <= 65535:
  341. raise SettingInvalidException("port must be in range 1024-65535")
  342. except KeyError, e:
  343. # print e
  344. raise SettingNotFound("%s settings not found" % e)
  345. # config ok, we can return the rest api object
  346. rest_api_obj = RestAPI(password_protected=password_protected, login=login, password=password,
  347. active=active, port=port)
  348. return rest_api_obj
  349. else:
  350. raise NullSettingException("rest_api settings cannot be null")
  351. @staticmethod
  352. def _get_cache_path(settings):
  353. """
  354. Return the path where to store the cache
  355. :param settings: The YAML settings file
  356. :type settings: dict
  357. :return: the path to store the cache
  358. :rtype: String
  359. :Example:
  360. cache_path = cls._get_cache_path(settings)
  361. .. seealso::
  362. .. raises:: SettingNotFound, NullSettingException, SettingInvalidException
  363. .. warnings:: Class Method and Private
  364. """
  365. try:
  366. cache_path = settings["cache_path"]
  367. except KeyError, e:
  368. raise SettingNotFound("%s setting not found" % e)
  369. if cache_path is None:
  370. raise NullSettingException("cache_path setting cannot be null")
  371. # test if that path is usable
  372. if FileManager.is_path_exists_or_creatable(cache_path):
  373. return cache_path
  374. else:
  375. raise SettingInvalidException("The cache_path seems to be invalid: %s" % cache_path)