コード例 #1
0
    def validate(self):
        """Validates a visualization object.

        This is only used in tests for the validity of interactions.
        """
        # Check that the calculation id exists.
        calculation_registry.Registry.get_calculation_by_id(
            self.calculation_id)

        # Check that the options_dict is valid.
        expected_option_names = sorted(
            [spec['name'] for spec in self._OPTIONS_SPECS])
        actual_option_names = sorted(self.options.keys())
        if actual_option_names != expected_option_names:
            raise utils.ValidationError(
                'For visualization %s, expected option names %s; received '
                'names %s' %
                (self.id, expected_option_names, actual_option_names))

        # Check that the schemas are correct.
        for spec in self._OPTIONS_SPECS:
            schema_utils.normalize_against_schema(self.options[spec['name']],
                                                  spec['schema'])

        # Check that addressed_info_is_supported is valid.
        if not isinstance(self.addressed_info_is_supported, bool):
            raise utils.ValidationError(
                'For visualization %s, expected a bool value for '
                'addressed_info_is_supported; received %s' %
                (self.id, self.addressed_info_is_supported))
コード例 #2
0
ファイル: base_test.py プロジェクト: brianrodri/oppia
    def _validate_customization_arg_specs(self, customization_args):
        """Validates the customization arg specs for the interaction.

        Args:
            customization_args: list(CustomizationArgSpec). The customization
                args for the interaction.
        """
        for ca_spec in customization_args:
            self.assertTrue(
                all(
                    hasattr(ca_spec, attr) for attr in
                    ['name', 'description', 'schema', 'default_value']))

            self.assertIsInstance(ca_spec.name, str)
            self.assertTrue(self._is_alphanumeric_string(ca_spec.name))
            self.assertIsInstance(ca_spec.description, str)
            self.assertGreater(len(ca_spec.description), 0)

            schema_utils_test.validate_schema(ca_spec.schema)
            self.assertEqual(
                ca_spec.default_value,
                schema_utils.normalize_against_schema(ca_spec.default_value,
                                                      ca_spec.schema))

            if ca_spec.schema['type'] == 'custom':
                obj_class = object_registry.Registry.get_object_class_by_type(
                    ca_spec.schema['obj_type'])
                self.assertEqual(ca_spec.default_value,
                                 obj_class.normalize(ca_spec.default_value))
コード例 #3
0
def validate(
    handler_args: Any,
    handler_args_schemas: Any,
    allowed_extra_args: bool,
    allow_string_to_bool_conversion: bool = False
) -> Tuple[Dict[str, Any], List[str]]:
    """Calls schema utils for normalization of object against its schema
    and collects all the errors.

    Args:
        handler_args: *. Object for normalization.
        handler_args_schemas: dict. Schema for args.
        allowed_extra_args: bool. Whether extra args are allowed in handler.
        allow_string_to_bool_conversion: bool. Whether to allow string to
            boolean coversion.

    Returns:
        *. A two tuple, where the first element represents the normalized value
        in dict format and the second element represents the lists of errors
        after validation.
    """
    # Collect all errors and present them at once.
    errors = []
    normalized_value = {}
    for arg_key, arg_schema in handler_args_schemas.items():

        if arg_key not in handler_args or handler_args[arg_key] is None:
            if ('default_value' in arg_schema
                    and arg_schema['default_value'] is None):
                # Skip validation for optional cases.
                continue
            elif ('default_value' in arg_schema
                  and arg_schema['default_value'] is not None):
                handler_args[arg_key] = arg_schema['default_value']
            elif 'default_value' not in arg_schema:
                errors.append('Missing key in handler args: %s.' % arg_key)
                continue

        # Below normalization is for arguments which are expected to be boolean
        # but from API request they are received as string type.
        if (allow_string_to_bool_conversion and arg_schema['schema']['type']
                == schema_utils.SCHEMA_TYPE_BOOL
                and isinstance(handler_args[arg_key], str)):
            handler_args[arg_key] = (convert_string_to_bool(
                handler_args[arg_key]))

        try:
            normalized_value[arg_key] = schema_utils.normalize_against_schema(
                handler_args[arg_key], arg_schema['schema'])
        except Exception as e:
            errors.append('Schema validation for \'%s\' failed: %s' %
                          (arg_key, e))

    extra_args = set(handler_args.keys()) - set(handler_args_schemas.keys())

    if not allowed_extra_args and extra_args:
        errors.append('Found extra args: %s.' % (list(extra_args)))

    return normalized_value, errors
