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))
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))
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
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)
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())
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())
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())
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)
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
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']))
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
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)