import functools import tango tasks = {} # note: f.__name__ is of type is_XXX_allowed # f.__name__[3:-8] select the command name # this decorator build a dictionary with the command name as key and # the handler as value. task = lambda f:tasks.setdefault(f.__name__[3:-8], f) @task def is_standby_allowed(device_instance): """ Allowed method for Standby method. Command *Standby* is allowed when the device *State* is ON or STANDBY. :return: True if the method is allowed, otherwise False. """ if device_instance.get_state() in [tango.DevState.ON, tango.DevState.STANDBY]: return True return False @task def is_on_allowed(device_instance): """ Allowed method for On method. Command *On* is allowed when the device *State* is ON or STANDBY. :return: True if the method is allowed, otherwise False. """ if device_instance.get_state() in [tango.DevState.ON, tango.DevState.STANDBY]: return True return False @task def is_off_allowed(device_instance): """ Allowed method for Off method. Command *Off* is allowed when the device *State* is OFF or STANDBY. :return: True if the method is allowed, otherwise False. """ if device_instance.get_state() in [tango.DevState.OFF, tango.DevState.STANDBY]: return True return False def is_command_allowed(device_instance, cmd_name): """ Call the allowed method for the command name specified as input argument :param device_istance: the TANGO device instance :param cmd_name: the name of command to execute :return: True/False """ tasks[cmd_name](device_instance) class IsCommandAllowed(object): """ Class designed to be a decorator for the Master power methods. The *decorator function* performs a check on the input argument to control if the command is issued on the whole sub-element. If this is the case, it checks the State of the sub-element Master device and rejects the command accordingly to the State machine setting. :raise: tango.DevFailed exception if the command can't be executed """ def __init__(self, *args, **kwargs): # store the decorators parameters: # args: the list of sub-element attributes to subscribe, to track the # sub-element command progress and detect a command timeout # kwargs: a dictionary: key ="cmd_name", # value = command to execute ('on', 'off'...) self._args = args self._kwargs = kwargs def __call__(self, f): @functools.wraps(f) def input_args_check(*args, **kwargs): # the Master device instance dev_instance = args[0] # the command name cmd_to_exec = f.__name__ # the command input argument input_arg = args[1] #device_list = input_arg # Note: device list is a reference to args[1]: changing # device_list content, args[1] changes accordingly! num_of_devices = len(input_arg) if num_of_devices == 0: # check the device State: if it not the proper value the command is # not executed if not is_command_allowed(dev_instance, cmd_to_exec.lower()): msg = "Command {} can't be executed when the device is {}".format(cmd_to_exec, dev_instance.get_state()) tango.Except.throw_exception("Command failure",msg, "IsCommandAllowed decorator", tango.ErrSeverity.ERR) return f(*args, **kwargs) return input_args_check