Exemple #1
0
    def _validate_final_value(self, schemas_by_id):

        if self.final_value_source == UNDEFINED:
            return

        assert isinstance(self.final_value_source, ProtocolPath)

        if self.final_value_source.start_protocol not in schemas_by_id:

            raise ValueError(
                f"The value source {self.final_value_source} does not exist.")

        protocol_schema = schemas_by_id[self.final_value_source.start_protocol]
        protocol_object = protocol_schema.to_protocol()
        protocol_object.get_value(self.final_value_source)

        attribute_type = protocol_object.get_class_attribute(
            self.final_value_source).type_hint

        # TODO: In Python < 3.7 the Union type will collapse pint.Quantity
        #       and pint.Measurement into pint.Quantity such that this check
        #       will fail. For now we allow Measurements or Quantities, but
        #       this should be reverted to just pint.Measurement when dropping
        #       3.6 support.
        if is_union_type(attribute_type):
            assert is_type_subclass_of_type(attribute_type, pint.Quantity)
        else:
            assert is_type_subclass_of_type(attribute_type, pint.Measurement)
    def _validate_final_value(self, schemas_by_id):

        if self.final_value_source == UNDEFINED:
            return

        assert isinstance(self.final_value_source, ProtocolPath)

        if self.final_value_source.start_protocol not in schemas_by_id:

            raise ValueError(
                f"The value source {self.final_value_source} does not exist.")

        protocol_schema = schemas_by_id[self.final_value_source.start_protocol]
        protocol_object = protocol_schema.to_protocol()
        protocol_object.get_value(self.final_value_source)

        attribute_type = protocol_object.get_class_attribute(
            self.final_value_source).type_hint

        assert is_type_subclass_of_type(attribute_type, Observable)
Exemple #3
0
    def _validate_gradients(self, schemas_by_id):

        if self.gradients_sources == UNDEFINED:
            return

        assert all(isinstance(x, ProtocolPath) for x in self.gradients_sources)

        for gradient_source in self.gradients_sources:

            if gradient_source.start_protocol not in schemas_by_id:

                raise ValueError(
                    f"The gradient source {gradient_source} does not exist.")

            protocol_schema = schemas_by_id[gradient_source.start_protocol]

            protocol_object = protocol_schema.to_protocol()
            protocol_object.get_value(gradient_source)

            attribute_type = protocol_object.get_class_attribute(
                gradient_source).type_hint

            assert is_type_subclass_of_type(attribute_type, ParameterGradient)
def test_negative_is_type_subclass_of_type(type_a, type_b):
    """A negative test of the `is_type_subclass_of_type` method."""
    assert not is_type_subclass_of_type(type_a, type_b)
def test_positive_is_type_subclass_of_type(type_a, type_b):
    """A positive test of the `is_type_subclass_of_type` method."""
    assert is_type_subclass_of_type(type_a, type_b)
Exemple #6
0
    def _validate_interfaces(self, schemas_by_id):
        """Validates the flow of the data between protocols, ensuring
        that inputs and outputs correctly match up.
        """

        for protocol_schema in schemas_by_id.values():

            protocol_object = protocol_schema.to_protocol()

            for input_path in protocol_object.required_inputs:

                input_value = protocol_object.get_value(input_path)
                input_attribute = protocol_object.get_class_attribute(
                    input_path)

                if not isinstance(input_attribute, InputAttribute):
                    continue

                is_optional = input_attribute.optional

                if input_value == UNDEFINED and is_optional is False:

                    raise ValueError(
                        f"The {input_path} required input of protocol "
                        f"{protocol_schema.id} was not set.")

            for input_path in protocol_object.required_inputs:

                value_references = protocol_object.get_value_references(
                    input_path)

                for source_path, value_reference in value_references.items():

                    if value_reference.is_global:
                        # We handle global input validation separately
                        continue

                    value_reference = self._get_unreplicated_path(
                        value_reference)

                    # Make sure the other protocol whose output we are interested
                    # in actually exists.
                    if (value_reference.start_protocol not in schemas_by_id
                            and value_reference.start_protocol !=
                            protocol_object.id):

                        raise ValueError(
                            f"The {protocol_object.id} protocol tries to take input "
                            f"from a non-existent protocol: {value_reference.full_path}"
                        )

                    if value_reference.start_protocol != protocol_object.id:

                        other_protocol_schema = schemas_by_id[
                            value_reference.start_protocol]
                        other_protocol_object = other_protocol_schema.to_protocol(
                        )

                    else:
                        other_protocol_object = protocol_object

                    unnested_value_reference = self._get_unnested_protocol_path(
                        value_reference)
                    unnested_source_path = self._get_unnested_protocol_path(
                        source_path)

                    # Make sure the other protocol has the output referenced
                    # by this input.
                    other_protocol_object.get_value(unnested_value_reference)

                    # Do a very rudimentary type check between the input and
                    # output types. This is not currently possible for nested
                    # or indexed properties, or outputs of replicated protocols.
                    if (value_reference.full_path !=
                            unnested_value_reference.full_path
                            or source_path.full_path !=
                            unnested_source_path.full_path):

                        continue

                    is_replicated_reference = False
                    protocol_replicators = self.protocol_replicators

                    if protocol_replicators == UNDEFINED:
                        protocol_replicators = []

                    for replicator in protocol_replicators:

                        if (replicator.placeholder_id in protocol_schema.id
                                and replicator.placeholder_id
                                in value_reference.protocol_path) or (
                                    replicator.placeholder_id
                                    not in protocol_schema.id
                                    and replicator.placeholder_id
                                    not in value_reference.protocol_path):

                            continue

                        is_replicated_reference = True
                        break

                    if is_replicated_reference:
                        continue

                    expected_input_type = protocol_object.get_class_attribute(
                        unnested_source_path).type_hint
                    expected_output_type = other_protocol_object.get_class_attribute(
                        unnested_value_reference).type_hint

                    if expected_input_type is None or expected_output_type is None:
                        continue

                    if not is_type_subclass_of_type(expected_output_type,
                                                    expected_input_type):

                        raise ValueError(
                            f"The output type ({expected_output_type}) of "
                            f"{value_reference} does not match the requested "
                            f"input type ({expected_input_type}) of {source_path}."
                        )