浏览代码

add models

Nicolas Marcq 8 年之前
父节点
当前提交
0e9cdd0ef9

+ 78 - 0
core/ConfigurationManager/BrainLoader.py

@@ -1,4 +1,11 @@
+
 from YAMLLoader import YAMLLoader
+from core.ConfigurationManager.ConfigurationChecker import ConfigurationChecker
+from core.Models.Brain import Brain
+from core.Models.Event import Event
+from core.Models.Neurone import Neurone
+from core.Models.Order import Order
+from core.Models.Synapse import Synapse
 
 FILE_NAME = "brain.yml"
 
@@ -15,5 +22,76 @@ class BrainLoader(YAMLLoader):
     def get_config(self):
         return YAMLLoader.get_config(self)
 
+    def get_events(self):
+        events_in_brain = list()
+        for el in self.get_config():
+            whens = el["when"]
+            for when in whens:
+                # if key event exist in when of the task
+                if 'event' in when:
+                    events_in_brain.append(when['event'])
+
+        return events_in_brain
+
+    def get_brain(self):
+        # get the brain with dict
+        dict_brain = self.get_config()
+        # create a new brain
+        brain = Brain()
+        # create list of Synapse
+        synapses = list()
+        for synapes_dict in dict_brain:
+            print synapes_dict
+            if ConfigurationChecker().check_synape_dict(synapes_dict):
+                print "synapes_dict ok"
+                name = synapes_dict["name"]
+                neurons = self._get_neurons(synapes_dict["neurons"])
+                signals = self._get_signals(synapes_dict["signals"])
+                new_synapse = Synapse(name=name, neurons=neurons, signals=signals)
+                synapses.append(new_synapse)
+
+    def _get_neurons(self, neurons_dict):
+        """
+        Get a list of Neuron object from a neuron dict
+        :param neurons_dict:
+        :return:
+        """
+        neurons = list()
+        for neuron_dict in neurons_dict:
+            print neuron_dict
+            if ConfigurationChecker().check_neuron_dict(neuron_dict):
+                print "Neurons dict ok"
+            for neuron_name in neuron_dict:
+                name = neuron_name
+                parameters = neuron_dict[name]
+                # print parameters
+                new_neuron = Neurone(name=name, parameters=parameters)
+                neurons.append(new_neuron)
+
+        return neurons
+
+    def _get_signals(self, signals_dict):
+        print signals_dict
+        signals = list()
+        for signal_dict in signals_dict:
+            if ConfigurationChecker().check_signal_dict(signal_dict):
+                print "Signals dict ok"
+                event_or_oder = self._get_event_or_order_from_dict(signal_dict)
+
+        return signals
+
+    @staticmethod
+    def _get_event_or_order_from_dict(signal_or_event_dict):
+
+        if 'event' in signal_or_event_dict:
+            print "is event"
+            event = signal_or_event_dict["event"]
+            if ConfigurationChecker.check_event_dict(event):
+                return Event(identifier=event["id"], period=event["period"])
+
+        if 'order' in signal_or_event_dict:
+            print "is order"
+            if ConfigurationChecker.check_order_dict(signal_or_event_dict["order"]):
+                return Order(signal_or_event_dict["order"])
 
 

+ 68 - 0
core/ConfigurationManager/ConfigurationChecker.py

@@ -0,0 +1,68 @@
+class NoSynapeName(Exception):
+    pass
+
+
+class NoSynapeNeurons(Exception):
+    pass
+
+
+class NoSynapeSignals(Exception):
+    pass
+
+
+class NoValidSignal(Exception):
+    pass
+
+
+class NoEventID(Exception):
+    pass
+
+
+class NoEventPeriod(Exception):
+    pass
+
+
+class ConfigurationChecker:
+
+    def __init__(self):
+        pass
+
+    @staticmethod
+    def check_synape_dict(synape_dict):
+
+        if 'name' not in synape_dict:
+            raise NoSynapeName("The Synape does not have a name: %s" % synape_dict)
+
+        if 'neurons' not in synape_dict:
+            raise NoSynapeNeurons("The Synape does not have neurons: %s" % synape_dict)
+
+        if 'signals' not in synape_dict:
+            raise NoSynapeSignals("The Synape does not have signals: %s" % synape_dict)
+
+        return True
+
+    @staticmethod
+    def check_neuron_dict(neuron_dict):
+        # TODO check that the Neuron plugin exist
+        return True
+
+    @staticmethod
+    def check_signal_dict(signal_dict):
+        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):
+        if 'id' not in event_dict:
+            raise NoEventID("Event must contain a unique ID: %s" % event_dict)
+        if 'period' not in event_dict:
+            raise NoEventPeriod("Event must contain a period: %s" % event_dict)
+
+        return True
+
+    @staticmethod
+    def check_order_dict(order_dict):
+        if order_dict is not None:
+            return True
+        return False

