def decode_union_old(self, data_type, obj): """ The data_type argument must be a Union. See json_compat_obj_decode() for argument descriptions. """ val = None if isinstance(obj, six.string_types): # Union member has no associated value tag = obj if data_type.definition._is_tag_present(tag, self.caller_permissions): val_data_type = data_type.definition._get_val_data_type(tag, self.caller_permissions) if not isinstance(val_data_type, (bv.Void, bv.Nullable)): raise bv.ValidationError( "expected object for '%s', got symbol" % tag) else: if not self.strict and data_type.definition._catch_all: tag = data_type.definition._catch_all else: raise bv.ValidationError("unknown tag '%s'" % tag) elif isinstance(obj, dict): # Union member has value if len(obj) != 1: raise bv.ValidationError('expected 1 key, got %s' % len(obj)) tag = list(obj)[0] raw_val = obj[tag] if data_type.definition._is_tag_present(tag, self.caller_permissions): val_data_type = data_type.definition._get_val_data_type(tag, self.caller_permissions) if isinstance(val_data_type, bv.Nullable) and raw_val is None: val = None elif isinstance(val_data_type, bv.Void): if raw_val is None or not self.strict: # If raw_val is None, then this is the more verbose # representation of a void union member. If raw_val isn't # None, then maybe the spec has changed, so check if we're # in strict mode. val = None else: raise bv.ValidationError('expected null, got %s' % bv.generic_type_name(raw_val)) else: try: val = self.json_compat_obj_decode_helper(val_data_type, raw_val) except bv.ValidationError as e: e.add_parent(tag) raise else: if not self.strict and data_type.definition._catch_all: tag = data_type.definition._catch_all else: raise bv.ValidationError("unknown tag '%s'" % tag) else: raise bv.ValidationError("expected string or object, got %s" % bv.generic_type_name(obj)) return data_type.definition(tag, val)
def decode_union(self, data_type, obj): """ The data_type argument must be a Union. See json_compat_obj_decode() for argument descriptions. """ val = None if isinstance(obj, six.string_types): # Handles the shorthand format where the union is serialized as only # the string of the tag. tag = obj if data_type.definition._is_tag_present(tag, self.caller_permissions): val_data_type = data_type.definition._get_val_data_type( tag, self.caller_permissions) if not isinstance(val_data_type, (bv.Void, bv.Nullable)): raise bv.ValidationError( "expected object for '%s', got symbol" % tag) if tag == data_type.definition._catch_all: raise bv.ValidationError( "unexpected use of the catch-all tag '%s'" % tag) elif not self.strict and data_type.definition._catch_all: tag = data_type.definition._catch_all else: raise bv.ValidationError("unknown tag '%s'" % tag) elif isinstance(obj, dict): tag, val = self.decode_union_dict(data_type, obj) else: raise bv.ValidationError("expected string or object, got %s" % bv.generic_type_name(obj)) return data_type.definition(tag, val)
def decode_struct(self, data_type, obj): """ The data_type argument must be a Struct. See json_compat_obj_decode() for argument descriptions. """ if obj is None and data_type.has_default(): return data_type.get_default() elif not isinstance(obj, dict): raise bv.ValidationError('expected object, got %s' % bv.generic_type_name(obj)) all_fields = data_type.definition._all_fields_ for extra_permission in self.caller_permissions.permissions: all_extra_fields = '_all_{}_fields_'.format(extra_permission) all_fields = all_fields + getattr(data_type.definition, all_extra_fields, []) if self.strict: all_field_names = data_type.definition._all_field_names_ for extra_permission in self.caller_permissions.permissions: all_extra_field_names = '_all_{}_field_names_'.format( extra_permission) all_field_names = all_field_names.union( getattr(data_type.definition, all_extra_field_names, {})) for key in obj: if (key not in all_field_names and not key.startswith('.tag')): raise bv.ValidationError("unknown field '%s'" % key) ins = data_type.definition() self.decode_struct_fields(ins, all_fields, obj) # Check that all required fields have been set. data_type.validate_fields_only_with_permissions( ins, self.caller_permissions) return ins
def determine_struct_tree_subtype(self, data_type, obj): """ Searches through the JSON-object-compatible dict using the data type definition to determine which of the enumerated subtypes `obj` is. """ if '.tag' not in obj: raise bv.ValidationError("missing '.tag' key") if not isinstance(obj['.tag'], six.string_types): raise bv.ValidationError('expected string, got %s' % bv.generic_type_name(obj['.tag']), parent='.tag') # Find the subtype the tags refer to full_tags_tuple = (obj['.tag'],) if full_tags_tuple in data_type.definition._tag_to_subtype_: subtype = data_type.definition._tag_to_subtype_[full_tags_tuple] if isinstance(subtype, bv.StructTree): raise bv.ValidationError("tag '%s' refers to non-leaf subtype" % ('.'.join(full_tags_tuple))) return subtype else: if self.strict: # In strict mode, the entirety of the tag hierarchy should # point to a known subtype. raise bv.ValidationError("unknown subtype '%s'" % '.'.join(full_tags_tuple)) else: # If subtype was not found, use the base. if data_type.definition._is_catch_all_: return data_type else: raise bv.ValidationError( "unknown subtype '%s' and '%s' is not a catch-all" % ('.'.join(full_tags_tuple), data_type.definition.__name__))
def _decode_union(data_type, obj, alias_validators, strict, for_msgpack): """ The data_type argument must be a Union. See json_compat_obj_decode() for argument descriptions. """ val = None if isinstance(obj, six.string_types): # Handles the shorthand format where the union is serialized as only # the string of the tag. tag = obj if tag in data_type.definition._tagmap: val_data_type = data_type.definition._tagmap[tag] if not isinstance(val_data_type, (bv.Void, bv.Nullable)): raise bv.ValidationError( "expected object for '%s', got symbol" % tag) if tag == data_type.definition._catch_all: raise bv.ValidationError( "unexpected use of the catch-all tag '%s'" % tag) else: if not strict and data_type.definition._catch_all: tag = data_type.definition._catch_all else: raise bv.ValidationError("unknown tag '%s'" % tag) elif isinstance(obj, dict): tag, val = _decode_union_dict(data_type, obj, alias_validators, strict, for_msgpack) else: raise bv.ValidationError("expected string or object, got %s" % bv.generic_type_name(obj)) return data_type.definition(tag, val)
def decode_union(self, data_type, obj): """ The data_type argument must be a Union. See json_compat_obj_decode() for argument descriptions. """ val = None if isinstance(obj, six.string_types): # Handles the shorthand format where the union is serialized as only # the string of the tag. tag = obj if data_type.definition._is_tag_present(tag, self.caller_permissions): val_data_type = data_type.definition._get_val_data_type( tag, self.caller_permissions) if not isinstance(val_data_type, (bv.Void, bv.Nullable)): raise bv.ValidationError( "expected object for '%s', got symbol" % tag) if tag == data_type.definition._catch_all: raise bv.ValidationError( "unexpected use of the catch-all tag '%s'" % tag) elif not self.strict and data_type.definition._catch_all: tag = data_type.definition._catch_all else: raise bv.ValidationError("unknown tag '%s'" % tag) elif isinstance(obj, dict): tag, val = self.decode_union_dict( data_type, obj) else: raise bv.ValidationError("expected string or object, got %s" % bv.generic_type_name(obj)) return data_type.definition(tag, val)
def _decode_union(data_type, obj, alias_validators, strict, for_msgpack): """ The data_type argument must be a Union. See json_compat_obj_decode() for argument descriptions. """ val = None if isinstance(obj, six.string_types): # Handles the shorthand format where the union is serialized as only # the string of the tag. tag = obj if tag in data_type.definition._tagmap: val_data_type = data_type.definition._tagmap[tag] if not isinstance(val_data_type, (bv.Void, bv.Nullable)): raise bv.ValidationError( "expected object for '%s', got symbol" % tag) if tag == data_type.definition._catch_all: raise bv.ValidationError( "unexpected use of the catch-all tag '%s'" % tag) else: if not strict and data_type.definition._catch_all: tag = data_type.definition._catch_all else: raise bv.ValidationError("unknown tag '%s'" % tag) elif isinstance(obj, dict): tag, val = _decode_union_dict( data_type, obj, alias_validators, strict, for_msgpack) else: raise bv.ValidationError("expected string or object, got %s" % bv.generic_type_name(obj)) return data_type.definition(tag, val)
def decode_struct(self, data_type, obj): """ The data_type argument must be a Struct. See json_compat_obj_decode() for argument descriptions. """ if obj is None and data_type.has_default(): return data_type.get_default() elif not isinstance(obj, dict): raise bv.ValidationError('expected object, got %s' % bv.generic_type_name(obj)) all_fields = data_type.definition._all_fields_ for extra_permission in self.caller_permissions.permissions: all_extra_fields = '_all_{}_fields_'.format(extra_permission) all_fields = all_fields + getattr(data_type.definition, all_extra_fields, []) if self.strict: all_field_names = data_type.definition._all_field_names_ for extra_permission in self.caller_permissions.permissions: all_extra_field_names = '_all_{}_field_names_'.format(extra_permission) all_field_names = all_field_names.union( getattr(data_type.definition, all_extra_field_names, {})) for key in obj: if (key not in all_field_names and not key.startswith('.tag')): raise bv.ValidationError("unknown field '%s'" % key) ins = data_type.definition() self.decode_struct_fields(ins, all_fields, obj) # Check that all required fields have been set. data_type.validate_fields_only_with_permissions(ins, self.caller_permissions) return ins
def decode_list(self, data_type, obj): """ The data_type argument must be a List. See json_compat_obj_decode() for argument descriptions. """ if not isinstance(obj, list): raise bv.ValidationError( 'expected list, got %s' % bv.generic_type_name(obj)) return [ self.json_compat_obj_decode_helper(data_type.item_validator, item) for item in obj]
def decode_map(self, data_type, obj): """ The data_type argument must be a Map. See json_compat_obj_decode() for argument descriptions. """ if not isinstance(obj, dict): raise bv.ValidationError( 'expected dict, got %s' % bv.generic_type_name(obj)) return { self.json_compat_obj_decode_helper(data_type.key_validator, key): self.json_compat_obj_decode_helper(data_type.value_validator, value) for key, value in obj.items() }
def _decode_list( data_type, obj, alias_validators, strict, old_style, for_msgpack): """ The data_type argument must be a List. See json_compat_obj_decode() for argument descriptions. """ if not isinstance(obj, list): raise bv.ValidationError( 'expected list, got %s' % bv.generic_type_name(obj)) return [ _json_compat_obj_decode_helper( data_type.item_validator, item, alias_validators, strict, old_style, for_msgpack) for item in obj]
def _decode_map( data_type, obj, alias_validators, strict, old_style, for_msgpack): """ The data_type argument must be a Map. See json_compat_obj_decode() for argument descriptions. """ if not isinstance(obj, dict): raise bv.ValidationError( 'expected dict, got %s' % bv.generic_type_name(obj)) result = {} for key, value in obj.items(): result[_json_compat_obj_decode_helper(data_type.key_validator, key, alias_validators, strict,old_style, for_msgpack)] = _json_compat_obj_decode_helper(data_type.value_validator, value, alias_validators, strict,old_style, for_msgpack) return result
def _decode_map(data_type, obj, alias_validators, strict, old_style, for_msgpack): """ The data_type argument must be a Map. See json_compat_obj_decode() for argument descriptions. """ if not isinstance(obj, dict): raise bv.ValidationError('expected dict, got %s' % bv.generic_type_name(obj)) return { _json_compat_obj_decode_helper(data_type.key_validator, key, alias_validators, strict, old_style, for_msgpack): _json_compat_obj_decode_helper(data_type.value_validator, value, alias_validators, strict, old_style, for_msgpack) for key, value in obj.items() }
def _decode_struct(data_type, obj, alias_validators, strict, old_style, for_msgpack): """ The data_type argument must be a Struct. See json_compat_obj_decode() for argument descriptions. """ if obj is None and data_type.has_default(): return data_type.get_default() elif not isinstance(obj, dict): raise bv.ValidationError('expected object, got %s' % bv.generic_type_name(obj)) if strict: for key in obj: if (key not in data_type.definition._all_field_names_ and not key.startswith('.tag')): raise bv.ValidationError("unknown field '%s'" % key) ins = data_type.definition() _decode_struct_fields(ins, data_type.definition._all_fields_, obj, alias_validators, strict, old_style, for_msgpack) # Check that all required fields have been set. data_type.validate_fields_only(ins) return ins
def _decode_struct( data_type, obj, alias_validators, strict, old_style, for_msgpack): """ The data_type argument must be a Struct. See json_compat_obj_decode() for argument descriptions. """ if obj is None and data_type.has_default(): return data_type.get_default() elif not isinstance(obj, dict): raise bv.ValidationError('expected object, got %s' % bv.generic_type_name(obj)) if strict: for key in obj: if (key not in data_type.definition._all_field_names_ and not key.startswith('.tag')): raise bv.ValidationError("unknown field '%s'" % key) ins = data_type.definition() _decode_struct_fields( ins, data_type.definition._all_fields_, obj, alias_validators, strict, old_style, for_msgpack) # Check that all required fields have been set. data_type.validate_fields_only(ins) return ins
def decode_union_dict(self, data_type, obj): if '.tag' not in obj: raise bv.ValidationError("missing '.tag' key") tag = obj['.tag'] if not isinstance(tag, six.string_types): raise bv.ValidationError('tag must be string, got %s' % bv.generic_type_name(tag)) if not data_type.definition._is_tag_present(tag, self.caller_permissions): if not self.strict and data_type.definition._catch_all: return data_type.definition._catch_all, None else: raise bv.ValidationError("unknown tag '%s'" % tag) if tag == data_type.definition._catch_all: raise bv.ValidationError( "unexpected use of the catch-all tag '%s'" % tag) val_data_type = data_type.definition._get_val_data_type( tag, self.caller_permissions) if isinstance(val_data_type, bv.Nullable): val_data_type = val_data_type.validator nullable = True else: nullable = False if isinstance(val_data_type, bv.Void): if self.strict: # In strict mode, ensure there are no extraneous keys set. In # non-strict mode, we accept that other keys may be set due to a # change of the void type to another. if tag in obj: if obj[tag] is not None: raise bv.ValidationError( 'expected null, got %s' % bv.generic_type_name(obj[tag])) for key in obj: if key != tag and key != '.tag': raise bv.ValidationError("unexpected key '%s'" % key) val = None elif isinstance( val_data_type, (bv.Primitive, bv.List, bv.StructTree, bv.Union, bv.Map)): if tag in obj: raw_val = obj[tag] try: val = self.json_compat_obj_decode_helper( val_data_type, raw_val) except bv.ValidationError as e: e.add_parent(tag) raise else: # Check no other keys if nullable: val = None else: raise bv.ValidationError("missing '%s' key" % tag) for key in obj: if key != tag and key != '.tag': raise bv.ValidationError("unexpected key '%s'" % key) elif isinstance(val_data_type, bv.Struct): if nullable and len(obj) == 1: # only has a .tag key val = None else: # assume it's not null raw_val = obj try: val = self.json_compat_obj_decode_helper( val_data_type, raw_val) except bv.ValidationError as e: e.add_parent(tag) raise else: assert False, type(val_data_type) return tag, val
def _decode_union_dict(data_type, obj, alias_validators, strict, for_msgpack): if '.tag' not in obj: raise bv.ValidationError("missing '.tag' key") tag = obj['.tag'] if not isinstance(tag, six.string_types): raise bv.ValidationError( 'tag must be string, got %s' % bv.generic_type_name(tag)) if tag not in data_type.definition._tagmap: if not strict and data_type.definition._catch_all: return data_type.definition._catch_all, None else: raise bv.ValidationError("unknown tag '%s'" % tag) if tag == data_type.definition._catch_all: raise bv.ValidationError( "unexpected use of the catch-all tag '%s'" % tag) val_data_type = data_type.definition._tagmap[tag] if isinstance(val_data_type, bv.Nullable): val_data_type = val_data_type.validator nullable = True else: nullable = False if isinstance(val_data_type, bv.Void): if tag in obj: if obj[tag] is not None: raise bv.ValidationError('expected null, got %s' % bv.generic_type_name(obj[tag])) for key in obj: if key != tag and key != '.tag': raise bv.ValidationError("unexpected key '%s'" % key) val = None elif isinstance(val_data_type, (bv.Primitive, bv.List, bv.StructTree, bv.Union)): if tag in obj: raw_val = obj[tag] try: val = _json_compat_obj_decode_helper( val_data_type, raw_val, alias_validators, strict, False, for_msgpack) except bv.ValidationError as e: e.add_parent(tag) raise else: # Check no other keys if nullable: val = None else: raise bv.ValidationError("missing '%s' key" % tag) for key in obj: if key != tag and key != '.tag': raise bv.ValidationError("unexpected key '%s'" % key) elif isinstance(val_data_type, bv.Struct): if nullable and len(obj) == 1: # only has a .tag key val = None else: # assume it's not null raw_val = obj try: val = _json_compat_obj_decode_helper( val_data_type, raw_val, alias_validators, strict, False, for_msgpack) except bv.ValidationError as e: e.add_parent(tag) raise else: assert False, type(val_data_type) return tag, val
def decode_union_dict(self, data_type, obj): if '.tag' not in obj: raise bv.ValidationError("missing '.tag' key") tag = obj['.tag'] if not isinstance(tag, six.string_types): raise bv.ValidationError( 'tag must be string, got %s' % bv.generic_type_name(tag)) if not data_type.definition._is_tag_present(tag, self.caller_permissions): if not self.strict and data_type.definition._catch_all: return data_type.definition._catch_all, None else: raise bv.ValidationError("unknown tag '%s'" % tag) if tag == data_type.definition._catch_all: raise bv.ValidationError( "unexpected use of the catch-all tag '%s'" % tag) val_data_type = data_type.definition._get_val_data_type(tag, self.caller_permissions) if isinstance(val_data_type, bv.Nullable): val_data_type = val_data_type.validator nullable = True else: nullable = False if isinstance(val_data_type, bv.Void): if self.strict: # In strict mode, ensure there are no extraneous keys set. In # non-strict mode, we accept that other keys may be set due to a # change of the void type to another. if tag in obj: if obj[tag] is not None: raise bv.ValidationError('expected null, got %s' % bv.generic_type_name(obj[tag])) for key in obj: if key != tag and key != '.tag': raise bv.ValidationError("unexpected key '%s'" % key) val = None elif isinstance(val_data_type, (bv.Primitive, bv.List, bv.StructTree, bv.Union, bv.Map)): if tag in obj: raw_val = obj[tag] try: val = self.json_compat_obj_decode_helper(val_data_type, raw_val) except bv.ValidationError as e: e.add_parent(tag) raise else: # Check no other keys if nullable: val = None else: raise bv.ValidationError("missing '%s' key" % tag) for key in obj: if key != tag and key != '.tag': raise bv.ValidationError("unexpected key '%s'" % key) elif isinstance(val_data_type, bv.Struct): if nullable and len(obj) == 1: # only has a .tag key val = None else: # assume it's not null raw_val = obj try: val = self.json_compat_obj_decode_helper(val_data_type, raw_val) except bv.ValidationError as e: e.add_parent(tag) raise else: assert False, type(val_data_type) return tag, val