.. _Recobs Doc Tests:

RecognitionObserver base class
==========================================================================

If you're looking for the class and function reference for recognition
observers, you want :ref:`this page <Recobs>`.

.. note:: :class:`RecognitionObserver` instances can be used for both
   the DNS and the WSR backend engines.  However, WSR will sometimes call
   observer methods multiple times, so be careful using observers with it.

Test fixture initialization::

    >>> from dragonfly import *
    >>> from dragonfly.test import ElementTester


Trivial demonstration of RecognitionObserver class
----------------------------------------------------------------------------

The following class is derived from RecognitionObserver and prints
when its callback methods are called::

    >>> class RecognitionObserverDemo(RecognitionObserver):
    ...     def on_begin(self):
    ...         print("on_begin()")
    ...     def on_recognition(self, words):
    ...         print("on_recognition(): %s" % (words,))
    ...     def on_failure(self):
    ...         print("on_failure()")
    ...     def on_end(self):
    ...         print("on_end()")
    ...     def on_post_recognition(self, words, rule):
    ...         print("on_post_recognition(): %r from %r" % (words, rule))
    ...
    >>> recobs_demo = RecognitionObserverDemo()
    >>> recobs_demo.register()
    >>> test_lit = ElementTester(Literal("hello world"))
    >>> test_lit.recognize("hello world")
    on_begin()
    on_recognition(): (u'hello', u'world')
    on_end()
    on_post_recognition(): (u'hello', u'world') from _ElementTestRule(rule)
    u'hello world'
    >>> test_lit.recognize("hello universe")
    on_begin()
    on_failure()
    on_end()
    RecognitionFailure
    >>> recobs_demo.unregister()


Tests for RecognitionObserver class
----------------------------------------------------------------------------

A class derived from RecognitionObserver which will be used here for
testing it::

    >>> class RecognitionObserverTester(RecognitionObserver):
    ...     def __init__(self):
    ...         RecognitionObserver.__init__(self)
    ...         self.waiting = False
    ...         self.words = None
    ...     def on_begin(self):
    ...         self.waiting = True
    ...     def on_recognition(self, words):
    ...         self.waiting = False
    ...         self.words = words
    ...     def on_failure(self):
    ...         self.waiting = False
    ...         self.words = False
    ...
    >>> test_recobs = RecognitionObserverTester()
    >>> test_recobs.register()
    >>> test_recobs.waiting, test_recobs.words
    (False, None)

Simple literal element recognitions::

    >>> test_lit = ElementTester(Literal("hello world"))
    >>> test_lit.recognize("hello world")
    u'hello world'
    >>> test_recobs.waiting, test_recobs.words
    (False, (u'hello', u'world'))
    >>> test_lit.recognize("hello universe")
    RecognitionFailure
    >>> test_recobs.waiting, test_recobs.words
    (False, False)


Integer element recognitions::

    >>> test_int = ElementTester(Integer(min=1, max=100))
    >>> test_int.recognize("seven")
    7
    >>> test_recobs.waiting, test_recobs.words
    (False, (u'seven',))
    >>> test_int.recognize("forty seven")
    47
    >>> test_recobs.waiting, test_recobs.words
    (False, (u'forty', u'seven'))
    >>> test_int.recognize("one hundred")
    RecognitionFailure
    >>> test_recobs.waiting, test_recobs.words
    (False, False)
    >>> test_lit.recognize("hello world")
    u'hello world'


RecognitionHistory class
==========================================================================

Basic usage of the RecognitionHistory class::

    >>> history = RecognitionHistory()
    >>> test_lit.recognize("hello world")
    u'hello world'
    >>> # Not yet registered, so didn't receive previous recognition.
    >>> history
    []
    >>> history.register()
    >>> test_lit.recognize("hello world")
    u'hello world'
    >>> # Now registered, so should have received previous recognition.
    >>> history
    [(u'hello', u'world')]
    >>> test_lit.recognize("hello universe")
    RecognitionFailure
    >>> # Failed recognitions are ignored, so history is unchanged.
    >>> history
    [(u'hello', u'world')]
    >>> test_int.recognize("eighty six")
    86
    >>> history
    [(u'hello', u'world'), (u'eighty', u'six')]

The RecognitionHistory class allows its maximum length to be set::

    >>> history = RecognitionHistory(3)
    >>> history.register()
    >>> history
    []
    >>> for i, word in enumerate(["one", "two", "three", "four", "five"]):
    ...     assert test_int.recognize(word) == i + 1
    >>> history
    [(u'three',), (u'four',), (u'five',)]

The length must be a positive integer.  A length of 0 is not allowed::

    >>> history = RecognitionHistory(0)
    Traceback (most recent call last):
      ...
    ValueError: length must be a positive int or None, received 0.

Minimum length is 1::

    >>> history = RecognitionHistory(1)
    >>> history.register()
    >>> history
    []
    >>> for i, word in enumerate(["one", "two", "three", "four", "five"]):
    ...     assert test_int.recognize(word) == i + 1
    >>> history
    [(u'five',)]


Recognition callback functions
==========================================================================

Register recognition callback functions::

    >>> # Define and register functions for each recognition state event.
    >>> def on_begin():
    ...     print("on_begin()")
    ...
    >>> def on_recognition(words):
    ...     print("on_recognition(): %s" % (words,))
    ...
    >>> def on_failure():
    ...     print("on_failure()")
    ...
    >>> def on_end():
    ...     print("on_end()")
    ...
    >>> def on_post_recognition(words, rule):
    ...     print("on_post_recognition(): %r from %r" % (words, rule))
    ...
    >>> on_begin_obs = register_beginning_callback(on_begin)
    >>> on_success_obs = register_recognition_callback(on_recognition)
    >>> on_failure_obs = register_failure_callback(on_failure)
    >>> on_end_obs = register_ending_callback(on_end)
    >>> on_post_recognition_obs = register_post_recognition_callback(on_post_recognition)

Callback functions are called during recognitions::

    >>> test_lit = ElementTester(Literal("hello world"))
    >>> test_lit.recognize("hello world")
    on_begin()
    on_recognition(): (u'hello', u'world')
    on_end()
    on_post_recognition(): (u'hello', u'world') from _ElementTestRule(rule)
    u'hello world'
    >>> test_lit.recognize("hello universe")
    on_begin()
    on_failure()
    on_end()
    RecognitionFailure

Callback functions are unregistered using the observer objects returned by
each function::

    >>> on_begin_obs.unregister()
    >>> on_success_obs.unregister()
    >>> on_failure_obs.unregister()
    >>> on_end_obs.unregister()
    >>> on_post_recognition_obs.unregister()
