Browse Source

Merge branch 'Doc' into dev

monf 10 năm trước cách đây
mục cha
commit
3aa525d3c9
55 tập tin đã thay đổi với 927 bổ sung và 196 xóa
  1. 78 9
      core/ConfigurationManager/BrainLoader.py
  2. 138 17
      core/ConfigurationManager/ConfigurationChecker.py
  3. 213 26
      core/ConfigurationManager/SettingLoader.py
  4. 32 5
      core/ConfigurationManager/YAMLLoader.py
  5. 27 7
      core/CrontabManager.py
  6. 29 6
      core/FileManager.py
  7. 14 11
      core/MainController.py
  8. 5 0
      core/Models/Brain.py
  9. 13 0
      core/Models/Event.py
  10. 11 1
      core/Models/Neuron.py
  11. 13 0
      core/Models/Order.py
  12. 4 0
      core/Models/RestAPI.py
  13. 6 0
      core/Models/Settings.py
  14. 2 0
      core/Models/Singleton.py
  15. 5 1
      core/Models/Stt.py
  16. 14 1
      core/Models/Synapse.py
  17. 5 2
      core/Models/Trigger.py
  18. 5 1
      core/Models/Tts.py
  19. 40 16
      core/NeuronModule.py
  20. 1 6
      core/NeuroneLauncher.py
  21. 12 0
      core/OrderAnalyser.py
  22. 16 3
      core/OrderListener.py
  23. 20 5
      core/Players/Mplayer.py
  24. 9 10
      core/ShellGui.py
  25. 5 1
      core/SynapseLauncher.py
  26. 3 0
      core/TTS/TTSLauncher.py
  27. 21 8
      core/TTS/TTSModule.py
  28. 1 2
      core/TriggerLauncher.py
  29. 12 1
      core/Utils.py
  30. 0 2
      kalliope.py
  31. 10 0
      neurons/gmail_checker/gmail_checker.py
  32. 3 0
      neurons/kill_switch/kill_switch.py
  33. 10 2
      neurons/neurotransmitter/neurotransmitter.py
  34. 2 0
      neurons/openweathermap/Openweathermap.py
  35. 4 3
      neurons/push_message/Push_message.py
  36. 2 0
      neurons/say/say.py
  37. 2 0
      neurons/script/script.py
  38. 10 0
      neurons/shell/shell.py
  39. 8 8
      neurons/sleep/sleep.py
  40. 0 3
      neurons/systemdate/systemdate.py
  41. 2 0
      neurons/tasker_autoremote/tasker_autoremote.py
  42. 2 0
      neurons/twitter/Twitter.py
  43. 4 2
      neurons/wake_on_lan/Wake_on_lan.py
  44. 5 2
      neurons/wikipedia/Wikipedia.py
  45. 4 4
      stt/apiai/Apiai.py
  46. 5 4
      stt/bing/Bing.py
  47. 5 4
      stt/google/Google.py
  48. 8 13
      stt/houndify/Houndify.py
  49. 5 4
      stt/wit/Wit.py
  50. 0 1
      trigger/snowboy/snowboydecoder.py
  51. 24 0
      tts/acapela/acapela.py
  52. 15 0
      tts/googletts/googletts.py
  53. 10 2
      tts/pico2wave/pico2wave.py
  54. 14 1
      tts/voicerss/voicerss.py
  55. 19 2
      tts/voxygen/voxygen.py

+ 78 - 9
core/ConfigurationManager/BrainLoader.py

@@ -15,12 +15,27 @@ logger = logging.getLogger("kalliope")
 
 
 class BrainLoader(object):
+    """
+    This Class is used to get the brain YAML and the Brain as an object
+    """
 
     def __init__(self):
         pass
 
     @classmethod
     def get_yaml_config(cls, file_path=None):
+        """
+        Class Methods which loads default or the provided YAML file and return it as a String
+        :param file_path: the brain file path to load
+        :type file_path: String
+        :return: The loaded brain YAML
+        :rtype: String
+
+        :Example:
+            brain_yaml = BrainLoader.get_yaml_config(/var/tmp/brain.yml)
+
+        .. warnings:: Class Method
+        """
         if file_path is None:
             brain_file_path = cls._get_root_brain_path()
         else:
@@ -30,9 +45,19 @@ class BrainLoader(object):
     @classmethod
     def get_brain(cls, file_path=None):
         """
-        return a brain object from YAML settings
-        :return: Brain object
+        Class Methods which loads default or the provided YAML file and return a Brain
+
+        :param file_path: the brain file path to load
+        :type file_path: String
+        :return: The loaded Brain
         :rtype: Brain
+
+        :Example:
+
+            brain = BrainLoader.get_brain(file_path="/var/tmp/brain.yml")
+
+        .. seealso:: Brain
+        .. warnings:: Class Method
         """
 
         # Instantiate a brain
@@ -46,7 +71,7 @@ class BrainLoader(object):
             # create list of Synapse
             synapses = list()
             for synapses_dict in dict_brain:
-                if "includes" not in synapses_dict: # we don't need to check includes as it's not a synapse
+                if "includes" not in synapses_dict:     # we don't need to check includes as it's not a synapse
                     if ConfigurationChecker().check_synape_dict(synapses_dict):
                         # print "synapses_dict ok"
                         name = synapses_dict["name"]
@@ -71,9 +96,20 @@ class BrainLoader(object):
     def _get_neurons(neurons_dict):
         """
         Get a list of Neuron object from a neuron dict
-        :param neurons_dict:
-        :return:
+
+        :param neurons_dict: Neuron name or dictionary of Neuron_name/Neuron_parameters
+        :type neurons_dict: String or dict
+        :return: A list of Neurons
+        :rtype: List
+
+        :Example:
+
+            neurons = cls._get_neurons(synapses_dict["neurons"])
+
+        .. seealso:: Neuron
+        .. warnings:: Static and Private
         """
+
         neurons = list()
         for neuron_dict in neurons_dict:
             if isinstance(neuron_dict, dict):
@@ -96,6 +132,21 @@ class BrainLoader(object):
 
     @classmethod
     def _get_signals(cls, signals_dict):
+        """
+        Get a list of Signal object from a signals dict
+
+        :param signals_dict: Signal name or dictionary of Signal_name/Signal_parameters
+        :type signals_dict: String or dict
+        :return: A list of Event and/or Order
+        :rtype: List
+
+        :Example:
+
+            signals = cls._get_signals(synapses_dict["signals"])
+
+        .. seealso:: Event, Order
+        .. warnings:: Class method and Private
+        """
         # print signals_dict
         signals = list()
         for signal_dict in signals_dict:
@@ -108,7 +159,21 @@ class BrainLoader(object):
 
     @staticmethod
     def _get_event_or_order_from_dict(signal_or_event_dict):
+        """
+        The signal is either an Event or an Order
 
+        :param signal_or_event_dict: A dict of event or signal
+        :type signal_or_event_dict: dict
+        :return: The object corresponding to An Order or an Event
+        :rtype: An Order or an Event
+
+        :Example:
+
+            event_or_order = cls._get_event_or_order_from_dict(signal_dict)
+
+        .. seealso:: Event, Order
+        .. warnings:: Static method and Private
+        """
         if 'event' in signal_or_event_dict:
             # print "is event"
             event = signal_or_event_dict["event"]
@@ -124,8 +189,15 @@ class BrainLoader(object):
     def _get_root_brain_path():
         """
         Return the full path of the default brain file
-        :return:
+
+        :Example:
+
+            brain.brain_file = cls._get_root_brain_path()
+
+        .. raises:: IOError
+        .. warnings:: Static method and Private
         """
+
         # get current script directory path. We are in /an/unknown/path/kalliope/core/ConfigurationManager
         cur_script_directory = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
         # get parent dir. Now we are in /an/unknown/path/kalliope
@@ -135,6 +207,3 @@ class BrainLoader(object):
         if os.path.isfile(brain_path):
             return brain_path
         raise IOError("Default brain.yml file not found")
-
-
-

+ 138 - 17
core/ConfigurationManager/ConfigurationChecker.py

@@ -4,48 +4,90 @@ from core.Utils import ModuleNotFoundError
 
 
 class InvalidSynapeName(Exception):
+    """
+    The name of the synapse is not correct. It should only contains alphanumerics at the beginning and the end of
+    its name. It can also contains dash in beetween alphanumerics.
+    """
     pass
 
 
 class NoSynapeName(Exception):
+    """
+    A synapse needs a name
+    """
     pass
 
 
 class NoSynapeNeurons(Exception):
+    """
+    A synapse must contains at least one neuron
+
+    .. seealso:: Synapse, Neuron
+    """
     pass
 
 
 class NoSynapeSignals(Exception):
+    """
+    A synapse must contains at least an Event or an Order
+
+    .. seealso:: Event, Order
+    """
     pass
 
 
 class NoValidSignal(Exception):
-    pass
+    """
+    A synapse must contains at least a valid Event or an Order
 
+    .. seealso:: Event, Order
+    """
 
-class NoEventID(Exception):
     pass
 
 
 class NoEventPeriod(Exception):
-    pass
-
+    """
+    An Event must contains a period corresponding to its execution
 
-class MultipleSameSynapseName(Exception):
+    .. seealso:: Event
+    """
     pass
 
 
