def format(self, value): try: if value is None: return text_type(utils.float_to_decimal(float(self.default))) return text_type(utils.float_to_decimal(float(value))) except ValueError as ve: raise MarshallingError(ve)
def __init__(self, choices, labels=None, error=None): self.choices = choices self.choices_text = ', '.join( text_type(choice) for choice in self.choices) self.labels = labels if labels is not None else [] self.labels_text = ', '.join(text_type(label) for label in self.labels) self.error = error or self.default_message
def _validated(self, value): """Format ``value`` or raise ``exception_class`` if an error occurs.""" try: if value is None: return self.default return text_type(utils.float_to_decimal(float(value))) except ValueError as ve: raise ValidationError(text_type(ve))
def _serialize(self, value, attr, obj): if isinstance(value, text_type) or value is None: return value elif isinstance(value, binary_type): for codec in self.codecs: try: return text_type(value, codec) except UnicodeDecodeError: pass raise ValueError("Could not decode {value} to unicode" " with the given codecs: {codecs}".format( value=value, codecs=self.codecs)) else: return text_type(value)
def marshal(self, data, fields_dict, many=False): """Takes raw data (a dict, list, or other object) and a dict of fields to output and filters the data based on those fields. :param data: The actual object(s) from which the fields are taken from :param dict fields: A dict whose keys will make up the final serialized response output. :param bool many: Set to ``True`` if ``data`` is a collection object that is iterable. :returns: An OrderedDict of the marshalled data """ if many and data is not None: return [self.marshal(d, fields_dict, many=False) for d in data] items = [] for attr_name, field_obj in iteritems(fields_dict): key = self.prefix + attr_name try: item = (key, field_obj.output(attr_name, data)) except MarshallingError as err: # Store errors if self.strict: raise err self.errors[key] = text_type(err) item = (key, None) except TypeError: # field declared as a class, not an instance if isinstance(field_obj, type) and \ issubclass(field_obj, FieldABC): msg = ('Field for "{0}" must be declared as a ' "Field instance, not a class. " 'Did you mean "fields.{1}()"?'.format( attr_name, field_obj.__name__)) raise TypeError(msg) raise items.append(item) return OrderedDict(items)
def marshal(self, data, fields_dict, many=False): """Takes raw data (a dict, list, or other object) and a dict of fields to output and filters the data based on those fields. :param data: The actual object(s) from which the fields are taken from :param dict fields: A dict whose keys will make up the final serialized response output. :param bool many: Set to ``True`` if ``data`` is a collection object that is iterable. :returns: An OrderedDict of the marshalled data """ if many and data is not None: return [self.marshal(d, fields_dict, many=False) for d in data] items = [] for attr_name, field_obj in iteritems(fields_dict): key = self.prefix + attr_name try: item = (key, field_obj.output(attr_name, data)) except MarshallingError as err: # Store errors if self.strict: raise err self.errors[key] = text_type(err) item = (key, None) except TypeError: # field declared as a class, not an instance if isinstance(field_obj, type) and \ issubclass(field_obj, FieldABC): msg = ('Field for "{0}" must be declared as a ' "Field instance, not a class. " 'Did you mean "fields.{1}()"?' .format(attr_name, field_obj.__name__)) raise TypeError(msg) raise items.append(item) return OrderedDict(items)
def marshal(self, data, fields_dict): """Takes the data (a dict, list, or object) and a dict of fields. Stores any errors that occur. :param data: The actual object(s) from which the fields are taken from :param dict fields_dict: A dict whose keys will make up the final serialized response output """ if utils.is_collection(data): return [self.marshal(d, fields_dict) for d in data] items = [] for attr_name, field_obj in iteritems(fields_dict): key = self.prefix + attr_name try: if isinstance(field_obj, dict): item = (key, self.marshal(data, field_obj)) else: try: item = (key, field_obj.output(attr_name, data)) except TypeError: # field declared as a class, not an instance if issubclass(field_obj, base.FieldABC): msg = ('Field for "{0}" must be declared as a ' "Field instance, not a class. " 'Did you mean "fields.{1}()"?' .format(attr_name, field_obj.__name__)) raise TypeError(msg) raise except exceptions.MarshallingError as err: # Store errors if self.strict or self.opts.strict: raise err self.errors[key] = text_type(err) item = (key, None) items.append(item) return OrderedDict(items)
def run_validator(self, validator_func, output, original_data, fields_dict, index=None, many=False, pass_original=False): try: if pass_original: # Pass original, raw data (before unmarshalling) res = validator_func(output, original_data) else: res = validator_func(output) if res is False: raise ValidationError(self.default_schema_validation_error) except ValidationError as err: errors = self.get_errors(index=index) # Store or reraise errors if err.field_names: field_names = err.field_names field_objs = [fields_dict[each] if each in fields_dict else None for each in field_names] else: field_names = [SCHEMA] field_objs = [] self.error_field_names = field_names self.error_fields = field_objs for field_name in field_names: if isinstance(err.messages, (list, tuple)): # self.errors[field_name] may be a dict if schemas are nested if isinstance(errors.get(field_name), dict): errors[field_name].setdefault( SCHEMA, [] ).extend(err.messages) else: errors.setdefault(field_name, []).extend(err.messages) elif isinstance(err.messages, dict): errors.setdefault(field_name, []).append(err.messages) else: errors.setdefault(field_name, []).append(text_type(err))
def _validated(self, value): """Format the value or raise a :exc:`ValidationError` if an error occurs.""" try: return self._format_num(value) except (TypeError, ValueError) as err: raise ValidationError( getattr(self, 'error', None) or text_type(err))
def __init__(self, src_str, *args, **kwargs): warnings.warn( 'FormattedString is deprecated and will be removed in marshmallow 3. ' 'Use a Method or Function field instead.', RemovedInMarshmallow3Warning) Field.__init__(self, *args, **kwargs) self.src_str = text_type(src_str)
def _validated(self, value): """Format the value or raise ``exception_class`` if an error occurs.""" if value is None: return self.default try: return self._format_num(value) except (TypeError, ValueError, decimal.InvalidOperation) as err: raise ValidationError(getattr(self, 'error', None) or text_type(err))
def __init__(self, underlying_exception): if isinstance(underlying_exception, Exception): self.underlying_exception = underlying_exception else: self.underlying_exception = None super(_WrappingException, self).__init__( text_type(underlying_exception) )
def format(self, value): try: dvalue = utils.float_to_decimal(float(value)) except ValueError as ve: raise MarshallingError(ve) if not dvalue.is_normal() and dvalue != ZERO: raise MarshallingError('Invalid Fixed precision number.') return text_type(dvalue.quantize(self.precision, rounding=ROUND_HALF_EVEN))
def _deserialize(self, value): if not value: return False try: value_str = text_type(value) except TypeError as error: raise ValidationError(text_type(error)) if value_str in self.falsy: return False elif self.truthy: if value_str in self.truthy: return True else: raise ValidationError( '{0!r} is not in {1} nor {2}'.format( value_str, self.truthy, self.falsy )) return True
def handle_invalid_json_error(self, error, req, *args, **kwargs): messages = {"json": ["Invalid JSON body."]} response = exception_response(400, detail=text_type(messages), content_type="application/json") body = json.dumps(messages) response.body = body.encode("utf-8") if isinstance(body, text_type) else body raise response
def __init__(self, underlying_exception, field=None, field_name=None): if isinstance(underlying_exception, Exception): self.underlying_exception = underlying_exception else: self.underlying_exception = None self.field = field self.field_name = field_name super(_WrappingException, self).__init__( text_type(underlying_exception) )
def get_pk_from_identity(obj): """Get primary key for `obj`. If `obj` has a compound primary key, return a string of keys separated by ``":"``. This is the default keygetter for used by `ModelSchema <marshmallow_sqlalchemy.ModelSchema>`. """ _, key = identity_key(instance=obj) if len(key) == 1: return key[0] else: # Compund primary key return ':'.join(text_type(x) for x in key)
def _deserialize(self, value): if not value: return False try: value_str = text_type(value) except TypeError as error: msg = getattr(self, 'error', None) or text_type(error) raise ValidationError(msg) if value_str in self.falsy: return False elif self.truthy: if value_str in self.truthy: return True else: default_message = '{0!r} is not in {1} nor {2}'.format( value_str, self.truthy, self.falsy) msg = getattr(self, 'error', None) or default_message raise ValidationError(msg) return True
def _serialize(self, value, attr, obj): if value: self.dateformat = self.dateformat or self.DEFAULT_FORMAT format_func = self.DATEFORMAT_SERIALIZATION_FUNCS.get(self.dateformat, None) if format_func: try: return format_func(value, localtime=self.localtime) except (AttributeError, ValueError) as err: raise ValidationError(getattr(self, 'error', None) or text_type(err)) else: return value.strftime(self.dateformat)
def get_is_old(self, obj): if obj is None: return missing if isinstance(obj, dict): age = obj.get('age') else: age = obj.age try: return age > 80 except TypeError as te: raise ValidationError(text_type(te))
def _validated(self, value): if value is None: return None try: dvalue = utils.float_to_decimal(float(value)) except (TypeError, ValueError) as err: raise ValidationError(getattr(self, 'error', None) or text_type(err)) if not dvalue.is_normal() and dvalue != utils.ZERO_DECIMAL: raise ValidationError( getattr(self, 'error', None) or 'Invalid Fixed precision number.' ) return utils.decimal_to_fixed(dvalue, self.precision)
def _call_and_store(getter_func, data, field_name, field_obj, errors_dict, exception_class, strict=False): """Helper method for DRYing up logic in the :meth:`Marshaller.serialize` and :meth:`UnMarshaller.deserialize` methods. Call ``getter_func`` with ``data`` as its argument, and store any errors of type ``exception_class`` in ``error_dict``. :param callable getter_func: Function for getting the serialized/deserialized value from ``data``. :param data: The data passed to ``getter_func``. :param str field_name: Field name. :param FieldABC field_obj: Field object that performs the serialization/deserialization behavior. :param dict errors_dict: Dictionary to store errors on. :param type exception_class: Exception class that will be caught during serialization/deserialization. Errors of this type will be stored in ``errors_dict``. """ try: value = getter_func(data) except RegistryError: raise except exception_class as err: # Store errors if strict: err.field = field_obj err.field_name = field_name raise err # Warning: Mutation! if (hasattr(err, 'underlying_exception') and isinstance(err.underlying_exception, ValidationError)): validation_error = err.underlying_exception if isinstance(validation_error.messages, dict): errors_dict[field_name] = validation_error.messages else: errors_dict.setdefault(field_name, []).extend(validation_error.messages) else: errors_dict.setdefault(field_name, []).append(text_type(err)) value = None except TypeError: # field declared as a class, not an instance if (isinstance(field_obj, type) and issubclass(field_obj, FieldABC)): msg = ('Field for "{0}" must be declared as a ' 'Field instance, not a class. ' 'Did you mean "fields.{1}()"?' .format(field_name, field_obj.__name__)) raise TypeError(msg) raise return value
def _validate(self, validators, output, raw_data, fields_dict, strict=False): """Perform schema-level validation. Stores errors if ``strict`` is `False`. """ for validator_func in validators: try: func_args = utils.get_func_args(validator_func) if len(func_args) < 3: res = validator_func(output) else: res = validator_func(output, raw_data) if res is False: func_name = utils.get_func_name(validator_func) raise ValidationError( 'Schema validator {0}({1}) is False'.format( func_name, dict(output))) except ValidationError as err: # Store or reraise errors if err.field_names: field_names = err.field_names field_objs = [fields_dict[each] for each in field_names] else: field_names = ['_schema'] field_objs = [] for field_name in field_names: if isinstance(err.messages, (list, tuple)): # self.errors[field_name] may be a dict if schemas are nested if isinstance(self.errors.get(field_name), dict): self.errors[field_name].setdefault( '_schema', []).extend(err.messages) else: self.errors.setdefault(field_name, []).extend(err.messages) elif isinstance(err.messages, dict): self.errors.setdefault(field_name, []).append(err.messages) else: self.errors.setdefault(field_name, []).append(text_type(err)) if strict: raise ValidationError(self.errors, fields=field_objs, field_names=field_names) return output
def handle_error(self, error, req, schema, error_status_code, error_headers): """Handles errors during parsing. Aborts the current HTTP request and responds with a 400 error. """ status_code = error_status_code or self.DEFAULT_VALIDATION_STATUS response = exception_response( status_code, detail=text_type(error), headers=error_headers, content_type="application/json", ) body = json.dumps(error.messages) response.body = body.encode("utf-8") if isinstance(body, text_type) else body raise response
def test_boolean_field_deserialization_with_custom_truthy_values_invalid( self, in_val): class MyBoolean(fields.Boolean): truthy = set(['yep']) field = MyBoolean() with pytest.raises(ValidationError) as excinfo: field.deserialize(in_val) expected_msg = '{0!r} is not in {1} nor {2}'.format( text_type(in_val), field.truthy, field.falsy) assert str(excinfo.value.args[0]) == expected_msg field2 = MyBoolean(error='bad input') with pytest.raises(ValidationError) as excinfo: field2.deserialize(in_val) assert str(excinfo.value.args[0]) == 'bad input'
def run_validator(self, validator_func, output, original_data, fields_dict, index=None, many=False, pass_original=False): try: if pass_original: # Pass original, raw data (before unmarshalling) res = validator_func(output, original_data) else: res = validator_func(output) if res is False: raise ValidationError(self.default_schema_validation_error) except ValidationError as err: errors = self.get_errors(index=index) # Store or reraise errors if err.field_names: field_names = err.field_names field_objs = [ fields_dict[each] if each in fields_dict else None for each in field_names ] else: field_names = [SCHEMA] field_objs = [] self.error_field_names = field_names self.error_fields = field_objs for field_name in field_names: if isinstance(err.messages, (list, tuple)): # self.errors[field_name] may be a dict if schemas are nested if isinstance(errors.get(field_name), dict): errors[field_name].setdefault(SCHEMA, []).extend(err.messages) else: errors.setdefault(field_name, []).extend(err.messages) elif isinstance(err.messages, dict): errors.setdefault(field_name, []).append(err.messages) else: errors.setdefault(field_name, []).append(text_type(err)) raise ValidationError(self.errors, fields=field_objs, field_names=field_names, data=output)
def _validate(self, validators, output, raw_data, fields_dict, strict=False): """Perform schema-level validation. Stores errors if ``strict`` is `False`. """ for validator_func in validators: try: func_args = utils.get_func_args(validator_func) if len(func_args) < 3: res = validator_func(output) else: res = validator_func(output, raw_data) if res is False: func_name = utils.get_func_name(validator_func) raise ValidationError('Schema validator {0}({1}) is False'.format( func_name, dict(output) )) except ValidationError as err: # Store or reraise errors if err.field_names: field_names = err.field_names field_objs = [fields_dict[each] for each in field_names] else: field_names = ['_schema'] field_objs = [] for field_name in field_names: if isinstance(err.messages, (list, tuple)): # self.errors[field_name] may be a dict if schemas are nested if isinstance(self.errors.get(field_name), dict): self.errors[field_name].setdefault( '_schema', [] ).extend(err.messages) else: self.errors.setdefault(field_name, []).extend(err.messages) elif isinstance(err.messages, dict): self.errors.setdefault(field_name, []).append(err.messages) else: self.errors.setdefault(field_name, []).append(text_type(err)) if strict: raise ValidationError( self.errors, fields=field_objs, field_names=field_names ) return output
def _validate(self, validators, output, fields_dict, strict=False): """Perform schema-level validation. Stores errors if ``strict`` is `False`. """ for validator_func in validators: try: if validator_func(output) is False: func_name = utils.get_func_name(validator_func) raise ValidationError(u'Schema validator {0}({1}) is False'.format( func_name, dict(output) )) except ValidationError as err: # Store or reraise errors if err.field: field_name = err.field field_obj = fields_dict[field_name] else: field_name = '_schema' field_obj = None if strict: raise UnmarshallingError(err, field=field_obj, field_name=field_name) self.errors.setdefault(field_name, []).append(text_type(err)) return output
def __init__(self, iterable, error=None): self.iterable = iterable self.values_text = ', '.join(text_type(each) for each in self.iterable) self.error = error or self.default_message
def test_arbitrary_field_deserialization(self): field = fields.Arbitrary() expected = text_type(utils.float_to_decimal(float(42))) assert field.deserialize('42') == expected
def ensure_text_type(val): if isinstance(val, binary_type): val = val.decode('utf-8') return text_type(val)
def __init__(self, src_str, *args, **kwargs): Field.__init__(self, *args, **kwargs) self.src_str = text_type(src_str)
def __init__(self, choices, labels=None, error=None): self.choices = choices self.choices_text = ', '.join(text_type(choice) for choice in self.choices) self.labels = labels if labels is not None else [] self.labels_text = ', '.join(text_type(label) for label in self.labels) self.error = error or self.default_message
def handle_error(self, error): """Handles errors during parsing. Aborts the current HTTP request and responds with a 400 error. """ status_code = getattr(error, "status_code", 400) raise exception_response(status_code, detail=text_type(error))
def test_arbitrary_field(self, user): field = fields.Arbitrary() user.age = 12.3 result = field.serialize('age', user) assert result == text_type(utils.float_to_decimal(user.age))
def format(self, value): try: return text_type(value) except ValueError as ve: raise MarshallingError(self.error or ve)
def validator(value): try: converter(value) except Exception as e: raise ValidationError(compat.text_type(e))
def _format_error(self, value): value_text = ', '.join(text_type(val) for val in value) return super(ContainsOnly, self)._format_error(value_text)
def handle_error(self, error): """Handles errors during parsing. Aborts the current HTTP request and responds with a 400 error. """ status_code = getattr(error, 'status_code', 422) raise exception_response(status_code, detail=text_type(error))
def decimal_to_fixed(value, precision): """Convert a `Decimal` to a fixed-precision number as a string.""" return text_type(value.quantize(precision, rounding=ROUND_HALF_EVEN))
def __init__(self, src_str): super(FormattedString, self).__init__() self.src_str = text_type(src_str)