Beispiel #1
0
    def add_parameter_from_output_interface(self, input_name, output_name,
                                            output_interface):
        """Adds an output parameter from the given output interface to this interface with the given input name. This is
        used to create a connecting interface that can be validated for passing to another interface.

        :param input_name: The name of the input parameter to add
        :type input_name: string
        :param output_name: The name of the output parameter in the output interface
        :type output_name: string
        :param output_interface: The output interface
        :type output_interface: :class:`data.interface.interface.Interface`
        :returns: A list of warnings discovered during validation
        :rtype: :func:`list`

        :raises :class:`data.interface.exceptions.InvalidInterfaceConnection`: If the interface connection is invalid
        """

        if input_name in self.parameters:
            msg = 'Input \'%s\' has more than one parameter connected to it' % input_name
            raise InvalidInterfaceConnection('DUPLICATE_INPUT', msg)

        try:
            new_param = output_interface.parameters[output_name].copy()
        except KeyError:
            msg = 'Input %s cannot be connected to output %s; no output exists with that name' % (
                input_name, output_name)
            raise InvalidInterfaceConnection('MISSING_OUTPUT_NAME', msg)

        new_param.name = input_name
        self.add_parameter(new_param)

        return []
Beispiel #2
0
    def validate_connection(self, connecting_interface):
        """Validates that the given connecting interface can be accepted by this interface

        :param connecting_interface: The interface attempting to connect to this interface
        :type connecting_interface: :class:`data.interface.interface.Interface`
        :returns: A list of warnings discovered during validation
        :rtype: :func:`list`

        :raises :class:`data.interface.exceptions.InvalidInterfaceConnection`: If the interface connection is invalid
        """

        warnings = []

        for parameter in self.parameters.values():
            if parameter.name in connecting_interface.parameters:
                connecting_parameter = connecting_interface.parameters[
                    parameter.name]
                warnings.extend(
                    parameter.validate_connection(connecting_parameter))
            elif parameter.required:
                raise InvalidInterfaceConnection(
                    'PARAM_REQUIRED',
                    'Parameter \'%s\' is required' % parameter.name)

        return warnings
Beispiel #3
0
    def test_validate_connection(self):
        """Tests calling Interface.validate_connection()"""

        interface = Interface()
        connecting_interface = Interface()

        file_param = FileParameter('input_1', ['application/json'])
        interface.add_parameter(file_param)
        connecting_interface.add_parameter(file_param)
        json_param = JsonParameter('input_2', 'integer')
        interface.add_parameter(json_param)
        connecting_interface.add_parameter(json_param)

        # Valid connection
        interface.validate_connection(connecting_interface)

        new_file_param = FileParameter('input_3', ['image/gif'], required=True)
        interface.add_parameter(new_file_param)

        # Connection is missing required input 3
        with self.assertRaises(InvalidInterfaceConnection) as context:
            interface.validate_connection(connecting_interface)
        self.assertEqual(context.exception.error.name, 'PARAM_REQUIRED')

        connecting_interface.add_parameter(new_file_param)
        mock_param = MagicMock()
        mock_param.name = 'input_4'
        mock_param.validate_connection.side_effect = InvalidInterfaceConnection('MOCK', '')
        interface.add_parameter(mock_param)
        connecting_interface.add_parameter(mock_param)

        # Invalid connection
        with self.assertRaises(InvalidInterfaceConnection) as context:
            interface.validate_connection(connecting_interface)
        self.assertEqual(context.exception.error.name, 'MOCK')
Beispiel #4
0
    def validate(self, all_dependencies):
        """See :meth:`recipe.handlers.connection.InputConnection.validate`
        """

        # Check that the connection's dependency is met
        if self.node_name not in all_dependencies:
            msg = 'Cannot get output \'%s\' without dependency on node \'%s\''
            raise InvalidInterfaceConnection(
                'MISSING_DEPENDENCY', msg % (self.output_name, self.node_name))

        return []
