58 lines
2.1 KiB
Python
58 lines
2.1 KiB
Python
import logging
|
|
from io import BytesIO
|
|
from twisted.python.failure import Failure
|
|
from lbrynet.core.Error import DownloadCanceledError, InvalidDataError
|
|
from lbrynet.core.cryptoutils import get_lbry_hash_obj
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class HashBlobWriter(object):
|
|
def __init__(self, length_getter, finished_cb):
|
|
self.write_handle = BytesIO()
|
|
self.length_getter = length_getter
|
|
self.finished_cb = finished_cb
|
|
self.finished_cb_d = None
|
|
self._hashsum = get_lbry_hash_obj()
|
|
self.len_so_far = 0
|
|
|
|
def __del__(self):
|
|
if self.finished_cb_d is None:
|
|
log.warn("Garbage collection was called, but writer was not closed yet")
|
|
self.close()
|
|
|
|
@property
|
|
def blob_hash(self):
|
|
return self._hashsum.hexdigest()
|
|
|
|
def write(self, data):
|
|
if self.write_handle is None:
|
|
log.exception("writer has already been closed")
|
|
raise IOError('I/O operation on closed file')
|
|
|
|
self._hashsum.update(data)
|
|
self.len_so_far += len(data)
|
|
if self.len_so_far > self.length_getter():
|
|
self.finished_cb_d = self.finished_cb(
|
|
self,
|
|
Failure(InvalidDataError("Length so far is greater than the expected length."
|
|
" %s to %s" % (self.len_so_far,
|
|
self.length_getter()))))
|
|
else:
|
|
self.write_handle.write(data)
|
|
if self.len_so_far == self.length_getter():
|
|
self.finished_cb_d = self.finished_cb(self)
|
|
|
|
def close_handle(self):
|
|
if self.write_handle is not None:
|
|
self.write_handle.close()
|
|
self.write_handle = None
|
|
|
|
def close(self, reason=None):
|
|
# if we've already called finished_cb because we either finished writing
|
|
# or closed already, do nothing
|
|
if self.finished_cb_d is not None:
|
|
return
|
|
if reason is None:
|
|
reason = Failure(DownloadCanceledError())
|
|
self.finished_cb_d = self.finished_cb(self, reason)
|