Source code for striptease.procedures
# -*- encoding: utf-8 -*-
from copy import deepcopy
from urllib.parse import urlparse
import json
import sys
from config import Config
from striptease.stripconn import StripConnection
[docs]def dump_procedure_as_json(outf, obj, indent_level=0, use_newlines=True):
"""
Dump a list of commands into a JSON file.
This is similar to what the standard function ``json.dump`` does,
but it uses less carriage returns to make the output easier to
read and to search with ``grep``.
"""
outf.write("[\n")
outf.write(",\n".join([json.dumps(x) for x in obj]))
outf.write("\n]\n")
[docs]class JSONCommandEmitter:
"""This class captures commands sent to the board and outputs a JSON
representation on some text stream.
"""
def __init__(self, conn):
self.command_list = []
self.conn = conn
[docs] def post_command(self, url, cmd):
if "tag" in cmd:
kind = "tag"
elif "message" in cmd.keys():
kind = "log"
elif "wait_time_s" in cmd.keys():
kind = "wait"
else:
kind = "command"
if url != "":
url_components = urlparse(url)
path = url_components.path
else:
path = ""
new_command = {"path": path, "kind": kind, "command": cmd}
self.command_list.append(deepcopy(new_command))
return {"status": "OK", "data": [0]}
[docs] def wait(self, seconds):
return self.post_command("", {"wait_time_s": seconds})
[docs] def tag_start(self, name, comment=""):
# Making this command share the same name and parameters as
# StripConnection allows us to use StripTag on a Worker class
# instead of a StripConnection object!
return self.conn.tag_start(name, comment)
[docs] def tag_stop(self, name, comment=""):
# See the comment for tag_stop
return self.conn.tag_stop(name, comment)
def __call__(self, url, cmd):
return self.post_command(url, cmd)
[docs]class StripProcedure:
"""A test procedure that records commands in JSON objects
This is a base class to be used when you need to implement a test
procedure. Instead of sending commands to the true instrument, the
class records all the commands in a JSON object, which can be
saved in a text file and ran using the command-line program
``program_batch_runner.py``.
You must define a new class from this, and redefine the ``run``
method. In this method, you can use `self.conn` as a
:class:`.StripConnection` object.
"""
def __init__(self):
self.command_history = []
with StripConnection() as conn:
# We need to load the configuration from the server, as it
# includes vital information about the board
# configuration. This information is needed to properly
# initialize the hardware
self.conf = Config()
self.conf.load(conn)
self.command_emitter = JSONCommandEmitter(conn)
conn.post_command = self.command_emitter
self.conn = conn
[docs] def wait(self, seconds):
"Make the test procedure wait for some time before continuing"
return self.command_emitter.wait(seconds)
[docs] def run(self):
"Redefine this method in derived classes"
pass
[docs] def get_command_list(self):
"""Return a list object containing the commands executed so far.
This list will be dumped as a JSON object by :meth:`.output_json`.
"""
return self.command_emitter.command_list
[docs] def clear_command_list(self):
"Remove all the commands produced so far from memory"
self.command_emitter.command_list = []
[docs] def output_json(self, output_filename=None):
"""Write the list of commands executed so far in a JSON object.
Args
----
output_filename (str or Path): path to the file to be
created that will contain the list of commands in JSON
format. If ``None`` is used, the commands will be
printed to ``stdout``.
"""
if (not output_filename) or (output_filename == ""):
dump_procedure_as_json(sys.stdout, self.get_command_list())
else:
with open(str(output_filename), "wt") as outf:
dump_procedure_as_json(outf, self.get_command_list())