-class NotValidSynapseName(Exception):
+class MultipleSameSynapseName(Exception):
+    """
+    A synapse name must be unique
+    """
     pass
 
 
 class ConfigurationChecker:
+    """
+    This Class provides all method to Check the configuration files are properly set up.
+    """
 
     def __init__(self):
         pass
 
     @staticmethod
     def check_synape_dict(synape_dict):
+        """
+        Return True if the provided dict is well corresponding to a Synapse
+
+        :param synape_dict: The synapse Dictionary
+        :type synape_dict: Dict
+        :return: True if synapse are ok
+        :rtype: Boolean
+
+        :Example:
+
+            ConfigurationChecker().check_synape_dict(synapses_dict):
+
+        .. seealso:: Synapse
+        .. raises:: NoSynapeName, InvalidSynapeName, NoSynapeNeurons, NoSynapeSignals
+        .. warnings:: Static and Public
+        """
 
         if 'name' not in synape_dict:
             raise NoSynapeName("The Synapse does not have a name: %s" % synape_dict)
@@ -71,17 +113,35 @@ class ConfigurationChecker:
     def check_neuron_dict(neuron_dict):
         """
         Check received neuron dict is valid:
-        - neuron exist
-        :param neuron_dict:
-        :return:
+
+        :param neuron_dict: The neuron Dictionary
+        :type neuron_dict: Dict
+        :return: True if neuron is ok
+        :rtype: Boolean
+
+        :Example:
+
+            ConfigurationChecker().check_neuron_dict(neurons_dict):
+
+        .. seealso:: Synapse
+        .. raises:: ModuleNotFoundError
+        .. warnings:: Static and Public
         """
-        def check_neuron_exist(neuron_name):
+
+        def check_neuron_exist(neuron_module_name):
+            """
+            Return True if the neuron_name python Class exist in neurons package
+            :param neuron_module_name: Name of the neuron module to check
+            :type neuron_module_name: str
+            :return:
+            """
             package_name = "neurons"
-            mod = __import__(package_name, fromlist=[neuron_name])
+            mod = __import__(package_name, fromlist=[neuron_module_name])
             try:
-                getattr(mod, neuron_name)
+                getattr(mod, neuron_module_name)
             except AttributeError:
-                raise ModuleNotFoundError("The module %s does not exist in package %s" % (neuron_name, package_name))
+                raise ModuleNotFoundError("The module %s does not exist in package %s" % (neuron_module_name,
+                                                                                          package_name))
             return True
 
         if isinstance(neuron_dict, dict):
@@ -93,12 +153,46 @@ class ConfigurationChecker:
 
     @staticmethod
     def check_signal_dict(signal_dict):
+        """
+        Check received signal dictionary is valid:
+
+        :param signal_dict: The signal Dictionary
+        :type signal_dict: Dict
+        :return: True if signal are ok
+        :rtype: Boolean
+
+        :Example:
+
+            ConfigurationChecker().check_signal_dict(signal_dict):
+
+        .. seealso:: Order, Event
+        .. raises:: NoValidSignal
+        .. warnings:: Static and Public
+        """
+
         if ('event' not in signal_dict) and ('order' not in signal_dict):
             raise NoValidSignal("The signal is not an event or an order %s" % signal_dict)
         return True
 
     @staticmethod
     def check_event_dict(event_dict):
+        """
+        Check received event dictionary is valid:
+
+        :param event_dict: The event Dictionary
+        :type event_dict: Dict
+        :return: True if event are ok
+        :rtype: Boolean
+
+        :Example:
+
+            ConfigurationChecker().check_event_dict(event_dict):
+
+        .. seealso::  Event
+        .. raises:: NoEventPeriod
+        .. warnings:: Static and Public
+        """
+
         if event_dict is None:
             raise NoEventPeriod("Event must contain a period: %s" % event_dict)
 
@@ -106,6 +200,22 @@ class ConfigurationChecker:
 
     @staticmethod
     def check_order_dict(order_dict):
+        """
+        Check received order dictionary is valid:
+
+        :param order_dict: The Order Dict
+        :type order_dict: Dict
+        :return: True if event are ok
+        :rtype: Boolean
+
+        :Example:
+
+            ConfigurationChecker().check_order_dict(order_dict):
+
+        .. seealso::  Order
+        .. warnings:: Static and Public
+        """
+
         if order_dict is not None:
             return True
         return False
@@ -114,11 +224,22 @@ class ConfigurationChecker:
     def check_synapes(synapses_list):
         """
         Check the synapse list is ok:
-         - No double same name
-        :param synapses_list:
-        :type synapses_list: list of Synapse
-        :return:
+                - No double same name
+
+        :param synapses_list: The Synapse List
+        :type synapses_list: List
+        :return: list of Synapse
+        :rtype: List
+
+        :Example:
+
+            ConfigurationChecker().check_synapes(order_dict):
+
+        .. seealso::  Synapse
+        .. raises:: MultipleSameSynapseName
+        .. warnings:: Static and Public
         """
+
         seen = set()
         for synapse in synapses_list:
             # convert ascii to UTF-8

+ 213 - 26
core/ConfigurationManager/SettingLoader.py

@@ -2,7 +2,6 @@ import logging
 
 from YAMLLoader import YAMLLoader
 from core.FileManager import FileManager
-from core.Models import Singleton
 from core.Models.RestAPI import RestAPI
 from core.Models.Settings import Settings
 from core.Models.Stt import Stt
@@ -16,24 +15,56 @@ logger = logging.getLogger("kalliope")
 
 
 class SettingInvalidException(Exception):
+    """
+    Some data must match the expected value/type
+
+    .. seealso:: Settings
+    """
     pass
 
 
 class NullSettingException(Exception):
+    """
+    Some Attributes can not be Null
+
+    .. seealso:: Settings
+    """
     pass
 
 
 class SettingNotFound(Exception):
+    """
+    Some Attributes are missing
+
+    .. seealso:: Settings
+    """
     pass
 
 
 class SettingLoader(object):
+    """
+    This Class is used to get the Settings YAML and the Settings as an object
+    """
 
     def __init__(self):
         pass
 
     @classmethod
     def get_yaml_config(cls, file_path=None):
+        """
+        Class Methods which loads default or the provided YAML file and return it as a String
+
+        :param file_path: the setting file path to load if None takes default
+        :type file_path: str
+        :return: The loaded settings YAML
+        :rtype: dict
+
+        :Example:
+            settings_yaml = SettingLoader.get_yaml_config(/var/tmp/settings.yml)
+
+        .. warnings:: Class Method
+        """
+
         if file_path is None:
             file_path = FILE_NAME
         return YAMLLoader.get_config(file_path)
@@ -41,8 +72,19 @@ class SettingLoader(object):
     @classmethod
     def get_settings(cls, file_path=None):
         """
-        Return a Settings object from settings.yml file
-        :return:
+        Class Methods which loads default or the provided YAML file and return a Settings Object
+
+        :param file_path: the setting file path to load
+        :type file_path: str
+        :return: The loaded Settings
+        :rtype: Settings
+
+        :Example:
+
+            settings = SettingLoader.get_settings(file_path="/var/tmp/settings.yml")
+
+        .. seealso:: Settings
+        .. warnings:: Class Method
         """
 
         # create a new setting
@@ -64,16 +106,16 @@ class SettingLoader(object):
             cache_path = cls._get_cache_path(settings)
 
             # Load the setting singleton with the parameters
-            setting_object.default_tts_name=default_tts_name
-            setting_object.default_stt_name=default_stt_name
-            setting_object.default_trigger_name=default_trigger_name
-            setting_object.stts=stts
-            setting_object.ttss=ttss
-            setting_object.triggers=triggers
-            setting_object.random_wake_up_answers=random_wake_up_answers
-            setting_object.random_wake_up_sounds=random_wake_up_sounds
-            setting_object.rest_api=rest_api
-            setting_object.cache_path=cache_path
+            setting_object.default_tts_name = default_tts_name
+            setting_object.default_stt_name = default_stt_name
+            setting_object.default_trigger_name = default_trigger_name
+            setting_object.stts = stts
+            setting_object.ttss = ttss
+            setting_object.triggers = triggers
+            setting_object.random_wake_up_answers = random_wake_up_answers
+            setting_object.random_wake_up_sounds = random_wake_up_sounds
+            setting_object.rest_api = rest_api
+            setting_object.cache_path = cache_path
             # The Settings Singleton is loaded
             setting_object.is_loaded = True
 
@@ -81,6 +123,22 @@ class SettingLoader(object):
 
     @staticmethod
     def _get_default_speech_to_text(settings):
+        """
+        Get the default speech to text defined in the settings.yml file
+
+        :param settings: The YAML settings file
+        :type settings: dict
+        :return: the default speech to text
+        :rtype: str
+
+        :Example:
+
+            default_stt_name = cls._get_default_speech_to_text(settings)
+
+        .. seealso:: Stt
+        .. raises:: NullSettingException, SettingNotFound
+        .. warnings:: Static and Private
+        """
 
         try:
             default_speech_to_text = settings["default_speech_to_text"]
@@ -93,6 +151,23 @@ class SettingLoader(object):
 
     @staticmethod
     def _get_default_text_to_speech(settings):
