silf.backend.client Package

api Module

exception silf.backend.client.api.ClientException

Bases: Exception

Base class for all Client related exceptions

exception silf.backend.client.api.ClientNoErrorNamespaceException

Bases: silf.backend.client.api.ClientException

Thrown when send_error is called in a way that does not provide namespace (all args None)

class silf.backend.client.api.IClient(config='config/default.ini', section='Client', block=False)

Bases: object

Message
copy() → silf.backend.client.api.IClient

Creates a copy of this client

create_random_id()
disconnect(wait)
initialize()
make_labdata_message(namespace=None, type=None, suite=None, labdata=None)

Create XMPP message stanza with labdata substanza using suppliend parameters

Parameters:
  • namespace – Namespace of labdata substanza
  • type – Type of labdata substanza
  • suite – Data suite that will be inserted into labdata substanza
  • labdata – Labdata substanza

Note

if labdata parameter is None, new labdata substanza is created using namespace, type and suite parameters, otherwise they are ignored.

make_message(mto, labdata, mbody=None, msubject=None, mtype=None, mhtml=None, mfrom=None, mnick=None)
random_resource(jid)

Add random resource to JID

register_callback(callback, namespace=None, type=None)
register_error_callback(func)
send(namespace, suite, ltype='query', id=None, incoming_stanza=None)

Send labdata stanza with body containing JSON from suite, take namespace and id from state if serializing/sending labdata fails for some reason send error labdata instead

Parameters:
  • state (IncomingStanza) – IncomingStanza object (see IncomingStanza class description)
  • suite – Data to be sent (JSON serializable object - suite/stanza)
  • ltype (str) – Labtata type to use (string)
Returns:

None

send_error(suite, incoming_stanza=None, lnamespace=None)

Send error labdata

Parameters:
  • suite (ErrorSuite) – ErrorSuite object (contains info about errors - seraializable to JSON)
  • incoming_stanza – IncomingStanza object
  • lnamespace – Labdata namespace to use
Returns:

None

Note

labdata namespace is taken from state object, if state is None, namespace is taken from lnamespace parameter, if both are None exception is thrown.

send_labdata(labdata)
send_results(suite)

Send experiment results in ‘data’ labdata stanza :param suite: DataSuite object (serializable to JSON)

send_standalone_stanza(namespace, suite=None)

Sends standalone stanza (results, stop etc).

Parameters:
  • namespace (str) – Namespace to
  • suite
Returns:

client Module

class silf.backend.client.client.CallbackWrapper(name, matcher, pointer, client, **kwargs)

Bases: sleekxmpp.xmlstream.handler.callback.Callback

SleekXMPP does not allow passing additional arguments to _callbacks CallbackWrapper adds one layer between sleekxmpp and actual callback function.

run(payload, instream=False)
class silf.backend.client.client.Client(config='config/default.ini', section='Client', block=False)

Bases: silf.backend.client.api.IClient

XMPP client

Initiates connection to XMPP server, joins multi user chat.

After initialization use register_*_callback functions to add handlers for labdata messages in specific namespaces.

Message
copy() → silf.backend.client.client.Client

Creates a copy of this client

disconnect(wait=None)

Terminate connection to XMPP server. Both clients will be disconnected

initialize(time_to_wait_for_connection=0)

Connect to XMPP server, register necessary plugins

Create SleekXMPP client, for sending labdata stanzas. Use unencrypted plain authentication, because Tigase has problem with SSL. Insert self.error_handler into modified SleekXMPP clinets which will be called when XML perser error occurs.

make_message(mto, labdata, mbody=None, msubject=None, mtype=None, mhtml=None, mfrom=None, mnick=None)

Create XMPP message stanza and insert labdata into it

Parameters:
  • labdata – Labdata substanza which will be inserted into message
  • mbody – Body of message (text)
  • msubject – Message subject
  • mtype – Message type (None for user to user messages, ‘groupchat’ for muc messages)
  • mhtml – HTML body content (optional)
  • mfrom – JID of sender (some servers require full client JID)
  • mnick – Nick of sender (optional)
register_error_callback(func)

Register callback function executed before client reset when XML parser error occurs

send_labdata(stanza)

Send message with labdata substanza to groupchat Add dummy <body> tag, XMPP server (openfire) does not pass groupchat messages without it :param stanza: received message.

start(event)

Fired automatically after successful connection to XMPP server Join groupchat.

wait_until_online(timeout=15)

Wait until client gets online :param timeout: max time to wait

