def _event(func): arg_names = get_function_arg_names(func) if len(arg_names) < 2: raise InvalidApi('Event action has too few parameters. ' 'There must be a "self" and a second parameter to receive data from the event.') @wraps(func) def wrapper(*args, **kwargs): result = AsyncResult() @event_.connect def send(data): if len(kwargs) > 0: result.set(func(args[0], data, **kwargs)) else: result.set(func(args[0], data)) try: result = result.get(timeout=timeout) except Timeout: result = 'Getting event {0} timed out at {1} seconds'.format(event_.name, timeout), 'EventTimedOut' event_.disconnect(send) return format_result(result) tag(wrapper, 'action') wrapper.__arg_names = arg_names wrapper.__event_name = event_.name return wrapper
def validate_action_params(parameters, dereferencer, app_name, action_name, action_func, event=''): seen = set() for parameter in parameters: parameter = deref(parameter, dereferencer) name = parameter['name'] if name in seen: raise InvalidApi('Duplicate parameter {0} in api for {1} ' 'for action {2}'.format(name, app_name, action_name)) seen.add(name) if hasattr(action_func, '__arg_names'): method_params = list(action_func.__arg_names) else: method_params = get_function_arg_names(action_func) if method_params and method_params[0] == 'self': method_params.pop(0) if event: method_params.pop(0) if action_func.__event_name != event: logger.warning('In app {0} action {1}, event documented {2} does not match ' 'event specified {3}'.format(app_name, action_name, event, action_func.__event_name)) if not seen == set(method_params): only_in_api = seen - set(method_params) only_in_definition = set(method_params) - seen message = ('Discrepancy between defined parameters in API and in method definition ' 'for app {0} action {1}.'.format(app_name, action_name)) if only_in_api: message += ' Only in API: {0}.'.format(only_in_api) if only_in_definition: message += ' Only in definition: {0}'.format(only_in_definition) raise InvalidApi(message)
def _event(func): arg_names = get_function_arg_names(func) if not arg_names or (arg_names[0] == 'self' and len(arg_names) < 2): raise InvalidApi('Event action has too few parameters. ' 'There must be at least one parameter to receive data from the event.') @wraps(func) def wrapper(*args, **kwargs): result = [('Getting event {0} timed out at {1} seconds'.format(event_.name, timeout), 'EventTimedOut')] await_result_condition = Condition() @event_.connect def send(data): await_result_condition.acquire() if len(kwargs) > 0: result.append(func(args[0], data, **kwargs)) else: result.append(func(args[0], data)) await_result_condition.notify() await_result_condition.release() await_result_condition.acquire() while not len(result) >= 2: await_result_condition.wait(timeout=timeout) break await_result_condition.release() event_.disconnect(send) return format_result(result[-1]) tag(wrapper, 'action') wrapper.__arg_names = arg_names wrapper.__event_name = event_.name return wrapper
def action(func): """ Decorator used to tag a method or function as an action Args: func (func): Function to tag Returns: (func) Tagged function """ @wraps(func) def wrapper(*args, **kwargs): return format_result(func(*args, **kwargs)) tag(wrapper, 'action') wrapper.__arg_names = get_function_arg_names(func) return wrapper
def _validate_handler_function_args(func, is_controller): """Validates a handler function by checking how many arguments it has Args: func (func): The function to check is_controller (bool): Is the function intended to handle controller events? Raises: InvalidEventHandler: If the number of arguments is incorrect """ num_args = len(get_function_arg_names(func)) if is_controller: if num_args != 0: raise InvalidEventHandler( 'Handlers for controller events take no arguments') elif num_args != 1: raise InvalidEventHandler( 'Handlers for events non-controller events take one argument')