# Path: sevenbridges/errors.py
# class SbgError(Exception):
#     """Base class for SBG errors.
# 
#     Provides a base exception for all errors
#     that are thrown by sevenbridges-python library.
#     """
# 
#     def __init__(self, message=None, code=None, status=None, more_info=None):
#         """
#         :param code: Custom error code
#         :param status: Http status code.
#         :param message: Message describing the error.
#         """
#         self.code = code
#         self.status = status
#         self.message = message
#         self.more_info = more_info
# 
#     def __str__(self):
#         return str(self.message)
# 
# Path: sevenbridges/http/client.py
# def generate_session(
#         pool_connections, pool_maxsize, pool_block, proxies=None,
#         retry_count=None, backoff_factor=None,
# ):
#     """
#     Utility method to generate request sessions.
#     :param pool_connections: The number of urllib3 connection pools to
#         cache.
#     :param pool_maxsize: The maximum number of connections to save in the
#         pool.
#     :param pool_block: Whether the connection pool should block for
#         connections.
#     :param proxies: Proxies dictionary.
#     :param retry_count: Number of retries to attempt
#     :param backoff_factor: Backoff factor for retries
#     :return: requests.Session object.
#     """
#     session = RequestSession()
# 
#     # Retry if no response from server, this applies to failed DNS lookups,
#     # socket connections and connection timeouts
#     retry_count = retry_count or RequestParameters.DEFAULT_RETRY_COUNT
#     backoff_factor = backoff_factor or RequestParameters.DEFAULT_BACKOFF_FACTOR
#     retries = urllib3.Retry(total=retry_count, backoff_factor=backoff_factor)
# 
#     # noinspection PyUnresolvedReferences
#     adapter = requests.adapters.HTTPAdapter(
#         pool_connections=pool_connections,
#         pool_maxsize=pool_maxsize,
#         pool_block=pool_block,
#         max_retries=retries
#     )
#     session.mount('http://', adapter)
#     session.mount('https://', adapter)
#     session.proxies = proxies
#     return session
# 
# Path: sevenbridges/models/enums.py
# class PartSize:
#     KB = 1024
#     MB = 1024 * KB
#     GB = 1024 * MB
#     TB = 1024 * GB
#     MAXIMUM_UPLOAD_SIZE = 5 * GB
#     MAXIMUM_OBJECT_SIZE = 5 * TB
#     MAXIMUM_TOTAL_PARTS = 10000
# 
#     DOWNLOAD_MINIMUM_PART_SIZE = 5 * MB
#     UPLOAD_MINIMUM_PART_SIZE = 5 * MB
#     UPLOAD_RECOMMENDED_SIZE = 32 * MB
# 
# class TransferState:
#     ABORTED = 'ABORTED'
#     RUNNING = 'RUNNING'
#     PAUSED = 'PAUSED'
#     COMPLETED = 'COMPLETED'
#     PREPARING = 'PREPARING'
#     STOPPED = 'STOPPED'
#     FAILED = 'FAILED'
# 
# class RequestParameters:
#     MAX_URL_LENGTH = 6000
#     DEFAULT_TIMEOUT = 300
#     DEFAULT_RETRY_COUNT = 6
#     DEFAULT_BACKOFF_FACTOR = 1
#     DEFAULT_BULK_LIMIT = 100
# 
# Path: sevenbridges/transfer/utils.py
# class Part:
#     def __init__(self, start=None, size=None):
#         self._start = start
#         self._size = size
# 
#     @property
#     def start(self):
#         return self._start
# 
#     @property
#     def size(self):
#         return self._size
# 
# class Progress:
#     def __init__(self, num_of_parts, parts_done, bytes_done,
#                  file_size, duration):
#         self._num_of_parts = num_of_parts
#         self._parts_done = parts_done
#         self._bytes_done = bytes_done
#         self._file_size = file_size
#         self._duration = duration
# 
#     @property
#     def num_of_parts(self):
#         return self._num_of_parts
# 
#     @property
#     def parts_done(self):
#         return self._parts_done
# 
#     @property
#     def bytes_done(self):
#         return self._bytes_done
# 
#     @property
#     def file_size(self):
#         return self._file_size
# 
#     @property
#     def duration(self):
#         return self._duration
# 
#     @property
#     def progress(self):
#         progress = (self._bytes_done / float(self._file_size)) * 100
#         progress = progress if progress <= 100 else 100
#         return progress
# 
#     @property
#     def bandwidth(self):
#         return (self._bytes_done / 1000000) / self.duration
# 
# def total_parts(file_size, part_size):
#     return int(math.ceil(file_size / float(part_size)))


