Defined file transferer abstract base class

This will allow for different file transfer classes uploading to different
services.
This commit is contained in:
Sybren A. Stüvel 2018-03-09 13:04:14 +01:00
parent ac3f6142b3
commit 0778b3a6ec
3 changed files with 54 additions and 14 deletions

View File

@ -4,6 +4,7 @@ import pathlib
import sys import sys
import typing import typing
import blender_asset_tracer.pack.transfer
from blender_asset_tracer import pack from blender_asset_tracer import pack
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -34,7 +35,7 @@ def cli_pack(args):
try: try:
packer.execute() packer.execute()
except pack.queued_copy.FileCopyError as ex: except blender_asset_tracer.pack.transfer.FileTransferError as ex:
log.error("%d files couldn't be copied, starting with %s", log.error("%d files couldn't be copied, starting with %s",
len(ex.files_remaining), ex.files_remaining[0]) len(ex.files_remaining), ex.files_remaining[0])
raise SystemExit(1) raise SystemExit(1)

View File

@ -6,23 +6,17 @@ import queue
import shutil import shutil
import typing import typing
from . import transfer
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class FileCopyError(IOError):
"""Raised when one or more files could not be transferred."""
def __init__(self, message, files_remaining: typing.List[pathlib.Path]) -> None:
super().__init__(message)
self.files_remaining = files_remaining
class Action(enum.Enum): class Action(enum.Enum):
COPY = 1 COPY = 1
MOVE = 2 MOVE = 2
class FileCopier(threading.Thread): class FileCopier(threading.Thread, transfer.FileTransferer):
"""Copies or moves files in source directory order.""" """Copies or moves files in source directory order."""
def __init__(self, *args, **kwargs) -> None: def __init__(self, *args, **kwargs) -> None:
@ -62,8 +56,9 @@ class FileCopier(threading.Thread):
src, dst = self.queue.get_nowait() src, dst = self.queue.get_nowait()
files_remaining.append(src) files_remaining.append(src)
assert files_remaining assert files_remaining
raise FileCopyError("%d files couldn't be transferred" % len(files_remaining), raise transfer.FileTransferError(
files_remaining) "%d files couldn't be transferred" % len(files_remaining),
files_remaining)
def run(self): def run(self):
files_transferred = 0 files_transferred = 0
@ -98,8 +93,8 @@ class FileCopier(threading.Thread):
dst.parent.mkdir(parents=True, exist_ok=True) dst.parent.mkdir(parents=True, exist_ok=True)
# TODO(Sybren): when we target Py 3.6+, remove the str() calls. # TODO(Sybren): when we target Py 3.6+, remove the str() calls.
transfer = transfer_funcs[act] tfunc = transfer_funcs[act]
transfer(str(src), str(dst)) tfunc(str(src), str(dst))
files_transferred += 1 files_transferred += 1
except Exception: except Exception:

View File

@ -0,0 +1,44 @@
import abc
import pathlib
import typing
class FileTransferError(IOError):
"""Raised when one or more files could not be transferred."""
def __init__(self, message, files_remaining: typing.List[pathlib.Path]) -> None:
super().__init__(message)
self.files_remaining = files_remaining
class FileTransferer(metaclass=abc.ABCMeta):
"""Interface for file transfer classes."""
@abc.abstractmethod
def start(self):
"""Starts the file transfer thread/process.
This could spin up a separate thread to perform the actual file
transfer. After start() is called, implementations should still accept
calls to the queue_xxx() methods. In other words, this is not to be
used as queue-and-then-start, but as start-and-then-queue.
"""
@abc.abstractmethod
def queue_copy(self, src: pathlib.Path, dst: pathlib.Path) -> None:
"""Queue a copy action from 'src' to 'dst'."""
@abc.abstractmethod
def queue_move(self, src: pathlib.Path, dst: pathlib.Path) -> None:
"""Queue a move action from 'src' to 'dst'."""
@abc.abstractmethod
def done_and_join(self) -> None:
"""Indicate all files have been queued, and wait until done.
After this function has been called, the queue_xxx() methods should not
be called any more.
:raises FileTransferError: if there was an error transferring one or
more files.
"""