+        """
+        Get the default text to speech defined in the settings.yml file
+
+        :param settings: The YAML settings file
+        :type settings: dict
+        :return: the default text to speech
+        :rtype: str
+
+        :Example:
+
+            default_tts_name = cls._get_default_text_to_speech(settings)
+
+        .. seealso:: Tts
+        .. raises:: NullSettingException, SettingNotFound
+        .. warnings:: Static and Private
+        """
+
         try:
             default_text_to_speech = settings["default_text_to_speech"]
             if default_text_to_speech is None:
@@ -104,6 +179,22 @@ class SettingLoader(object):
 
     @staticmethod
     def _get_default_trigger(settings):
+        """
+        Get the default trigger defined in the settings.yml file
+        :param settings: The YAML settings file
+        :type settings: dict
+        :return: the default trigger
+        :rtype: str
+
+        :Example:
+
+            default_trigger_name = cls._get_default_trigger(settings)
+
+        .. seealso:: Trigger
+        .. raises:: NullSettingException, SettingNotFound
+        .. warnings:: Static and Private
+        """
+
         try:
             default_trigger = settings["default_trigger"]
             if default_trigger is None:
@@ -117,13 +208,25 @@ class SettingLoader(object):
     def _get_stts(cls, settings):
         """
         Return a list of stt object
-        :param settings: loaded settings file
+
+        :param settings: The YAML settings file
+        :type settings: dict
         :return: List of Stt
+        :rtype: list
+
+        :Example:
+
+            stts = cls._get_stts(settings)
+
+        .. seealso:: Stt
+        .. raises:: SettingNotFound
+        .. warnings:: Class Method and Private
         """
+
         try:
             speechs_to_text_list = settings["speech_to_text"]
         except KeyError:
-            raise NullSettingException("speech_to_text settings not found")
+            raise SettingNotFound("speech_to_text settings not found")
 
         stts = list()
         for speechs_to_text_el in speechs_to_text_list:
@@ -143,10 +246,23 @@ class SettingLoader(object):
     @classmethod
     def _get_ttss(cls, settings):
         """
-        Return a list of Tts object
-        :param settings: loaded settings file
-        :return: List of Tts
+
+        Return a list of stt object
+
+        :param settings: The YAML settings file
+        :type settings: dict
+        :return: List of Ttss
+        :rtype: list
+
+        :Example:
+
+            ttss = cls._get_ttss(settings)
+
+        .. seealso:: Tts
+        .. raises:: SettingNotFound
+        .. warnings:: Class Method and Private
         """
+
         try:
             text_to_speech_list = settings["text_to_speech"]
         except KeyError, e:
@@ -171,9 +287,21 @@ class SettingLoader(object):
     def _get_triggers(cls, settings):
         """
         Return a list of Trigger object
-        :param settings: loaded settings file
+
+        :param settings: The YAML settings file
+        :type settings: dict
         :return: List of Trigger
+        :rtype: list
+
+        :Example:
+
+            triggers = cls._get_triggers(settings)
+
+        .. seealso:: Trigger
+        .. raises:: SettingNotFound
+        .. warnings:: Class Method and Private
         """
+
         try:
             triggers_list = settings["triggers"]
         except KeyError, e:
@@ -197,10 +325,22 @@ class SettingLoader(object):
     @classmethod
     def _get_random_wake_up_answers(cls, settings):
         """
-        return a list of string
-        :param settings:
-        :return:
+        Return a list of the wake up answers set up on the settings.yml file
+
+        :param settings: The YAML settings file
+        :type settings: dict
+        :return: List of wake up answers
+        :rtype: list of str
+
+        :Example:
+
+            wakeup = cls._get_random_wake_up_answers(settings)
+
+        .. seealso::
+        .. raises:: NullSettingException
+        .. warnings:: Class Method and Private
         """
+
         try:
             random_wake_up_answers_list = settings["random_wake_up_answers"]
         except KeyError:
@@ -216,10 +356,22 @@ class SettingLoader(object):
     @classmethod
     def _get_random_wake_up_sounds(cls, settings):
         """
-        return a list of string
-        :param settings:
-        :return: List of string
+        Return a list of the wake up sounds set up on the settings.yml file
+
+        :param settings: The YAML settings file
+        :type settings: dict
+        :return: list of wake up sounds
+        :rtype: list of str
+
+        :Example:
+
+            wakeup_sounds = cls._get_random_wake_up_sounds(settings)
+
+        .. seealso::
+        .. raises:: NullSettingException
+        .. warnings:: Class Method and Private
         """
+
         try:
             random_wake_up_sounds_list = settings["random_wake_up_sounds"]
         except KeyError:
@@ -234,6 +386,23 @@ class SettingLoader(object):
 
     @classmethod
     def _get_rest_api(cls, settings):
+        """
+        Return the settings of the RestApi
+
+        :param settings: The YAML settings file
+        :type settings: dict
+        :return: the RestApi object
+        :rtype: RestApi
+
+        :Example:
+
+            rest_api = cls._get_rest_api(settings)
+
+        .. seealso:: RestApi
+        .. raises:: SettingNotFound, NullSettingException, SettingInvalidException
+        .. warnings:: Class Method and Private
+        """
+
         try:
             rest_api = settings["rest_api"]
         except KeyError, e:
@@ -271,13 +440,31 @@ class SettingLoader(object):
                 raise SettingNotFound("%s settings not found" % e)
 
             # config ok, we can return the rest api object
-            rest_api_obj = RestAPI(password_protected=password_protected, login=login, password=password, active=active, port=port)
+            rest_api_obj = RestAPI(password_protected=password_protected, login=login, password=password,
+                                   active=active, port=port)
             return rest_api_obj
         else:
             raise NullSettingException("rest_api settings cannot be null")
 
     @classmethod
     def _get_cache_path(cls, settings):
+        """
+        Return the path where to store the cache
+
+        :param settings: The YAML settings file
+        :type settings: dict
+        :return: the path to store the cache
+        :rtype: String
+
+        :Example:
+
+            cache_path = cls._get_cache_path(settings)
+
+        .. seealso::
+        .. raises:: SettingNotFound, NullSettingException, SettingInvalidException
+        .. warnings:: Class Method and Private
+        """
+
         try:
             cache_path = settings["cache_path"]
         except KeyError, e:

+ 32 - 5
core/ConfigurationManager/YAMLLoader.py

@@ -8,10 +8,16 @@ logger = logging.getLogger("kalliope")
 
 
 class YAMLFileNotFound(Exception):
+    """
+    YAML file has not been found
+    """
     pass
 
 
 class YAMLLoader:
+    """
+    Simple Class to Verify / Load a YAML file.
+    """
 
     def __init__(self):
         pass
@@ -19,9 +25,22 @@ class YAMLLoader:
     @classmethod
     def get_config(cls, yaml_file):
         """
-        Load settings file
-        :return: cfg : the configuration file
+        Return the provided YAML configuration file
+
+        :param yaml_file: The path of the configuration file
+        :type yaml_file: String
+        :return: the configuration file
+        :rtype: String
+
+        :Example:
+
+            YAMLLoader.get_config(brain_file_path)
+
+        .. seealso::  SettingLoader, BrainLoader
+        .. raises:: YAMLFileNotFound
+        .. 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, "../../")
@@ -38,6 +57,9 @@ class YAMLLoader:
 
 
 class IncludeImport(object):
+    """
+    This class manages the Include Import statement in the brain.yml file
+    """
 
     def __init__(self, file_path):
         """
@@ -63,14 +85,19 @@ class IncludeImport(object):
                         self.update(yaml.load(open(inc)))
 
     def get_data(self):
+        """
+        :return: the data for the IncludeImport
+        """
         return self.data
 
     def update(self, data_to_add):
-        # print "cur_data: %s" % self.data
-        # print "data to add %s" % data_to_add
+        """
+        Method to Add an other Include statement to the original brain.yml file
+        :param data_to_add: the data to add to the current brain.yml, provided by an Include Statement
+        """
+
         # we add each synapse inside the extended brain into the main brain data
         if data_to_add is not None:
             for el in data_to_add:
                 self.data.append(el)
-        # print "final data: %s" % self.data
 

+ 27 - 7
core/CrontabManager.py

@@ -1,16 +1,20 @@
-from crontab import CronTab
+import logging
+
 from crontab import CronSlices
+from crontab import CronTab
 
 from core import Utils
-from core.ConfigurationManager.BrainLoader import BrainLoader
 from core.Models import Event
-import logging
 
 logging.basicConfig()
 logger = logging.getLogger("kalliope")
 
 
 class InvalidCrontabPeriod(Exception):
+    """
+    Event are based on the Crontab. The Period must be corresponding to the Crontab format
+    .. seealso:: Event
+    """
     pass
 
 CRONTAB_COMMENT = "KALLIOPE"
@@ -28,7 +32,6 @@ class CrontabManager:
         """
         Remove all line in crontab with the CRONTAB_COMMENT
         Then add back line from event in the brain.yml
-        :return:
         """
         # clean the current crontab from all Kalliope event
         self._remove_all_job()
@@ -42,6 +45,19 @@ class CrontabManager:
                     self._add_event(period_string=signal.period, event_id=synapse.name)
 
     def _add_event(self, period_string, event_id):