exception silf.backend.client.client.DisconnectedException

Bases: Exception

Raised when Client couldn’t connect during startup.

We treat all connection errors as fatal errors, that force experiments to be terminated and then resurrected by systemd.

class silf.backend.client.client.SleekErrorHandler

Bases: object

SleekXMPP sometimes receives XMPP conflict, XML interpreter (expat?) throws SyntaxError exception, and tries to reconnect (XML stream is stuck in some unmanageable condition, and reconnect never succeeds). This triggers endless stream of reconnect attempts, experinment server becomes unusable. Resetting XML stream from inside of SleekXMPP (abort and then connect) does not work (triggers SocketError). XML processing thread must be killed (we must do this from Client context)

add_callable(c)

Add callback function (called on stream error from main experiment thread) avoid using this function directly, use Client.register_error_handler

check_flag()
fire()

Called when error is caught, calls all stored callback functions, flag marks client as ‘broken’ and can be read by other threads

const Module

echo Module

class silf.backend.client.echo.Echo(config, section='Echo')

Bases: silf.backend.client.listener.Listener

Test XMPP echo bot - bounces back all messages Used for labdata/Client debugging

muc_message(msg)

labdata Module

Labdata XMPP stanza (substanza of Message)

exception silf.backend.client.labdata.InvalidLabdataContentException

Bases: silf.backend.client.labdata.LabdataException

Thrown when we find labdata with invalid content.

class silf.backend.client.labdata.LabdataBase(xml=None, parent=None, type=None, suite=None, id=None)

Bases: sleekxmpp.xmlstream.stanzabase.ElementBase

body_as_dict
content
get_body()
has_body
insert_into_message(msg)

Insert Labdata substanza into message

interfaces = {'id', 'type', 'body'}
name = 'labdata'
namespace = 'silf'
plugin_attrib = 'labdata'
set_body(value)

Set body of labdata element in XML: <labdata …> HERE </labdata>

set_type(value)

Set type of Labdata substanza, ‘result’, ‘ack’ and ‘done’ need ‘id’ attribute set before type

sub_interfaces = set()
suite
suite_type
type
exception silf.backend.client.labdata.LabdataException

Bases: Exception

Base class for all Labdata stanza related exceptions

