Example #1
0
 def init_on_load(self):
     """Loads all necessary fields upon Action being loaded from database"""
     if not self.errors:
         errors = []
         try:
             self._run, self._arguments_api = get_app_action_api(self.app_name, self.action_name)
             get_app_action(self.app_name, self._run)
         except UnknownApp:
             errors.append('Unknown app {}'.format(self.app_name))
         except UnknownAppAction:
             errors.append('Unknown app action {}'.format(self.action_name))
         self.errors = errors
     self._last_status = None
     self._execution_id = 'default'
     self._resolved_device_id = -1
Example #2
0
def validate_actions(actions, dereferencer, app_name):
    from walkoff.appgateway import get_app_action
    from walkoff.appgateway import get_all_actions_for_app
    defined_actions = get_all_actions_for_app(app_name)
    seen = set()
    for action_name, action in actions.items():
        if action['run'] not in defined_actions:
            raise InvalidApi('Action {0} has "run" property {1} '
                             'which is not defined in App {2}'.format(
                                 action_name, action['run'], app_name))
        action = dereferencer(action)
        action_params = dereferencer(action.get('parameters', []))
        event = action.get('event', '')
        if action_params:
            validate_action_params(action_params,
                                   dereferencer,
                                   app_name,
                                   action_name,
                                   get_app_action(app_name, action['run']),
                                   event=event)
        if 'default_return' in action:
            if action['default_return'] not in action.get('returns', []):
                raise InvalidApi(
                    'Default return {} not in defined return codes {}'.format(
                        action['default_return'],
                        action.get('returns', []).keys()))

        validate_app_action_return_codes(action.get('returns', []), app_name,
                                         action_name)
        seen.add(action['run'])
    if seen != set(defined_actions):
        logger.warning(
            'App {0} has defined the following actions which do not have a corresponding API: '
            '{1}'.format(app_name, (set(defined_actions) - seen)))
Example #3
0
 def init_on_load(self):
     """Loads all necessary fields upon Action being loaded from database"""
     self._run, self._arguments_api = get_app_action_api(
         self.app_name, self.action_name)
     self._output = None
     self._action_executable = get_app_action(self.app_name, self._run)
     self._execution_id = 'default'
Example #4
0
def validate_actions(actions, dereferencer, app_name):
    from walkoff.appgateway import get_app_action
    from walkoff.appgateway import get_all_actions_for_app
    defined_actions = get_all_actions_for_app(app_name)
    seen = set()
    for action_name, action in actions.items():
        if action['run'] not in defined_actions:
            raise InvalidApi('Action {0} has "run" property {1} '
                             'which is not defined in App {2}'.format(action_name, action['run'], app_name))
        action = dereferencer(action)
        action_params = dereferencer(action.get('parameters', []))
        event = action.get('event', '')
        if action_params:
            validate_action_params(action_params, dereferencer, app_name,
                                   action_name, get_app_action(app_name, action['run']), event=event)
        if 'default_return' in action:
            if action['default_return'] not in action.get('returns', []):
                raise InvalidApi(
                    'Default return {} not in defined return codes {}'.format(
                        action['default_return'], action.get('returns', []).keys()))

        validate_app_action_return_codes(action.get('returns', []), app_name, action_name)
        seen.add(action['run'])
    if seen != set(defined_actions):
        logger.warning('App {0} has defined the following actions which do not have a corresponding API: '
                       '{1}'.format(app_name, (set(defined_actions) - seen)))
Example #5
0
 def init_on_load(self):
     """Loads all necessary fields upon Action being loaded from database"""
     if not self.errors:
         errors = []
         try:
             self._run, self._arguments_api = get_app_action_api(
                 self.app_name, self.action_name)
             get_app_action(self.app_name, self._run)
         except UnknownApp:
             errors.append('Unknown app {}'.format(self.app_name))
         except UnknownAppAction:
             errors.append('Unknown app action {}'.format(self.action_name))
         self.errors = errors
     self._last_status = None
     self._execution_id = 'default'
     self._resolved_device_id = -1
Example #6
0
 def validate(self):
     """Validates the object"""
     errors = []
     try:
         self._run, self._arguments_api = get_app_action_api(self.app_name, self.action_name)
         get_app_action(self.app_name, self._run)
         if is_app_action_bound(self.app_name, self._run) and not self.device_id:
             message = 'App action is bound but no device ID was provided.'.format(self.name)
             errors.append(message)
         validate_app_action_parameters(self._arguments_api, self.arguments, self.app_name, self.action_name)
     except UnknownApp:
         errors.append('Unknown app {}'.format(self.app_name))
     except UnknownAppAction:
         errors.append('Unknown app action {}'.format(self.action_name))
     except InvalidArgument as e:
         errors.extend(e.errors)
     self.errors = errors