+ 112 - 0
core/ConfigurationManager/SettingLoader.py

@@ -1,8 +1,21 @@
 from YAMLLoader import YAMLLoader
+import logging
 
 FILE_NAME = "settings.yml"
 
 
+class DefaultSpeechToTextNotFound(Exception):
+    pass
+
+
+class DefaultSpeechNull(Exception):
+    pass
+
+
+class NoSpeechToTextConfiguration(Exception):
+    pass
+
+
 class SettingLoader(YAMLLoader):
 
     def __init__(self, filename=None):
@@ -14,3 +27,102 @@ class SettingLoader(YAMLLoader):
 
     def get_config(self):
         return YAMLLoader.get_config(self)
+
+    def get_default_speech_to_text(self):
+        settings = self.get_config()
+
+        try:
+            default_speech_to_text = settings["default_speech_to_text"]
+            if default_speech_to_text is None:
+                raise DefaultSpeechNull("Attribute default_speech_to_text is null")
+            logging.info("Default STT: %s" % default_speech_to_text)
+            return default_speech_to_text
+        except KeyError:
+            raise DefaultSpeechToTextNotFound("Attribute default_speech_to_text not found in settings")
+
+    def get_default_text_to_speech(self):
+        settings = self.get_config()
+
+        try:
+            default_text_to_speech = settings["default_text_to_speech"]
+            if default_text_to_speech is None:
+                raise DefaultSpeechNull("Attribute default_text_to_speech is null")
+            logging.info("Default TTS: %s" % default_text_to_speech)
+            return default_text_to_speech
+        except KeyError:
+            raise DefaultSpeechToTextNotFound("Attribute default_text_to_speech not found in settings")
+
+    def get_stt_args(self, default_stt_plugin_name):
+        """
+        Return argument set for the current STT engine
+        :param default_stt_plugin_name: Name of the STT engine
+        :return:
+        """
+
+        def find(lst, key):
+            """
+            Find a key name in a list
+            :param lst: list()
+            :param key: key name to find i the list
+            :return: Return the dict
+            """
+            for el in lst:
+                try:
+                    if el[key]:
+                        return el[key]
+                except TypeError:
+                    pass
+                except KeyError:
+                    pass
+            return None
+
+        settings = self.get_config()
+        try:
+            speechs_to_text = settings["speech_to_text"]
+        except KeyError:
+            raise NoSpeechToTextConfiguration("No speech_to_text in settings")
+
+        logging.debug("Settings file content: %s" % speechs_to_text)
+        # get args
+        args = find(speechs_to_text, default_stt_plugin_name)
+
+        logging.debug("Args for %s STT: %s" % (default_stt_plugin_name, args))
+
+        return args
+
+    def get_tts_args(self, tts_name):
+        """
+        Return argument set for the current STT engine
+        :param tts_name: Name of the TTS engine
+        :return:
+        """
+
+        def find(lst, key):
+            """
+            Find a key name in a list
+            :param lst: list()
+            :param key: key name to find i the list
+            :return: Return the dict
+            """
+            for el in lst:
+                try:
+                    if el[key]:
+                        return el[key]
+                except TypeError:
+                    pass
+                except KeyError:
+                    pass
+            return None
+
+        settings = self.get_config()
+        try:
+            texts_to_speech = settings["text_to_speech"]
+        except KeyError:
+            raise NoSpeechToTextConfiguration("No text_to_speech in settings")
+
+        logging.debug("Settings file content: %s" % texts_to_speech)
+        # get args
+        args = find(texts_to_speech, tts_name)
+        logging.debug("Args for %s TTS: %s" % (tts_name, args))
+        # print args
+        return args

+ 10 - 3
core/ConfigurationManager/YAMLLoader.py

@@ -2,6 +2,10 @@ import os
 import yaml
 
 
+class YAMLFileNotFound(Exception):
+    pass
+
+
 class YAMLLoader:
 
     def __init__(self, yaml_file):
