6. ASTM protocol implementation

6.1. astm.protocol :: Common protocol routines

class astm.protocol.ASTMProtocol(sock=None, map=None, timeout=None)

Common ASTM protocol routines.

dispatch(data)

Dispatcher of received data.

on_ack()

Calls on <ACK> message receiving.

on_enq()

Calls on <ENQ> message receiving.

on_eot()

Calls on <EOT> message receiving.

on_message()

Calls on ASTM message receiving.

on_nak()

Calls on <NAK> message receiving.

on_timeout()

Calls when timeout event occurs. Used to limit waiting time for response data.

6.2. astm.server :: ASTM Server

class astm.server.BaseRecordsDispatcher(encoding=None)

Abstract dispatcher of received ASTM records by RequestHandler. You need to override his handlers or extend dispatcher for your needs. For instance:

class Dispatcher(BaseRecordsDispatcher):

    def __init__(self, encoding=None):
        super(Dispatcher, self).__init__(encoding)
        # extend it for your needs
        self.dispatch['M'] = self.my_handler
        # map custom wrappers for ASTM records to their type if you
        # don't like to work with raw data.
        self.wrapper['M'] = MyWrapper

    def on_header(self, record):
        # initialize state for this session
        ...

    def on_patient(self, record):
        # handle patient info
        ...

    # etc handlers

    def my_handler(self, record):
        # handle custom record that wasn't implemented yet by
        # python-astm due to some reasons
        ...

After defining our dispatcher, we left only to let Server use it:

server = Server(dispatcher=Dispatcher)
on_comment(record)

Comment record handler.

on_header(record)

Header record handler.

on_order(record)

Order record handler.

on_patient(record)

Patient record handler.

on_result(record)

Result record handler.

on_terminator(record)

Terminator record handler.

on_unknown(record)

Fallback handler for dispatcher.

class astm.server.RequestHandler(sock, dispatcher, timeout=None)

ASTM protocol request handler.

Parameters:
  • sock – Socket object.
  • dispatcher (BaseRecordsDispatcher) – Request handler records dispatcher instance.
  • timeout (int) – Number of seconds to wait for incoming data before connection closing.
on_timeout()

Closes connection on timeout.

class astm.server.Server(host='localhost', port=15200, request=None, dispatcher=None, timeout=None, encoding=None)

Asyncore driven ASTM server.

Parameters:
  • host (str) – Server IP address or hostname.
  • port (int) – Server port number.
  • request – Custom server request handler. If omitted the RequestHandler will be used by default.
  • dispatcher – Custom request handler records dispatcher. If omitted the BaseRecordsDispatcher will be used by default.
  • timeout (int) – RequestHandler connection timeout. If None request handler will wait for data before connection closing.
  • encoding (str) – Dispatcher‘s encoding.
dispatcher

alias of BaseRecordsDispatcher

request

alias of RequestHandler

serve_forever(*args, **kwargs)

Enters into the polling loop to let server handle incoming requests.

6.3. astm.client :: ASTM Client

class astm.client.Client(emitter, host='localhost', port=15200, encoding=None, timeout=20, flow_map={'C': ['*'], 'H': ['C', 'P', 'L'], 'L': ['H'], 'O': ['C', 'P', 'O', 'R', 'L'], 'P': ['C', 'O', 'L'], 'R': ['C', 'P', 'O', 'R', 'L'], None: ['H']}, chunk_size=None, bulk_mode=False)

Common ASTM client implementation.

Parameters:
  • emitter (function) – Generator function that will produce ASTM records.
  • host (str) – Server IP address or hostname.
  • port (int) – Server port number.
  • timeout (int) – Time to wait for response from server. If response wasn’t received, the on_timeout() will be called. If None this timer will be disabled.
  • flow_map – Records flow map. Used by RecordsStateMachine.
  • chunk_size (int) – Chunk size in bytes. None value prevents records chunking.
  • bulk_mode (bool) – Sends all records for single session (starts from Header and ends with Terminator records) via single message instead of sending each record separately. If result message is too long, it may be split by chunks if chunk_size is not None. Keep in mind, that collecting all records for single session may take some time and server may reject data by timeout reason.
Type:

dict

Base emitter is a generator that yield ASTM records one by one preserving their order:

from astm.records import (
    HeaderRecord, PatientRecord, OrderRecord, TerminatorRecord
)
def emitter():
    assert (yield HeaderRecord()), 'header was rejected'
    ok = yield PatientRecord(name={'last': 'foo', 'first': 'bar'})
    if ok:  # you also can decide what to do in case of record rejection
        assert (yield OrderRecord())
    yield TerminatorRecord()  # we may do not care about rejection

Client thought RecordsStateMachine keep track on this order, raising AssertionError if it is broken.

When emitter terminates with StopIteration or GeneratorExit exception client connection to server closing too. You may provide endless emitter by wrapping function body with while True: ... loop polling data from source from time to time. Note, that server may have communication timeouts control and may close session after some time of inactivity, so be sure that you’re able to send whole session (started by Header record and ended by Terminator one) within limited time frame (commonly 10-15 sec.).

emitter_wrapper

alias of Emitter

handle_connect()

Initiates ASTM communication session.

on_ack()

Handles ACK response from server.

Provides callback value True to the emitter and sends next message to server.

on_enq()

Raises NotAccepted exception.

on_eot()

Raises NotAccepted exception.

on_message()

Raises NotAccepted exception.

on_nak()

Handles NAK response from server.

If it was received on ENQ request, the client tries to repeat last request for allowed amount of attempts. For others it send callback value False to the emitter.

on_timeout()

Sends final EOT message and closes connection after his receiving.

run(timeout=1.0, *args, **kwargs)

Enters into the polling loop to let client send outgoing requests.

class astm.client.Emitter(emitter, flow_map, encoding, chunk_size=None, bulk_mode=False)

ASTM records emitter for Client.

Used as wrapper for user provided one to provide proper routines around for sending Header and Terminator records.

Parameters:
  • emitter – Generator/coroutine.
  • encoding (str) – Data encoding.
  • flow_map – Records flow map. Used by RecordsStateMachine.
  • chunk_size (int) – Chunk size in bytes. If None, emitter record wouldn’t be split into chunks.
  • bulk_mode (bool) – Sends all records for single session (starts from Header and ends with Terminator records) via single message instead of sending each record separately. If result message is too long, it may be split by chunks if chunk_size is not None. Keep in mind, that collecting all records for single session may take some time and server may reject data by timeout reason.
Type:

dict

close()

Closes the emitter. Acts in same way as close() for generators.

send(value=None)

Passes value to the emitter. Semantically acts in same way as send() for generators.

If the emitter has any value within local buffer the returned value will be extracted from it unless value is False.

Parameters:value (bool) – Callback value. True indicates that previous record was successfully received and accepted by server, False signs about his rejection.
Returns:Next record data to send to server.
Return type:bytes
state_machine

alias of RecordsStateMachine

throw(exc_type, exc_val=None, exc_tb=None)

Raises exception inside the emitter. Acts in same way as throw() for generators.

If the emitter had catch an exception and return any record value, it will be proceeded in common way.