Example #7
0
 def validate(self):
     """Validates the object"""
     errors = []
     try:
         self._run, self._arguments_api = get_app_action_api(
             self.app_name, self.action_name)
         get_app_action(self.app_name, self._run)
         if is_app_action_bound(self.app_name,
                                self._run) and not self.device_id:
             message = 'App action is bound but no device ID was provided.'.format(
                 self.name)
             errors.append(message)
         validate_app_action_parameters(self._arguments_api, self.arguments,
                                        self.app_name, self.action_name)
     except UnknownApp:
         errors.append('Unknown app {}'.format(self.app_name))
     except UnknownAppAction:
         errors.append('Unknown app action {}'.format(self.action_name))
     except InvalidArgument as e:
         errors.extend(e.errors)
     self.errors = errors
 def test_validate_action_params_too_few_params_in_api(self):
     self.basicapi['actions']['Add Three'] = {'run': 'main.Main.addThree',
                                              'parameters': [{'name': 'num1',
                                                              'type': 'number'},
                                                             {'name': 'num2',
                                                              'type': 'number'}]}
     self.__generate_resolver_dereferencer(self.basicapi)
     with self.assertRaises(InvalidApi):
         validate_action_params(self.basicapi['actions']['Add Three']['parameters'],
                                self.dereferencer,
                                'HelloWorldBounded',
                                'Add Three',
                                get_app_action('HelloWorldBounded', 'main.Main.addThree'))
 def test_validate_action_params_no_duplicate_params_matches_signature(self):
     self.basicapi['actions']['Add Three'] = {'run': 'main.Main.addThree',
                                              'parameters': [{'name': 'num1',
                                                              'type': 'number'},
                                                             {'name': 'num2',
                                                              'type': 'number'},
                                                             {'name': 'num3',
                                                              'type': 'number'}]}
     self.__generate_resolver_dereferencer(self.basicapi)
     validate_action_params(self.basicapi['actions']['Add Three']['parameters'],
                            self.dereferencer,
                            'HelloWorldBounded',
                            'Add Three',
                            get_app_action('HelloWorldBounded', 'main.Main.addThree'))
Example #10
0
 def test_validate_action_params_duplicate_param_name(self):
     self.basicapi['actions']['Add Three'] = {'run': 'main.Main.addThree',
                                              'parameters': [{'name': 'num1',
                                                              'type': 'number'},
                                                             {'name': 'num1',
                                                              'type': 'string'},
                                                             {'name': 'num2',
                                                              'type': 'number'}]}
     self.__generate_resolver_dereferencer(self.basicapi, expected_success=False)
     with self.assertRaises(InvalidApi):
         validate_action_params(self.basicapi['actions']['Add Three']['parameters'],
                                self.dereferencer,
                                'HelloWorldBounded',
                                'Add Three',
                                get_app_action('HelloWorldBounded', 'main.Main.addThree'))
Example #11
0
    def __init__(self,
                 app_name,
                 action_name,
                 name,
                 device_id=None,
                 id=None,
                 arguments=None,
                 trigger=None,
                 position=None):
        """Initializes a new Action object. A Workflow has one or more actions that it executes.
        Args:
            app_name (str): The name of the app associated with the Action
            action_name (str): The name of the action associated with a Action
            name (str): The name of the Action object.
            device_id (int, optional): The id of the device associated with the app associated with the Action. Defaults
                to None.
            id (str|UUID, optional): Optional UUID to pass into the Action. Must be UUID object or valid UUID string.
                Defaults to None.
            arguments (list[Argument], optional): A list of Argument objects that are parameters to the action.
                Defaults to None.
            trigger (ConditionalExpression, optional): A ConditionalExpression which causes an Action to wait until the
                data is sent fulfilling the condition. Defaults to None.
            position (Position, optional): Position object for the Action. Defaults to None.
        """
        ExecutionElement.__init__(self, id)

        self.trigger = trigger

        self.name = name
        self.device_id = device_id
        self.app_name = app_name
        self.action_name = action_name

        self.arguments = []
        if arguments:
            self.arguments = arguments

        self.position = position

        self._run = None
        self._arguments_api = None
        self._output = None
        self._execution_id = 'default'

        self.validate()
        self._action_executable = get_app_action(self.app_name, self._run)
