Added code for handling procedures - solves #1

This commit is contained in:
Fabio Manganiello 2017-12-25 17:23:09 +01:00
parent 6e019865bc
commit 617c0f8a07
5 changed files with 79 additions and 16 deletions

View File

@ -9,10 +9,10 @@ from .bus import Bus
from .config import Config
from .context import register_backends
from .event.processor import EventProcessor
from .utils import get_or_load_plugin, get_module_and_name_from_action
from .message.event import Event, StopEvent
from .message.request import Request
from .message.response import Response
from .procedure import Procedure
__author__ = 'Fabio Manganiello <blacklight86@gmail.com>'
__version__ = '0.6'
@ -75,9 +75,15 @@ class Daemon(object):
msg -- platypush.message.Message instance """
if isinstance(msg, Request):
logging.info('Processing request: {}'.format(msg))
msg.execute(n_tries=self.n_tries)
if msg.action.startswith('procedure.'):
logging.info('Executing procedure request: {}'.format(msg))
proc_name = msg.action.split('.')[-1]
proc_config = Config.get_procedures()[proc_name]
msg = Procedure.build(name=proc_name, requests=proc_config, backend=msg.backend, id=msg.id)
else:
logging.info('Processing request: {}'.format(msg))
msg.execute(n_tries=self.n_tries)
self.processed_requests += 1
if self.requests_to_process \
and self.processed_requests >= self.requests_to_process:

View File

@ -62,14 +62,14 @@ class Config(object):
if 'device_id' not in self._config:
self._config['device_id'] = socket.gethostname()
self.backends = {}
self.plugins = {}
self.event_hooks = {}
self.procedures = {}
self._init_components()
def _init_components(self):
self.backends = {}
self.plugins = {}
self.event_hooks = {}
for key in self._config.keys():
if key.startswith('backend.'):
backend_name = '.'.join(key.split('.')[1:])
@ -77,6 +77,9 @@ class Config(object):
elif key.startswith('event.hook.'):
hook_name = '.'.join(key.split('.')[2:])
self.event_hooks[hook_name] = self._config[key]
elif key.startswith('procedure.'):
procedure_name = '.'.join(key.split('.')[1:])
self.procedures[procedure_name] = self._config[key]
else:
self.plugins[key] = self._config[key]
@ -98,6 +101,12 @@ class Config(object):
if _default_config_instance is None: _default_config_instance = Config()
return _default_config_instance.event_hooks
@staticmethod
def get_procedures():
global _default_config_instance
if _default_config_instance is None: _default_config_instance = Config()
return _default_config_instance.procedures
@staticmethod
def get_default_pusher_backend():
"""

View File

@ -5,22 +5,21 @@ import traceback
from threading import Thread
from threading import Thread
from platypush.message import Message
from platypush.message.response import Response
from platypush.utils import get_or_load_plugin, get_module_and_name_from_action
from platypush.utils import get_or_load_plugin, get_module_and_method_from_action
class Request(Message):
""" Request message class """
def __init__(self, target, action, origin=None, id=None, args={}):
def __init__(self, target, action, origin=None, id=None, backend=None, args={}):
"""
Params:
target -- Target node [String]
action -- Action to be executed (e.g. music.mpd.play) [String]
origin -- Origin node [String]
id -- Message ID, or None to get it auto-generated
backend -- Backend connected to the request, where the response will be delivered
args -- Additional arguments for the action [Dict]
"""
@ -29,7 +28,7 @@ class Request(Message):
self.action = action
self.origin = origin
self.args = args
self.backend = None
self.backend = backend
@classmethod
def build(cls, msg):
@ -58,7 +57,7 @@ class Request(Message):
n_tries -- Number of tries in case of failure before raising a RuntimeError
"""
def _thread_func(n_tries):
(module_name, method_name) = get_module_and_name_from_action(self.action)
(module_name, method_name) = get_module_and_method_from_action(self.action)
plugin = get_or_load_plugin(module_name)

View File

@ -0,0 +1,50 @@
import logging
from ..config import Config
from ..message.request import Request
class Procedure(object):
""" Procedure class. A procedure is a pre-configured list of requests """
def __init__(self, name, requests, backend=None):
"""
Params:
name -- Procedure name
requests -- List of platylist.message.request.Request objects
"""
self.name = name
self.requests = requests
self.backend = backend
for req in requests:
req.backend = self.backend
@classmethod
def build(cls, name, requests, backend=None, id=None, **kwargs):
reqs = []
for request_config in requests:
request_config['origin'] = Config.get('device_id')
request_config['id'] = id
if 'target' not in request_config:
request_config['target'] = request_config['origin']
request = Request.build(request_config)
reqs.append(request)
return cls(name=name, requests=reqs, backend=backend, **kwargs)
def execute(self, n_tries=1):
"""
Execute the requests in the procedure
Params:
n_tries -- Number of tries in case of failure before raising a RuntimeError
"""
logging.info('Executing request {}'.format(self.name))
for request in self.requests:
request.execute(n_tries)
# vim:sw=4:ts=4:et:

View File

@ -35,14 +35,13 @@ def get_or_load_plugin(plugin_name, reload=False):
plugin = plugin_class(**plugin_conf)
modules[plugin_name] = plugin
except AttributeError as e:
logging.warning('No such class in {}: {}'.format(
plugin_name, cls_name))
logging.warning('No such class in {}: {}'.format(plugin_name, cls_name))
raise RuntimeError(e)
return plugin
def get_module_and_name_from_action(action):
def get_module_and_method_from_action(action):
""" Input : action=music.mpd.play
Output : ('music.mpd', 'play') """