def validate(self, value): super(DecimalField, self).validate(value) if value in validators.EMPTY_VALUES: return # Check for NaN, Inf and -Inf values. We can't compare directly for NaN, # since it is never equal to itself. However, NaN is the only value that # isn't equal to itself, so we can use this to identify NaN if value != value or value == Decimal("Inf") or value == Decimal( "-Inf"): raise ValidationError(self.error_messages["invalid"]) sign, digittuple, exponent = value.as_tuple() decimals = abs(exponent) # digittuple doesn't include any leading zeros. digits = len(digittuple) if decimals > digits: # We have leading zeros up to or past the decimal point. Count # everything past the decimal point as a digit. We do not count # 0 before the decimal point as a digit since that would mean # we would not allow max_digits = decimal_places. digits = decimals whole_digits = digits - decimals if self.max_digits is not None and digits > self.max_digits: raise ValidationError(self.error_messages["max_digits"] % self.max_digits) if self.decimal_places is not None and decimals > self.decimal_places: raise ValidationError(self.error_messages["max_decimal_places"] % self.decimal_places) if self.max_digits is not None and self.decimal_places is not None and whole_digits > ( self.max_digits - self.decimal_places): raise ValidationError(self.error_messages["max_whole_digits"] % (self.max_digits - self.decimal_places)) return value
def _validate_tag_field(value): # Valid field: # - ["tag1", "tag2", "tag3"...] # - ["tag1", ["tag2", None], ["tag3", "#ccc"], [tag4, #cccccc]...] for tag in value: if isinstance(tag, str): continue if isinstance(tag, (list, tuple)) and len(tag) == 2: name = tag[0] color = tag[1] if isinstance(name, str): if color is None or color == "": continue if isinstance(color, str) and re.match( '^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$', color): continue raise ValidationError( _("Invalid tag '{value}'. The color is not a " "valid HEX color or null.").format(value=tag)) raise ValidationError( _("Invalid tag '{value}'. it must be the name or a pair " "'[\"name\", \"hex color/\" | null]'.").format( value=tag))
def from_native(self, value): # Convert URL -> model instance pk # TODO: Use values_list queryset = self.queryset if queryset is None: raise Exception("Writable related fields must include a `queryset` argument") try: http_prefix = value.startswith(("http:", "https:")) except AttributeError: msg = self.error_messages["incorrect_type"] raise ValidationError(msg % type(value).__name__) if http_prefix: # If needed convert absolute URLs to relative path value = urlparse.urlparse(value).path prefix = get_script_prefix() if value.startswith(prefix): value = "/" + value[len(prefix):] try: match = resolve(value) except Exception: raise ValidationError(self.error_messages["no_match"]) if match.view_name != self.view_name: raise ValidationError(self.error_messages["incorrect_match"]) try: return self.get_object(queryset, match.view_name, match.args, match.kwargs) except (ObjectDoesNotExist, TypeError, ValueError): raise ValidationError(self.error_messages["does_not_exist"])
def validate_attributes_values(self, attrs, source): # values must be a dict data_values = attrs.get("attributes_values", None) if self.object: data_values = (data_values or self.object.attributes_values) if type(data_values) is not dict: raise ValidationError( _("Invalid content. It must be {\"key\": \"value\",...}")) # Values keys must be in the container object project data_container = attrs.get(self._container_field, None) if data_container: project_id = data_container.project_id elif self.object: project_id = getattr(self.object, self._container_field).project_id else: project_id = None values_ids = list(data_values.keys()) qs = self._custom_attribute_model.objects.filter(project=project_id, id__in=values_ids) if qs.count() != len(values_ids): raise ValidationError(_("It contain invalid custom fields.")) return attrs
def from_native(self, data): if self.queryset is None: raise Exception("Writable related fields must include a `queryset` argument") try: return self.queryset.get(**{self.slug_field: data}) except ObjectDoesNotExist: raise ValidationError(self.error_messages["does_not_exist"] % (self.slug_field, smart_text(data))) except (TypeError, ValueError): msg = self.error_messages["invalid"] raise ValidationError(msg)
def from_native(self, data): if self.queryset is None: raise Exception("Writable related fields must include a `queryset` argument") try: return self.queryset.get(pk=data) except ObjectDoesNotExist: msg = self.error_messages["does_not_exist"] % smart_text(data) raise ValidationError(msg) except (TypeError, ValueError): received = type(data).__name__ msg = self.error_messages["incorrect_type"] % received raise ValidationError(msg)
def validate_milestone_id(self, attrs, source): filters = {"project__id": attrs["project_id"], "id": attrs[source]} if not Milestone.objects.filter(**filters).exists(): raise ValidationError(_("Invalid milestone id.")) return attrs
def from_native(self, value): if value in validators.EMPTY_VALUES: return None if isinstance(value, datetime.time): return value for format in self.input_formats: if format.lower() == ISO_8601: try: parsed = parse_time(value) except (ValueError, TypeError): pass else: if parsed is not None: return parsed else: try: parsed = datetime.datetime.strptime(value, format) except (ValueError, TypeError): pass else: return parsed.time() msg = self.error_messages["invalid"] % readable_time_formats( self.input_formats) raise ValidationError(msg)
def from_native(self, value): if value in validators.EMPTY_VALUES: return None if isinstance(value, datetime.datetime): if timezone and settings.USE_TZ and timezone.is_aware(value): # Convert aware datetimes to the default time zone # before casting them to dates (#17742). default_timezone = timezone.get_default_timezone() value = timezone.make_naive(value, default_timezone) return value.date() if isinstance(value, datetime.date): return value for format in self.input_formats: if format.lower() == ISO_8601: try: parsed = parse_date(value) except (ValueError, TypeError): pass else: if parsed is not None: return parsed else: try: parsed = datetime.datetime.strptime(value, format) except (ValueError, TypeError): pass else: return parsed.date() msg = self.error_messages["invalid"] % readable_date_formats( self.input_formats) raise ValidationError(msg)
def _validate_tag_field(value): for tag in value: if isinstance(tag, str): continue raise ValidationError( _("Invalid tag '{value}'. It must be the tag name."). format(value=tag))
def field_from_native(self, data, files, field_name, into): """ Given a dictionary and a field name, updates the dictionary `into`, with the field and it's deserialized value. """ if self.read_only: return try: data = data or {} if self.use_files: files = files or {} try: native = files[field_name] except KeyError: native = data[field_name] else: native = data[field_name] except KeyError: if self.default is not None and not self.partial: # Note: partial updates shouldn't set defaults native = self.get_default_value() else: if self.required: raise ValidationError(self.error_messages["required"]) return value = self.from_native(native) if self.source == "*": if value: into.update(value) else: self.validate(value) self.run_validators(value) into[self.source or field_name] = value
def validate_username(self, attrs, source): username = attrs.get(source, None) try: validate_user_email_allowed_domains(username) except ValidationError: # If the validation comes from a request let's check the user is a valid contact request = self.context.get("request", None) if request is not None and request.user.is_authenticated(): valid_usernames = request.user.contacts_visible_by_user( request.user).values_list("username", flat=True) if username not in valid_usernames: raise ValidationError( _("The user must be a valid contact")) user = User.objects.filter(Q(username=username) | Q(email=username)).first() if user is not None: email = user.email self.user = user else: email = username self.email = email self._validate_member_doesnt_exist(attrs, email) return attrs
def field_from_native(self, data, files, field_name, into): if self.read_only: return try: if self.many: try: # Form data value = data.getlist(field_name) if value == [""] or value == []: raise KeyError except AttributeError: # Non-form data value = data[field_name] else: value = data[field_name] except KeyError: if self.partial: return value = self.get_default_value() if value in self.null_values: if self.required: raise ValidationError(self.error_messages["required"]) into[(self.source or field_name)] = None elif self.many: into[(self.source or field_name)] = [self.from_native(item) for item in value] else: into[(self.source or field_name)] = self.from_native(value)
def validate_from_tags(self, attrs, source): tags = attrs.get(source, None) for tag in tags: if not services.tag_exist_for_project_elements(self.project, tag): raise ValidationError(_("The tag doesn't exist.")) return attrs
def validate_color(self, attrs, source): color = attrs.get(source, None) if color and not re.match('^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$', color): raise ValidationError(_("The color is not a valid HEX color.")) return attrs
def validate_watchers(self, attrs, source): users = attrs.get(source, []) # Try obtain a valid project if self.object is None and "project" in attrs: project = attrs["project"] elif self.object: project = self.object.project else: project = None # If project is empty in all conditions, continue # without errors, because other validator should # validate the empty project field. if not project: return attrs # Check if incoming watchers are contained # in project members list member_ids = project.members.values_list("id", flat=True) existing_watcher_ids = project.get_watchers().values_list("id", flat=True) result = set(users).difference(member_ids).difference(existing_watcher_ids) if result: raise ValidationError(_("Watchers contains invalid users")) return attrs
def validate_status_id(self, attrs, source): filters = {"project__id": attrs["project_id"], "id": attrs[source]} if not TaskStatus.objects.filter(**filters).exists(): raise ValidationError(_("Invalid task status id.")) return attrs
def validate_is_admin(self, attrs, source): project = attrs.get( "project", None if self.object is None else self.object.project) if project is None: return attrs if (self.object and self.object.user): if self.object.user.id == project.owner_id and not attrs[source]: raise ValidationError(_("The project owner must be admin.")) if not services.project_has_valid_admins( project, exclude_user=self.object.user): raise ValidationError( _("At least one user must be an active admin for this project." )) return attrs
def validate(self, value): """ Validates that the input is in self.choices. """ super(ChoiceField, self).validate(value) if value and not self.valid_value(value): raise ValidationError(self.error_messages["invalid_choice"] % {"value": value})
def from_native(self, value): if value in validators.EMPTY_VALUES: return None try: value = int(str(value)) except (ValueError, TypeError): raise ValidationError(self.error_messages["invalid"]) return value
def from_native(self, value): if value in validators.EMPTY_VALUES: return None try: return float(value) except (TypeError, ValueError): msg = self.error_messages["invalid"] % value raise ValidationError(msg)
def validate_status_id(self, attrs, source): filters = {"project__id": attrs["project_id"]} filters["id"] = attrs[source] if not TaskStatus.objects.filter(**filters).exists(): raise ValidationError( _("Invalid task status id. The status must belong to " "the same project.")) return attrs
def validate_bulk_stories(self, attrs, source): filters = { "project__id": attrs["project_id"], "id__in": [us["us_id"] for us in attrs[source]] } if UserStory.objects.filter(**filters).count() != len(filters["id__in"]): raise ValidationError(_("All the user stories must be from the same project")) return attrs
def validate_name(self, attrs, source): """ Check the milestone name is not duplicated in the project """ name = attrs[source] qs = self.project.milestones.filter(name=name) if qs.exists(): raise ValidationError(_("Name duplicated for the project")) return attrs
def validate_username(self, attrs, source): value = attrs[source] validator = core_validators.RegexValidator(re.compile('^[\w.-]+$'), _("invalid username"), "invalid") try: validator(value) except ValidationError: raise ValidationError(_("Required. 255 characters or fewer. Letters, numbers " "and /./-/_ characters'")) return attrs
def validate_url(self, attrs, source): if settings.WEBHOOKS_BLOCK_PRIVATE_ADDRESS: host = urlparse(attrs[source]).hostname try: ipa = ipaddress.ip_address(host) except ValueError: return attrs if ipa.is_private: raise ValidationError(_("Not allowed IP Address")) return attrs return attrs
def validate_bulk_memberships(self, attrs, source): project_id = attrs["project_id"] role_ids = [r["role_id"] for r in attrs["bulk_memberships"]] if Role.objects.filter(project_id=project_id, id__in=role_ids).count() != len(set(role_ids)): raise ValidationError( _("Invalid role ids. All roles must belong to the same project." )) return attrs
def validate_status_id(self, attrs, source): filters = { "project__id": attrs["project_id"], "id": attrs[source] } if not UserStoryStatus.objects.filter(**filters).exists(): raise ValidationError(_("Invalid user story status id. The status must belong " "to the same project.")) return attrs
def from_native(self, data): if data in validators.EMPTY_VALUES: return None # UploadedFile objects should have name and size attributes. try: file_name = data.name file_size = data.size except AttributeError: raise ValidationError(self.error_messages["invalid"]) if self.max_length is not None and len(file_name) > self.max_length: error_values = {"max": self.max_length, "length": len(file_name)} raise ValidationError(self.error_messages["max_length"] % error_values) if not file_name: raise ValidationError(self.error_messages["invalid"]) if not self.allow_empty_file and not file_size: raise ValidationError(self.error_messages["empty"]) return data
def validate_role(self, attrs, source): project = attrs.get( "project", None if self.object is None else self.object.project) if project is None: return attrs role = attrs[source] if project.roles.filter(id=role.id).count() == 0: raise ValidationError(_("Invalid role for the project")) return attrs