# 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

    checksum = db.Column(db.String(255), nullable=True)
    """String representing the checksum of the part."""

    # Relationships definitions
    multipart = db.relationship(MultipartObject, backref='parts')
    """Relationship to multipart objects."""

    @property
    def start_byte(self):
        """Get start byte in file of this part."""
        return self.part_number * self.multipart.chunk_size

    @property
    def end_byte(self):
        """Get end byte in file for this part."""
        return min(
            (self.part_number + 1) * self.multipart.chunk_size,
            self.multipart.size
        )

    @property
    def part_size(self):
        """Get size of this part."""
        return self.end_byte - self.start_byte

    @classmethod
    def create(cls, mp, part_number, stream=None, **kwargs):
        """Create a new part object in a multipart object."""
        if part_number < 0 or part_number > mp.last_part_number:

# 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


    checksum = db.Column(db.String(255), nullable=True)
    """String representing the checksum of the part."""

    # Relationships definitions
    multipart = db.relationship(MultipartObject, backref='parts')
    """Relationship to multipart objects."""

    @property
    def start_byte(self):
        """Get start byte in file of this part."""
        return self.part_number * self.multipart.chunk_size

    @property
    def end_byte(self):
        """Get end byte in file for this part."""
        return min(
            (self.part_number + 1) * self.multipart.chunk_size,
            self.multipart.size
        )

    @property
    def part_size(self):
        """Get size of this part."""
        return self.end_byte - self.start_byte

    @classmethod
    def create(cls, mp, part_number, stream=None, **kwargs):
        """Create a new part object in a multipart object."""
        if part_number < 0 or part_number > mp.last_part_number:

            raise MultipartInvalidPartNumber()