class silf.backend.client.labdata.LabdataExperimentStop(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:experiment:stop'
plugin_attrib = 'silf:experiment:stop'
class silf.backend.client.labdata.LabdataLangSet(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:lang:set'
plugin_attrib = 'silf:lang:set'
class silf.backend.client.labdata.LabdataMatcher(lnamespace=None, ltype=None)

Bases: sleekxmpp.xmlstream.matcher.base.MatcherBase

match(stanza)

Test if message stanza contains proper labdata substanza, check if labdata satisfies conditions set in __init__

class silf.backend.client.labdata.LabdataMiscError(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:misc:error'
plugin_attrib = 'silf:misc:error'
class silf.backend.client.labdata.LabdataModeGet(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:mode:get'
plugin_attrib = 'silf:mode:get'
class silf.backend.client.labdata.LabdataModeSet(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:mode:set'
plugin_attrib = 'silf:mode:set'
class silf.backend.client.labdata.LabdataResults(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:results'
plugin_attrib = 'silf:results'
class silf.backend.client.labdata.LabdataSeriesStart(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:series:start'
plugin_attrib = 'silf:series:start'
class silf.backend.client.labdata.LabdataSeriesStop(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:series:stop'
plugin_attrib = 'silf:series:stop'
class silf.backend.client.labdata.LabdataSettingsCheck(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:settings:check'
plugin_attrib = 'silf:settings:check'
class silf.backend.client.labdata.LabdataSettingsUpdate(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:settings:update'
plugin_attrib = 'silf:settings:update'
class silf.backend.client.labdata.LabdataState(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:state'
plugin_attrib = 'silf:state'
class silf.backend.client.labdata.LabdataVersionGet(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:protocol:version:get'
plugin_attrib = 'silf:protocol:version:get'
class silf.backend.client.labdata.LabdataVersionSet(xml=None, parent=None, type=None, suite=None, id=None)

Bases: silf.backend.client.labdata.LabdataBase

namespace = 'silf:protocol:version:set'
plugin_attrib = 'silf:protocol:version:set'
exception silf.backend.client.labdata.NoLabdataException

Bases: silf.backend.client.labdata.LabdataException

Thrown when reply_labdata() is called on message without labdata substanza.

exception silf.backend.client.labdata.NoLabdataIdException

Bases: silf.backend.client.labdata.LabdataException

Thrown when user tries to set labdata type to ack, result or done wtithout setting id first

exception silf.backend.client.labdata.NoLabdataNamespaceException

Bases: silf.backend.client.labdata.LabdataException

Thrown when matcher encounters labdata stanza without namespace

exception silf.backend.client.labdata.UnknownLabdataNamespaceException

Bases: silf.backend.client.labdata.LabdataException

Thrown when user tries to format_labdata with namespace not in LABDATA_NAMESPACES

exception silf.backend.client.labdata.UnknownLabdataTypeException

Bases: silf.backend.client.labdata.LabdataException

Thrown when user tries to create labdata of unknown type (not in LABDATA_TYPES array)

silf.backend.client.labdata.check_labdata(stanza)

Check if stanza is valid labdata

silf.backend.client.labdata.check_message_labdata(stanza)

Check if message contains valid labdata

silf.backend.client.labdata.format_labdata(lnamespace, ltype='ack', lid=None, lbody=None, suite=None)

Prepare labdata stanza using supplied data

silf.backend.client.labdata.labdata_subclass

alias of LabdataResults

silf.backend.client.labdata.reply_labdata(labdata, ltype='ack', lbody=None)

Reply to labdata stanza (create another labdata)

labdata_sender Module

class silf.backend.client.labdata_sender.LabdataSender(args, config='config/default.ini', section='Sender')

Bases: object

Connects to XMPP server, joins groupchat, sends single labdata stanza with parameters specified by command line args and disconnects. Used only for labdata/Client debugging

initialize(block=True)
muc_message(msg)
send_labdata(stanza)
start(event)

listener Module

class silf.backend.client.listener.Listener(config, section='Listener')

Bases: object

Test XMPP client - Sits quietly on room and dumps everything it hears to stdout Used oinly for labdata/Client debugging

disconnect()
initialize(block)
muc_message(msg)
muc_online(presence)
start(event)

mock_client Module

class silf.backend.client.mock_client.Client(config='config/default.ini', section='Client', block=False, log_file=None)

Bases: silf.backend.client.api.IClient

>>> mock = Client()
>>> mock.sent_stanzas
{}

We are registering callback for all incoming stanzas:

>>> mock.register_callback(lambda x: print("Reclieved {}".format(x)))
>>> mock.fire_synthetic_event( "silf:mode:get", "query")
Reclieved <IncomingStanza type='query' namespace='silf:mode:get' contents=<<empty>> >

Sent stanzas contains stanzas sent by this client so it is empty:

>>> mock.sent_stanzas
{}
>>> mock.register_send_callback(lambda  x: print("Sent {}".format(x)))
>>> mock.send_standalone_stanza('silf:experiment:stop')
Sent <IncomingStanza type='data' namespace='silf:experiment:stop' contents=<<empty>> >
>>> mock.sent_stanzas
{'silf:experiment:stop': [<labdata data silf:experiment:stop None>]}
assert_and_get_stanza(namespace, types=None)

Returns stanza with proper namespace and type if it was sent by the remote side (experiment)

Parameters:
  • namespace (string) – What namespace to return
  • types (list) – Is not None we will return only stanzas of specified type. This can be either a string or a list.
Raises:

AssertionError – If stanza was not found

Returns:

Specified labdata

Return type:

LabdataBase

assert_no_errors()
clear_client()
copy() → silf.backend.client.mock_client.Client
disconnect(wait=None)
fire_synthetic_event(namespace, type, contents=None, suite=None)
Parameters:incoming_stanza (LabdataState) – Event to be fired.
Returns:
get_and_clear_errors()
get_stanza(namespace, types=None)
initialize()
register_error_callback(func)
register_send_callback(callback, *, type=None, namespace=None)
send_labdata(labdata)
sent_errors
sent_stanzas
class silf.backend.client.mock_client.TestClient(config='config/default.ini', section='Client', block=False, log_file=None)

Bases: silf.backend.client.mock_client.Client

send_set_mode(mode)
send_set_mode_and_wait(mode, wait=2)
send_start_series(**kwargs)
send_start_series_and_wait(settings, wait_time=3)
send_stop_experiment()
send_stop_experiment_and_wait(wait_time=3)
send_stop_series()
send_stop_series_and_wait(wait_time=5)
watch_for_results(max_time, on_result_callback=None, do_print=False)