Source code for s4.clarity.scripts.triggered_step_epp
# Copyright 2016 Semaphore Solutions, Inc.
# ---------------------------------------------------------------------------
from .stepepp import StepEPP
import logging
import re
log = logging.getLogger(__name__)
class TriggeredStepEPP(StepEPP):
""" TriggeredStepEPP acts as an EPP with multiple entry points, to allow the developer to group all scripts
associated with a step together in a single file. A script implementing this class is intended to be called
multiple times in the same step at different stages, with the Action parameter determining which method is called.
Choices for the Action parameter are automatically generated from all class methods starting with ``on_``. The
Action value is generated by taking the method name, trimming the ``on_``, and transforming the rest of the name to
Pascal-case. For example, an EPP String containing ``-a TestThing`` would attempt to execute a method named
``on_test_thing``.
Usage:
``python <script.py> -u {username} -p {password} --step-uri {stepURI:v2} -l {compoundOutputFileLuid#} -a <Action>``
Our suggested implementation when creating method names is to mirror Clarity's language for scripts triggered
on step transitions, and having button-triggered scripts follow the button label, as shown here:
==================== ===============
Action Parameter EPP Method Name
==================== ===============
BeginningOfStep on_beginning_of_step
EndOfStep on_end_of_step
PlacementEnter on_placement_enter
PlacementExit on_placement_exit
PoolingEnter on_pooling_enter
PoolingExit on_pooling_exit
AddReagentsEnter on_add_reagents_enter
AddReagentsExit on_add_reagents_exit
RecordDetailsEnter on_record_details_enter
RecordDetailsExit on_record_details_exit
CalculateQc on_calculate_qc (Record Details buttons example)
==================== ===============
Ultimately, though, as long as the ``on_`` rules for method naming is followed, the pattern used in your
implementation is up to you.
"""
triggered_step_actions = {}
[docs] @classmethod
def add_triggered_step_actions(cls):
action_handler_names = [method for method in dir(cls) if method.startswith('on_')]
for action_handler_name in action_handler_names:
cls.triggered_step_actions[cls._generate_action(action_handler_name)] = getattr(cls, action_handler_name)
@classmethod
def _generate_action(cls, action_handler_name):
# Converts snake-case to camel-case, and remove the ``on`` from the front
# eg. ``on_record_details_enter`` would be transformed to ``RecordDetailsEnter``
return re.sub('_.', lambda x: x.group()[1].upper(), action_handler_name).lstrip('on')
[docs] @classmethod
def add_arguments(cls, argparser):
super(TriggeredStepEPP, cls).add_arguments(argparser)
cls.add_triggered_step_actions()
argparser.add_argument("-a", "--action", choices=list(cls.triggered_step_actions), required=True)
[docs] def run(self):
log.info("Handling Action '%s'" % self.options.action)
action_arg = self.triggered_step_actions.get(self.options.action)
if action_arg:
action_arg(self)