Defined file transferer abstract base class
This will allow for different file transfer classes uploading to different services.
This commit is contained in:
parent
ac3f6142b3
commit
0778b3a6ec
@ -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)
|
||||||
|
|||||||
@ -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,7 +56,8 @@ 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(
|
||||||
|
"%d files couldn't be transferred" % len(files_remaining),
|
||||||
files_remaining)
|
files_remaining)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@ -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:
|
||||||
|
|||||||
44
blender_asset_tracer/pack/transfer.py
Normal file
44
blender_asset_tracer/pack/transfer.py
Normal 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.
|
||||||
|
"""
|
||||||
Loading…
x
Reference in New Issue
Block a user