Source code for contour.validators
"""
Validators to check e.g. uploaded data or calculated contours.
"""
import re
import numpy as np
from django.core.exceptions import ValidationError
from .settings import MAX_FILE_SIZE_M_IN_MIB, MAX_LENGTH_FILE_NAME
[docs]def validate_contour_coordinates(contour_coordinates):
"""
Validates contour coordinates.
They are not allowed to contain NaN or inf.
Parameters
----------
contour_coordinates : list of list of numpy.ndarray,
The coordinates of the environmental contour.
The format is defined by compute_interface.iform() and
compute_interface.hdc().
Raises
-------
ValidationError,
If the contour coordinates contain unsupported values like
NaN or inf.
"""
for i in range(len(contour_coordinates)): # Loop over multiple contour paths
for j in range(len(contour_coordinates[i])): # Loop over the EEDC vectors
for k in range(len(contour_coordinates[i][j])): # Loop over scalars
scalar = contour_coordinates[i][j][k]
if np.isnan(scalar):
raise ValidationError('The contour coordinates contain '
'values, which are set to NaN.')
if np.isinf(scalar):
print('Raising ValidationError because of inf.')
raise ValidationError('The contour coordinates contain '
'values, which are set to inf '
'(Infinity).')
[docs]def validate_csv_upload(value):
"""
Parameters
----------
value : django.core.files.File,
The file that the user wants to upload.
Raises
------
ValidationError,
If the file is too large ot does not have the right format.
"""
# Validate the file name's length.
if len(value.name) > MAX_LENGTH_FILE_NAME:
raise ValidationError(
'File name too long. The size should not exceed ' +
str(MAX_LENGTH_FILE_NAME) + ' characters, but was ' +
str(len(value.name)) + ' characters.')
# Validate the file size.
limit = MAX_FILE_SIZE_M_IN_MIB * 1024 * 1024
if value.size > limit:
raise ValidationError('File too large. Size should not exceed ' +
str(MAX_FILE_SIZE_M_IN_MIB) + ' MiB.')
elif value.size == 0:
raise ValidationError("File is empty.")
# Validate if it is a text file.
try:
input_str = value.read().decode("utf-8")
except UnicodeDecodeError:
raise ValidationError("Only plain text files are allowed.")
input_lines = input_str.splitlines()
header_line_1 = input_lines[0]
header_line_2 = input_lines[1]
body = "\n".join(input_lines[2:]) + "\n"
# Validate the header and start with the first line, which should contain
# the variable names.
header_parts = header_line_1.split(";")
if len(header_parts) == 0:
raise ValidationError("Empty header.", code="invalid")
var_num = int(len(header_parts))
h_pattern_str = r"^(?:[^;]{1,50};){1,9}[^;]{1,50}$"
h_pattern = re.compile(h_pattern_str, re.ASCII)
header_is_ok = False
result = h_pattern.match(header_line_1)
if result:
header_is_ok = (result.end()-result.start() == len(header_line_1))
if not header_is_ok:
raise ValidationError("Error in header's first line.", code="invalid")
# Valide the second line, which should contain the variable symbols.
header_parts = header_line_2.split(";")
if int(len(header_parts)) != var_num:
raise ValidationError("Error in the header's second line. "
"A variable symbol for each variable must "
"be provided.", code="invalid")
h_pattern_str = r"^(?:[^,\s]{1,5};){1,9}[^;\s]{1,5}$"
h_pattern = re.compile(h_pattern_str, re.ASCII)
header_is_ok = False
result = h_pattern.match(header_line_2)
if result:
header_is_ok = (result.end()-result.start() == len(header_line_2))
if not header_is_ok:
raise ValidationError("Error in header's second line.", code="invalid")
# Validate the body.
if len(body) == 0:
raise ValidationError("Empty body.", code="invalid")
b_pattern_str = (r"(?:(?:\s*\d+[\.,]?\d*\s*;){1," + str(var_num-1)
+ r"}\s*\d+[\.,]?\d*\s*\n)+")
b_pattern = re.compile(b_pattern_str, re.ASCII)
body_is_ok = False
result = b_pattern.match(body)
if result:
body_is_ok = result.end()-result.start() == len(body)
if not body_is_ok:
end_of_line = body.find("\n", result.end())
start_of_line = body.rfind("\n", 0, result.end())
if end_of_line == -1:
end_of_line = len(body)
if start_of_line == -1:
start_of_line = 0
error_line = body[start_of_line : end_of_line].strip()
if len(error_line) > 50:
error_line = error_line[0:50] + "..."
raise ValidationError("Error in the following line: %(err_line)s",
code="invalid",
params={"err_line" : error_line})
else:
if not body_is_ok:
raise ValidationError("Error in body.", code="invalid")
value.seek(0)