+        """
+        Add a single event in the crontab.
+        Will add a line like:
+        <period_string> python /path/to/kalliope.py start --brain-file /path/to/brain.yml --run-synapse "<event_id>"
+
+        E.g:
+        30 7 * * * python /home/me/kalliope/kalliope.py start --brain-file /home/me/brain.yml --run-synapse  "Say-hello"
+        :param period_string: crontab period
+        :type period_string: str
+        :param event_id:
+        :type event_id: str
+        :return:
+        """
         my_user_cron = CronTab(user=True)
         job = my_user_cron.new(command=self.base_command+" "+str("\"" + event_id + "\""), comment=CRONTAB_COMMENT)
         if CronSlices.is_valid(period_string):
@@ -54,15 +70,18 @@ class CrontabManager:
         Utils.print_info("Synapse \"%s\" added to the crontab" % event_id)
 
     def get_jobs(self):
+        """
+        Return all current jobs in the crontab
+        :return:
+        """
         return self.my_user_cron.find_comment(CRONTAB_COMMENT)
 
     def _remove_all_job(self):
         """
         Remove all line in crontab that are attached to Kalliope
-        :return:
         """
-        iter = self.my_user_cron.find_comment(CRONTAB_COMMENT)
-        for job in iter:
+        iter_item = self.my_user_cron.find_comment(CRONTAB_COMMENT)
+        for job in iter_item:
             logger.debug("remove job %s from crontab" % job)
             self.my_user_cron.remove(job)
         # write the file
@@ -80,6 +99,7 @@ class CrontabManager:
         Return the path of the entry point of Kalliope
         Example: /home/user/kalliope/kalliope.py
         :return: The path of the entry point script kalliope.py
+        :rtype: str
         """
         import inspect
         import os

+ 29 - 6
core/FileManager.py

@@ -1,6 +1,5 @@
 import logging
 import os
-import shutil
 
 
 logging.basicConfig()
@@ -8,16 +7,33 @@ logger = logging.getLogger("kalliope")
 
 
 class FileManager:
+    """
+    Class used to manage Files
+    """
     def __init__(self):
         pass
 
     @staticmethod
     def create_directory(cache_path):
+        """
+        Create a directory at the provided `cache_path`
+        :param cache_path: the path of the directory to create
+        :type cache_path: str
+        """
         if not os.path.exists(cache_path):
             os.makedirs(cache_path)
 
     @staticmethod
     def write_in_file(file_path, content):
+        """
+        Write contents into a file
+        :param file_path: the path of the file to write on
+        :type file_path: str
+        :param content: the contents to write in the file
+        :type content: str
+
+        .. raises:: IOError
+        """
         try:
             with open(file_path, "wb") as file_open:
                 file_open.write(content)
@@ -26,20 +42,25 @@ class FileManager:
         except IOError as e:
             logger.error("I/O error(%s): %s", e.errno, e.strerror)
 
-    @staticmethod
-    def wipe_cache(cache_path):
-        shutil.rmtree(cache_path)
-
     @staticmethod
     def file_is_empty(file_path):
+        """
+        Check if the file is empty
+        :param file_path: the path of the file
+        :return: True if the file is empty, False otherwise
+        """
         return os.path.getsize(file_path) == 0
 
     @staticmethod
     def remove_file(file_path):
+        """
+        Remove the file locate at the provided `file_path`
+        :param file_path:
+        :return: True if the file has been removed successfully, False otherwise
+        """
         if os.path.exists(file_path):
             return os.remove(file_path)
 
-
     @staticmethod
     def is_path_creatable(pathname):
         """
@@ -56,6 +77,8 @@ class FileManager:
         either currently exists or is hypothetically creatable; `False` otherwise.
 
         This function is guaranteed to _never_ raise exceptions.
+
+        .. raises:: OSError
         """
         try:
             return os.path.exists(pathname) or FileManager.is_path_creatable(pathname)

+ 14 - 11
core/MainController.py

@@ -2,15 +2,15 @@ import logging
 import os
 import random
 
+from flask import Flask
+
 from core import Utils
 from core.ConfigurationManager import SettingLoader
-from core.ConfigurationManager.BrainLoader import BrainLoader
 from core.OrderAnalyser import OrderAnalyser
 from core.OrderListener import OrderListener
 from core.Players import Mplayer
-from core.TriggerLauncher import TriggerLauncher
-from flask import Flask
 from core.RestAPI.FlaskAPI import FlaskAPI
+from core.TriggerLauncher import TriggerLauncher
 from neurons import Say
 
 logging.basicConfig()
@@ -18,6 +18,9 @@ logger = logging.getLogger("kalliope")
 
 
 class MainController:
+    """
+    This Class is the global controller of the application.
+    """
     def __init__(self, brain=None):
         self.brain = brain
         # get global configuration
@@ -39,11 +42,10 @@ class MainController:
 
     def callback(self):
         """
-        # we have detected the hotword, we can now pause the kalliope Trigger for a while
-        # The user can speak out loud his order during this time.
-        :return:
+        we have detected the hotword, we can now pause the Trigger for a while
+        The user can speak out loud his order during this time.
         """
-        # pause the snowboy process
+        # pause the trigger process
         self.trigger_instance.pause()
         # start listening for an order
         self.order_listener.start()
@@ -57,7 +59,8 @@ class MainController:
     def analyse_order(self, order):
         """
         Receive an order, try to retreive it in the brain.yml to launch to attached plugins
-        :return:
+        :param order: the sentence received
+        :type order: str
         """
         order_analyser = OrderAnalyser(order, main_controller=self, brain=self.brain)
         order_analyser.start()
@@ -72,7 +75,7 @@ class MainController:
     def _get_default_trigger(self):
         """
         Return an instance of the default trigger
-        :return:
+        :return: Trigger
         """
         for trigger in self.settings.triggers:
             if trigger.name == self.settings.default_trigger_name:
@@ -84,8 +87,8 @@ class MainController:
         Return a path of a sound to play
         If the path is absolute, test if file exist
         If the path is relative, we check if the file exist in the sound folder
-        :param random_wake_up_sounds:
-        :return:
+        :param random_wake_up_sounds: List of wake_up sounds
+        :return: path of a sound to play
         """
         # take first randomly a path
         random_path = random.choice(random_wake_up_sounds)

+ 5 - 0
core/Models/Brain.py

@@ -3,6 +3,11 @@ from core.Models import Singleton
 
 @Singleton
 class Brain:
+    # TODO review the Singleton, should be Instantiate at the BrainLoader level
+    """
+    This Class is a Singleton Representing the Brain.yml file with synapse
+    .. note:: the is_loaded Boolean is True when the Brain has been properly loaded.
+    """
 
     def __init__(self, synapses=None, brain_file=None, brain_yaml=None):
         self.synapses = synapses

+ 13 - 0
core/Models/Event.py

@@ -1,4 +1,10 @@
 class Event(object):
+    """
+    This Class is representing an Event which is raised by when the System at some defined time.
+
+    .. note:: Events are based on the system crontab
+    """
+
     def __init__(self, period):
         self.period = period
 
@@ -7,6 +13,13 @@ class Event(object):
                                    self.period)
 
     def serialize(self):
+        """
+        This method allows to serialize in a proper way this object
+
+        :return: A dict of name / period
+        :rtype: Dict
+        """
+
         return {
             'event': self.period
         }

+ 11 - 1
core/Models/Neuron.py

@@ -1,11 +1,21 @@
+class Neuron(object):
+    """
+    This Class is representing a Neuron which is corresponding to an action to perform.
 
+    .. note:: Neurons are defined in the brain file
+    """
 
-class Neuron(object):
     def __init__(self, name=None, parameters=None):
         self.name = name
         self.parameters = parameters
 
     def serialize(self):
