# Path: invenio_files_rest/errors.py
# class BucketLockedError(InvalidOperationError):
#     """Exception raised when a bucket is locked."""
# 
#     code = 403
#     description = "Bucket is locked for modifications."
# 
# class FileInstanceAlreadySetError(InvalidOperationError):
#     """Exception raised when file instance already set on object."""
# 
# class FileInstanceUnreadableError(InvalidOperationError):
#     """Exception raised when trying to get an unreadable file."""
# 
#     code = 503
#     description = "File storage is offline."
# 
# class FileSizeError(StorageError):
#     """Exception raised when a file larger than allowed."""
# 
#     code = 400
# 
# class InvalidKeyError(InvalidOperationError):
#     """Invalid key."""
# 
#     code = 400
#     description = "Filename is too long."
# 
# class InvalidOperationError(FilesException):
#     """Exception raised when an invalid operation is performed."""
# 
#     code = 403
# 
# class MultipartAlreadyCompleted(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 403
#     description = "Multipart upload is already completed."
# 
# class MultipartInvalidChunkSize(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 400
#     description = "Invalid part size."
# 
# class MultipartInvalidPartNumber(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 400
#     description = "Invalid part number."
# 
# class MultipartInvalidSize(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 400
#     description = "Invalid file size."
# 
# class MultipartMissingParts(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 400
#     description = "Not all parts have been uploaded."
# 
# class MultipartNotCompleted(MultipartException):
#     """Exception raised when multipart object is not already completed."""
# 
#     code = 400
#     description = "Multipart upload is already completed."
# 
# Path: invenio_files_rest/proxies.py

# 
# Path: invenio_files_rest/utils.py
# def guess_mimetype(filename):
#     """Map extra mimetype with the encoding provided.
# 
#     :returns: The extra mimetype.
#     """
#     m, encoding = mimetypes.guess_type(filename)
#     if encoding:
#         m = ENCODING_MIMETYPES.get(encoding, None)
#     return m or 'application/octet-stream'


import re
import sys
import uuid
from datetime import datetime
from flask import current_app
from functools import wraps
from invenio_db import db
from os.path import basename
from sqlalchemy.dialects import mysql
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import validates
from sqlalchemy.orm.exc import MultipleResultsFound
from sqlalchemy_utils.types import UUIDType
from .errors import BucketLockedError, FileInstanceAlreadySetError, \
    FileInstanceUnreadableError, FileSizeError, InvalidKeyError, \
    InvalidOperationError, MultipartAlreadyCompleted, \
    MultipartInvalidChunkSize, MultipartInvalidPartNumber, \
    MultipartInvalidSize, MultipartMissingParts, MultipartNotCompleted
from .proxies import current_files_rest
from .utils import guess_mimetype
                self.key,
                _file_id=self.file_id,
                version_id=version_id
            )
            self.delete()
        return obj

    def delete(self):
        """Delete a multipart object."""
        # Update bucket size.
        self.bucket.size -= self.size
        # Remove parts
        Part.query_by_multipart(self).delete()
        # Remove self
        self.query.filter_by(upload_id=self.upload_id).delete()

    @classmethod
    def create(cls, bucket, key, size, chunk_size):
        """Create a new object in a bucket."""
        bucket = as_bucket(bucket)

        if bucket.locked:
            raise BucketLockedError()

        # Validate chunk size.
        if not cls.is_valid_chunksize(chunk_size):
            raise MultipartInvalidChunkSize()

        # Validate max theoretical size.
        if not cls.is_valid_size(size, chunk_size):

# Path: invenio_files_rest/errors.py
# class BucketLockedError(InvalidOperationError):
#     """Exception raised when a bucket is locked."""
# 
#     code = 403
#     description = "Bucket is locked for modifications."
# 
# class FileInstanceAlreadySetError(InvalidOperationError):
#     """Exception raised when file instance already set on object."""
# 
# class FileInstanceUnreadableError(InvalidOperationError):
#     """Exception raised when trying to get an unreadable file."""
# 
#     code = 503
#     description = "File storage is offline."
# 
# class FileSizeError(StorageError):
#     """Exception raised when a file larger than allowed."""
# 
#     code = 400
# 
# class InvalidKeyError(InvalidOperationError):
#     """Invalid key."""
# 
#     code = 400
#     description = "Filename is too long."
# 
# class InvalidOperationError(FilesException):
#     """Exception raised when an invalid operation is performed."""
# 
#     code = 403
# 
# class MultipartAlreadyCompleted(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 403
#     description = "Multipart upload is already completed."
# 
# class MultipartInvalidChunkSize(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 400
#     description = "Invalid part size."
# 
# class MultipartInvalidPartNumber(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 400
#     description = "Invalid part number."
# 
# class MultipartInvalidSize(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 400
#     description = "Invalid file size."
# 
# class MultipartMissingParts(MultipartException):
#     """Exception raised when multipart object is already completed."""
# 
#     code = 400
#     description = "Not all parts have been uploaded."
# 
# class MultipartNotCompleted(MultipartException):
#     """Exception raised when multipart object is not already completed."""
# 
#     code = 400
#     description = "Multipart upload is already completed."
# 
# Path: invenio_files_rest/proxies.py

# 
# Path: invenio_files_rest/utils.py
# def guess_mimetype(filename):
#     """Map extra mimetype with the encoding provided.
# 
#     :returns: The extra mimetype.
#     """
#     m, encoding = mimetypes.guess_type(filename)
#     if encoding:
#         m = ENCODING_MIMETYPES.get(encoding, None)
#     return m or 'application/octet-stream'


# Path: invenio_files_rest/models.py
import re
import sys
import uuid
from datetime import datetime
from flask import current_app
from functools import wraps
from invenio_db import db
from os.path import basename
from sqlalchemy.dialects import mysql
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import validates
from sqlalchemy.orm.exc import MultipleResultsFound
from sqlalchemy_utils.types import UUIDType
from .errors import BucketLockedError, FileInstanceAlreadySetError, \
    FileInstanceUnreadableError, FileSizeError, InvalidKeyError, \
    InvalidOperationError, MultipartAlreadyCompleted, \
    MultipartInvalidChunkSize, MultipartInvalidPartNumber, \
    MultipartInvalidSize, MultipartMissingParts, MultipartNotCompleted
from .proxies import current_files_rest
from .utils import guess_mimetype

                self.key,
                _file_id=self.file_id,
                version_id=version_id
            )
            self.delete()
        return obj

    def delete(self):
        """Delete a multipart object."""
        # Update bucket size.
        self.bucket.size -= self.size
        # Remove parts
        Part.query_by_multipart(self).delete()
        # Remove self
        self.query.filter_by(upload_id=self.upload_id).delete()

    @classmethod
    def create(cls, bucket, key, size, chunk_size):
        """Create a new object in a bucket."""
        bucket = as_bucket(bucket)

        if bucket.locked:
            raise BucketLockedError()

        # Validate chunk size.
        if not cls.is_valid_chunksize(chunk_size):
            raise MultipartInvalidChunkSize()

        # Validate max theoretical size.
        if not cls.is_valid_size(size, chunk_size):

            raise MultipartInvalidSize()