The low-level Python/C interface

The ktlc module is the sole interface between the ktl module and the underlying KTL/C API. The operations performed in this module strive to be the absolute minimum required to cleanly wrap calls to the KTL/C API; complex operations are better handled in the ktl module, as mistakes in the Python half tend to be less subtle, easier to correct, and more straight-forward to test.

Because all calls to the ktlc module are filtered by an Usher thread, no great effort was made to ensure thread-safety internal to the module itself. On the contrary, the only concessions made by the ktlc module to thread-awareness are to release the Python interpreter to execute other threads if a KTL call will obviously block, such as a KTL_WAIT invocation of read() or write().

Functions

ktlc.dumpster(append, stop)

Set the function reference that will be used to hand off Trash instances to the Janitor for disposal.

ktlc.probe(service, keyword)

Open a new instance of the KTL client library for the designated service, and attempt to read a value for keyword. Upon completion, close the newly opened instance of service. This is done independently of any cached metadata elsewhere in ktlc, as the encapsulated read is used by the FirstResponder thread to determine whether the already open KTL handle is no longer functioning. The read values are not returned, as they are not significant for this purpose.

If a component of the ktl module were constructed as a .sin (substitution) file, this mechanism would not be necessary, as the Python module could instead invoke $RELDIR/bin/show via the subprocess module. While less efficient, it would eliminate the possibility of a client library itself being clever about reusing cached resources.

Classes

class ktlc.Service

The Service class is a low-level interface to service-specific KTL functions. In addition, it contains a dictionary of Keyword instances, populated on a just-in-time basis for use by the Python layers of the KTL Python module. A direct reference to a Service instance must be maintained in order for the Keyword instances to remain functional.

descriptors()

Determine which file descriptors, if any, are associated with this Service instance. Returns a tuple of file descriptor numbers, as integers. If no descriptors are available, an empty tuple will be returned.

dispatch()

Process pending KTL events for this Service by invoking ktl_dispatch(). dispatch() will return the total number of events dispatched.

headers()

Enumerate the keywords and associated FITS comments for this Service. Returns a tuple of tuples, each of which will contain a keyword name and a FITS comment. If no such values are available, an empty tuple will be returned.

Note

The keyword values normally returned with the ‘oneshot’ are completely ignored. This may be modified in a future version, but in general a less intensive approach should be adopted to acquire and format keyword values. This function exists solely to enable easy transitions to such mechanisms.

list()

List all of the keywords available in this Service instance. The list is populated when the Service is first instantiated, and will not change for the duration of its existence.

Significant attributes of the Service class:

name

Service name

notify

support for KTL_NOTIFY reads

class ktlc.Keyword

The Keyword class is a low-level interface to keyword-specific KTL functions. Direct references to Keyword instances do not need to be retained, but the high-level KTL Python interface does so for efficiency’s sake.

monitor(callback)

Subscribe to broadcasts for this Keyword. A KTL callback will be registered, with readNotifyHandler() as the C callback function; it will in turn invoke the provided callback function, handing it a single object: a (timestamp, binary, ascii) tuple, or an exception. In practice, the only callback function ever registered with monitor() is ktl.Keyword._update(). If callback is set to False, the subscription to broadcasts (if any) for this Keyword will be cancelled. This second usage is uncommon: it is more likely that a KTL service will be closed without first cancelling any active subscriptions.

range()

Determine the allowed range of values for this Keyword. If a keyword has both a minimum and a a maximum, a dictionary will be returned with keys ‘minimum’ and ‘maximum’. If only one of those values is not available, None will be assigned to its place in the dictionary. If no range is available, range() will raise a ktl.ktlError. These values are, by convention, appropriate for the binary representation of a numeric keyword. The ascii translation of those values will be in a nested and similarly constructed ‘ascii’ dictionary.

read()

Invoke ktl_read() to determine the current value of this :class`Keyword`. If successful, the callback will be invoked with a (timestamp, binary, ascii) tuple for the new values. In practice, the only callback function used is ktl.Keyword._update(). read() will perform KTL_NOTIFY reads whenever possible; when it is not, read() will automatically fall back to performing a KTL_WAIT read, and will manually invoke callback with the new values.

Note

No values are returned by read(); the callback is the sole mechanism used to provide results, and will be invoked for both the KTL_NOTIFY and the KTL_WAIT branches.

servers()

Return a tuple naming the dispatchers implementing this Keyword.

units()

Return the ‘units’ description associated with this Keyword.

Note

The ‘units’ value is an array of strings, and is regularly overloaded with additional values in implementation-specific ways. Some standard uses include listing the enumerators for enumerated keyword types, and the array position names for array types.

write(value, binary, wait, callback)

Perform a ktl_write() of value to this Keyword. If supported, a KTL_NOTIFY write will be performed regardless of the wait argument; if not supported, KTL_NOWAIT will be used if wait is False, and KTL_WAIT will be used if wait is True. If binary is set to True, value will be interpreted as the binary representation; if set to False, value will instead be interpreted as the ascii representation.

Warning

The use of KTL_NOWAIT in write() does not agree with the basic KTL specification; it really should be a KTL_NOREPLY write, as no attempt is made to match the KTL_NOWAIT write with a ktl_read(KTL_WAITFOR) call. A switch to using KTL_NOREPLY here must be cautious, as many KTL implementations do not support it; some implementations instead expect this incorrect use of KTL_NOWAIT. There is also some disagreement about the precise arguments that should be used with a ktl_read(KTL_WAITFOR) call, which is a large part of why KTL Python chooses instead to emulate this functionality with KTL_NOTIFY if the latter is supported.

Significant attributes of the Keyword class:

broadcasts

Keyword support for broadcasts

name

Keyword name

monitored

Keyword monitoring status

notify

Keyword support for notify writes

reads

Keyword support for reads

service

parent Service instance

type

Keyword KTL_DATATYPE

writes

Keyword support for writes

class ktlc.Trash

The Trash class is an internal construct used to safely close KTL services whose Service instances have been deallocated. This artifice is only necessary to ensure that calls to ktl_close() originate from the same thread used to originally invoke ktl_open(); in the absence of that restriction, ktl_close() would be invoked directly when the Service instance is in the process of being deallocated.

dispose()

Invoke ktl_close() on any KTL handles present, and subsequently decrement the local garbage reference, if any.