Low level client API (client)

Clients for the KAT device control language.

class katcp.client.AsyncClient(host, port, tb_limit=20, timeout=5.0, logger=<logging.Logger object>, auto_reconnect=True)

Bases: katcp.client.DeviceClient

Implement async and callback-based requests on top of DeviceClient.

This client will use message IDs if the server supports them.

Parameters:

host : string

Host to connect to.

port : int

Port to connect to.

tb_limit : int, optional

Maximum number of stack frames to send in error traceback.

logger : object, optional

Python Logger object to log to. Default is a logger named ‘katcp’.

auto_reconnect : bool, optional

Whether to automatically reconnect if the connection dies.

timeout : float in seconds, optional

Default number of seconds to wait before a callback callback_request times out. Can be overridden in individual calls to callback_request.

Examples

>>> def reply_cb(msg):
...     print "Reply:", msg
...
>>> def inform_cb(msg):
...     print "Inform:", msg
...
>>> c = AsyncClient('localhost', 10000)
>>> c.start()
>>> c.ioloop.add_callback(
...     c.callback_request,
...     katcp.Message.request('myreq'),
...     reply_cb=reply_cb,
...     inform_cb=inform_cb,
... )
...
>>> # expect reply to be printed here
>>> # stop the client once we're finished with it
>>> c.stop()
>>> c.join()

Methods

AsyncClient.blocking_request(msg[, timeout, ...]) Send a request messsage and wait for its reply.
AsyncClient.callback_request(msg[, ...]) Send a request messsage.
AsyncClient.convert_seconds(time_seconds) Convert a time in seconds to the device timestamp units.
AsyncClient.disconnect() Force client connection to close, reconnect if auto-connect set.
AsyncClient.enable_thread_safety() Enable thread-safety features.
AsyncClient.future_request(msg[, timeout, ...]) Send a request messsage, with future replies.
AsyncClient.handle_inform(msg) Handle inform messages related to any current requests.
AsyncClient.handle_message(msg) Handle a message from the server.
AsyncClient.handle_reply(msg) Handle a reply message related to the current request.
AsyncClient.handle_request(msg) Dispatch a request message to the appropriate method.
AsyncClient.inform_build_state(msg) Handle katcp v4 and below build-state inform.
AsyncClient.inform_version(msg) Handle katcp v4 and below version inform.
AsyncClient.inform_version_connect(msg) Process a #version-connect message.
AsyncClient.is_connected() Check if the socket is currently connected.
AsyncClient.join([timeout]) Rejoin the client thread.
AsyncClient.notify_connected(connected) Event handler that is called whenever the connection status changes.
AsyncClient.preset_protocol_flags(protocol_flags) Preset server protocol flags.
AsyncClient.request(msg[, use_mid]) Send a request message, with automatic message ID assignment.
AsyncClient.running() Whether the client is running.
AsyncClient.send_message(msg) Send any kind of message.
AsyncClient.send_request(msg) Send a request messsage.
AsyncClient.set_ioloop([ioloop]) Set the tornado.ioloop.IOLoop instance to use.
AsyncClient.start([timeout]) Start the client in a new thread.
AsyncClient.stop(*args, **kwargs)
AsyncClient.unhandled_inform(msg) Fallback method for inform messages without a registered handler.
AsyncClient.unhandled_reply(msg) Fallback method for reply messages without a registered handler.
AsyncClient.unhandled_request(msg) Fallback method for requests without a registered handler.
AsyncClient.until_connected(*args, **kwargs) Return future that resolves when the client is connected.
AsyncClient.until_protocol(*args, **kwargs) Return future that resolves after receipt of katcp protocol info.
AsyncClient.until_running([timeout]) Return future that resolves when the client is running.
AsyncClient.wait_connected([timeout]) Wait until the client is connected.
AsyncClient.wait_protocol([timeout]) Wait until katcp protocol information has been received from server.
AsyncClient.wait_running([timeout]) Wait until the client is running.
blocking_request(msg, timeout=None, use_mid=None)

Send a request messsage and wait for its reply.

Parameters:

msg : Message object

The request Message to send.

timeout : float in seconds

How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.

use_mid : boolean, optional

Whether to use message IDs. Default is to use message IDs if the server supports them.