Beispiel #5
0
    def validate_connection(self, connecting_parameter):
        """Validates that the given connecting parameter can be accepted by this parameter

        :param connecting_parameter: The parameter attempting to connect to this parameter
        :type connecting_parameter: :class:`data.interface.parameter.Parameter`
        :returns: A list of warnings discovered during validation
        :rtype: :func:`list`

        :raises :class:`data.interface.exceptions.InvalidInterfaceConnection`: If the interface connection is invalid
        """

        if self.param_type != connecting_parameter.param_type:
            msg = 'Parameter \'%s\' of type \'%s\' cannot accept type \'%s\''
            msg = msg % (self.name, self.param_type, connecting_parameter.param_type)
            raise InvalidInterfaceConnection('MISMATCHED_PARAM_TYPE', msg)

        if self.required and not connecting_parameter.required:
            msg = 'Parameter \'%s\' is required and cannot accept an optional value' % self.name
            raise InvalidInterfaceConnection('PARAM_REQUIRED', msg)

        return []
Beispiel #6
0
    def validate_connection(self, connecting_parameter):
        """See :meth:`data.interface.parameter.Parameter.validate_connection`
        """

        warnings = super(JsonParameter, self).validate_connection(connecting_parameter)

        if self.json_type != connecting_parameter.json_type:
            msg = 'Parameter \'%s\' of JSON type \'%s\' cannot accept JSON type \'%s\''
            msg = msg % (self.name, self.json_type, connecting_parameter.json_type)
            raise InvalidInterfaceConnection('MISMATCHED_JSON_TYPE', msg)

        return warnings
Beispiel #7
0
    def test_validate_invalid_connection(self):
        """Tests calling RecipeDefinition.validate() with an invalid connection to a node's input interface"""

        input_interface = Interface()
        definition = RecipeDefinition(input_interface)
        definition.add_job_node('A', 'job_type_1', '1.0', 1)
        definition.add_recipe_node('B', 'recipe_type_1', 1)
        definition.add_dependency('A', 'B')
        definition.add_dependency_input_connection('B', 'input_1', 'A',
                                                   'output_1')
        mocked_interfaces = {'A': MagicMock(), 'B': MagicMock()}
        mocked_interfaces[
            'B'].validate_connection.side_effect = InvalidInterfaceConnection(
                '', '')

        with self.assertRaises(InvalidDefinition) as context:
            definition.validate(mocked_interfaces, mocked_interfaces)
        self.assertEqual(context.exception.error.name, 'NODE_INTERFACE')
Beispiel #8
0
    def add_connection(self, connection):
        """Adds a connection that connects a parameter to one of this node's inputs

        :param connection: The connection to add
        :type connection: :class:`recipe.definition.connection.InputConnection`

        :raises :class:`recipe.definition.exceptions.InvalidDefinition`: If the definition is invalid
        """

        try:
            if connection.input_name in self.connections:
                msg = 'Input \'%s\' has more than one parameter connected to it' % connection.input_name
                raise InvalidInterfaceConnection('DUPLICATE_INPUT', msg)

            self.connections[connection.input_name] = connection
        except InvalidInterfaceConnection as ex:
            msg = 'Node \'%s\' interface error: %s' % (self.name, ex.error.description)
            raise InvalidDefinition('NODE_INTERFACE', msg)
Beispiel #9
0
    def validate_connection(self, connecting_parameter):
        """See :meth:`data.interface.parameter.Parameter.validate_connection`
        """

        warnings = super(FileParameter, self).validate_connection(connecting_parameter)

        if not self.multiple and connecting_parameter.multiple:
            msg = 'Parameter \'%s\' cannot accept multiple files' % self.name
            raise InvalidInterfaceConnection('NO_MULTIPLE_FILES', msg)

        mismatched_media_types = []
        for media_type in connecting_parameter.media_types:
            if media_type not in self.media_types:
                mismatched_media_types.append(media_type)
        if mismatched_media_types:
            msg = 'Parameter \'%s\' might not accept [%s]' % (self.name, ', '.join(mismatched_media_types))
            warnings.append(ValidationWarning('MISMATCHED_MEDIA_TYPES', msg))

        return warnings