# This is part of Kaylee # -- this code is licensed GPLv3 # Copyright 2015-2017 Clayton G. Hobbs # Portions Copyright 2013 Jezra """Builtin Kaylee plugins and base classes""" from abc import ABC, abstractmethod class PluginBase(ABC): """Base class for Kaylee plugins Each Kaylee plugin module must define a subclass of this class, named ``Plugin``. """ def __init__(self, config, name): """Initialize the plugin All strings to be included in the corpus should be elements of ``corpus_strings`` by the end of __init__'s execution. Note however that the words required for number support are automatically included, so they need not be listed explicitly on a per-plugin basis. """ super().__init__() self.config = config self.name = name self.options = config.plugins[name] self.corpus_strings = set() @abstractmethod def get_handler(self, text): """Return a handler for the given text This method returns a Handler object which handles the command when called. If the plugin does not recognize the command at all, this method must return None instead. The method must also return None if the command is recognized, but for some reason would not perform any action currently, e.g. "pause music" when no music player is running. """ class Handler(ABC): """Base class for Kaylee plugin handlers Plugins should subclass this for their own command handlers. Rich comparison methods are defined for use with queue.PriorityQueue. They compare Handler objects based on their confidence alone, with Handlers of high confidence comparing less than ones of low confidence. """ def __init__(self, confidence): """Initialize the handler The confidence with which this handler will handle the command must be passed as ``confidence``, a floating-point number in (0, 1]. A confidence of 1 indicates that the handler is definitely supposed to handle the command it was created for. Values between 0 and 1 may be used to indicate that the plugin may be able to handle the command, but it was misunderstood by the speech recognition system. """ self.confidence = confidence @abstractmethod def __call__(self, tts): """Handle the command When called, ``tts`` is a function which takes a string as its only parameter and passes it to Kaylee's configured text-to-speech system. If command handling fails for some reason that can be anticipated, this method must raise a HandlerFailure to tell Kaylee to keep trying other handlers. """ def __eq__(self, other): if isinstance(other, Handler): return (self.confidence == other.confidence) return NotImplemented def __lt__(self, other): if isinstance(other, Handler): # Intentionally reversed return (self.confidence > other.confidence) return NotImplemented def __le__(self, other): if isinstance(other, Handler): # Intentionally reversed return (self.confidence >= other.confidence) return NotImplemented def __ge__(self, other): if isinstance(other, Handler): # Intentionally reversed return (self.confidence <= other.confidence) return NotImplemented def __gt__(self, other): if isinstance(other, Handler): # Intentionally reversed return (self.confidence < other.confidence) return NotImplemented class HandlerFailure(Exception): """Handler failed to handle its command."""