def _serialize(self, value, attr, obj): try: data = utils.to_marshallable_type(obj) return self.src_str.format(**data) except (TypeError, IndexError) as error: raise ValidationError(getattr(self, 'error', None) or error)
def validate_subca(self, data): if data["type"] == "subca": if not data.get("parent"): raise ValidationError( "If generating a subca, parent 'authority' must be specified." )
def __call__(self, value): if self.regex.match(value) is None: raise ValidationError(self._format_error(value)) return value
def _deserialize(self, value, attr, data, **kwargs): if isinstance(value, (list, tuple)) and len(value) == 2: if isinstance(value[1], float) and 0 <= value[1] < 1: return value raise ValidationError( "This field expects a list of [value<Any>, dist<float>].")
def dump(self, obj, many=None, update_fields=True, **kwargs): """Serialize an object to native Python data types according to this Schema's fields. :param obj: The object to serialize. :param bool many: Whether to serialize `obj` as a collection. If `None`, the value for `self.many` is used. :param bool update_fields: Whether to update the schema's field classes. Typically set to `True`, but may be `False` when serializing a homogenous collection. This parameter is used by `fields.Nested` to avoid multiple updates. :return: A tuple of the form (``data``, ``errors``) :rtype: `MarshalResult`, a `collections.namedtuple` .. versionadded:: 1.0.0 """ # Callable marshalling object marshal = marshalling.Marshaller(prefix=self.prefix) errors = {} many = self.many if many is None else bool(many) if many and utils.is_iterable_but_not_string(obj): obj = list(obj) if self._has_processors: try: processed_obj = self._invoke_dump_processors(PRE_DUMP, obj, many, original_data=obj) except ValidationError as error: errors = error.normalized_messages() result = None else: processed_obj = obj if not errors: if update_fields: obj_type = type(processed_obj) if obj_type not in self._types_seen: self._update_fields(processed_obj, many=many) if not isinstance(processed_obj, Mapping): self._types_seen.add(obj_type) try: preresult = marshal( processed_obj, self.fields, many=many, # TODO: Remove self.__accessor__ in a later release accessor=self.get_attribute or self.__accessor__, dict_class=self.dict_class, index_errors=self.opts.index_errors, **kwargs) except ValidationError as error: errors = marshal.errors preresult = error.data result = self._postprocess(preresult, many, obj=obj) if not errors and self._has_processors: try: result = self._invoke_dump_processors(POST_DUMP, result, many, original_data=obj) except ValidationError as error: errors = error.normalized_messages() if errors: # TODO: Remove self.__error_handler__ in a later release if self.__error_handler__ and callable(self.__error_handler__): self.__error_handler__(errors, obj) exc = ValidationError(errors, field_names=marshal.error_field_names, fields=marshal.error_fields, data=obj, **marshal.error_kwargs) self.handle_error(exc, obj) if self.strict: raise exc return MarshalResult(result, errors)
def validate_week_days_length(self, value): if len(value) < 1: raise ValidationError('week_days cannot be empty')
def validate_pchoice(values): dists = [v for v in values if v] if sum(dists) > 1: raise ValidationError( "The distribution of different outcomes should sum to 1.")
def _validate(self, value): if not dates.validate(value): raise ValidationError('Invalid date: %s' % value)
def _validate(self, value): schema = model.get(value) if schema is None: raise ValidationError('Invalid schema name: %s' % value)
def _validate(self, value): if not languages.validate(value): raise ValidationError('Invalid language code.')
def _validate(self, value): if not countries.validate(value): raise ValidationError('Invalid country code: %s' % value)
def _validate(self, value): if value not in Collection.CATEGORIES.keys(): raise ValidationError('Invalid category.')
def deserialize(self, data, fields_dict, many=False, partial=False, dict_class=dict, index_errors=True, index=None): """Deserialize ``data`` based on the schema defined by ``fields_dict``. :param dict data: The data to deserialize. :param dict fields_dict: Mapping of field names to :class:`Field` objects. :param bool many: Set to `True` if ``data`` should be deserialized as a collection. :param bool|tuple partial: Whether to ignore missing fields. If its value is an iterable, only missing fields listed in that iterable will be ignored. :param type dict_class: Dictionary class used to construct the output. :param bool index_errors: Whether to store the index of invalid items in ``self.errors`` when ``many=True``. :param int index: Index of the item being serialized (for storing errors) if serializing a collection, otherwise `None`. :return: A dictionary of the deserialized data. """ # Reset errors if not deserializing a collection if not self._pending: self.reset_errors() if many and data is not None: self._pending = True ret = [ self.deserialize(d, fields_dict, many=False, partial=partial, dict_class=dict_class, index=idx, index_errors=index_errors) for idx, d in enumerate(data) ] self._pending = False if self.errors: raise ValidationError( self.errors, field_names=self.error_field_names, fields=self.error_fields, data=ret, ) return ret if data is not None: partial_is_collection = is_collection(partial) ret = dict_class() for attr_name, field_obj in iteritems(fields_dict): if field_obj.dump_only: continue try: raw_value = data.get(attr_name, missing) except AttributeError: # Input data is not a dict errors = self.get_errors(index=index) msg = field_obj.error_messages['type'].format( input=data, input_type=data.__class__.__name__) self.error_field_names = [SCHEMA] self.error_fields = [] errors = self.get_errors() errors.setdefault(SCHEMA, []).append(msg) # Input data type is incorrect, so we can bail out early break field_name = attr_name if raw_value is missing and field_obj.load_from: field_name = field_obj.load_from raw_value = data.get(field_obj.load_from, missing) if raw_value is missing: # Ignore missing field if we're allowed to. if (partial is True or (partial_is_collection and attr_name in partial)): continue _miss = field_obj.missing raw_value = _miss() if callable(_miss) else _miss if raw_value is missing and not field_obj.required: continue getter = lambda val: field_obj.deserialize( val, field_obj.load_from or attr_name, data) value = self.call_and_store( getter_func=getter, data=raw_value, field_name=field_name, field_obj=field_obj, index=(index if index_errors else None)) if value is not missing: key = fields_dict[attr_name].attribute or attr_name set_value(ret, key, value) else: ret = None if self.errors and not self._pending: raise ValidationError( self.errors, field_names=self.error_field_names, fields=self.error_fields, data=ret, ) return ret
def serialize(self, obj, fields_dict, many=False, accessor=None, dict_class=dict, index_errors=True, index=None): """Takes raw data (a dict, list, or other object) and a dict of fields to output and serializes the data based on those fields. :param obj: The actual object(s) from which the fields are taken from :param dict fields_dict: Mapping of field names to :class:`Field` objects. :param bool many: Set to `True` if ``data`` should be serialized as a collection. :param callable accessor: Function to use for getting values from ``obj``. :param type dict_class: Dictionary class used to construct the output. :param bool index_errors: Whether to store the index of invalid items in ``self.errors`` when ``many=True``. :param int index: Index of the item being serialized (for storing errors) if serializing a collection, otherwise `None`. :return: A dictionary of the marshalled data .. versionchanged:: 1.0.0 Renamed from ``marshal``. """ # Reset errors dict if not serializing a collection if not self._pending: self.reset_errors() if many and obj is not None: self._pending = True ret = [ self.serialize(d, fields_dict, many=False, dict_class=dict_class, accessor=accessor, index=idx, index_errors=index_errors) for idx, d in enumerate(obj) ] self._pending = False if self.errors: raise ValidationError( self.errors, field_names=self.error_field_names, fields=self.error_fields, data=ret, ) return ret items = [] for attr_name, field_obj in iteritems(fields_dict): if getattr(field_obj, 'load_only', False): continue key = ''.join([self.prefix or '', field_obj.dump_to or attr_name]) getter = lambda d: field_obj.serialize( attr_name, d, accessor=accessor) value = self.call_and_store( getter_func=getter, data=obj, field_name=key, field_obj=field_obj, index=(index if index_errors else None)) if value is missing: continue items.append((key, value)) ret = dict_class(items) if self.errors and not self._pending: raise ValidationError(self.errors, field_names=self.error_field_names, fields=self.error_fields, data=ret) return ret
def validate_authority(self, data): if not data['authority'].active: raise ValidationError("The authority is inactive.", ['authority'])
def validate_id(self, id): print("Validate ID: ", id) print("is_create: ", self.is_create()) if self.is_create() or int(id) == int(self.instance.id): return raise ValidationError('ids do not match')
def keys(self, data): if data.get('destinations'): if not data.get('private_key'): raise ValidationError('Destinations require private key.')
def dump(self, obj, many=None, update_fields=True): """Serialize an object to native Python data types according to this Schema's fields. :param obj: The object to serialize. :param bool many: Whether to serialize `obj` as a collection. If `None`, the value for `self.many` is used. :param bool update_fields: Whether to update the schema's field classes. Typically set to `True`, but may be `False` when serializing a homogenous collection. This parameter is used by `fields.Nested` to avoid multiple updates. :return: A dict of serialized data :rtype: dict .. versionadded:: 1.0.0 .. versionchanged:: 3.0.0b7 This method returns the serialized data rather than a ``(data, errors)`` duple. A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised if ``obj`` is invalid. """ # Callable marshalling object marshal = marshalling.Marshaller(prefix=self.prefix) errors = {} many = self.many if many is None else bool(many) if many and utils.is_iterable_but_not_string(obj): obj = list(obj) if self._has_processors(PRE_DUMP): try: processed_obj = self._invoke_dump_processors(PRE_DUMP, obj, many, original_data=obj) except ValidationError as error: errors = error.normalized_messages() result = None else: processed_obj = obj if not errors: if update_fields: obj_type = type(processed_obj) if obj_type not in self._types_seen: self._update_fields(processed_obj, many=many) if not isinstance(processed_obj, Mapping): self._types_seen.add(obj_type) try: result = marshal(processed_obj, self.fields, many=many, accessor=self.get_attribute, dict_class=self.dict_class, index_errors=self.opts.index_errors) except ValidationError as error: errors = marshal.errors result = error.data if not errors and self._has_processors(POST_DUMP): try: result = self._invoke_dump_processors( POST_DUMP, result, many, original_data=obj, ) except ValidationError as error: errors = error.normalized_messages() if errors: exc = ValidationError(errors, field_names=marshal.error_field_names, data=obj, valid_data=result, **marshal.error_kwargs) # User-defined error handler self.handle_error(exc, obj) raise exc return result
def validate_months_length(self, value): if len(value) < 1: raise ValidationError('months cannot be empty')
def _do_load(self, data, many=None, partial=None, unknown=None, postprocess=True): """Deserialize `data`, returning the deserialized result. :param data: The data to deserialize. :param bool many: Whether to deserialize `data` as a collection. If `None`, the value for `self.many` is used. :param bool|tuple partial: Whether to validate required fields. If its value is an iterable, only fields listed in that iterable will be ignored will be allowed missing. If `True`, all fields will be allowed missing. If `None`, the value for `self.partial` is used. :param unknown: Whether to exclude, include, or raise an error for unknown fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`. If `None`, the value for `self.unknown` is used. :param bool postprocess: Whether to run post_load methods.. :return: A dict of deserialized data :rtype: dict """ # Callable unmarshalling object unmarshal = marshalling.Unmarshaller() errors = {} many = self.many if many is None else bool(many) unknown = unknown or self.unknown if partial is None: partial = self.partial if self._has_processors(PRE_LOAD): try: processed_data = self._invoke_load_processors( PRE_LOAD, data, many, original_data=data, ) except ValidationError as err: errors = err.normalized_messages() result = None else: processed_data = data if not errors: try: result = unmarshal( processed_data, self.fields, many=many, partial=partial, unknown=unknown, dict_class=self.dict_class, index_errors=self.opts.index_errors, ) except ValidationError as error: result = error.data self._invoke_field_validators(unmarshal, data=result, many=many) errors = unmarshal.errors # Run schema-level validation. if self._has_processors(VALIDATES_SCHEMA): field_errors = bool(errors) try: self._invoke_schema_validators( unmarshal, pass_many=True, data=result, original_data=data, many=many, field_errors=field_errors, ) except ValidationError as err: errors.update(err.messages) try: self._invoke_schema_validators( unmarshal, pass_many=False, data=result, original_data=data, many=many, field_errors=field_errors, ) except ValidationError as err: errors.update(err.messages) # Run post processors if not errors and postprocess and self._has_processors(POST_LOAD): try: result = self._invoke_load_processors( POST_LOAD, result, many, original_data=data, ) except ValidationError as err: errors = err.normalized_messages() if errors: exc = ValidationError(errors, field_names=unmarshal.error_field_names, data=data, valid_data=result, **unmarshal.error_kwargs) self.handle_error(exc, data) raise exc return result
def validate_matrix(values): v = sum(map(lambda x: 1 if x else 0, values)) if v == 0 or v > 1: raise ValidationError( "Matrix element is not valid, one and only one option is required." )
def verify_phone(country_calling_code, phone, code, eth_address): """Check a phone verification code against the Twilio Verify API for a phone number. Args: country_calling_code (str): Dialling prefix for the country. phone (str): Phone number in national format. code (int): Verification code for the country_calling_code and phone combination eth_address (str): Address of ERC725 identity token for claim Returns: VerificationServiceResponse Raises: ValidationError: Verification request failed due to invalid arguments PhoneVerificationError: Verification request failed for a reason not related to the arguments """ params = { 'country_code': country_calling_code, 'phone_number': phone, 'verification_code': code } headers = {'X-Authy-API-Key': settings.TWILIO_VERIFY_API_KEY} url = 'https://api.authy.com/protected/json/phones/verification/check' response = requests.get(url, params=params, headers=headers) try: response.raise_for_status() except requests.exceptions.HTTPError as exc: logger.exception(exc) if response.json()['error_code'] == '60023': # This error code could also mean that no phone verification was ever # created for that country calling code and phone number raise ValidationError('Verification code has expired.', field_names=['code']) elif response.json()['error_code'] == '60022': raise ValidationError('Verification code is incorrect.', field_names=['code']) else: raise PhoneVerificationError( 'Could not verify code. Please try again shortly.') # This may be unnecessary because the response has a 200 status code # but it a good precaution to handle any inconsistency between the # success field and the status code if response.json()['success'] is True: # TODO: determine what the text should be data = 'phone verified' # TODO: determine claim type integer code for phone verification signature = attestations.generate_signature( signing_key, eth_address, TOPICS['phone'], data) attestation = Attestation(method=AttestationTypes.PHONE, eth_address=eth_address, value="{} {}".format( country_calling_code, phone), signature=signature, remote_ip_address=request.remote_addr) db.session.add(attestation) db.session.commit() return VerificationServiceResponse({ 'signature': signature, 'claim_type': TOPICS['phone'], 'data': data }) raise PhoneVerificationError( 'Could not verify code. Please try again shortly.')
def _deserialize(self, value, attr, data, **kwargs): # pylint:disable=too-many-branches if isinstance(value, str): value = value.split(":") elif isinstance(value, Mapping): if set(self.REQUIRED_KEYS) - set(value.keys()): raise ValidationError("{} dict must have {} keys {}.".format( self.__class__.__name__, len(self.REQUIRED_KEYS), self.REQUIRED_KEYS, )) if len(value) == len(self.REQUIRED_KEYS): value = [value[k] for k in self.REQUIRED_KEYS] elif len(value) == len(self.KEYS): value = [value[k] for k in self.KEYS] elif not isinstance(value, list): raise ValidationError( "{} accept values formatted as the following:\n" " * str: {}\n" " * dict: {}\n" " * list: {}".format( self.__class__.__name__, ":".join(self.REQUIRED_KEYS), dict( zip( self.REQUIRED_KEYS, [ "v{}".format(i) for i in range(len(self.REQUIRED_KEYS)) ], )), self.REQUIRED_KEYS, )) if len(value) != len(self.REQUIRED_KEYS) and len(value) != len( self.KEYS): raise ValidationError( "{} requires {} or {} elements received {}".format( self.__class__.__name__, len(self.REQUIRED_KEYS), len(self.KEYS), len(value), )) for i, v in enumerate(value): try: float(v) except (ValueError, TypeError): raise ValidationError( "{}: {} must of type int or float, received instead {}". format(self.__class__.__name__, self.REQUIRED_KEYS[i], v)) if not isinstance(v, (int, float)): value[i] = ast.literal_eval(v) # Check that lower value is smaller than higher value if self.CHECK_ORDER and value[0] >= value[1]: raise ValidationError( "{key2} value must be strictly higher that {key1} value, " "received instead {key1}: {val1}, {key2}: {val2}".format( key1=self.REQUIRED_KEYS[0], key2=self.REQUIRED_KEYS[1], val1=value[0], val2=value[1], )) if len(self.REQUIRED_KEYS) == 3 and value[2] == 0: raise ValidationError("{} cannot be 0".format( self.REQUIRED_KEYS[2])) value = dict(zip(self.KEYS, value)) return value
def validate_airbnb_user_id(airbnbUserId): if not re.compile(r"^\d*$").match(airbnbUserId): raise ValidationError('AirbnbUserId should be a number.', 'airbnbUserId')
def _do_load(self, data, many=None, partial=None, postprocess=True): """Deserialize `data`, returning the deserialized result and a dictonary of validation errors. :param data: The data to deserialize. :param bool many: Whether to deserialize `data` as a collection. If `None`, the value for `self.many` is used. :param bool|tuple partial: Whether to validate required fields. If its value is an iterable, only fields listed in that iterable will be ignored will be allowed missing. If `True`, all fields will be allowed missing. If `None`, the value for `self.partial` is used. :param bool postprocess: Whether to run post_load methods.. :return: A tuple of the form (`data`, `errors`) """ # Callable unmarshalling object unmarshal = marshalling.Unmarshaller() errors = {} many = self.many if many is None else bool(many) if partial is None: partial = self.partial try: processed_data = self._invoke_load_processors(PRE_LOAD, data, many, original_data=data) except ValidationError as err: errors = err.normalized_messages() result = None if not errors: try: result = unmarshal( processed_data, self.fields, many=many, partial=partial, dict_class=self.dict_class, index_errors=self.opts.index_errors, ) except ValidationError as error: result = error.data self._invoke_field_validators(unmarshal, data=result, many=many) errors = unmarshal.errors field_errors = bool(errors) # Run schema-level migration try: self._invoke_validators(unmarshal, pass_many=True, data=result, original_data=data, many=many, field_errors=field_errors) except ValidationError as err: errors.update(err.messages) try: self._invoke_validators(unmarshal, pass_many=False, data=result, original_data=data, many=many, field_errors=field_errors) except ValidationError as err: errors.update(err.messages) # Run post processors if not errors and postprocess: try: result = self._invoke_load_processors(POST_LOAD, result, many, original_data=data) except ValidationError as err: errors = err.normalized_messages() if errors: # TODO: Remove self.__error_handler__ in a later release if self.__error_handler__ and callable(self.__error_handler__): self.__error_handler__(errors, data) exc = ValidationError(errors, field_names=unmarshal.error_field_names, fields=unmarshal.error_fields, data=data, **unmarshal.error_kwargs) self.handle_error(exc, data) if self.strict: raise exc return result, errors
def _do_load( self, data: typing.Union[ typing.Mapping[str, typing.Any], typing.Iterable[typing.Mapping[str, typing.Any]], ], *, many: bool = None, partial: typing.Union[bool, types.StrSequenceOrSet] = None, unknown: str = None, postprocess: bool = True ): """Deserialize `data`, returning the deserialized result. This method is private API. :param data: The data to deserialize. :param many: Whether to deserialize `data` as a collection. If `None`, the value for `self.many` is used. :param partial: Whether to validate required fields. If its value is an iterable, only fields listed in that iterable will be ignored will be allowed missing. If `True`, all fields will be allowed missing. If `None`, the value for `self.partial` is used. :param unknown: Whether to exclude, include, or raise an error for unknown fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`. If `None`, the value for `self.unknown` is used. :param postprocess: Whether to run post_load methods.. :return: Deserialized data """ error_store = ErrorStore() errors = {} # type: typing.Dict[str, typing.List[str]] many = self.many if many is None else bool(many) unknown = unknown or self.unknown if partial is None: partial = self.partial # Run preprocessors if self._has_processors(PRE_LOAD): try: processed_data = self._invoke_load_processors( PRE_LOAD, data, many=many, original_data=data, partial=partial ) except ValidationError as err: errors = err.normalized_messages() result = ( None ) # type: typing.Optional[typing.Union[typing.List, typing.Dict]] else: processed_data = data if not errors: # Deserialize data result = self._deserialize( processed_data, error_store=error_store, many=many, partial=partial, unknown=unknown, ) # Run field-level validation self._invoke_field_validators( error_store=error_store, data=result, many=many ) # Run schema-level validation if self._has_processors(VALIDATES_SCHEMA): field_errors = bool(error_store.errors) self._invoke_schema_validators( error_store=error_store, pass_many=True, data=result, original_data=data, many=many, partial=partial, field_errors=field_errors, ) self._invoke_schema_validators( error_store=error_store, pass_many=False, data=result, original_data=data, many=many, partial=partial, field_errors=field_errors, ) errors = error_store.errors # Run post processors if not errors and postprocess and self._has_processors(POST_LOAD): try: result = self._invoke_load_processors( POST_LOAD, result, many=many, original_data=data, partial=partial, ) except ValidationError as err: errors = err.normalized_messages() if errors: exc = ValidationError(errors, data=data, valid_data=result) self.handle_error(exc, data, many=many, partial=partial) raise exc return result
def __call__(self, value): if value != self.comparable: raise ValidationError(self._format_error(value)) return value
def keys(self, data): if data.get("destinations"): if not data.get("private_key"): raise ValidationError("Destinations require private key.")
def __call__(self, value): # We can't use set.issubset because does not handle unhashable types for val in value: if val not in self.choices: raise ValidationError(self._format_error(value)) return value
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))