Source code for dragontide._elements

from dragonfly import Dictation

from dragontide._grammars import GlobalRegistry
from dragontide._support import _safe_kwargs


class _RegistryElement(object):
    # An internal object used to indicate that the element has a _registry
    # attribute due to its use of Registry services
    pass


[docs]class SplitDictation(_RegistryElement, Dictation): """ A rule element used to split recognized dictation into an initial free dictation part, and a following command part. Either part is optional, unless the element is initialized with the forced_dictation element to True. The following example shows this element being used and retrieved in the standard expected way. :: from dragontide import RegistryRule, SplitDictation class SplitterRule(RegistryRule): spec = "set name <name_split>" extras = (SplitDictation("name_split"), ) def _process_recognition(self, node, extras): name_split = extras["name_split"] name = name_split.dictation The result is a type of container from which parts of the result may be retrieved. The full list of attributes are individually documented below, but a simple naming scheme is in place. The first part of the attribute name indicates the part desired: * **full** - The entire utterance * **dictation** - The utterance only up to the first accepted command, may be the empty string if the utterance began with an accepted command * **command** - The rest of the utterance starting with the first accepted command, through the end of the utterance The second part indicates the return type desired: * **_words** - A string list of the words * **_container** - The same type of dictation container that a Dictation element would yield, some derived class of BaseDictationContainer as appropriate for the speech recognition system in use. * *default* - If neither of the above are indicated, the default result type is a string. The third part indicates whether literal tags should be retained or translated out: * **_notrans** - Retain the literal tags * **_trans** - Strip literal tags and return only the intended content * *default* - If neither of the above are indicated, the result will have the default behavior most common when using the part requested. **full** and **command** parts will retain literal tags, while **dictation** parts will strip them so as to only return the intended free speech. Default translation of the parts applies to all return types. There is also an issue of formatting. The various dictation containers have a formatting option. For Windows Speech Recognition there is no real formatting provided beyond separating words with spaces. Dragon NaturallySpeaking provides more sophisticated formatting. All return types except for the **_container** values have formatting applied to the result returned. If you absolutely do not want the formatting applied, you must request the containers directly, from which you can choose to apply formatting or not. If you choose a **_trans** container, it will have had literal tags stripped, but otherwise be unmodified. """
[docs] def __init__(self, name, registry=None, forced_dictation=False, **kwargs): """ :param string name: The name of this element, used as the keyname in the extras dictionary passed back to _process_recognition :param `Registry` registry: The `Registry` instance that determines what words form a command and what literal tags are in effect. If None, the `ActiveGrammarRule` decorator will set the registry of any `RegistryGrammar` derived instance the containing rule is added to. :param bool forced_dictation: When True, refuses to recognize utterance-initial commands, so as to ensure this element returns non-empty free dictation. :param kwargs: Passed safely to Dictation.__init__ """ self._registry = registry self._forced_dictation = forced_dictation _safe_kwargs(Dictation.__init__, self, name=name, **kwargs)
@property def registry(self): if self._registry: return self._registry else: return GlobalRegistry.registry @registry.setter def registry(self, value): self._registry = value
[docs] def value(self, node): # The element instance lives on between invocations of the rule in # which it lives. This value method is called from each invocation to # obtain the *current* value. Therefore below we reset any state so # that elements retrieved respect the `node` passed in. self._node = node # store the context node from which to parse values # clear memoize variables of any previous values self._formatted_words_list_memo = None self._command_index_memo = None return self
@property def command_index(self): """ Returns the 0-based word index at which the first accepted full command intro occurs, or the index beyond last if no such intro occurs. If forced_dictation was set True during initialization, any utterance-initial command will be skipped to ensure dictation content is non-empty. """ if self._command_index_memo is None: command_index = self.registry._determine_command_index( self._formatted_words_list ) if self._forced_dictation and command_index == 0: # do not allow empty dictation bypass utterance-initial command next_command_index = self.registry._determine_command_index( self._formatted_words_list[1:] ) if next_command_index is not None: command_index = next_command_index + 1 else: # return index beyond last as None indicator command_index = len(self._formatted_words_list) self._command_index_memo = command_index return self._command_index_memo
[docs] def translate(self, words_iterable): """Returns a word list, as translated.""" return self.registry.translate_literals(words_iterable)
def mimic_command(self): command = self.command_words_notrans if command: self._node.engine.mimic(command) def mimic_full(self): full = self.full_words_notrans if full: self._node.engine.mimic(full) @property def full(self): """Alias for `full_notrans`.""" return self.full_notrans @property def full_notrans(self): """ Returns the full content, as a string, with formatting applied and with literal tags retained. """ return " ".join(self.full_words_notrans) @property def full_trans(self): """ Returns the full content, as a string, with formatting applied and with literal tags translated to their intended result. """ return " ".join(self.full_words_trans) @property def full_words(self): """Alias for `full_words_notrans`.""" return self.full_words_notrans @property def full_words_notrans(self): """ Returns the full content, as a word list, with formatting applied and with literal tags retained. """ return self._formatted_words_list @property def full_words_trans(self): """ Returns the full content, as a word list, with formatting applied and with literal tags translated to their intended result. """ return self.translate(self.full_words_notrans) @property def full_container(self): """Alias for `full_container_notrans`.""" return self.full_container_notrans @property def full_container_notrans(self): """ Returns the full content, as a BaseDictationContainer of the appropriate type given the speech recognition system in use, without any alterations of any sort applied to the container contents. """ return self._node.engine.DictationContainer(self._node.words()) @property def full_container_trans(self): """ Returns the full content, as a BaseDictationContainer of the appropriate type given the speech recognition system in use, with no formatting applied yet with literal tags translated to their intended result. """ tag_indices = self.registry._get_literal_tag_indices(self.full_words_notrans) notrans_words = self._node.words() translated_words = [ notrans_words[i] for i in range(len(notrans_words)) if i not in tag_indices ] return self._node.engine.DictationContainer(translated_words) @property def dictation(self): """Alias for `dictation_trans`.""" return self.dictation_trans @property def dictation_trans(self): """ Returns any and all content up to the first full command intro, if any. Content is returned as a string with formatting and with literal tags translated to their intended result. """ return " ".join(self.dictation_words_trans) @property def dictation_notrans(self): """ Returns any and all content up to the first full command intro, if any. Content is returned as a string with formatting and with literal tags retained. """ return " ".join(self.dictation_words_notrans) @property def dictation_words(self): """Alias for `dictation_words_trans`.""" return self.dictation_words_trans @property def dictation_words_trans(self): """ Returns any and all content up to the first full command intro, if any. Content is returned as a word list with formatting and with literal tags translated to their intended result. """ return self.translate(self.dictation_words_notrans) @property def dictation_words_notrans(self): """ Returns any and all content up to the first full command intro, if any. Content is returned as a word list with formatting and with literal tags retained. """ return self._formatted_words_list[: self.command_index] @property def dictation_container(self): """Alias for `dictation_container_trans`.""" return self.dictation_container_trans @property def dictation_container_notrans(self): """ Returns any and all content up to the first full command intro, if any. Content is returned as a BaseDictationContainer of the appropriate type given the speech recognition system in use, without any alterations of any sort applied to the container contents. """ return self._node.engine.DictationContainer( self._node.words()[: self.command_index] ) @property def dictation_container_trans(self): """ Returns any and all content up to the first full command intro, if any. Content is returned as a BaseDictationContainer of the appropriate type given the speech recognition system in use, with no formatting applied yet with literal tags translated to their intended result. """ tag_indices = self.registry._get_literal_tag_indices( self.dictation_words_notrans ) notrans_words = self._node.words()[: self.command_index] translated_words = [ notrans_words[i] for i in range(len(notrans_words)) if i not in tag_indices ] return self._node.engine.DictationContainer(translated_words) @property def command(self): """Alias for `command_notrans`""" return self.command_notrans @property def command_notrans(self): """ Returns any and all content starting from first full command intro, if any. Content is returned as a string with formatting and with literal tags retained. """ return " ".join(self.command_words) @property def command_trans(self): """ Returns any and all content starting from first full command intro, if any. Content is returned as a string with formatting and with literal tags retained. """ return " ".join(self.command_words_trans) @property def command_words(self): """Alias for `command_words_notrans`""" return self.command_words_notrans @property def command_words_notrans(self): """ Returns any and all content starting from first full command intro, if any. Content is returned as a word list with formatting and with literal tags retained. """ return self._formatted_words_list[self.command_index :] @property def command_words_trans(self): """ Returns any and all content starting from first full command intro, if any. Content is returned as a word list with formatting and with literal tags translated to their intended result. """ return self.translate(self.command_words) @property def command_container(self): """Alias for `command_container_notrans`""" return self.command_container_notrans @property def command_container_notrans(self): """ Returns any and all content starting from first full command intro, if any. Content is returned as a BaseDictationContainer of the appropriate type given the speech recognition system in use, without any alterations of any sort applied to the container contents. """ return self._node.engine.DictationContainer( self._node.words()[self.command_index :] ) @property def command_container_trans(self): """ Returns any and all content starting from first full command intro, if any. Content is returned as a BaseDictationContainer of the appropriate type given the speech recognition system in use, with no formatting applied yet with literal tags translated to their intended result. """ tag_indices = self.registry._get_literal_tag_indices(self.command_words_notrans) notrans_words = self._node.words()[self.command_index :] translated_words = [ notrans_words[i] for i in range(len(notrans_words)) if i not in tag_indices ] return self._node.engine.DictationContainer(translated_words) @property def _formatted_words_list(self): if getattr(self, "_formatted_words_list_memo", None) is None: self._formatted_words_list_memo = ( self._node.engine.DictationContainer(self._node.words()) .format() .split() ) return self._formatted_words_list_memo
[docs]class SplitForcedDictation(SplitDictation): """ A SplitDictation with forced_dictation set to True, guaranteed to return a value for dictation, even if it must ignore an utterance-initial command from which to provide it. """
[docs] def __init__(self, name, registry=None, **kwargs): """ :param string name: The name of this element, used as the keyname in the extras dictionary passed back to _process_recognition :param _Registry registry: The _Registry instance that determines what words form a command :param kwargs: Passed safely to `SplitDictation` """ # ensure only one forced_dictation argument passed kwargs["forced_dictation"] = True SplitDictation.__init__(self, name=name, registry=registry, **kwargs)