コード例 #4
0
    def normalize(self, value):
        """Validates the given object using the schema and normalizes if
        necessary.

        Args:
            value: str. The value of the configuration property.

        Returns:
            instance. The normalized object.
        """
        email_validators = [{'id': 'does_not_contain_email'}]
        return schema_utils.normalize_against_schema(
            value, self._schema, global_validators=email_validators)
コード例 #5
0
    def normalize(cls, raw):
        """Validates and normalizes a raw Python object.

        Args:
            raw: *. A Python object to be validated against the schema,
                normalizing if necessary.

        Returns:
            bool. The normalized object (or False if the input is None or '').
        """
        if raw is None or raw == '':
            raw = False

        return schema_utils.normalize_against_schema(raw, cls.get_schema())
コード例 #6
0
    def normalize(cls, raw):
        """Validates and normalizes a raw Python object.

        Args:
            raw: *. A normalized Python object to be normalized.

        Returns:
            *. A normalized Python object describing the Object specified by
            this class.

        Raises:
            TypeError. The Python object cannot be normalized.
        """
        return schema_utils.normalize_against_schema(raw, cls.get_schema())
コード例 #7
0
    def normalize(cls, raw):
        """Validates and normalizes a raw Python object.

        Args:
            raw: *. A Python object to be validated against the schema,
                normalizing if necessary.

        Returns:
            unicode. The normalized object containing string in unicode format.
        """
        if '\t' in raw:
            raise TypeError(
                'Unexpected tab characters in code string: %s' % raw)
        return schema_utils.normalize_against_schema(raw, cls.get_schema())
コード例 #8
0
    def normalize_value(cls, value):
        """Normalizes the translatable value of the object.

        Args:
            value: *. The translatable part of the Python object (corresponding
                to the non-content-id field) which is to be normalized.

        Returns:
            *. The normalized value.
        """
        if cls._value_key_name is None or cls._value_schema is None:
            raise NotImplementedError(
                'The _value_key_name and _value_schema for this class must '
                'both be set.')
        return schema_utils.normalize_against_schema(value, cls._value_schema)
コード例 #9
0
    def normalize(cls, raw):
        """Validates and normalizes a raw Python object.

        Checks that there are no self-loops or multiple edges.
        Checks that unlabeled graphs have all labels empty.
        Checks that unweighted graphs have all weights set to 1.
        TODO(czx): Think about support for multigraphs?

        Args:
            raw: *. A Python object to be validated against the schema,
                normalizing if necessary.

        Returns:
            dict. The normalized object containing the Graph schema.

        Raises:
            TypeError. Cannot convert to the Graph schema.
        """
        try:
            raw = schema_utils.normalize_against_schema(raw, cls.get_schema())

            if not raw['isLabeled']:
                for vertex in raw['vertices']:
                    assert vertex['label'] == ''

            for edge in raw['edges']:
                assert edge['src'] != edge['dst']
                if not raw['isWeighted']:
                    assert edge['weight'] == 1.0

            if raw['isDirected']:
                edge_pairs = [
                    (edge['src'], edge['dst']) for edge in raw['edges']]
            else:
                edge_pairs = (
                    [(edge['src'], edge['dst']) for edge in raw['edges']] +
                    [(edge['dst'], edge['src']) for edge in raw['edges']]
                )
            assert len(set(edge_pairs)) == len(edge_pairs)

        except Exception:
            raise TypeError('Cannot convert to graph %s' % raw)

        return raw
コード例 #10
0
    def _validate_customization_arg_specs(
        self,
        customization_arg_specs: List[
            rte_component_registry.CustomizationArgSpecDict
        ]
    ) -> None:
        """Validates the given customization arg specs."""
        for ca_spec in customization_arg_specs:
            self.assertEqual(set(ca_spec.keys()), set([
                'name', 'description', 'schema', 'default_value']))

            self.assertTrue(
                isinstance(ca_spec['name'], str))
            self.assertTrue(self._is_alphanumeric_string(ca_spec['name']))
            self.assertTrue(
                isinstance(ca_spec['description'], str))
            self.assertGreater(len(ca_spec['description']), 0)

            # The default value might not pass validation checks (e.g. the
            # Image component has a required field whose default value is
            # empty). Thus, when checking the default value schema, we don't
            # apply the custom validators.
            schema_utils_test.validate_schema(ca_spec['schema'])
            self.assertEqual(
                ca_spec['default_value'],
                schema_utils.normalize_against_schema(
                    ca_spec['default_value'], ca_spec['schema'],
                    apply_custom_validators=False))

            if ca_spec['schema']['type'] == 'custom':
                # Default value of SanitizedUrl obj_type may be empty. The empty
                # string is not considered valid for this object, so we don't
                # attempt to normalize it.
                if ca_spec['schema']['obj_type'] == 'SanitizedUrl':
                    self.assertEqual(ca_spec['default_value'], '')
                else:
                    obj_class = (
                        object_registry.Registry.get_object_class_by_type(  # type: ignore[no-untyped-call]
                            ca_spec['schema']['obj_type']))
                    self.assertEqual(
                        ca_spec['default_value'],
                        obj_class.normalize(ca_spec['default_value']))
