Source code for b2sdk.upload_source

######################################################################
#
# File: b2sdk/upload_source.py
#
# Copyright 2019 Backblaze Inc. All Rights Reserved.
#
# License https://www.backblaze.com/using_b2_code.html
#
######################################################################

import hashlib
import os
from abc import (ABCMeta, abstractmethod)

import six

from .exception import InvalidUploadSource
from .utils import (BytesIoContextManager, hex_sha1_of_stream)


[docs]@six.add_metaclass(ABCMeta) class AbstractUploadSource(object): """ The source of data for uploading to b2. """
[docs] @abstractmethod def get_content_length(self): """ Return the number of bytes of data in the file. """
[docs] @abstractmethod def get_content_sha1(self): """ Return a 40-character string containing the hex SHA1 checksum of the data in the file. """
[docs] @abstractmethod def open(self): """ Return a binary file-like object from which the data can be read. :return: """
[docs]class UploadSourceBytes(AbstractUploadSource):
[docs] def __init__(self, data_bytes): self.data_bytes = data_bytes
[docs] def get_content_length(self): return len(self.data_bytes)
[docs] def get_content_sha1(self): return hashlib.sha1(self.data_bytes).hexdigest()
[docs] def open(self): return BytesIoContextManager(self.data_bytes)
[docs]class UploadSourceLocalFile(AbstractUploadSource):
[docs] def __init__(self, local_path, content_sha1=None): self.local_path = local_path if not os.path.isfile(local_path): raise InvalidUploadSource(local_path) self.content_length = os.path.getsize(local_path) self.content_sha1 = content_sha1
[docs] def get_content_length(self): return self.content_length
[docs] def get_content_sha1(self): if self.content_sha1 is None: self.content_sha1 = self._hex_sha1_of_file(self.local_path) return self.content_sha1
[docs] def open(self): return open(self.local_path, 'rb')
def _hex_sha1_of_file(self, local_path): with open(local_path, 'rb') as f: return hex_sha1_of_stream(f, self.content_length)