import os
import time
import logging
import hashlib
import threading
import requests
from sevenbridges.errors import SbgError
from sevenbridges.http.client import generate_session
from sevenbridges.models.enums import (
    PartSize, TransferState, RequestParameters
)
from sevenbridges.transfer.utils import Part, Progress, total_parts
            start_b = end_byte + 1
            end_byte = start_b + self.part_size - 1
        return parts


# noinspection PyCallingNonCallable,PyTypeChecker,PyProtectedMember
class Download(threading.Thread):
    def __init__(
            self, url, file_path, part_size=None, retry_count=None,
            timeout=None, api=None
     ):
        """
        File multipart downloader.
        :param url: URL of the file.
        :param file_path: Local file path.
        :param retry_count: Number of times to retry on error.
        :param timeout: Connection timeout in seconds.
        :param part_size: Size of the parts in bytes.
        :param api: Api instance.
        """
        threading.Thread.__init__(self)
        self.daemon = True

        if api is None:
            raise SbgError('Api instance missing.')

        if part_size and part_size < PartSize.DOWNLOAD_MINIMUM_PART_SIZE:
            self._status = TransferState.FAILED
            raise SbgError(
                f'Part size is too small! Minimum get_parts size '

# Path: sevenbridges/errors.py
# class SbgError(Exception):
#     """Base class for SBG errors.
# 
#     Provides a base exception for all errors
#     that are thrown by sevenbridges-python library.
#     """
# 
#     def __init__(self, message=None, code=None, status=None, more_info=None):
#         """
#         :param code: Custom error code
#         :param status: Http status code.
#         :param message: Message describing the error.
#         """
#         self.code = code
#         self.status = status
#         self.message = message
#         self.more_info = more_info
# 
#     def __str__(self):
#         return str(self.message)
# 
# Path: sevenbridges/http/client.py
# def generate_session(
#         pool_connections, pool_maxsize, pool_block, proxies=None,
#         retry_count=None, backoff_factor=None,
# ):
#     """
#     Utility method to generate request sessions.
#     :param pool_connections: The number of urllib3 connection pools to
#         cache.
#     :param pool_maxsize: The maximum number of connections to save in the
#         pool.
#     :param pool_block: Whether the connection pool should block for
#         connections.
#     :param proxies: Proxies dictionary.
#     :param retry_count: Number of retries to attempt
#     :param backoff_factor: Backoff factor for retries
#     :return: requests.Session object.
#     """
#     session = RequestSession()
# 
#     # Retry if no response from server, this applies to failed DNS lookups,
#     # socket connections and connection timeouts
#     retry_count = retry_count or RequestParameters.DEFAULT_RETRY_COUNT
#     backoff_factor = backoff_factor or RequestParameters.DEFAULT_BACKOFF_FACTOR
#     retries = urllib3.Retry(total=retry_count, backoff_factor=backoff_factor)
# 
#     # noinspection PyUnresolvedReferences
#     adapter = requests.adapters.HTTPAdapter(
#         pool_connections=pool_connections,
#         pool_maxsize=pool_maxsize,
#         pool_block=pool_block,
#         max_retries=retries
#     )
#     session.mount('http://', adapter)
#     session.mount('https://', adapter)
#     session.proxies = proxies
#     return session
# 
# Path: sevenbridges/models/enums.py
# class PartSize:
#     KB = 1024
#     MB = 1024 * KB
#     GB = 1024 * MB
#     TB = 1024 * GB
#     MAXIMUM_UPLOAD_SIZE = 5 * GB
#     MAXIMUM_OBJECT_SIZE = 5 * TB
#     MAXIMUM_TOTAL_PARTS = 10000
# 
#     DOWNLOAD_MINIMUM_PART_SIZE = 5 * MB
#     UPLOAD_MINIMUM_PART_SIZE = 5 * MB
#     UPLOAD_RECOMMENDED_SIZE = 32 * MB
# 
# class TransferState:
#     ABORTED = 'ABORTED'
#     RUNNING = 'RUNNING'
#     PAUSED = 'PAUSED'
#     COMPLETED = 'COMPLETED'
#     PREPARING = 'PREPARING'
#     STOPPED = 'STOPPED'
#     FAILED = 'FAILED'
# 
# class RequestParameters:
#     MAX_URL_LENGTH = 6000
#     DEFAULT_TIMEOUT = 300
#     DEFAULT_RETRY_COUNT = 6
#     DEFAULT_BACKOFF_FACTOR = 1
#     DEFAULT_BULK_LIMIT = 100
# 
# Path: sevenbridges/transfer/utils.py
# class Part:
#     def __init__(self, start=None, size=None):
#         self._start = start
#         self._size = size
# 
#     @property
#     def start(self):
#         return self._start
# 
#     @property
#     def size(self):
#         return self._size
# 
# class Progress:
#     def __init__(self, num_of_parts, parts_done, bytes_done,
#                  file_size, duration):
#         self._num_of_parts = num_of_parts
#         self._parts_done = parts_done
#         self._bytes_done = bytes_done
#         self._file_size = file_size
#         self._duration = duration
# 
#     @property
#     def num_of_parts(self):
#         return self._num_of_parts
# 
#     @property
#     def parts_done(self):
#         return self._parts_done
# 
#     @property
#     def bytes_done(self):
#         return self._bytes_done
# 
#     @property
#     def file_size(self):
#         return self._file_size
# 
#     @property
#     def duration(self):
#         return self._duration
# 
#     @property
#     def progress(self):
#         progress = (self._bytes_done / float(self._file_size)) * 100
#         progress = progress if progress <= 100 else 100
#         return progress
# 
#     @property
#     def bandwidth(self):
#         return (self._bytes_done / 1000000) / self.duration
# 
# def total_parts(file_size, part_size):
#     return int(math.ceil(file_size / float(part_size)))


# Path: sevenbridges/transfer/download.py
import os
import time
import logging
import hashlib
import threading
import requests
from sevenbridges.errors import SbgError
from sevenbridges.http.client import generate_session
from sevenbridges.models.enums import (
    PartSize, TransferState, RequestParameters
)
from sevenbridges.transfer.utils import Part, Progress, total_parts

            start_b = end_byte + 1
            end_byte = start_b + self.part_size - 1
        return parts


# noinspection PyCallingNonCallable,PyTypeChecker,PyProtectedMember
class Download(threading.Thread):
    def __init__(
            self, url, file_path, part_size=None, retry_count=None,
            timeout=None, api=None
     ):
        """
        File multipart downloader.
        :param url: URL of the file.
        :param file_path: Local file path.
        :param retry_count: Number of times to retry on error.
        :param timeout: Connection timeout in seconds.
        :param part_size: Size of the parts in bytes.
        :param api: Api instance.
        """
        threading.Thread.__init__(self)
        self.daemon = True

        if api is None:
            raise SbgError('Api instance missing.')

        if part_size and part_size < PartSize.DOWNLOAD_MINIMUM_PART_SIZE:
            self._status = TransferState.FAILED
            raise SbgError(
                f'Part size is too small! Minimum get_parts size '

                f'is {PartSize.DOWNLOAD_MINIMUM_PART_SIZE}'