KBUS Python bindings for Limpets

Limpet - a mechanism for proxying KBUS messages to/from another Limpet.

This allows messages to be communicated from one KBUS device to another, either on the same machine or over a network.

Limpets

See also the LimpetExample class, which shows how a limpet might be deployed in practise.

Limpet and run_a_limpet

class kbus.limpet.LimpetKsock(which, our_network_id, their_network_id, message_name='$.*', verbosity=1, termination_message=None)

Bases: kbus.ksock.Ksock

A Limpet proxies KBUS messages to/from another Limpet.

This class wraps itself around a Ksock, transforming messages as they are read from the Ksock, or written to it.

bind(*args)

Not meaningful for this class.

could_not_send_to_kbus_msg(msg, exc)

If a send to our Ksock failed, call this to generate a message.

‘msg’ is the message we tried to send.

‘exc’ is the IOError exception that was raised by the failed call of ‘send_msg()’

We return an appropriate message to send to the other Limpet, or None if we could not determine one.

discard()

Not meaningful for this class.

We only support reading an entire message in one go with read_next_msg().

len_left()

Not meaningful for this class.

We only support reading an entire message in one go with read_next_msg().

read_data(count)

Not meaningful for this class.

We only support reading an entire message in one go with read_next_msg().

read_msg(length)

Read a Message of length length bytes.

It is assumed that length was returned by a previous call of next_msg(). It must be large enough to cause the entire message to be read.

After the data has been read, it is passed to Message() to construct a message instance, which is returned.

Returns None if there was nothing to be read, or if the message read is one that this Limpet should ignore.

read_next_msg()

Read the next Message completely.

Equivalent to a call of kbus.Ksock.next_msg(), followed by reading the appropriate number of bytes and passing that to Message() to construct a message instance, which is returned.

Returns None if there was nothing to be read, or if the message read is one that this Limpet should ignore.

report_replier_binds(report_events=True, just_ask=False)

Not meaningful for this class.

Limpets require this option to be set in order to work properly, and do not allow the user to change it.

send_msg(message)

Write a Message (from the other Limpet) to our Ksock, and send it.

Entirely equivalent to calling write_msg() and then send(), and returns the MessageId of the sent message, like send() does.

If the message was one we need to ignore (i.e., we’re not interested in sending it), raises NoMessage.

If we need to send a message back to the other Limpet, then that exception will have the messsage as its argument.

unbind(*args)

Not meaningful for this class.

want_messages_once(only_once=False, just_ask=False)

Not meaningful for this class.

Limpets require this option to be set in order to work properly, and do not allow the user to change it.

write_data(data)

Not meaningful for this class.

We only support writing an entire message in one go with send_msg().

write_msg(message)

Not meaningful for this class.

We only support writing and sending an entire message in one go with send_msg().

kbus.limpet.run_a_limpet(is_server, address, family, kbus_device, network_id, message_name='$.*', termination_message=None, verbosity=1)

Run a Limpet.

A Limpet has two “ends”:

  1. kbus_device specifies which KBUS device it should communicate with, via ksock = Ksock(kbus_device, 'rw').
  2. socket_address is the address for the socket used to communicate with its paired Limpet. This should generally be a path name (if communication is with another Limpet on the same machine, via Unix domain sockets), or a (host, port) tuple (for communication with a Limpet on another machine, via the internet).

Messages received from KBUS get sent to the other Limpet.

Messages sent from the other Limpet get sent to KBUS.

  • is_server is true if we are the “server” of the Limpet pair, false if we are the “client”
  • address is the socket address we use to talk to the other Limpet
  • family is AF_UNIX or AF_INET, determining what sort of address we want – a pathname for the former, a <host>:<port> string for the latter
  • kbus_device is which KBUS device to open
  • network_id is the network id to set in message ids when we are forwarding a message to the other Limpet. It must be greater than zero.
  • message_name is the name of the message (presumably a wildcard) we are forwarding
  • if termination_message is not None, then we will stop when a message with that name is read from KBUS
  • if verbosity is 0, we don’t output any “useful” messages, if it is 1 we just announce ourselves, if it is 2 (or higher) we output information about each message as it is processed.

Limpet exceptions

class kbus.limpet.GiveUp

Bases: exceptions.Exception

Signifies a fatal condition such as a failure to connect to the other Limpet, or when the termination_message of a LimpetKsock is read.

class kbus.limpet.OtherLimpetGoneAway

Bases: exceptions.Exception

The other end has closed its end of the socket.

class kbus.limpet.NoMessage

Bases: exceptions.Exception

There was no message.

class kbus.limpet.BadMessage

Bases: exceptions.Exception

We have read a badly formatted KBUS message.

class kbus.limpet.ErrorMessage(error)

Bases: exceptions.Exception

Something went wrong trying to send a message to KBUS.

There is an error message, for sending back to the other Limpet, in our .error value.

Helper functions

kbus.limpet.parse_address(word)

Work out what sort of address we have.

Returns (address, family).

kbus.limpet.connect_as_server(address, family, verbosity=1)

Connect to a socket as a server.

We start listening, until we get someone connecting to us.

Returns a tuple (listener_socket, connection_socket).

kbus.limpet.connect_as_client(address, family, verbosity=1)

Connect to a socket as a client.

Returns the socket.

kbus.limpet.remove_socket_file(name)

Attempts to clean up a socket whose address is a file in the filesystem. This currently only applies to sockets of the AF_UNIX family.