Object-oriented KTL Python
==========================

.. currentmodule:: ktl


The object-oriented approach in KTL Python can greatly simplify a client
application's overall use of the module. When using the procedural approach,
values must be cached, callbacks are more complicated to establish, and a
lot of client-side metadata must be stored to correctly handle exceptional
circumstances, such as an inability to monitor a given KTL keyword.

The :class:`Service` and :class:`Keyword` classes address these repetitive
needs internally as much as possible in order to streamline the use of
KTL Python.

.. toctree::
   :maxdepth: 2


:class:`Service` objects
------------------------

.. autoclass:: Service

   When accessing :class:`Keyword` instances within a :class:`Service`
   instance, the :class:`Service` can be treated like a dictionary. See the
   :ref:`basic use section <basic-service>` of the :doc:`examples` document.

   .. method:: has_key (keyword)

      Alias for :func:`Service.has_keyword`.

   .. automethod:: has_keyword
   .. automethod:: heartbeat
   .. automethod:: keywords

   .. method:: list ()

      Alias for :func:`Service.keywords`.

   .. automethod:: monitor
   .. automethod:: monitored
   .. automethod:: populated
   .. automethod:: read

   .. method:: subscribe (start=True, prime=True)

      Alias for :func:`Service.monitor`.

   .. automethod:: wait
   .. automethod:: waitFor

   .. method:: waitfor (expression, timeout=None)

      Alias for :func:`Service.waitFor`.

   .. automethod:: write


:class:`Keyword` objects
------------------------

.. autoclass:: Keyword
   :members:
   :exclude-members: notify, waitfor

   See also the :ref:`basic use section <basic-service>` of the :doc:`examples`
   document.

   :class:`Keyword` instances can be used with all
   :ref:`boolean <python:boolean>`, :ref:`comparison <python:stdcomparisons>`,
   and :ref:`arithmetic <python:typesnumeric>` operations. The support for
   these operations has its caveats. For all such operations, the
   :class:`Keyword` instance must have a value, either via a
   :func:`Keyword.read` call, or by enabling asynchronous updates via
   :func:`Keyword.monitor`. Note that in-place operations (``+=``, ``-=``, etc.)
   will automatically invoke :func:`Keyword.monitor` if necessary. In-place
   operations also imply a blocking invocation of :func:`Keyword.write`.
   In order to support the use of :class:`Keyword` instances as dictionary
   keys, comparison operations between two :class:`Keyword` instances do not
   compare the *values* of the two keywords, such operations compare their
   *names*. The :class:`Expression` class goes to some length to manage
   comparisons between two :class:`Keyword` instances to defeat this behavior.
   Comparisons between :class:`Keyword` instances and all other data types
   are intended to match the behavior of comparisons between standard Python
   types; for example, a boolean :class:`Keyword` can meaningfully be compared
   against the integers 0 and 1, just like the standard Python bool type.

   In addition its member functions, a :class:`Keyword` also provides
   significant functionality via dictionary-like keys. Many of these
   keys trigger just-in-time acquisition of data, caching the result
   for future use. The following keys are supported:


   ============================ ================================================
   *Key*                        *Operation performed*
   ============================ ================================================
   **ascii** or **asc**         Return the current ascii representation of the
                                :class:`Keyword`; if the :class:`Keyword` has
                                no value, a :func:`Keyword.read` operation will
                                be performed. Will raise an exception if one is
                                active for this :class:`Keyword` instance.

   **binary** or **bin**        Same as **ascii**, but will return the binary
                                representation.

   **broadcasts**               Return a boolean indicating whether this KTL
                                keyword supports broadcasts.

   **dictionary** or **dict**   Same as **ascii**, but will return a dictionary
                                representation of the current value, if and
                                only if the KTL keyword is a numeric array
                                type.

   **enumerators** or **enum**  For enumerated KTL keyword types (including
                                booleans), return a tuple containing the
                                enumerators for all available named positions.

   **error**                    Return a string representation of the active
                                exception associated with this :class:`Keyword`,
                                if any. The exception object itself is stored
                                as :attr:`Keyword.error`.

   **history**                  Return a tuple containing a small chronological
                                set of the most recent :class:`HistorySlice`
                                instances for this :class:`Keyword`. The most
                                recent broadcast is at the *end* of the
                                sequence.

   **keys**                     For numeric KTL array types, return a tuple
                                containing the key name for each individual
                                array value.

   **name**                     Return the name of the keyword. All keyword
                                names are case-insensitive, and are handled
                                internally in all upper-case.

   **monitor** or **monitored** Return a boolean indicating whether this
                                :class:`Keyword` instance is currently
                                subscribed to broadcasts.

   **notify_reads**             Return a boolean indicating whether this
                                KTL keyword supports KTL_NOTIFY read operations.

   **notify_writes**            Return a boolean indicating whether this
                                KTL keyword supports KTL_NOTIFY write
                                operations.

   **populated**                Return a boolean indicating whether this
                                :class:`Keyword` instance has a value,
                                either from an explicit :func:`Keyword.read`
                                operation or from a broadcast.

   **range**                    Return a dictionary containing the minimum and
                                maximum values for this KTL keyword. If no
                                range is set, return None. If either the
                                minimum or maximum is not set, that specific
                                value will be set to None. These values are
                                expected to be the binary representation; a
                                a nested 'ascii' dictionary will contain the
                                same numeric values put through the keyword's
                                binary-to-ascii routine. For most keywords,
                                there is no significant distinction between
                                the two.

   **reads**                    Return a boolean indicating whether this
                                KTL keyword supports read operations.

   **servers**                  Return a tuple containing the server names
                                associated with this KTL keyword.

   **timestamp**                Return the floating point timestamp (in UNIX
                                seconds) associated with the most recent
                                update to the value of the :class:`Keyword`.
                                It is recommended that you work instead with
                                the :class:`HistorySlice` instances provided
                                by the **history** key.

   **type**                     Return the KTL type of this KTL keyword as a
                                string. Use the top-level :data:`KTL_DATATYPE`
                                dictionary to map between string and integer
                                representations of the KTL type.

   **units**                    Return the 'units' associated with this KTL
                                keyword, if any.

   **writes**                   Return a boolean indicating whether this
                                KTL keyword supports write operations.
   ============================ ================================================

   a :class:`Keyword` defines the following functions:


Other objects
-------------

.. autoclass:: HistorySlice