+        """
+        This method allows to serialize in a proper way this object
+
+        :return: A dict of name and parameters
+        :rtype: Dict
+        """
         return {
             'name': self.name,
             'parameters': str(self.parameters)

+ 13 - 0
core/Models/Order.py

@@ -1,4 +1,10 @@
 class Order(object):
+    """
+    This Class is representing an Order which is raised by when an entry (Vocal/REST/ anything ...) is matching it.
+
+    .. note:: Order are defined in the brain file for each synapse.
+    """
+
     def __init__(self, sentence):
         self.sentence = sentence
 
@@ -6,6 +12,13 @@ class Order(object):
         return "%s: Sentence: %s" % (self.__class__.__name__, self.sentence)
 
     def serialize(self):
+        """
+        This method allows to serialize in a proper way this object
+
+        :return: A dict of order
+        :rtype: Dict
+        """
+
         return {
             'order': self.sentence
         }

+ 4 - 0
core/Models/RestAPI.py

@@ -1,4 +1,8 @@
 class RestAPI(object):
+    """
+    This Class is representing the rest API with all its configuration.
+    """
+
     def __init__(self, password_protected=None, login=None, password=None, active=None, port=None):
         """
 

+ 6 - 0
core/Models/Settings.py

@@ -3,6 +3,12 @@ from core.Models import Singleton
 
 @Singleton
 class Settings(object):
+    # TODO review the Singleton, should be Instantiate at the BrainLoader level
+    """
+    This Class is a Singleton Representing the settings.yml file with synapse
+
+    .. note:: the is_loaded Boolean is True when the Settings has been properly loaded.
+    """
     def __init__(self,
                  default_tts_name=None,
                  default_stt_name=None,

+ 2 - 0
core/Models/Singleton.py

@@ -1,5 +1,7 @@
 class Singleton:
     """
+    (From Stackoverflow : http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons-in-python)
+
     A non-thread-safe helper class to ease implementing singletons.
     This should be used as a decorator -- not a metaclass -- to the
     class that should be a singleton.

+ 5 - 1
core/Models/Stt.py

@@ -1,6 +1,10 @@
+class Stt(object):
+    """
+    This Class is representing a Speech To Text (STT) element with name and parameters
 
+    .. note:: must be defined in the settings.yml
+    """
 
-class Stt(object):
     def __init__(self, name=None, parameters=None):
         self.name = name
         self.parameters = parameters

+ 14 - 1
core/Models/Synapse.py

@@ -1,10 +1,23 @@
 class Synapse(object):
-    def __init__(self, name, neurons, signals):
+    """
+    This Class is representing a Synapse with its name, and a dict of Neurons and a dict of signals
+
+    .. note:: must be defined in the brain.yml
+    """
+
+    def __init__(self, name=None, neurons=None, signals=None):
         self.name = name
         self.neurons = neurons
         self.signals = signals
 
     def serialize(self):
+        """
+        This method allows to serialize in a proper way this object
+
+        :return: A dict of name, neurons, signals
+        :rtype: Dict
+        """
+
         return {
             'name': self.name,
             'neurons': [e.serialize() for e in self.neurons],

+ 5 - 2
core/Models/Trigger.py

@@ -1,10 +1,13 @@
+class Trigger(object):
+    """
+    This Class is representing a Trigger with its name and parameters
 
+    .. note:: must be defined in the settings.yml
+    """
 
-class Trigger(object):
     def __init__(self, name=None, parameters=None):
         self.name = name
         self.parameters = parameters
 
     def __str__(self):
         return "Trigger name: %s, parameters: %s" % (str(self.name), str(self.parameters))
-

+ 5 - 1
core/Models/Tts.py

@@ -1,6 +1,10 @@
+class Tts(object):
+    """
+    This Class is representing a Text To Speech (TTS) with its name and parameters
 
+    .. note:: must be defined in the settings.yml
+    """
 
-class Tts(object):
     def __init__(self, name=None, parameters=None):
         self.name = name
         self.parameters = parameters

+ 40 - 16
core/NeuronModule.py

@@ -16,34 +16,45 @@ logger = logging.getLogger("kalliope")
 
 
 class InvalidParameterException(Exception):
+    """
+   Some Neuron parameters are invalid.
+    """
     pass
 
 
 class MissingParameterException(Exception):
+    """
+    Some Neuron parameters are missing.
+    """
     pass
 
 
 class NoTemplateException(Exception):
-    pass
-
-
-class MultipleTemplateException(Exception):
+    """
+    You must specify a say_template or a file_template
+    """
     pass
 
 
 class TemplateFileNotFoundException(Exception):
+    """
+    Template file can not be found. Check the provided path.
+    """
     pass
 
 
 class TTSModuleNotFound(Exception):
-    pass
-
-
-class TTSNotInstantiable(Exception):
+    """
+    TTS module can not be find. It must be configured in the settings file.
+    """
     pass
 
 
 class NeuronModule(object):
+    """
+    This Abstract Class is representing main Class for Neuron.
+    Each Neuron must implement this Class.
+    """
     def __init__(self, **kwargs):
         """
         Class used by neuron for talking
@@ -81,8 +92,9 @@ class NeuronModule(object):
         If it's a string, simply use the TTS with the message
         If it's a list, we select randomly a string in the list and give it to the TTS
         If it's a dict, we use the template given in parameter to create a string that we give to the TTS
-        :param message: Can be a String or a dict
-        :return:
+        :param message: Can be a String or a dict or a list
+
+        .. raises:: TTSModuleNotFound
         """
         logger.debug("NeuronModule Say() called with message: %s" % message)
 
@@ -109,7 +121,7 @@ class NeuronModule(object):
                 raise TTSModuleNotFound("The tts module name %s does not exist in settings file" % self.tts)
             # change the cache settings with the one precised for the current neuron
             if self.override_cache is not None:
-                tts_object.parameter = self._update_cache_var(self.override_cache, tts_object.parameter)
+                tts_object.parameters = self._update_cache_var(self.override_cache, tts_object.parameters)
 
             logger.debug("NeuroneModule: TTS args: %s" % tts_object)
 
@@ -121,9 +133,11 @@ class NeuronModule(object):
 
     def _get_message_from_dict(self, message_dict):
         """
-        Generate a message taht can be played by a TTS engine from a dict of variable and the jinja template
-        :param message_dict:
-        :return:
+        Generate a message that can be played by a TTS engine from a dict of variable and the jinja template
+        :param message_dict: the dict of message
+        :return: The message to say
+
+        .. raises:: TemplateFileNotFoundException
         """
         returned_message = None
 
@@ -162,11 +176,22 @@ class NeuronModule(object):
 
     @staticmethod
     def _get_content_of_file(real_file_template_path):
+        """
+        Return the content of a file in path <real_file_template_path>
+        :param real_file_template_path: path of the file to return the content
+        :return: file content str
+        """
         with open(real_file_template_path, 'r') as content_file:
             return content_file.read()
 
     @staticmethod
     def _update_cache_var(new_override_cache, args_list):
+        """
+        update the value for the key "cache" in the dict args_list
+        :param new_override_cache: cache bolean to set in place of the current one in args_list
+        :param args_list: arg list that contain "cache" to update
+        :return:
+        """
         logger.debug("args for TTS plugin before update: %s" % str(args_list))
         args_list["cache"] = new_override_cache
         logger.debug("args for TTS plugin after update: %s" % str(args_list))
@@ -176,8 +201,7 @@ class NeuronModule(object):
     def get_audio_from_stt(callback):
         """
         Call the default STT to get an audio sample and return it into the callback method
-        :param callback:
-        :return:
+        :param callback: A callback function
         """
         # call the order listener
         oa = OrderListener(callback=callback)

+ 1 - 6
core/NeuroneLauncher.py

@@ -6,10 +6,6 @@ logging.basicConfig()
 logger = logging.getLogger("kalliope")
 
 
-class NeuroneNotFoundError(Exception):
-    pass
-
-
 class NeuroneLauncher:
 
     def __init__(self):
@@ -20,9 +16,8 @@ class NeuroneLauncher:
         """
         Start a neuron plugin
         :param neuron: neuron object
-        :type neuron: Neurone
+        :type neuron: Neuron
         :return:
         """
         logger.debug("Run plugin \"%s\" with parameters %s" % (neuron.name, neuron.parameters))
         return Utils.get_dynamic_class_instantiation("neurons", neuron.name.capitalize(), neuron.parameters)
-

+ 12 - 0
core/OrderAnalyser.py

@@ -13,6 +13,9 @@ logger = logging.getLogger("kalliope")
 
 
 class OrderAnalyser:
+    """
+    This Class is used to compare the incoming message to the Signal/Order sentences.
+    """
     def __init__(self, order, main_controller=None, brain=None):
         """
         Class used to load brain and run neuron attached to the received order
@@ -28,6 +31,10 @@ class OrderAnalyser:
         logger.debug("OrderAnalyser, Received order: %s" % self.order)
 
     def start(self):
+        # TODO : refactor this method !!
+        """
+        This method matches the incoming messages to the signals/order sentences provided in the Brain
+        """
         synapses_found = False
         problem_in_neuron_found = False
         # create a dict of synapses that have benn launched
@@ -124,6 +131,11 @@ class OrderAnalyser:
 
     @staticmethod
     def _is_containing_bracket(sentence):
+        """
+        Return True if the text in <sentence> contains brackets
+        :param sentence:
+        :return:
+        """
         # print "sentence to test %s" % sentence
         pattern = r"{{|}}"
         # prog = re.compile(pattern)

+ 16 - 3
core/OrderListener.py

@@ -12,6 +12,12 @@ logger = logging.getLogger("kalliope")
 
 
 class OrderListener(Thread):
+    """
+    This Class allows to Listen to an Incoming voice order.
+
+    .. notes:: Thread are used to calibrate the sound of the microphone input with the noise while
+        starting to listen the incoming order. Basically it avoids delays.
+    """
 
     def __init__(self, callback=None, stt=None):
         """
@@ -19,8 +25,12 @@ class OrderListener(Thread):
         We now wait for an order spoken out loud by the user, translate the order into a text and run the action
          attached to this order from settings
         :param callback: callback function to call
+        :type callback: Callback function
         :param stt: Speech to text plugin name to load. If not provided,
+        :type stt: STT instance
         we will load the default one set in settings
+
+        .. seealso::  STT
         """
         # this is a trick to ignore ALSA output error
         # see http://stackoverflow.com/questions/7088672/pyaudio-working-but-spits-out-error-messages-each-time
@@ -32,6 +42,9 @@ class OrderListener(Thread):
         self.settings = SettingLoader.get_settings()
 
     def run(self):
+        """
+        Start thread
+        """
         self.load_stt_plugin()
 
     def load_stt_plugin(self):
@@ -47,7 +60,9 @@ class OrderListener(Thread):
 
     @staticmethod
     def _ignore_stderr():
-        """Try to forward PortAudio messages from stderr to /dev/null."""
+        """
+        Try to forward PortAudio messages from stderr to /dev/null.
+        """
         ffi = _FFI()
         ffi.cdef("""
         /* from stdio.h */
@@ -65,5 +80,3 @@ class OrderListener(Thread):
                 stdio.__stderrp = devnull
             except KeyError:
                 stdio.fclose(devnull)
-
-

+ 20 - 5
core/Players/Mplayer.py

@@ -5,17 +5,34 @@ import subprocess
 logging.basicConfig()
 logger = logging.getLogger("kalliope")
 
-
 MPLAYER_EXEC_PATH = "/usr/bin/mplayer"
 
 
 class Mplayer(object):
+    """
+    This Class is representing the MPlayer Object used to play the all sound of the system.
+    """
 
     def __init__(self):
         pass
 
     @classmethod
     def play(cls, filepath):
+        """
+        Play the sound located in the provided filepath
+
+        :param filepath: The file path of the sound to play
+        :type filepath: str
+
+        :Example:
+
+            Mplayer.play(self.file_path)
+
+        .. seealso::  TTS
+        .. raises::
+        .. warnings:: Class Method and Public
+        """
+
         mplayer_exec_path = [MPLAYER_EXEC_PATH]
         mplayer_options = ['-slave', '-quiet']
         mplayer_command = list()
@@ -25,8 +42,6 @@ class Mplayer(object):
         mplayer_command.append(filepath)
         logger.debug("Mplayer cmd: %s" % str(mplayer_command))
 
-        FNULL = open(os.devnull, 'w')
-
-        subprocess.call(mplayer_command, stdout=FNULL, stderr=FNULL)
-
+        fnull = open(os.devnull, 'w')
 
+        subprocess.call(mplayer_command, stdout=fnull, stderr=fnull)

+ 9 - 10
core/ShellGui.py

@@ -22,7 +22,6 @@ def signal_handler(signal, frame):
     Used to catch a keyboard signal like Ctrl+C in order to kill the kalliope program
     :param signal: signal handler
     :param frame: execution frame
-    :return:
     """
     print "\n"
     Utils.print_info("Ctrl+C pressed. Killing Kalliope")
@@ -35,7 +34,10 @@ class ShellGui:
     def __init__(self, brain=None):
         """
         Load a GUI in a shell console for testing TTS, STT and brain configuration
-        :param brain:
+        :param brain: The Brain object provided by the brain.yml
+        :type brain: Brain
+
+        .. seealso:: Brain
         """
         # override brain
         self.brain = brain
@@ -54,7 +56,6 @@ class ShellGui:
         """
         Main menu of the shell UI.
         Provide a list of action the user can select to test his settings
-        :return:
         """
 
         code, tag = self.d.menu("Test your Kalliope settings from this menu",
@@ -74,7 +75,6 @@ class ShellGui:
         """
         Show the list of available STT.
         Clicking on a STT will load the engine to catch the user audio and return a text
-        :return:
         """
         # we get STT from settings
         stt_list = self.settings.stts
@@ -101,7 +101,7 @@ class ShellGui:
         - select a TTS engine to test
         - type a sentence
         - press ok and listen the generated audio from the typed text
-        :return:
+        :param sentence_to_test: the screen written sentence to test
         """
         continue_bool = True
         # if we don't have yet a sentence to test, we ask the user to type one
@@ -139,7 +139,6 @@ class ShellGui:
         Call the TTS
         :param tts_name: Name of the TTS module to launch
         :param sentence_to_test: String text to send to the TTS engine
-        :return:
         """
         sentence_to_test = sentence_to_test.encode('utf-8')
         tts_name = tts_name.encode('utf-8')
@@ -149,9 +148,10 @@ class ShellGui:
     @staticmethod
     def _get_choices_tuple_from_list(list_to_convert):
         """
-        Return a list of tup that can be used in Dialog menu
-        :param list_to_convert: List of object to convert into tuple
-        :return:
+            Return a list of tup that can be used in Dialog menu
+            :param list_to_convert: List of object to convert into tuple
+            :return: List of choices
+            :rtype: List
         """
         # create a list of tuple that can be used by the dialog menu
         choices = list()
@@ -175,7 +175,6 @@ class ShellGui:
     def show_synapses_test_menu(self):
         """
         Show a list of available synapse in the brain to run it directly
-        :return:
         """
 
         # create a tuple for the list menu

+ 5 - 1
core/SynapseLauncher.py

@@ -1,8 +1,12 @@
-from core.ConfigurationManager.BrainLoader import BrainLoader
 from core.NeuroneLauncher import NeuroneLauncher
 
 
 class SynapseNameNotFound(Exception):
+    """
+    The Synapse has not been found
+
+    .. seealso: Synapse
+    """
     pass
 
 

+ 3 - 0
core/TTS/TTSLauncher.py

@@ -17,6 +17,9 @@ class TTSLauncher(object):
         :param tts: TTS model
         :type tts: Tts
         :return: TTS module instance
+
+        .. seealso::  TTS
+        .. warnings:: Class Method and Public
         """
         logger.debug("get TTS module \"%s\" with parameters %s" % (tts.name, tts.parameters))
         return Utils.get_dynamic_class_instantiation("tts", tts.name.capitalize(), tts.parameters)

+ 21 - 8
core/TTS/TTSModule.py

@@ -12,25 +12,37 @@ logger = logging.getLogger("kalliope")
 
 
 class MissingTTSParameter(Exception):
+    """
+    Some TTS Parameters are missing in the settings.yml file.
+
+    .. seealose:: Settings
+    """
     pass
 
 
 class TtsGenerateAudioFunctionNotFound(Exception):
+    """
+    You must provide a callBack to the TTS
+    """
     pass
 
 
 class FailToLoadSoundFile(Exception):
+    """
+    Fail while truing to load the sound file.
+    """
     pass
 
 
 class TTSModule(object):
+    """
+    Mother class of TTS module. Handle:
+    - Cache: call cache object to create file, delete file, check if file exist
+    - Player: call the default player to play the generated file
+    """
 
     def __init__(self, **kwargs):
-        """
-        Mother class of TTS module. Handle:
-        - Cache: call cache object to create file, delete file, check if file exist
-        - Player: call the default player to play the generated file
-        """
+
         # set parameter from what we receive from the settings
         self.cache = kwargs.get('cache', False)
         self.language = kwargs.get('language', None)
@@ -54,7 +66,6 @@ class TTSModule(object):
     def play_audio(self):
         """
         Play the audio file
-        :return:
         """
         Mplayer.play(self.file_path)
 
@@ -62,8 +73,11 @@ class TTSModule(object):
         """
         Generate an audio file from <words> if not already in cache and call the Player to play it
         :param words: Sentence text from which we want to generate an audio file
+        :type words: String
         :param generate_audio_function_from_child: The child function to generate a file if necessary
-        :return:
+        :type generate_audio_function_from_child; Callback function
+
+        .. raises:: TtsGenerateAudioFunctionNotFound
         """
         if generate_audio_function_from_child is None:
             raise TtsGenerateAudioFunctionNotFound
@@ -120,7 +134,6 @@ class TTSModule(object):
     def is_file_already_in_cache(self):
         """
         Return true if the file to generate has already been generated before
-        :return:
         """
         # generate sub folder
         FileManager.create_directory(self.base_cache_path)

+ 1 - 2
core/TriggerLauncher.py

@@ -24,5 +24,4 @@ class TriggerLauncher(object):
         trigger.parameters["callback"] = callback
         logger.debug("TriggerLauncher: Start trigger %s with parameters: %s" % (trigger.name, trigger.parameters))
         return Utils.get_dynamic_class_instantiation("trigger", trigger.name.capitalize(),
-                                                                 trigger.parameters)
-
+                                                     trigger.parameters)

+ 12 - 1
core/Utils.py

@@ -5,6 +5,11 @@ logger = logging.getLogger("kalliope")
 
 
 class ModuleNotFoundError(Exception):
+    """
+    The module can not been found
+
+    .. notes: Check the case: must be in lower case.
+    """
     pass
 
 
@@ -55,7 +60,13 @@ class Utils(object):
 
     @classmethod
     def get_dynamic_class_instantiation(cls, package_name, module_name, parameters=None):
-
+        """
+        Load a python class dynamically
+        :param package_name: name of the package where we will find the module to load (neurons, tts, stt, trigger)
+        :param module_name: name of the module from the package_name to load
+        :param parameters:  dict parameters to send as argument to the module
+        :return:
+        """
         logger.debug("Run plugin %s with parameter %s" % (module_name, parameters))
         mod = __import__(package_name, fromlist=[module_name])
         try:

+ 0 - 2
kalliope.py

@@ -22,7 +22,6 @@ def signal_handler(signal, frame):
     Used to catch a keyboard signal like Ctrl+C in order to kill the kalliope program
     :param signal: signal handler
     :param frame: execution frame
-    :return:
     """
     print "\n"
     Utils.print_info("Ctrl+C pressed. Killing Kalliope")
@@ -95,7 +94,6 @@ def configure_logging(debug=None):
     """
     Prepare log folder in current home directory
     :param debug: If true, set the lof level to debug
-    :return:
     """
     logger = logging.getLogger("kalliope")
     logger.propagate = False

+ 10 - 0
neurons/gmail_checker/gmail_checker.py

@@ -57,7 +57,15 @@ class Gmail_checker(NeuronModule):
 
     @staticmethod
     def try_parse(header, encoding):
+        """
+        Verifying the Encoding and return unicode
+
+        :param header: the header to decode
+        :param encoding: the targeted encoding
+        :return: either 'ASCII' or 'ISO-8859-1' or 'UTF-8'
 
+        .. raises:: UnicodeDecodeError
+        """
         if encoding is None:
             encoding = 'ASCII'
         try:
@@ -72,6 +80,8 @@ class Gmail_checker(NeuronModule):
         """
         Check if received parameters are ok to perform operations in the neuron
         :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: MissingParameterException
         """
         if self.username is None:
             raise MissingParameterException("Username parameter required")

+ 3 - 0
neurons/kill_switch/kill_switch.py

@@ -4,6 +4,9 @@ from core.NeuronModule import NeuronModule
 
 
 class Kill_switch(NeuronModule):
+    """
+    Class used to exit Kalliope process from system command
+    """
     def __init__(self, **kwargs):
         super(Kill_switch, self).__init__(**kwargs)
         sys.exit()

+ 10 - 2
neurons/neurotransmitter/neurotransmitter.py

@@ -19,6 +19,11 @@ class Neurotransmitter(NeuronModule):
             self.get_audio_from_stt(callback=self.callback)
 
     def callback(self, audio):
+        """
+        The callback used by the STT module to get the linked synapse
+
+        :param audio: the audio to play by STT
+        """
         logger.debug("Neurotransmitter, receiver audio from STT: %s" % audio)
         # print self.links
         # set a bool to know if we have found a valid answer
@@ -35,9 +40,12 @@ class Neurotransmitter(NeuronModule):
 
     def _links_content_ok(self):
         """
-        Check the content of the links parameter
-        :return:
+        Check if received links are ok to perform operations
+        :return: true if links are ok, raise an exception otherwise
+
+        .. raises:: MissingParameterException
         """
+
         if self.links is None:
             raise MissingParameterException("links parameter required and must contain at least one link")
         if self.default is None:

+ 2 - 0
neurons/openweathermap/Openweathermap.py

@@ -116,6 +116,8 @@ class Openweathermap(NeuronModule):
         """
         Check if received parameters are ok to perform operations in the neuron
         :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: NotImplementedError
         """
         if self.api_key is None:
             raise NotImplementedError("OpenWeatherMap neuron needs an api_key")

+ 4 - 3
neurons/push_message/Push_message.py

@@ -14,7 +14,6 @@ class Push_message(NeuronModule):
         :param message: Message to send
         :param api_key: The Pushetta service secret token
         :param channel_name: Pushetta channel name
-        :return:
         """
         super(Push_message, self).__init__(**kwargs)
 
@@ -24,13 +23,15 @@ class Push_message(NeuronModule):
 
         # check if parameters have been provided
         if self._is_parameters_ok():
-            p = Pushetta( self.api_key)
+            p = Pushetta(self.api_key)
             p.pushMessage(self.channel_name, self.message)
 
     def _is_parameters_ok(self):
         """
         Check if received parameters are ok to perform operations in the neuron
         :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: NotImplementedError
         """
         if self.message is None:
             raise NotImplementedError("Pushetta neuron needs message to send")
@@ -39,4 +40,4 @@ class Push_message(NeuronModule):
         if self.channel_name is None:
             raise NotImplementedError("Pushetta neuron needs channel_name")
 
-        return True
+        return True

+ 2 - 0
neurons/say/say.py

@@ -14,6 +14,8 @@ class Say(NeuronModule):
         """
         Check if received parameters are ok to perform operations in the neuron
         :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: MissingParameterException
         """
         if self.message is None:
             raise MissingParameterException("You must specify a message string or a list of messages as parameter")

+ 2 - 0
neurons/script/script.py

@@ -18,6 +18,8 @@ class Script(NeuronModule):
         """
         Check if received parameters are ok to perform operations in the neuron
         :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: MissingParameterException, InvalidParameterException
         """
         if self.path is None:
             raise MissingParameterException("You must provide a script path.")

+ 10 - 0
neurons/shell/shell.py

@@ -8,6 +8,11 @@ logger = logging.getLogger("kalliope")
 
 
 class AsyncShell(threading.Thread):
+    """
+    Class used to run an asynchrone Shell command
+
+    .. notes:: Impossible to get the success code of the command
+    """
     def __init__(self, cmd):
         self.stdout = None
         self.stderr = None
@@ -24,6 +29,9 @@ class AsyncShell(threading.Thread):
 
 
 class Shell(NeuronModule):
+    """
+    Run a shell command in a synchron mode
+    """
     def __init__(self, **kwargs):
         super(Shell, self).__init__(**kwargs)
 
@@ -52,6 +60,8 @@ class Shell(NeuronModule):
         """
         Check if received parameters are ok to perform operations in the neuron
         :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: MissingParameterException
         """
         if self.cmd is None:
             raise MissingParameterException("cmd parameter required")

+ 8 - 8
neurons/sleep/sleep.py

@@ -12,12 +12,12 @@ class Sleep(NeuronModule):
         if self._is_parameters_ok():
             time.sleep(self.seconds)
 
-        def _is_parameters_ok(self):
-            """
-            Check if received parameters are ok to perform operations in the neuron
-            :return: true if parameters are ok, raise an exception otherwise
-            """
-            if self.seconds is None:
-                raise MissingParameterException("You must set a number of seconds as parameter")
-
+    def _is_parameters_ok(self):
+        """
+        Check if received parameters are ok to perform operations in the neuron
+        :return: true if parameters are ok, raise an exception otherwise
 
+        .. raises:: MissingParameterException
+        """
+        if self.seconds is None:
+            raise MissingParameterException("You must set a number of seconds as parameter")

+ 0 - 3
neurons/systemdate/systemdate.py

@@ -1,4 +1,3 @@
-#!/usr/bin/python
 import time
 
 from core.NeuronModule import NeuronModule
@@ -12,8 +11,6 @@ class Systemdate(NeuronModule):
             cache = False
         super(Systemdate, self).__init__(cache=cache, **kwargs)
 
-
-
         # local time and date
         hour = time.strftime("%H")          # Hour (24-hour clock) as a decimal number [00,23].
         minute = time.strftime("%M")        # Minute as a decimal number [00,59].

+ 2 - 0
neurons/tasker_autoremote/tasker_autoremote.py

@@ -30,6 +30,8 @@ class Tasker_autoremote(NeuronModule):
         """
         Check if received parameters are ok to perform operations in the neuron
         :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: MissingParameterException
         """
         if self.key is None:
             raise MissingParameterException("key parameter required")

+ 2 - 0
neurons/twitter/Twitter.py

@@ -32,6 +32,8 @@ class Twitter(NeuronModule):
         """
         Check if received parameters are ok to perform operations in the neuron
         :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: InvalidParameterException
         """
         if self.consumer_key is None:
             raise InvalidParameterException("Twitter needs a consumer_key")

+ 4 - 2
neurons/wake_on_lan/Wake_on_lan.py

@@ -31,8 +31,10 @@ class Wake_on_lan(NeuronModule):
 
     def _is_parameters_ok(self):
         """
-        Check if received parameters are ok to perform operations in the neuron
-        :return: true if parameters are ok, raise an exception otherwise
+            Check if received parameters are ok to perform operations in the neuron
+            :return: true if parameters are ok, raise an exception otherwise
+
+            .. raises:: InvalidParameterException, MissingParameterException
         """
         # check we provide a mac address
         if self.mac_address is None:

+ 5 - 2
neurons/wikipedia/Wikipedia.py

@@ -41,7 +41,7 @@ class Wikipedia(NeuronModule):
                 self.may_refer = list(set(self.may_refer))
                 self.returncode = "DisambiguationError"
                 summary = ""
-            except wikipedia.exceptions.PageError, e:
+            except wikipedia.exceptions.PageError:
                 # Exception raised when no Wikipedia matched a query.
                 self.returncode = "PageError"
                 summary = ""
@@ -58,8 +58,11 @@ class Wikipedia(NeuronModule):
     def _is_parameters_ok(self):
         """
         Check if received parameters are ok to perform operations in the neuron
-        :return:
+        :return: true if parameters are ok, raise an exception otherwise
+
+        .. raises:: InvalidParameterException
         """
+
         if self.query is None:
             raise InvalidParameterException("Wikipedia needs a query")
         if self.language is None:

+ 4 - 4
stt/apiai/Apiai.py

@@ -14,10 +14,6 @@ class Apiai(OrderListener):
         """
         OrderListener.__init__(self)
 
-        """
-        Start recording the microphone
-        :return:
-        """
         # callback function to call after the translation speech/tex
         self.callback = callback
         # obtain audio from the microphone
@@ -46,6 +42,10 @@ class Apiai(OrderListener):
             Utils.print_danger("Could not request results from Apiai Speech Recognition service; {0}".format(e))
 
     def _analyse_audio(self, audio):
+        """
+        Confirm the audio exists annd run it in a Callback
+        :param audio: the captured audio
+        """
         # if self.main_controller is not None:
         #     self.main_controller.analyse_order(audio)
         if self.callback is not None:

+ 5 - 4
stt/bing/Bing.py

@@ -14,10 +14,6 @@ class Bing(OrderListener):
         """
         OrderListener.__init__(self)
 
-        """
-        Start recording the microphone
-        :return:
-        """
         # callback function to call after the translation speech/tex
         self.callback = callback
         # obtain audio from the microphone
@@ -45,6 +41,11 @@ class Bing(OrderListener):
             Utils.print_danger("Could not request results from Bing Speech Recognition service; {0}".format(e))
 
     def _analyse_audio(self, audio):
+        """
+        Confirm the audio exists annd run it in a Callback
+        :param audio: the captured audio
+        """
+
         # if self.main_controller is not None:
         #     self.main_controller.analyse_order(audio)
         if self.callback is not None:

+ 5 - 4
stt/google/Google.py

@@ -14,10 +14,6 @@ class Google(OrderListener):
         """
         OrderListener.__init__(self)
 
-        """
-        Start recording the microphone
-        :return:
-        """
         # callback function to call after the translation speech/tex
         self.callback = callback
         # obtain audio from the microphone
@@ -48,6 +44,11 @@ class Google(OrderListener):
             Utils.print_danger("Could not request results from Google Speech Recognition service; {0}".format(e))
 
     def _analyse_audio(self, audio):
+        """
+        Confirm the audio exists annd run it in a Callback
+        :param audio: the captured audio
+        """
+
         # if self.main_controller is not None:
         #     self.main_controller.analyse_order(audio)
         if self.callback is not None:

+ 8 - 13
stt/houndify/Houndify.py

@@ -14,10 +14,6 @@ class Houndify(OrderListener):
         """
         OrderListener.__init__(self)
 
-        """
-        Start recording the microphone
-        :return:
-        """
         # callback function to call after the translation speech/tex
         self.callback = callback
         # obtain audio from the microphone
@@ -30,14 +26,13 @@ class Houndify(OrderListener):
 
         # recognize speech using Houndify Speech Recognition
         try:
-
-
-            id = kwargs.get('client_id', None)
+            client_id = kwargs.get('client_id', None)
             key = kwargs.get('key', None)
             language = kwargs.get('language', "en-US")
             show_all = kwargs.get('show_all', False)
 
-            captured_audio = r.recognize_houndify(audio, client_id=id, client_key=key, language=language, show_all=show_all)
+            captured_audio = r.recognize_houndify(audio, client_id=client_id, client_key=key,
+                                                  language=language, show_all=show_all)
             Utils.print_success("Houndify Speech Recognition thinks you said %s" % captured_audio)
             self._analyse_audio(captured_audio)
 
@@ -47,12 +42,12 @@ class Houndify(OrderListener):
             Utils.print_danger("Could not request results from Houndify Speech Recognition service; {0}".format(e))
 
     def _analyse_audio(self, audio):
+        """
+            Confirm the audio exists annd run it in a Callback
+            :param audio: the captured audio
+        """
+
         # if self.main_controller is not None:
         #     self.main_controller.analyse_order(audio)
         if self.callback is not None:
             self.callback(audio)
-
-
-
-
-

+ 5 - 4
stt/wit/Wit.py

@@ -14,10 +14,6 @@ class Wit(OrderListener):
         """
         OrderListener.__init__(self)
 
-        """
-        Start recording the microphone
-        :return:
-        """
         # callback function to call after the translation speech/tex
         self.callback = callback
         # obtain audio from the microphone
@@ -43,6 +39,11 @@ class Wit(OrderListener):
             Utils.print_danger("Could not request results from Wit.ai Speech Recognition service; {0}".format(e))
 
     def _analyse_audio(self, audio):
+        """
+        Confirm the audio exists annd run it in a Callback
+        :param audio: the captured audio
+        """
+
         # if self.main_controller is not None:
         #     self.main_controller.analyse_order(audio)
         if self.callback is not None:

+ 0 - 1
trigger/snowboy/snowboydecoder.py

@@ -114,7 +114,6 @@ class HotwordDetector(object):
             frames_per_buffer=2048,
             stream_callback=audio_callback)
 
-
     def start(self, detected_callback=play_audio_file,
               interrupt_check=lambda: False,
               sleep_time=0.03):

+ 24 - 0
tts/acapela/acapela.py

@@ -21,11 +21,19 @@ class Acapela(TTSModule):
             raise MissingTTSParameter("voice parameter is required by the Acapela TTS")
 
     def say(self, words):
+        """
+        :param words: The sentence to say
+        """
 
         self.generate_and_play(words, self._generate_audio_file)
 
     def _generate_audio_file(self):
+        """
+        Generic method used as a Callback in TTSModule
+            - must provided the audio file and write it on the disk
 
+        .. raises:: FailToLoadSoundFile
+        """
         # Prepare payload
         payload = self.get_payload()
 
@@ -48,6 +56,12 @@ class Acapela(TTSModule):
         FileManager.write_in_file(self.file_path, r.content)
 
     def get_payload(self):
+        """
+        Generic method used load the payload used to acces the remote api
+
+        :return: Payload to use to access the remote api
+        """
+
         return {
             "MyLanguages": self.language,
             "MySelectedVoice": self.voice,
@@ -58,6 +72,16 @@ class Acapela(TTSModule):
 
     @staticmethod
     def get_audio_link(url, payload, timeout_expected=TTS_TIMEOUT_SEC):
+        """
+        Return the audio link
+
+        :param url: the url to access
+        :param payload: the payload to use to acces the remote api
+        :param timeout_expected: timeout before the post request is cancel
+        :return: the audio link
+        :rtype: String
+        """
+
         r = requests.post(url, payload, timeout=timeout_expected)
         data = r.content
         return re.search("(?P<url>https?://[^\s]+).mp3", data).group(0)

+ 15 - 0
tts/googletts/googletts.py

@@ -16,10 +16,19 @@ class Googletts(TTSModule):
         super(Googletts, self).__init__(**kwargs)
 
     def say(self, words):
+        """
+        :param words: The sentence to say
+        """
 
         self.generate_and_play(words, self._generate_audio_file)
 
     def _generate_audio_file(self):
+        """
+        Generic method used as a Callback in TTSModule
+            - must provided the audio file and write it on the disk
+
+        .. raises:: FailToLoadSoundFile
+        """
 
         # Prepare payload
         payload = self.get_payload()
@@ -40,6 +49,12 @@ class Googletts(TTSModule):
         FileManager.write_in_file(self.file_path, r.content)
 
     def get_payload(self):
+        """
+        Generic method used load the payload used to access the remote api
+
+        :return: Payload to use to access the remote api
+        """
+
         return {
             "q": self.words,
             "tl": self.language,

+ 10 - 2
tts/pico2wave/pico2wave.py

@@ -15,10 +15,20 @@ class Pico2wave(TTSModule):
         super(Pico2wave, self).__init__(**kwargs)
 
     def say(self, words):
+        """
+        :param words: The sentence to say
+        """
 
         self.generate_and_play(words, self._generate_audio_file)
 
     def _generate_audio_file(self):
+        """
+        Generic method used as a Callback in TTSModule
+            - must provided the audio file and write it on the disk
+
+        .. raises:: FailToLoadSoundFile
+        """
+
         pico2wave_exec_path = ["/usr/bin/pico2wave"]
 
         # pico2wave needs that the file path ends with .wav
@@ -37,5 +47,3 @@ class Pico2wave(TTSModule):
 
         # remove the extension .wav
         os.rename(tmp_path, self.file_path)
-
-

+ 14 - 1
tts/voicerss/voicerss.py

@@ -16,11 +16,19 @@ class Voicerss(TTSModule):
         super(Voicerss, self).__init__(**kwargs)
 
     def say(self, words):
+        """
+        :param words: The sentence to say
+        """
 
         self.generate_and_play(words, self._generate_audio_file)
 
     def _generate_audio_file(self):
+        """
+        Generic method used as a Callback in TTSModule
+            - must provided the audio file and write it on the disk
 
+        .. raises:: FailToLoadSoundFile
+        """
         # Prepare payload
         payload = self.get_payload()
 
@@ -40,9 +48,14 @@ class Voicerss(TTSModule):
         FileManager.write_in_file(self.file_path, r.content)
 
     def get_payload(self):
+        """
+        Generic method used load the payload used to acces the remote api
+
+        :return: Payload to use to access the remote api
+        """
+
         return {
             "src": self.words,
             "hl": self.language,
             "c": "mp3"
         }
-

+ 19 - 2
tts/voxygen/voxygen.py

@@ -3,7 +3,7 @@ import logging
 import requests
 
 from core import FileManager
-from core.TTS.TTSModule import TTSModule, MissingTTSParameter, FailToLoadSoundFile
+from core.TTS.TTSModule import TTSModule, MissingTTSParameter
 
 logging.basicConfig()
 logger = logging.getLogger("kalliope")
@@ -24,9 +24,20 @@ class Voxygen(TTSModule):
             raise MissingTTSParameter("voice parameter is required by the Voxygen TTS")
 
     def say(self, words):
+        """
+        :param words: The sentence to say
+        """
+
         self.generate_and_play(words, self._generate_audio_file)
 
     def _generate_audio_file(self):
+        """
+        Generic method used as a Callback in TTSModule
+            - must provided the audio file and write it on the disk
+
+        .. raises:: FailToLoadSoundFile
+        """
+
         payload = self.get_payload(self.voice, self.words)
 
         # getting the mp3
@@ -45,8 +56,14 @@ class Voxygen(TTSModule):
 
     @staticmethod
     def get_payload(voice, words):
+        """
+        Generic method used load the payload used to access the remote api
+
+        :return: Payload to use to access the remote api
+        """
+
         return {
             "method": "redirect",
             "text": words,
             "voice": voice
-        }
+        }