Returns:

reply : Message object

The reply message received.

informs : list of Message objects

A list of the inform messages received.

callback_request(msg, reply_cb=None, inform_cb=None, user_data=None, timeout=None, use_mid=None)

Send a request messsage.

Parameters:

msg : Message object

The request message to send.

reply_cb : function

The reply callback with signature reply_cb(msg) or reply_cb(msg, *user_data)

inform_cb : function

The inform callback with signature inform_cb(msg) or inform_cb(msg, *user_data)

user_data : tuple

Optional user data to send to the reply and inform callbacks.

timeout : float in seconds

How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.

use_mid : boolean, optional

Whether to use message IDs. Default is to use message IDs if the server supports them.

future_request(msg, timeout=None, use_mid=None)

Send a request messsage, with future replies.

Parameters:

msg : Message object

The request Message to send.

timeout : float in seconds

How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.

use_mid : boolean, optional

Whether to use message IDs. Default is to use message IDs if the server supports them.

Returns:

A tornado.concurrent.Future that resolves with: :

reply : Message object

The reply message received.

informs : list of Message objects

A list of the inform messages received.

handle_inform(msg)

Handle inform messages related to any current requests.

Inform messages not related to the current request go up to the base class method.

Parameters:

msg : Message object

The inform message to dispatch.

handle_reply(msg)

Handle a reply message related to the current request.

Reply messages not related to the current request go up to the base class method.

Parameters:

msg : Message object

The reply message to dispatch.

class katcp.client.DeviceClient(host, port, tb_limit=20, logger=<logging.Logger object>, auto_reconnect=True)

Bases: object

Device client proxy.

Subclasses should implement .reply_*, .inform_* and send_request_* methods to take actions when messages arrive, and implement unhandled_inform, unhandled_reply and unhandled_request to provide fallbacks for messages for which there is no handler.

Request messages can be sent by calling .send_request().

Parameters:

host : string

Host to connect to.

port : int

Port to connect to.

tb_limit : int

Maximum number of stack frames to send in error traceback.

logger : object

Python Logger object to log to.

auto_reconnect : bool

Whether to automatically reconnect if the connection dies.

Notes

The client may block its ioloop if the default blocking tornado DNS resolver is used. When an ioloop is shared, it would make sens to configure one of the non-blocking resolver classes, see http://tornado.readthedocs.org/en/latest/netutil.html

Examples

>>> MyClient(DeviceClient):
...     def reply_myreq(self, msg):
...         print str(msg)
...
>>> c = MyClient('localhost', 10000)
>>> c.start()
>>> c.send_request(katcp.Message.request('myreq'))
>>> # expect reply to be printed here
>>> # stop the client once we're finished with it
>>> c.stop()
>>> c.join()

Methods

DeviceClient.convert_seconds(time_seconds) Convert a time in seconds to the device timestamp units.
DeviceClient.disconnect() Force client connection to close, reconnect if auto-connect set.
DeviceClient.enable_thread_safety() Enable thread-safety features.
DeviceClient.handle_inform(msg) Dispatch an inform message to the appropriate method.
DeviceClient.handle_message(msg) Handle a message from the server.
DeviceClient.handle_reply(msg) Dispatch a reply message to the appropriate method.
DeviceClient.handle_request(msg) Dispatch a request message to the appropriate method.
DeviceClient.inform_build_state(msg) Handle katcp v4 and below build-state inform.
DeviceClient.inform_version(msg) Handle katcp v4 and below version inform.
DeviceClient.inform_version_connect(msg) Process a #version-connect message.
DeviceClient.is_connected() Check if the socket is currently connected.
DeviceClient.join([timeout]) Rejoin the client thread.
DeviceClient.notify_connected(connected) Event handler that is called whenever the connection status changes.
DeviceClient.preset_protocol_flags(...) Preset server protocol flags.
DeviceClient.request(msg[, use_mid]) Send a request message, with automatic message ID assignment.
DeviceClient.running() Whether the client is running.
DeviceClient.send_message(msg) Send any kind of message.
DeviceClient.send_request(msg) Send a request messsage.
DeviceClient.set_ioloop([ioloop]) Set the tornado.ioloop.IOLoop instance to use.
DeviceClient.start([timeout]) Start the client in a new thread.
DeviceClient.stop([timeout]) Stop a running client (from another thread).
DeviceClient.unhandled_inform(msg) Fallback method for inform messages without a registered handler.
DeviceClient.unhandled_reply(msg) Fallback method for reply messages without a registered handler.
DeviceClient.unhandled_request(msg) Fallback method for requests without a registered handler.
DeviceClient.until_connected(*args, **kwargs) Return future that resolves when the client is connected.
DeviceClient.until_protocol(*args, **kwargs) Return future that resolves after receipt of katcp protocol info.
DeviceClient.until_running([timeout]) Return future that resolves when the client is running.
DeviceClient.wait_connected([timeout]) Wait until the client is connected.
DeviceClient.wait_protocol([timeout]) Wait until katcp protocol information has been received from server.
DeviceClient.wait_running([timeout]) Wait until the client is running.
MAX_LOOP_LATENCY = 0.03

