SettingLoader.py 15 KB

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