Files
old-krovovi-kalkulator/helix/validators/file_validator.py
2017-12-20 20:27:55 +01:00

173 lines
4.6 KiB
Python

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, expected, file=None, extension=None):
"""Validates the uploaded file by extension
and content
Arguments;
stream (string): File content
file (FileObject): A file object provided from the ui. Used only to get the file extension.
"""
try:
file_type = self.identify_file_type(stream)
assert file_type == expected
validator = file_type.validator(self.values)
if extension is None:
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