first commit
This commit is contained in:
171
helix/validators/file_validator.py
Normal file
171
helix/validators/file_validator.py
Normal file
@@ -0,0 +1,171 @@
|
||||
from enum import Enum
|
||||
import pathlib
|
||||
|
||||
from helix.constants.file_validation_error import FileValidationError
|
||||
from helix.constants.file_validation_error import FileValidationMessage
|
||||
from helix.validators.csv_input_validator import CsvInputValidator
|
||||
from helix.validators.dxf_input_validator import DxfInputValidator
|
||||
|
||||
|
||||
class UnknownFileValidator(object):
|
||||
def __init__(self, _):
|
||||
pass
|
||||
|
||||
def validate(self, _):
|
||||
return FileValidationError(FileValidationMessage.UnknownFileUploaded,
|
||||
None)
|
||||
|
||||
|
||||
class FileType(Enum):
|
||||
Csv = 0
|
||||
AuroraDxf = 1
|
||||
Unknown = 2
|
||||
|
||||
@property
|
||||
def validator(self):
|
||||
"""Provide the proper implementation
|
||||
of the validation for the selected
|
||||
FileType
|
||||
|
||||
"""
|
||||
|
||||
return {
|
||||
FileType.Csv: CsvInputValidator,
|
||||
FileType.AuroraDxf: DxfInputValidator,
|
||||
FileType.Unknown: UnknownFileValidator
|
||||
}.get(self)
|
||||
|
||||
def valid_mapping(self, extension):
|
||||
"""Validates the extension obtained file
|
||||
|
||||
Arguments;
|
||||
extension: string
|
||||
Returns:
|
||||
boolean
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
mapping = {FileType.Csv: ["txt", "csv"],
|
||||
FileType.AuroraDxf: ["dxf"],
|
||||
FileType.Unknown: [None]}.get(self)
|
||||
assert extension in mapping
|
||||
except AssertionError:
|
||||
raise InvalidMappingException
|
||||
|
||||
def get_invalid_mapping_error(self):
|
||||
"""Get the validation message
|
||||
when choosing the wrong file for the
|
||||
selected FileType
|
||||
|
||||
Returns:
|
||||
dict
|
||||
|
||||
"""
|
||||
|
||||
mapping = {FileType.Csv:
|
||||
FileValidationMessage.ExpectedTxtFile,
|
||||
FileType.AuroraDxf:
|
||||
FileValidationMessage.ExpectedDxfFile,
|
||||
FileType.Unknown:
|
||||
FileValidationMessage.UnknownFileUploaded}.get(self)
|
||||
|
||||
return mapping
|
||||
|
||||
|
||||
class FileValidator(object):
|
||||
"""Validates that the received stream
|
||||
belongs to a valid FileType
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, user_values):
|
||||
self.values = user_values
|
||||
|
||||
def obtain_stream(self, path):
|
||||
"""Obtain the content of the file
|
||||
|
||||
Argument:
|
||||
path (str): A path that will be opened
|
||||
Returns:
|
||||
str The content of the file, otherwise an empty string
|
||||
|
||||
"""
|
||||
|
||||
content = ""
|
||||
try:
|
||||
content = path.read().decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
finally:
|
||||
return content
|
||||
|
||||
def validate(self, stream, file, expected):
|
||||
"""Validates the uploaded file by extension
|
||||
and content
|
||||
|
||||
Arguments;
|
||||
stream (string): File content
|
||||
file (FileObject): A file object provided from the ui
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
file_type = self.identify_file_type(stream)
|
||||
assert file_type == expected
|
||||
validator = file_type.validator(self.values)
|
||||
extension = self.obtain_extension(file)
|
||||
file_type.valid_mapping(extension)
|
||||
return validator.validate(stream)
|
||||
except AssertionError:
|
||||
return FileValidationError(expected.get_invalid_mapping_error(),
|
||||
None)
|
||||
except InvalidMappingException:
|
||||
error_type = file_type.get_invalid_mapping_error()
|
||||
return FileValidationError(error_type, None)
|
||||
except IndexError:
|
||||
error_type = FileValidationMessage.UnknownFileUploaded
|
||||
return FileValidationError(error_type, None)
|
||||
except InvalidExtensionException:
|
||||
error_type = FileValidationMessage.UnknownFileUploaded
|
||||
return FileValidationError(error_type, None)
|
||||
|
||||
def obtain_extension(self, file_object):
|
||||
"""Obtain the extension from the
|
||||
user uploaded file
|
||||
|
||||
Arguments:
|
||||
file_object (file): A file like object
|
||||
|
||||
"""
|
||||
|
||||
extension = pathlib.Path(file_object.filename).suffix
|
||||
file_pieces = extension.split(".")
|
||||
return file_pieces[1]
|
||||
|
||||
def identify_file_type(self, file):
|
||||
"""Determines the FileType object
|
||||
based on the beginning of the provided string
|
||||
|
||||
Arguments;
|
||||
file (str): The raw stream
|
||||
Returns:
|
||||
enum
|
||||
|
||||
"""
|
||||
|
||||
if file.startswith("999\r\nDesign created by Aurora"):
|
||||
return FileType.AuroraDxf
|
||||
|
||||
if file.startswith("HANDLE\t"):
|
||||
return FileType.Csv
|
||||
|
||||
return FileType.Unknown
|
||||
|
||||
|
||||
class InvalidExtensionException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidMappingException(Exception):
|
||||
pass
|
||||
Reference in New Issue
Block a user