Do not spend more than this many seconds reading pipelined socket data

IOStream inline-reading can result in ioloop starvation (see https://groups.google.com/forum/#!topic/python-tornado/yJrDAwDR_kA).

MAX_MSG_SIZE = 2097152

Maximum message size that can be received in bytes.

If more than MAX_MSG_SIZE bytes are read from the socket without encountering a message terminator (i.e. newline), the connection is closed.

MAX_WRITE_BUFFER_SIZE = 4194304

Maximum outstanding bytes to be buffered by the server process.

If more than MAX_WRITE_BUFFER_SIZE bytes are outstanding, the connection is closed. Note that the OS also buffers socket writes, so more than MAX_WRITE_BUFFER_SIZE bytes may be untransmitted in total.

bind_address

(host, port) where the client is connecting

convert_seconds(time_seconds)

Convert a time in seconds to the device timestamp units.

KATCP v4 and earlier, specified all timestamps in milliseconds. Since KATCP v5, all timestamps are in seconds. If the device KATCP version has been detected, this method converts a value in seconds to the appropriate (seconds or milliseconds) quantity. For version smaller than V4, the time value will be truncated to the nearest millisecond.

disconnect()

Force client connection to close, reconnect if auto-connect set.

enable_thread_safety()

Enable thread-safety features.

Must be called before start().

handle_inform(msg)

Dispatch an inform message to the appropriate method.

Parameters:

msg : Message object

The inform message to dispatch.

handle_message(msg)

Handle a message from the server.

Parameters:

msg : Message object

The Message to dispatch to the handler methods.

handle_reply(msg)

Dispatch a reply message to the appropriate method.

Parameters:

msg : Message object

The reply message to dispatch.

handle_request(msg)

Dispatch a request message to the appropriate method.

Parameters:

msg : Message object

The request message to dispatch.

inform_build_state(msg)

Handle katcp v4 and below build-state inform.

inform_version(msg)

Handle katcp v4 and below version inform.

inform_version_connect(msg)

Process a #version-connect message.

ioloop = None

The Tornado IOloop to use, set by self.set_ioloop()

is_connected()

Check if the socket is currently connected.

Returns:

connected : bool

Whether the client is connected.

join(timeout=None)

Rejoin the client thread.

Parameters:

timeout : float in seconds

Seconds to wait for thread to finish.

Notes

Does nothing if the ioloop is not managed.

notify_connected(connected)

Event handler that is called whenever the connection status changes.

Override in derived class for desired behaviour.

Note

This function should never block. Doing so will cause the client to cease processing data from the server until notify_connected completes.

Parameters:

connected : bool

Whether the client has just connected (True) or just disconnected (False).

preset_protocol_flags(protocol_flags)

Preset server protocol flags.

Sets the assumed server protocol flags and disables automatic server version detection.

Parameters:protocol_flags : katcp.core.ProtocolFlags instance
request(msg, use_mid=None)

Send a request message, with automatic message ID assignment.

Parameters:

msg : katcp.Message request message

use_mid : bool or None, default=None

Returns:

mid : string or None

The message id, or None if no msg id is used

If use_mid is None and the server supports msg ids, or if use_mid is :

True a message ID will automatically be assigned msg.mid is None. :

if msg.mid has a value, and the server supports msg ids, that value :

will be used. If the server does not support msg ids, KatcpVersionError :

will be raised. :

running()

Whether the client is running.

Returns:

running : bool

Whether the client is running.

send_message(msg)

Send any kind of message.

Parameters:

msg : Message object

The message to send.

send_request(msg)

Send a request messsage.

Parameters:

msg : Message object

The request Message to send.

set_ioloop(ioloop=None)

Set the tornado.ioloop.IOLoop instance to use.

This defaults to IOLoop.current(). If set_ioloop() is never called the IOLoop is managed: started in a new thread, and will be stopped if self.stop() is called.

Notes

Must be called before start() is called

start(timeout=None)

Start the client in a new thread.

Parameters:

timeout : float in seconds

Seconds to wait for client thread to start. Do not specify a timeout if start() is being called from the same ioloop that this client will be installed on, since it will block the ioloop without progressing.

stop(timeout=None)

Stop a running client (from another thread).

Parameters:

timeout : float in seconds

Seconds to wait for client thread to have started.

unhandled_inform(msg)

Fallback method for inform messages without a registered handler.

Parameters:

msg : Message object

The inform message that wasn’t processed by any handlers.

unhandled_reply(msg)

Fallback method for reply messages without a registered handler.

Parameters:

msg : Message object

The reply message that wasn’t processed by any handlers.

unhandled_request(msg)

Fallback method for requests without a registered handler.

Parameters:

msg : Message object

The request message that wasn’t processed by any handlers.

until_connected(*args, **kwargs)

Return future that resolves when the client is connected.

until_protocol(*args, **kwargs)

Return future that resolves after receipt of katcp protocol info.

If the returned future resolves, the server’s protocol information is available in the ProtocolFlags instance self.protocol_flags.

until_running(timeout=None)

Return future that resolves when the client is running.

Notes

Must be called from the same ioloop as the client.

wait_connected(timeout=None)

Wait until the client is connected.

Parameters:

timeout : float in seconds

Seconds to wait for the client to connect.

Returns:

connected : bool

Whether the client is connected.

Notes

Do not call this from the ioloop, use until_connected().

wait_protocol(timeout=None)

Wait until katcp protocol information has been received from server.

Parameters:

timeout : float in seconds

Seconds to wait for the client to connect.

Returns:

received : bool

Whether protocol information was received

If this method returns True, the server’s protocol information is :

available in the ProtocolFlags instance self.protocol_flags. :

Notes

Do not call this from the ioloop, use until_protocol().

wait_running(timeout=None)

Wait until the client is running.

Parameters:

timeout : float in seconds

Seconds to wait for the client to start running.

Returns:

running : bool

Whether the client is running

Notes

Do not call this from the ioloop, use until_running().

katcp.client.make_threadsafe(meth)

Decorator for a DeviceClient method that should always run in ioloop.

Used with DeviceClient.enable_thread_safety(). If not called the method will be unprotected and it is the user’s responsibility to ensure that these methods are only called from the ioloop, otherwise the decorated methods are wrapped. Should only be used for functions that have no return value.

katcp.client.make_threadsafe_blocking(meth)

Decorator for a DeviceClient method that will block.

Used with DeviceClient.enable_thread_safety(). Used to provide blocking calls that can be made from other threads. If called in ioloop context, calls the original method directly to prevent deadlocks. Will route return value to caller. Add timeout keyword argument to limit blocking time. If meth returns a future, its result will be returned, otherwise its result will be passed back directly.

katcp.client.request_check(client, exception, *msg_parms, **kwargs)

Make blocking request to client and raise exception if reply is not ok.

Parameters:

client : DeviceClient instance

exception: Exception class to raise :

*msg_parms : Message parameters sent to the Message.request() call

**kwargs : Keyword arguments

Forwards kwargs[‘timeout’] to client.blocking_request(). Forwards kwargs[‘mid’] to Message.request().

Returns:

reply, informs : as returned by client.blocking_request

Raises:

*exception* passed as parameter is raised if reply.reply_ok() is False :

Notes

A typical use-case for this function is to use functools.partial() to bind a particular client and exception. The resulting function can then be used instead of direct client.blocking_request() calls to automate error handling.