@@ -14,6 +18,9 @@ class YAMLLoader:
         """
         # Load settings.
         __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
-        with open(os.path.join(__location__, self.file)) as ymlfile:
-            cfg = yaml.load(ymlfile)
-        return cfg
+        try:
+            with open(os.path.join(__location__, self.file)) as ymlfile:
+                cfg = yaml.load(ymlfile)
+            return cfg
+        except IOError:
+            raise YAMLFileNotFound("The file path %s does not exist" % self.file)

+ 3 - 1
core/ConfigurationManager/__init__.py

@@ -1 +1,3 @@
-from YAMLLoader import YAMLLoader
+from YAMLLoader import YAMLLoader
+from .ConfigurationManager import ConfigurationManager
+from .SettingLoader import SettingLoader

+ 49 - 0
core/CrontabManager.py

@@ -0,0 +1,49 @@
+from crontab import CronTab
+from crontab import CronSlices
+
+
+class InvalidCrontabPeriod(Exception):
+    pass
+
+CRONTAB_COMMENT = "JARVIS"
+
+
+class CrontabManager:
+
+    def __init__(self, brain_file=None):
+        self.my_user_cron = CronTab(user=True)
+        self.base_command = "/usr/bin/echo"
+
+    def load_events_in_crontab(self):
+        # clean the current crontab from all jarvis event
+        self._remove_all_jarvis_job()
+        # # load the brain file
+        period_string = "* * 5 5 *"
+        event_id = 1
+        # for all tasks with an event, we add the task id to the crontab
+        self._add_event(period_string=period_string, event_id=event_id)
+
+    def _add_event(self, period_string, event_id):
+        my_user_cron = CronTab(user=True)
+        job = my_user_cron.new(command=self.base_command, comment=CRONTAB_COMMENT)
+        if CronSlices.is_valid(period_string):
+            job.setall(period_string)
+            job.enable()
+        else:
+            raise InvalidCrontabPeriod("The crontab period %s is not valid" % period_string)
+        # write the file
+        my_user_cron.write()
+
+    def get_jobs(self):
+        return self.my_user_cron.find_comment(CRONTAB_COMMENT)
+
+    def _remove_all_jarvis_job(self):
+        """
+        Remove all line in crontab that are attached to JARVIS
+        :return:
+        """
+        iter = self.my_user_cron.find_comment(CRONTAB_COMMENT)
+        for job in iter:
+            self.my_user_cron.remove(job)
+        # write the file
+        self.my_user_cron.write()

+ 4 - 0
core/Models/Brain.py

@@ -0,0 +1,4 @@
+
+class Brain:
+    def __init__(self, synapes=None):
+        self.synapes = "synapes"

+ 4 - 0
core/Models/Event.py

@@ -0,0 +1,4 @@
+class Event:
+    def __init__(self, identifier, period):
+        self.identifier = identifier
+        self.period = period

+ 9 - 8
neurons/Neurone.py → core/Models/Neurone.py

@@ -1,10 +1,9 @@
-import importlib
 from jinja2 import Template
 import random
 import os.path
 import logging
 
-from core import ConfigurationManager
+from core.ConfigurationManager.SettingLoader import SettingLoader
 
 
 class NoTemplateException(Exception):
@@ -28,20 +27,22 @@ class TTSNotInstantiable(Exception):
 
 
 class Neurone:
-    def __init__(self, **kwargs):
+    def __init__(self, name=None, parameters=None):
         # get the name of the plugin who load Neurone mother class
         # print self.__class__.__name__
+        self.name = name
+        self.parameters = parameters
 
-        print "Neurone class called with parameters: %s" % kwargs
+        print "Neurone class called with name %s and parameters: %s" % (name, parameters)
 
         # get the tts if is specified otherwise use default
-        tts = kwargs.get('tts', None)
+        tts = self.parameters.get('tts', None)
         if tts is not None:
             self.tts = tts
         else:
-            self.tts = ConfigurationManager.get_default_text_to_speech()
+            self.tts = SettingLoader().get_default_text_to_speech()
         # get tts args
-        self.tts_args = ConfigurationManager.get_tts_args(self.tts)
+        self.tts_args = SettingLoader().get_tts_args(self.tts)
         # capitalise for loading module name
         self.tts = self.tts.capitalize()
         # load the module
@@ -52,7 +53,7 @@ class Neurone:
         tts = kwargs.get('tts', None)
         if tts is not None:
             self.tts = tts
-            self.tts_args = ConfigurationManager.get_tts_args(self.tts)
+            self.tts_args = SettingLoader().get_tts_args(self.tts)
 
         # get if the cache settings is present
         override_cache = kwargs.get('cache', None)

+ 3 - 0
core/Models/Order.py

@@ -0,0 +1,3 @@
+class Order:
+    def __init__(self, sentence):
+        self.sentence = sentence

+ 5 - 0
core/Models/Signal.py

@@ -0,0 +1,5 @@
+class Signal:
+
+    def __init__(self, events, orders):
+        self.events = events
+        self.orders = orders

+ 5 - 0
core/Models/Synapse.py

@@ -0,0 +1,5 @@
+class Synapse:
+    def __init__(self, name, neurons, signals):
+        self.name = name
+        self.neurons = neurons
+        self.signals = signals

+ 0 - 0
core/Models/__init__.py


+ 5 - 5
neurons/__init__.py

@@ -1,8 +1,8 @@
-from Neurone import Neurone
+from ansible_tasks import Ansible_tasks
+from command import Command
+from kill_switch import Kill_switch
 from say import Say
-from systemdate import Systemdate
 from script import Script
-from command import Command
-from ansible_tasks import Ansible_tasks
 from sleep import Sleep
-from kill_switch import Kill_switch
+from systemdate import Systemdate
+

+ 1 - 1
neurons/ansible_tasks/ansible_tasks.py

@@ -4,7 +4,7 @@ from ansible.vars import VariableManager
 from ansible.inventory import Inventory
 from ansible.executor.playbook_executor import PlaybookExecutor
 
-from neurons import Neurone
+from core.Models.Neurone import Neurone
 
 
 class Ansible_tasks(Neurone):

+ 1 - 1
neurons/command/command.py

@@ -1,6 +1,6 @@
 import subprocess
 
-from neurons import Neurone
+from core.Models.Neurone import Neurone
 
 
 class Command(Neurone):

+ 3 - 1
neurons/kill_switch/kill_switch.py

@@ -1,6 +1,8 @@
-from neurons import Neurone
 import sys
 
+from core.Models.Neurone import Neurone
+
+
 class Kill_switch(Neurone):
 
     def __init__(self, *args , **kwargs):

+ 1 - 1
neurons/say/say.py

@@ -1,4 +1,4 @@
-from neurons import Neurone
+from core.Models.Neurone import Neurone
 
 
 class NoMessageException(Exception):

+ 1 - 1
neurons/script/script.py

@@ -1,7 +1,7 @@
 import subprocess
 import os
 
-from neurons import Neurone
+from core.Models.Neurone import Neurone
 
 
 class ScriptNotFound(Exception):

+ 2 - 1
neurons/sleep/sleep.py

@@ -1,6 +1,7 @@
-from neurons import Neurone
 import time
 
+from core.Models.Neurone import Neurone
+
 
 class NoSecondsException(Exception):
     pass

+ 1 - 1
neurons/systemdate/systemdate.py

@@ -1,7 +1,7 @@
 #!/usr/bin/python
 import time
 
-from neurons import Neurone
+from core.Models.Neurone import Neurone
 
 
 class Systemdate(Neurone):

+ 24 - 28
test.py

@@ -1,7 +1,7 @@
 # coding=utf-8
-from crontab import CronTab
-
 from core import ConfigurationManager
+from core.ConfigurationManager.BrainLoader import BrainLoader
+from core.CrontabManager import CrontabManager
 from core.NeuroneLauncher import NeuroneLauncher
 from core.OrderAnalyser import OrderAnalyser
 from core.OrderListener import OrderListener
@@ -15,36 +15,32 @@ from crontab import CronSlices
 # oa = OrderAnalyser("dis bonjour", brain_file="test.yml")
 #
 # oa.start()
-from crontab import CronSlices
 
-class CronManager:
-
-    def __init__(self):
-        """
-        Manager the crontab to add JAVIS event
-        """
-        self.my_user_cron = CronTab(user=True)
-        # my_user_cron.remove_all()
-        self.command = "cat test > /home/nico/Desktop/test.txt"
+# test
+# cron_manager = CrontabManager()
+# cron_manager.load_events_in_crontab()
 
-    def add_event(self, period_string, event_id):
+class NoEventsFound(Exception):
+    pass
 
-        job = self.my_user_cron.new(command='self.command', comment='JARVIS')
-        if CronSlices.is_valid(period_string):
-            job.setall(period_string)
-            job.enable()
-            self.my_user_cron.write()
+class NoIdInEvent(Exception):
+    pass
 
-    def get_jobs(self):
-        for job in self.my_user_cron:
-                print job
+class NoPeriodInEvent(Exception):
+    pass
 
-    def _remove_all_jarvis_job(self):
-        pass
+# events = BrainLoader(filename="test.yml").get_events()
+#
+# # check there is some event in the brain file
+# if len(events) <= 0:
+#     raise NoEventsFound("There is no events in the brain file")
+#
+# # we must check that each event has an id and a period
+# for event in events:
+#     if "id" not in event:
+#         raise NoIdInEvent("No id found event must has an unique id")
+#     if "period" not in event:
+#         raise NoPeriodInEvent("An event must has a period")
 
+brain = BrainLoader(filename="test.yml").get_brain()
 
-# test
-cron_manager = CronManager()
-period_string = "* * 5 5 *"
-event_id = 1
-cron_manager.add_event(period_string=period_string, event_id=event_id)

+ 8 - 3
test.yml

@@ -3,6 +3,11 @@
     neurons:
       - say:
           message: "Script lancé, monsieur"
-    when:
-      - event: "* * 5 5 *"
-
+    signals:
+      - order: "sens de la vie"
+      - event:
+          id: 1
+          period: "* * 5 5 *"
+      - event:
+          id: 2
+          period: "* * 4 4 *"