Procházet zdrojové kódy

Merge pull request #120 from kalliope-project/tests_nico

review loading of settings,  brain and trigger files (model)
Monf před 8 roky
rodič
revize
0dfe459601

+ 2 - 1
Tests/test_brain_loader.py

@@ -1,3 +1,4 @@
+import os
 import unittest
 
 from kalliope.core.Models import Singleton
@@ -13,7 +14,7 @@ from kalliope.core.Models.Brain import Brain
 class TestBrainLoader(unittest.TestCase):
 
     def setUp(self):
-        self.brain_to_test = "../Tests/brains/brain_test.yml"
+        self.brain_to_test = os.getcwd() + os.sep + "Tests/brains/brain_test.yml"
         self.expected_result = [
             {'signals': [{'order': 'test_order'}],
              'neurons': [{'say': {'message': ['test message']}}],

+ 2 - 1
Tests/test_settings_loader.py

@@ -1,3 +1,4 @@
+import os
 import platform
 import unittest
 
@@ -14,7 +15,7 @@ class TestSettingLoader(unittest.TestCase):
 
     def setUp(self):
 
-        self.settings_file_to_test = "../Tests/settings/settings_test.yml"
+        self.settings_file_to_test = os.getcwd() + os.sep + "/Tests/settings/settings_test.yml"
 
         self.settings_dict = {
             'rest_api':

+ 2 - 1
Tests/test_yaml_loader.py

@@ -1,3 +1,4 @@
+import os
 import unittest
 
 from kalliope.core.ConfigurationManager.YAMLLoader import YAMLFileNotFound, YAMLLoader
@@ -13,7 +14,7 @@ class TestYAMLLoader(unittest.TestCase):
 
     def test_get_config(self):
 
-        valid_file_path_to_test = "../Tests/brains/brain_test.yml"
+        valid_file_path_to_test = os.getcwd() + os.sep + "Tests/brains/brain_test.yml"
         invalid_file_path = "brains/non_existing_brain.yml"
         expected_result = [
             {'signals': [{'order': 'test_order'}],

+ 0 - 0
kalliope/brains/ansible_playbook.yml → brain_examples/ansible_playbook.yml


+ 0 - 0
kalliope/brains/default.yml → brain_examples/default.yml


+ 0 - 0
kalliope/brains/gmail_checker.yml → brain_examples/gmail_checker.yml


+ 0 - 0
kalliope/brains/kill_switch.yml → brain_examples/kill_switch.yml


+ 0 - 0
kalliope/brains/neurotransmitter.yml → brain_examples/neurotransmitter.yml


+ 0 - 0
kalliope/brains/openweathermap.yml → brain_examples/openweathermap.yml


+ 0 - 0
kalliope/brains/push_message.yml → brain_examples/push_message.yml


+ 0 - 0
kalliope/brains/rss_reader.yml → brain_examples/rss_reader.yml


+ 0 - 0
kalliope/brains/say.yml → brain_examples/say.yml


+ 0 - 0
kalliope/brains/script.yml → brain_examples/script.yml


+ 0 - 0
kalliope/brains/shell.yml → brain_examples/shell.yml


+ 0 - 0
kalliope/brains/systemdate.yml → brain_examples/systemdate.yml


+ 0 - 0
kalliope/brains/tasker_autoremote.yml → brain_examples/tasker_autoremote.yml


+ 0 - 0
kalliope/brains/twitter.yml → brain_examples/twitter.yml


+ 0 - 0
kalliope/brains/wake_on_lan.yml → brain_examples/wake_on_lan.yml


+ 0 - 0
kalliope/brains/wikipedia.yml → brain_examples/wikipedia.yml


+ 17 - 17
kalliope/brain.yml

@@ -1,18 +1,18 @@
 ---
-  - includes:
-    - brains/ansible_playbook.yml
-    - brains/gmail_checker.yml
-    - brains/kill_switch.yml
-    - brains/openweathermap.yml
-    - brains/push_message.yml
-    - brains/rss_reader.yml
-    - brains/say.yml
-    - brains/script.yml
-    - brains/shell.yml
-    - brains/systemdate.yml
-    - brains/tasker_autoremote.yml
-    - brains/wake_on_lan.yml
-    - brains/twitter.yml
-    - brains/neurotransmitter.yml
-    - brains/wikipedia.yml
-    - brains/default.yml
+  - name: "say-hello-fr"
+    signals:
+      - order: "bonjour"
+      - order: "Bonjour"
+    neurons:
+      - say:
+          message:
+            - "Bonjour monsieur"
+
+  - name: "say-hello-en"
+    signals:
+      - order: "hello"
+      - order: "Hello"
+    neurons:
+      - say:
+          message:
+            - "Hello sir"

+ 14 - 1
kalliope/core/ConfigurationManager/BrainLoader.py

@@ -3,6 +3,7 @@ import logging
 import os
 
 from YAMLLoader import YAMLLoader
+from kalliope.core.ConfigurationManager import utils
 from kalliope.core.ConfigurationManager.ConfigurationChecker import ConfigurationChecker
 from kalliope.core.Models import Singleton
 from kalliope.core.Models.Brain import Brain
@@ -14,6 +15,12 @@ from kalliope.core.Models.Synapse import Synapse
 logging.basicConfig()
 logger = logging.getLogger("kalliope")
 
+FILE_NAME = "brain.yml"
+
+
+class BrainNotFound(Exception):
+    pass
+
 
 class BrainLoader(object):
     """
@@ -22,8 +29,14 @@ class BrainLoader(object):
     __metaclass__ = Singleton
 
     def __init__(self, file_path=None):
-        logger.debug("Loading brain with file path: %s" % file_path)
         self.file_path = file_path
+        if self.file_path is None:  # we don't provide a file path, so search for the default one
+            self.file_path = utils.get_real_file_path(FILE_NAME)
+        else:
+            self.file_path = utils.get_real_file_path(file_path)
+        # if the returned file path is none, the file doesn't exist
+        if self.file_path is None:
+            raise BrainNotFound("brain file not found")
         self.yaml_config = self.get_yaml_config()
         self.brain = self.get_brain()
 

+ 9 - 5
kalliope/core/ConfigurationManager/SettingLoader.py

@@ -1,6 +1,7 @@
 import logging
 
 from YAMLLoader import YAMLLoader
+from kalliope.core.ConfigurationManager import utils
 from kalliope.core.Models import Singleton
 from kalliope.core.Models.RestAPI import RestAPI
 from kalliope.core.Models.Settings import Settings
@@ -49,11 +50,14 @@ class SettingLoader(object):
     __metaclass__ = Singleton
 
     def __init__(self, file_path=None):
-        logger.debug("Loading settings with file path: %s" % file_path)
         self.file_path = file_path
         if self.file_path is None:
-            # use default file if not provided
-            self.file_path = FILE_NAME
+            self.file_path = utils.get_real_file_path(FILE_NAME)
+        else:
+            self.file_path = utils.get_real_file_path(file_path)
+        # if the returned file path is none, the file doesn't exist
+        if self.file_path is None:
+            raise SettingNotFound("Settings.yml file not found")
         self.yaml_config = self._get_yaml_config()
         self.settings = self._get_settings()
 
@@ -476,7 +480,6 @@ class SettingLoader(object):
         else:
             raise SettingInvalidException("The cache_path seems to be invalid: %s" % cache_path)
 
-
     @staticmethod
     def _get_default_synapse(settings):
         """
@@ -499,8 +502,9 @@ class SettingLoader(object):
         try:
             default_synapse = settings["default_synapse"]
             logger.debug("Default synapse: %s" % default_synapse)
-        except KeyError, e:
+        except KeyError:
             default_synapse = None
 
         return default_synapse
 
+

+ 1 - 6
kalliope/core/ConfigurationManager/YAMLLoader.py

@@ -41,12 +41,7 @@ class YAMLLoader:
         .. warnings:: Class Method and Public
         """
 
-        current_dir = os.path.dirname(os.path.abspath(__file__))
-        logger.debug("Current dir: %s " % current_dir)
-        root_dir = os.path.join(current_dir, "../../")
-        root_dir = os.path.normpath(root_dir)
-        logger.debug("Root dir: %s " % root_dir)
-        cls.file_path_to_load = os.path.join(root_dir, yaml_file)
+        cls.file_path_to_load = yaml_file
         logger.debug("File path to load: %s " % cls.file_path_to_load)
         if os.path.isfile(cls.file_path_to_load):
             inc_import = IncludeImport(cls.file_path_to_load)

+ 51 - 0
kalliope/core/ConfigurationManager/utils.py

@@ -0,0 +1,51 @@
+import inspect
+import logging
+import os
+
+logging.basicConfig()
+logger = logging.getLogger("kalliope")
+
+
+def get_root_kalliope_path():
+    # here we are in /an/unknown/path/kalliope/core/ConfigurationManager
+    current_script_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+    # get parent dir. Now we are in /an/unknown/path/kalliope
+    kalliope_root_path = os.path.normpath(current_script_path + os.sep + os.pardir + os.sep + os.pardir)
+    return kalliope_root_path
+
+
+def get_real_file_path(file_path_to_test):
+    """
+    Try to return a full path from a given <file_path_to_test>
+    If the path is an absolute on, we return it directly.
+
+    If the path is relative, we try to get the full path in this order:
+    - from the current directory where kalliope has been called + the file_path_to_test.
+    Eg: /home/me/Documents/kalliope_config
+    - from /etc/kalliope + file_path_to_test
+    - from the default file passed as <file_name> at the root of the project
+
+    :param file_path_to_test file path to test
+    :type file_path_to_test: str
+    :return: absolute path to the file file_path_to_test or None if is doen't exist
+    """
+
+    if not os.path.isabs(file_path_to_test):
+        path_order = {
+            1: os.getcwd() + os.sep + file_path_to_test,
+            2: "/etc/kalliope" + os.sep + file_path_to_test,
+            3: get_root_kalliope_path() + os.sep + file_path_to_test
+        }
+
+        for key in sorted(path_order):
+            new_file_path_to_test = path_order[key]
+            logger.debug("Try to load file from %s: %s" % (key, new_file_path_to_test))
+            if os.path.isfile(new_file_path_to_test):
+                logger.debug("File found in %s" % new_file_path_to_test)
+                return new_file_path_to_test
+
+    else:
+        if os.path.isfile(file_path_to_test):
+            return file_path_to_test
+        else:
+            return None

+ 32 - 0
kalliope/core/TriggerModule.py

@@ -0,0 +1,32 @@
+import os
+
+import logging
+
+from kalliope.core.ConfigurationManager import utils
+
+logging.basicConfig()
+logger = logging.getLogger("kalliope")
+
+
+class TriggerModule(object):
+    """
+    Mother class of a trigger object
+    """
+
+    def __init__(self):
+        super(TriggerModule, self).__init__()
+
+    @staticmethod
+    def get_file_from_path(file_path):
+        """
+        Trigger can be based on a model file, or other file.
+        If a file is precised in settings, the path can be relative or absolute.
+        If the path is absolute, there is no problem when can try to load it directly
+        If the path is relative, we need to test the get the full path of the file in the following order:
+            - from the current directory where kalliope has been called. Eg: /home/me/Documents/kalliope_config
+            - from /etc/kalliope
+            - from the root of the project. Eg: /usr/local/lib/python2.7/dist-packages/kalliope-version/kalliope/<file_path>
+
+        :return: absolute path
+        """
+        return utils.get_real_file_path(file_path)

+ 1 - 1
kalliope/settings.yml

@@ -15,7 +15,7 @@ default_trigger: "snowboy"
 # - snowboy
 triggers:
   - snowboy:
-      pmdl_file: "kalliope/trigger/snowboy/resources/kalliope-FR-6samples.pmdl"
+      pmdl_file: "trigger/snowboy/resources/kalliope-FR-13samples.pmdl"
 
 
 # ---------------------------

binární
kalliope/trigger/snowboy/resources/kalliope-FR-13samples.pmdl


binární
kalliope/trigger/snowboy/resources/kalliope-FR-6samples.pmdl


+ 15 - 3
kalliope/trigger/snowboy/snowboy.py

@@ -1,9 +1,16 @@
+import inspect
 import logging
+import os
 import time
 
+from kalliope.core.TriggerModule import TriggerModule
 from kalliope.trigger.snowboy import snowboydecoder
 
 
+class SnowboyModelNotFounfd(Exception):
+    pass
+
+
 class MissingParameterException(Exception):
     pass
 
@@ -11,9 +18,10 @@ logging.basicConfig()
 logger = logging.getLogger("kalliope")
 
 
-class Snowboy(object):
+class Snowboy(TriggerModule):
 
     def __init__(self, **kwargs):
+        super(Snowboy, self).__init__()
         # pause listening boolean
         self.interrupted = False
         self.kill_received = False
@@ -25,11 +33,14 @@ class Snowboy(object):
 
         # get the pmdl file to load
         self.pmdl = kwargs.get('pmdl_file', None)
-
         if self.pmdl is None:
             raise MissingParameterException("Pmdl file is required with snowboy")
 
-        self.detector = snowboydecoder.HotwordDetector(self.pmdl, sensitivity=0.5, detected_callback=self.callback,
+        self.pmdl_path = self.get_file_from_path(self.pmdl)
+        if not os.path.isfile(self.pmdl_path):
+            raise SnowboyModelNotFounfd("The snowboy model file %s does not exist" % self.pmdl_path)
+
+        self.detector = snowboydecoder.HotwordDetector(self.pmdl_path, sensitivity=0.5, detected_callback=self.callback,
                                                        interrupt_check=self.interrupt_callback,
                                                        sleep_time=0.03)
 
@@ -72,3 +83,4 @@ class Snowboy(object):
         """
         logger.debug("Unpausing snowboy process")
         self.detector.paused = False
+