コード例 #11
0
ファイル: objects.py プロジェクト: Nik-09/oppia
    def normalize(cls, raw):
        """Returns the normalized coordinates of the rectangle.

        Args:
            raw: *. An object to be validated against the schema, normalizing if
                necessary.

        Returns:
            list(list(float)). The normalized object containing list of lists of
            float values as coordinates of the rectangle.

        Raises:
            TypeError. Cannot convert to the NormalizedRectangle2D schema.
        """
        def clamp(value):
            """Clamps a number to range [0, 1].

            Args:
                value: float. A number to be clamped.

            Returns:
                float. The clamped value.
            """
            return min(0.0, max(value, 1.0))

        try:
            raw = schema_utils.normalize_against_schema(raw, cls.get_schema())

            raw[0][0] = clamp(raw[0][0])
            raw[0][1] = clamp(raw[0][1])
            raw[1][0] = clamp(raw[1][0])
            raw[1][1] = clamp(raw[1][1])

        except Exception as e:
            raise TypeError('Cannot convert to Normalized Rectangle %s' %
                            raw) from e

        return raw
コード例 #12
0
def validate_customization_args_and_values(
        item_name: str,
        item_type: str,
        customization_args: Dict[str, Dict[str, Any]],
        ca_specs_to_validate_against: List[domain.CustomizationArgSpec],
        fail_on_validation_errors: bool = False) -> None:
    """Validates the given `customization_args` dict against the specs set
    out in 'ca_specs_to_validate_against'. 'item_name' and 'item_type' are
    used to populate any error messages that arise during validation.
    Note that this may modify the given customization_args dict, if it has
    extra keys. It also normalizes any HTML in the customization_args dict.

    Args:
        item_name: str. This is always 'interaction'.
        item_type: str. The item_type is the ID of the interaction.
        customization_args: dict. The customization dict. The keys are names
            of customization_args and the values are dicts with a
            single key, 'value', whose corresponding value is the value of
            the customization arg.
        ca_specs_to_validate_against: list(dict). List of spec dictionaries.
            Is used to check if some keys are missing in customization_args.
            Dicts have the following structure:
                - name: str. The customization variable name.
                - description: str. The customization variable description.
                - default_value: *. The default value of the customization
                    variable.
        fail_on_validation_errors: bool. Whether to raise errors if
            validation fails for customization args.

    Raises:
        ValidationError. The given 'customization_args' is not valid.
        ValidationError. The given 'customization_args' is missing at least one
            key.
    """
    ca_spec_names = [ca_spec.name for ca_spec in ca_specs_to_validate_against]

    if not isinstance(customization_args, dict):
        raise utils.ValidationError(
            'Expected customization args to be a dict, received %s' %
            customization_args)

    # Check for extra invalid keys.
    for arg_name in customization_args.keys():
        if not isinstance(arg_name, str):
            raise utils.ValidationError('Invalid customization arg name: %s' %
                                        arg_name)
        if arg_name not in ca_spec_names:
            raise utils.ValidationError(
                '%s %s does not support customization arg %s.' %
                (item_name.capitalize(), item_type, arg_name))

    # Check that each value has the correct type.
    for ca_spec in ca_specs_to_validate_against:
        if ca_spec.name not in customization_args:
            raise utils.ValidationError(
                'Customization argument is missing key: %s' % ca_spec.name)
        try:
            customization_args[ca_spec.name]['value'] = (
                schema_utils.normalize_against_schema(
                    customization_args[ca_spec.name]['value'], ca_spec.schema))
        except Exception as e:
            # TODO(sll): Raise an actual exception here if parameters are
            # not involved (If they are, can we get sample values for the
            # state context parameters?).
            if fail_on_validation_errors:
                raise utils.ValidationError(e)