Example #12
0
 def test_validate_action_params_too_few_params_in_api(self):
     self.basicapi['actions']['Add Three'] = {
         'run':
         'main.Main.addThree',
         'parameters': [{
             'name': 'num1',
             'type': 'number'
         }, {
             'name': 'num2',
             'type': 'number'
         }]
     }
     self.__generate_resolver_dereferencer(self.basicapi)
     with self.assertRaises(InvalidApi):
         validate_action_params(
             self.basicapi['actions']['Add Three']['parameters'],
             self.dereferencer, 'HelloWorldBounded', 'Add Three',
             get_app_action('HelloWorldBounded', 'main.Main.addThree'))
Example #13
0
 def test_validate_action_params_no_duplicate_params_matches_signature(
         self):
     self.basicapi['actions']['Add Three'] = {
         'run':
         'main.Main.addThree',
         'parameters': [{
             'name': 'num1',
             'type': 'number'
         }, {
             'name': 'num2',
             'type': 'number'
         }, {
             'name': 'num3',
             'type': 'number'
         }]
     }
     self.__generate_resolver_dereferencer(self.basicapi)
     validate_action_params(
         self.basicapi['actions']['Add Three']['parameters'],
         self.dereferencer, 'HelloWorldBounded', 'Add Three',
         get_app_action('HelloWorldBounded', 'main.Main.addThree'))
Example #14
0
 def test_validate_action_params_duplicate_param_name(self):
     self.basicapi['actions']['Add Three'] = {
         'run':
         'main.Main.addThree',
         'parameters': [{
             'name': 'num1',
             'type': 'number'
         }, {
             'name': 'num1',
             'type': 'string'
         }, {
             'name': 'num2',
             'type': 'number'
         }]
     }
     self.__generate_resolver_dereferencer(self.basicapi,
                                           expected_success=False)
     with self.assertRaises(InvalidApi):
         validate_action_params(
             self.basicapi['actions']['Add Three']['parameters'],
             self.dereferencer, 'HelloWorldBounded', 'Add Three',
             get_app_action('HelloWorldBounded', 'main.Main.addThree'))
Example #15
0
    def __init__(self,
                 app_name,
                 action_name,
                 name='',
                 device_id=None,
                 arguments=None,
                 triggers=None,
                 position=None,
                 uid=None,
                 templated=False,
                 raw_representation=None):
        """Initializes a new Action object. A Workflow has many actions that it executes.

        Args:
            app_name (str): The name of the app associated with the Action
            action_name (str): The name of the action associated with a Action
            name (str, optional): The name of the Action object. Defaults to an empty string.
            device_id (int, optional): The id of the device associated with the app associated with the Action. Defaults
                to None.
            arguments ([Argument], optional): A list of Argument objects that are parameters to the action.
                Defaults to None.
            triggers (list[Flag], optional): A list of Flag objects for the Action. If a Action should wait for data
                before continuing, then include these Trigger objects in the Action init. Defaults to None.
            position (dict, optional): A dictionary with the x and y coordinates of the Action object. This is used
                for UI display purposes. Defaults to None.
            uid (str, optional): A universally unique identifier for this object.
                Created from uuid.uuid4().hex in Python
            templated (bool, optional): Whether or not the Action is templated. Used for Jinja templating.
            raw_representation (dict, optional): JSON representation of this object. Used for Jinja templating.
        """
        ExecutionElement.__init__(self, uid)

        self.triggers = triggers if triggers is not None else []
        self._incoming_data = None
        self._event = threading.Event()

        self.name = name
        self.device_id = device_id
        self.app_name = app_name
        self.action_name = action_name
        self._run, self._arguments_api = get_app_action_api(
            self.app_name, self.action_name)

        if is_app_action_bound(self.app_name,
                               self._run) and not self.device_id:
            raise InvalidArgument(
                "Cannot initialize Action {}. App action is bound but no device ID was provided."
                .format(self.name))

        self._action_executable = get_app_action(self.app_name, self._run)

        arguments = {argument.name: argument
                     for argument in arguments
                     } if arguments is not None else {}

        self.templated = templated
        if not self.templated:
            validate_app_action_parameters(self._arguments_api, arguments,
                                           self.app_name, self.action_name)
        self.arguments = arguments
        self.position = position if position is not None else {}

        self._output = None
        self._raw_representation = raw_representation if raw_representation is not None else {}
        self._execution_uid = 'default'